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

tomahawk2.c (306469B)


      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:        tomahawk2.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 #include <shared/bsl.h>
     12 #include <soc/tdm/core/tdm_top.h>
     13 
     14 #include <soc/defs.h>
     15 #include <soc/mem.h>
     16 #if defined(BCM_TOMAHAWK2_SUPPORT)
     17 #include <soc/tomahawk2.h>
     18 #include <soc/tomahawk.h>
     19 #include <soc/tomahawk2_tdm.h>
     20 #include <soc/pstats.h>
     21 #include <soc/bondoptions.h>
     22 #include <soc/scache.h>
     23 
     24 #ifndef MIN
     25 #define MIN(a, b)               (((a)<(b))?(a):(b))
     26 #endif
     27 
     28 #ifndef MAX
     29 #define MAX(a, b)               (((a)>(b))?(a):(b))
     30 #endif
     31 
     32 #define CEIL(x, y)              (((x) + ((y)-1)) / (y))
     33 
     34 #define TH2_MMU_SHARED_LIMIT_CHK(val1, val2, flags) \
     35     (((flags) && (val1 > val2)) || ((!flags) && (val1 < val2)))
     36 
     37 int
     38 _soc_th2_port_speed_cap[SOC_MAX_NUM_DEVICES][_TH2_DEV_PORTS_PER_DEV];
     39 
     40 int
     41 soc_th2_post_mmu_init_update(int unit)
     42 {
     43     int port;
     44     soc_info_t *si = &SOC_INFO(unit);
     45 
     46     PBMP_ALL_ITER(unit, port) {
     47         /* Set init speed to max speed by default */
     48         si->port_init_speed[port] = si->port_speed_max[port];
     49         if (_soc_th2_port_speed_cap[unit][port]) {
     50             /* If cap speed is available then adjust max speed for further use */
     51             si->port_speed_max[port] = _soc_th2_port_speed_cap[unit][port];
     52         }
     53     }
     54     return SOC_E_NONE;
     55 }
     56 
     57 STATIC int
     58 soc_tomahawk2_frequency_get(int unit, int *max_freq, int *def_freq)
     59 {
     60     if (soc_feature(unit, soc_feature_untethered_otp)) {
     61         *max_freq = SOC_BOND_INFO(unit)->max_core_freq;
     62         *def_freq = SOC_BOND_INFO(unit)->default_core_freq;
     63     } else {
     64         *max_freq = *def_freq = 1700;
     65     }
     66 
     67     return SOC_E_NONE;
     68 }
     69 
     70 STATIC int
     71 soc_tomahawk2_tsc_max_lane_speed_get(int unit, int tsc_id, int *speed)
     72 {
     73     SHR_BITDCL otp;
     74 
     75     memset(&otp, 0, sizeof(otp));
     76 
     77     /*
     78      * Each TSC has two bit.
     79      * 00 = no restriction
     80      * 01 = 21.875G
     81      * 10 = 10.9375G
     82      * 11 = reserved
     83      */
     84     SHR_BITCOPY_RANGE(&otp, 0, SOC_BOND_INFO(unit)->tsc_max_speed, tsc_id * 2, 2);
     85 
     86     switch(otp) {
     87         case 0:
     88             *speed = 27000; /* No restriction*/
     89             break;
     90         case 1:
     91             *speed = 21000; /* 21.875G */
     92             break;
     93         case 2:
     94             *speed = 11000; /* 10.9375G */
     95             break;
     96         default:
     97             return SOC_E_INTERNAL;
     98     }
     99 
    100     return SOC_E_NONE;
    101 }
    102 
    103 int
    104 soc_tomahawk2_tsc_otp_info_get(int unit, int tsc_id,
    105                                _soc_tomahawk2_tsc_otp_info_t *info)
    106 {
    107 
    108     if (soc_feature(unit, soc_feature_untethered_otp)) {
    109         info->disable =
    110             SHR_BITGET(SOC_BOND_INFO(unit)->tsc_disabled, tsc_id) ? 1 : 0;
    111         info->force_hg =
    112             SHR_BITGET(SOC_BOND_INFO(unit)->force_hg, tsc_id) ? 1 : 0;
    113         info->force_loopback =
    114             SHR_BITGET(SOC_BOND_INFO(unit)->tsc_in_loop, tsc_id) ? 1 : 0;
    115         SOC_IF_ERROR_RETURN(
    116             soc_tomahawk2_tsc_max_lane_speed_get(unit, tsc_id,
    117                                                  &info->max_lane_speed));
    118     } else {
    119         info->disable = 0;
    120         info->force_hg = 0;
    121         info->force_loopback = 0;
    122         info->max_lane_speed = 27000; /* No restriction*/
    123     }
    124 
    125     return SOC_E_NONE;
    126 }
    127 
    128 STATIC int
    129 _soc_th2_ports_per_pm_get(int unit, int pm_id)
    130 {
    131     soc_info_t *si;
    132     int phy_port, i, num_ports = 0;
    133 
    134     si = &SOC_INFO(unit);
    135 
    136     if (pm_id >= _TH2_PBLKS_PER_DEV) {
    137        return 0;
    138     }
    139 
    140     phy_port = 1 + (pm_id * _TH2_PORTS_PER_PBLK);
    141     for (i = 0; i < _TH2_PORTS_PER_PBLK; ) {
    142         if (si->port_p2l_mapping[phy_port + i] != -1) {
    143             num_ports ++;
    144             i += si->port_num_lanes[si->port_p2l_mapping[phy_port + i]];
    145         }else {
    146             i ++;
    147         }
    148     }
    149 
    150     return num_ports;
    151 }
    152 
    153 
    154 STATIC int
    155 _soc_tomahawk2_port_flex_init(int unit, int is_any_cap)
    156 {
    157     soc_info_t *si;
    158     int pm, blk_idx, blk_type;
    159     int flex_en, static_ports, max_ports;
    160 
    161     si = &SOC_INFO(unit);
    162     SHR_BITCLR_RANGE(si->flexible_pm_bitmap, 0, SOC_MAX_NUM_BLKS);
    163     
    164     /* portmap_x=y:speed:i */
    165     /* portmap_x=y:speed:cap */
    166     if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all)) || is_any_cap) {
    167         SHR_BITSET_RANGE(si->flexible_pm_bitmap, 1, _TH2_PBLKS_PER_DEV);
    168     } else {
    169         /* port_flex_enable */
    170         for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
    171             blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
    172             pm = SOC_BLOCK_NUMBER(unit, blk_idx);
    173             if (blk_type == SOC_BLK_CLPORT) {
    174                 /* port_flex_enable_corex=<0...1> */
    175                 flex_en = soc_property_suffix_num_get_only_suffix(unit, 
    176                     pm, spn_PORT_FLEX_ENABLE, "core", -1);
    177                 /* port_flex_enable{x}=<0...1> */
    178                 /* port_flex_enable=<0...1> */
    179                 if (flex_en == -1) {
    180                     flex_en = soc_property_phys_port_get(unit,
    181                         (pm * _TH2_PORTS_PER_PBLK + 1), 
    182                         spn_PORT_FLEX_ENABLE, 0);
    183                 }
    184                 if (flex_en) {
    185                     SHR_BITSET(si->flexible_pm_bitmap, blk_idx);
    186                 }
    187             }
    188         }
    189     }
    190 
    191     si->flex_eligible = 
    192         (!SHR_BITNULL_RANGE(si->flexible_pm_bitmap, 1, _TH2_PBLKS_PER_DEV));
    193 
    194     /* port_flex_max_ports */
    195     memset(&(si->pm_max_ports), 0xff, sizeof(si->pm_max_ports));
    196     for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
    197         blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
    198         pm = SOC_BLOCK_NUMBER(unit, blk_idx);
    199         if (blk_type == SOC_BLK_CLPORT) {
    200             static_ports = _soc_th2_ports_per_pm_get(unit, pm);
    201             if (SHR_BITGET(si->flexible_pm_bitmap, blk_idx)) {
    202                 /* port_flex_max_ports_corex=y */
    203                 max_ports = soc_property_suffix_num_get_only_suffix(unit, 
    204                     pm, spn_PORT_FLEX_MAX_PORTS, "core", -1);
    205                 /* port_flex_max_ports{x}=y */
    206                 /* port_flex_max_ports=y */
    207                 if (max_ports == -1) {
    208                     max_ports = soc_property_phys_port_get(unit, 
    209                         (pm * _TH2_PORTS_PER_PBLK + 1), 
    210                         spn_PORT_FLEX_MAX_PORTS, 4);
    211                 }
    212                 /* validation check */
    213                 if ((max_ports < 0) || (max_ports > 4) || (max_ports < static_ports)) {
    214                     LOG_CLI((BSL_META_U(unit,
    215                         "Core %d: Bad port_flex_max_ports %d; static ports %d"),
    216                         pm, max_ports, static_ports));
    217                     return SOC_E_CONFIG;
    218                 } 
    219                 si->pm_max_ports[blk_idx] = max_ports;
    220             } else {
    221                 si->pm_max_ports[blk_idx] = static_ports;
    222             }
    223 
    224         }
    225     }
    226 
    227     return SOC_E_NONE;
    228 }
    229 
    230 static int
    231 _soc_tomahawk2_phy_dev_port_check(int unit, int phy_port, int dev_port)
    232 {
    233     int num_phy_port = 264;
    234 
    235     if (phy_port < 0 || phy_port >= num_phy_port) {
    236         return FALSE;
    237     } else if (phy_port >= 1 && phy_port <= 64) {
    238         return (dev_port >= 1 && dev_port <=32);
    239     } else if (phy_port >= 65 && phy_port <= 128) {
    240         return (dev_port >= 34 && dev_port <= 66);
    241     } else if (phy_port >= 129 && phy_port <= 192) {
    242         return (dev_port >= 68 && dev_port <= 100);
    243     } else if (phy_port >= 193 && phy_port <= 256) {
    244         return (dev_port >= 102 && dev_port <= 133);
    245     } else if (phy_port == _TH2_PHY_PORT_MNG0) {
    246         return (dev_port >= 34 && dev_port <= 66);
    247     } else if (phy_port == _TH2_PHY_PORT_MNG1) {
    248         return (dev_port >= 68 && dev_port <= 100);
    249     } else {
    250         /*skip LBPORT(260,261,262,263) , CPU port(0) and hole (258)*/
    251         return TRUE;
    252     }
    253 }
    254 
    255 STATIC int
    256 _soc_tomahawk2_port_mapping_check(int unit)
    257 {
    258     soc_info_t *si;
    259     int port, phy_port, lanes, i;
    260 
    261     si = &SOC_INFO(unit);
    262 
    263     for (phy_port = 1; phy_port < _TH2_PORTS_PER_DEV;) {
    264         port = si->port_p2l_mapping[phy_port];
    265         if (port < 0) {
    266             phy_port ++;
    267             continue;
    268         }
    269         if (port >= _TH2_DEV_PORTS_PER_DEV) {
    270             LOG_CLI((BSL_META_U(unit, "wrong logical port %d, phy %d\n"),
    271                      port, phy_port));
    272             return SOC_E_CONFIG;
    273         }
    274         lanes = si->port_num_lanes[port];
    275         if ((lanes < 0) || (lanes > 4)) {
    276             LOG_CLI((BSL_META_U(unit, "wrong lane number, port %d, lanes %d\n"),
    277                      port, lanes));
    278             return SOC_E_CONFIG;
    279         }
    280         for (i = 1; i < lanes; i ++) {
    281             if (si->port_p2l_mapping[phy_port + i] != -1) {
    282                 LOG_CLI((BSL_META_U(unit, "port overlay, port %d(%d-%d) and "
    283                                           "port %d(%d..)\n"),
    284                          port, phy_port, phy_port + lanes - 1,
    285                          si->port_p2l_mapping[phy_port + i], phy_port + i));
    286                 return SOC_E_CONFIG;
    287             }
    288         }
    289         phy_port += lanes;
    290     }
    291 
    292     return SOC_E_NONE;
    293 }
    294 
    295 /*
    296  * Tomahawk2 port mapping
    297  *
    298  *                   physical   idb/       device   mmu
    299  *                   port       idb port   port     port
    300  *     CMIC          0          0/32       0        32
    301  *     CLPORT0-15    1-64       0/0-31     1-32     0-31
    302  *     CLPORT16-31   65-128     1/0-31     34-66    64-95
    303  *     CLPORT32-47   129-192    2/0-31     68-100   128-159
    304  *     CLPORT48-63   193-256    3/0-31     102-133  192-223
    305  *     XLPORT0/0     257        1/32       66       96
    306  *     hole          258        3/32       134      224
    307  *     XLPORT0/2     259        2/32       100      160
    308  *     LBPORT0       260        0/33       33       33
    309  *     LBPORT1       261        1/33       67       97
    310  *     LBPORT2       262        2/33       101      161
    311  *     LBPORT3       263        3/33       135      225
    312  * Although MMU port number is flexible within the above range, it is
    313  *     configured as a fixed mapped to IDB port number
    314  */
    315 int
    316 soc_tomahawk2_port_config_init(int unit, uint16 dev_id)
    317 {
    318     soc_info_t *si;
    319     char *config_str, *sub_str, *sub_str_end;
    320     static const char str_2p5[] = "2.5";
    321     char str_buf[8];
    322     int rv, oversub_mode, frequency, max_freq;
    323     int ratio_list_len, ratio_idx;
    324     int port, phy_port, mmu_port, idb_port, tsc_id;
    325     int pipe, xpe, sc, sed, index, bandwidth_cap, is_any_cap = FALSE;
    326     int port_bandwidth, freq_list_len, blk_idx;
    327     char option1, option2;
    328     uint32 pipe_map, xpe_map, sc_map, sed_map, ipipe_map, epipe_map;
    329     int latency;
    330     soc_pbmp_t eth_pbm, oversub_pbm;
    331     static const int freq_list[] = { 1700, 1625, 1525, 1425, 1325, 1275,
    332                                      1225, 1125, 1050, 950, 850 };
    333     const char *str_ratio[] = { "2:3", "1:2", "1:1" };
    334     static const int dpp_ratio_x10_list[] = {
    335         15, /* core clk : pp clk ratio is 3:2 (default) */
    336         20, /* core clk : pp clk ratio is 2:1 */
    337         10  /* core clk : pp clk ratio is 1:1 */
    338     };
    339     static const struct {
    340         int port;
    341         int phy_port;
    342         int pipe;
    343         int idb_port;
    344         int mmu_port;
    345     } fixed_ports[] = {
    346         { 0,   0,   0, 32, 32 },    /* cpu port */
    347         { 33,  260, 0, 33, 33 },    /* loopback port 0 */
    348         { 67,  261, 1, 33, 97 },    /* loopback port 1 */
    349         { 101, 262, 2, 33, 161 },   /* loopback port 2 */
    350         { 135, 263, 3, 33, 225 }    /* loopback port 3 */
    351     };
    352 
    353     si = &SOC_INFO(unit);
    354 
    355 
    356     SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency));
    357 
    358     SOC_PBMP_CLEAR(eth_pbm);
    359     eth_pbm = soc_property_get_pbmp(unit, spn_PBMP_XPORT_XE, 0);
    360 
    361     SOC_PBMP_CLEAR(oversub_pbm);
    362     oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 1);
    363     oversub_pbm  = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0);
    364     oversub_mode = oversub_mode || SOC_PBMP_NOT_NULL(oversub_pbm);
    365     si->oversub_mode = oversub_mode;
    366     si->os_mixed_sister_25_50_enable = soc_property_get(
    367                         unit, spn_OVERSUBSCRIBE_MIXED_SISTER_25_50_ENABLE, 0);
    368 
    369     soc_tomahawk2_frequency_get(unit, &max_freq, &si->frequency);
    370     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1);
    371 
    372 
    373     /* Core CLK frequency */
    374     if (frequency != -1 && frequency <= max_freq) {
    375         freq_list_len = COUNTOF(freq_list);
    376         for (index = 0; index < freq_list_len; index++) {
    377             if (freq_list[index] <= max_freq &&
    378                 frequency == freq_list[index]) {
    379                 break;
    380             }
    381         }
    382 
    383         if (index < freq_list_len) {
    384             si->frequency = frequency;
    385         } else {
    386             LOG_CLI((BSL_META_U(unit,
    387                                 "*** Input core clock frequency %dMHz is not "
    388                                 "supported!\n"), frequency));
    389         }
    390     }
    391 
    392     /* DPP CLK ratio */
    393     if (soc_feature(unit, soc_feature_untethered_otp)) {
    394         si->dpp_clk_ratio_x10 = SOC_BOND_INFO(unit)->dpp_clk_ratio;
    395     } else {
    396         si->dpp_clk_ratio_x10 = dpp_ratio_x10_list[0];
    397     }
    398     config_str = soc_property_get_str(unit, spn_DPP_CLOCK_RATIO);
    399     if (config_str) {
    400         ratio_list_len = COUNTOF(dpp_ratio_x10_list);
    401         for (ratio_idx = 0; ratio_idx < ratio_list_len; ratio_idx++) {
    402             if (!sal_strcmp(config_str, str_ratio[ratio_idx])) {
    403                 break;
    404             }
    405         }
    406         if (ratio_idx < ratio_list_len &&
    407             !(si->frequency > 1125 && dpp_ratio_x10_list[ratio_idx] == 10)) {
    408             /* ratio 1:1 with core freq larger than 1125MHz is not supported */
    409             si->dpp_clk_ratio_x10 = dpp_ratio_x10_list[ratio_idx];
    410         } else {
    411             LOG_CLI((BSL_META_U(unit,
    412                                 "*** Input dpp clock frequency ratio %s is not "
    413                                 "supported with core frequency %d!\n"),
    414                      config_str, si->frequency));
    415         }
    416     }
    417 
    418     /* Line rate mode requires DPR 1:1 and Core frequency no more than 1125MHz */
    419     if ((!si->oversub_mode)) {
    420         if (si->frequency > 1125) {
    421             LOG_CLI((BSL_META_U(unit,
    422                                 "*** Input core clock frequency %dMHz is not "
    423                                 "supported with line rate mode! "
    424                                 "Must be no more than 1125MHz.\n"), si->frequency));
    425             return SOC_E_FAIL;
    426         }
    427         if (si->dpp_clk_ratio_x10 != 10) {
    428             LOG_CLI((BSL_META_U(unit,
    429                                 "*** Input dpp clock frequency ratio %s is not "
    430                                 "supported with line rate mode! "
    431                                 "Must be 1:1.\n"), (config_str ? config_str : "")));
    432             return SOC_E_FAIL;
    433         }
    434     }
    435 
    436     for (phy_port = 0; phy_port < _TH2_PHY_PORTS_PER_DEV; phy_port++) {
    437         si->port_p2l_mapping[phy_port] = -1;
    438         si->port_p2m_mapping[phy_port] = -1;
    439     }
    440     for (port = 0; port < _TH2_DEV_PORTS_PER_DEV; port++) {
    441         si->port_l2p_mapping[port] = -1;
    442         si->port_l2i_mapping[port] = -1;
    443         si->port_speed_max[port] = -1;
    444         si->port_group[port] = -1;
    445         si->port_serdes[port] = -1;
    446         si->port_pipe[port] = -1;
    447         si->port_num_lanes[port] = -1;
    448         _soc_th2_port_speed_cap[unit][port] = 0;
    449     }
    450     for (mmu_port = 0; mmu_port < _TH2_MMU_PORTS_PER_DEV; mmu_port++) {
    451         si->port_m2p_mapping[mmu_port] = -1;
    452     }
    453     SOC_PBMP_CLEAR(si->eq_pbm);
    454     SOC_PBMP_CLEAR(si->management_pbm);
    455     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
    456         SOC_PBMP_CLEAR(si->pipe_pbm[pipe]);
    457     }
    458     SOC_PBMP_CLEAR(si->oversub_pbm);
    459     SOC_PBMP_CLEAR(si->all.disabled_bitmap);
    460 
    461     /* Populate the fixed mapped ports */
    462     for (index = 0; index < COUNTOF(fixed_ports); index++) {
    463         port = fixed_ports[index].port;
    464         phy_port = fixed_ports[index].phy_port;
    465         pipe = fixed_ports[index].pipe;;
    466         si->port_l2p_mapping[port] = phy_port;
    467         si->port_l2i_mapping[port] = fixed_ports[index].idb_port;
    468         si->port_p2l_mapping[phy_port] = port;
    469         si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port;
    470         si->port_pipe[port] = pipe;
    471 
    472         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
    473     }
    474 
    475     rv = SOC_E_NONE;
    476     for (port = 1; port < _TH2_DEV_PORTS_PER_DEV; port++) {
    477         if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */
    478             continue;
    479         }
    480         if (port == _TH2_DEV_RSV_PORT) { /* Reserved port */
    481             continue;
    482         }
    483 
    484         config_str = soc_property_port_get_str(unit, port, spn_PORTMAP);
    485         if (config_str == NULL) {
    486             continue;
    487         }
    488 
    489         /*
    490          * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>]
    491          * eg:    portmap_1=1:100
    492          *     or portmap_1=1:40
    493          *     or portmap_1=1:40:i
    494          *     or portmap_1=1:40:2
    495          *     or portmap_1=1:40:2:i
    496          *     or portmap_1=1:10:100
    497          */
    498         sub_str = config_str;
    499 
    500         /* Parse physical port number */
    501         phy_port = sal_ctoi(sub_str, &sub_str_end);
    502         if (sub_str == sub_str_end) {
    503             LOG_CLI((BSL_META_U(unit,
    504                                 "Port %d: Missing physical port information "
    505                                 "\"%s\"\n"),
    506                      port, config_str));
    507             rv = SOC_E_FAIL;
    508             continue;
    509         }
    510         if (phy_port < 0 || phy_port >= _TH2_PHY_PORTS_PER_DEV) {
    511             LOG_CLI((BSL_META_U(unit,
    512                                 "Port %d: Invalid physical port number %d\n"),
    513                      port, phy_port));
    514             rv = SOC_E_FAIL;
    515             continue;
    516         }
    517         tsc_id = (phy_port - 1) / _TH2_PORTS_PER_PBLK;
    518         if (soc_feature(unit, soc_feature_untethered_otp)) {
    519             if (SHR_BITGET(SOC_BOND_INFO(unit)->tsc_disabled, tsc_id)) {
    520                 LOG_CLI((BSL_META_U(unit,
    521                                     "Port %d: Invalid physical port number %d. Skipped\n"),
    522                          port, phy_port));
    523                 continue;
    524             }
    525             if (SHR_BITGET(SOC_BOND_INFO(unit)->force_hg, tsc_id) &&
    526                 (SOC_PBMP_MEMBER(eth_pbm, port))) {
    527                 LOG_CLI((BSL_META_U(unit,
    528                            "Port %d: non-hg port in TSC(%d) which is hg-only\n"),
    529                            port, tsc_id));
    530                 rv = SOC_E_FAIL;
    531                 continue;
    532             }
    533         }
    534         if (!_soc_tomahawk2_phy_dev_port_check(unit, phy_port, port)) {
    535             LOG_CLI((BSL_META_U(unit,
    536                                 "Port %d: Invalid mapping physical port number %d\n"),
    537                      port, phy_port));
    538             rv = SOC_E_FAIL;
    539             continue;
    540         }
    541         /* coverity[check_after_sink : FALSE] */
    542         if (si->port_p2l_mapping[phy_port] != -1) {
    543             LOG_CLI((BSL_META_U(unit,
    544                                 "Port %d: Physical port %d is used by port "
    545                                 "%d\n"),
    546                      port, phy_port, si->port_p2l_mapping[phy_port]));
    547             rv = SOC_E_FAIL;
    548             continue;
    549         }
    550         /* In order to reuse the mapping between logical and physical port
    551          * number for the mapping relationship between physical and IDB port
    552          * number, we have to make maping between IDB and logical port as fixed.
    553          * For the management ports:
    554          *  phy_port    IDB port  => Logical port
    555          *  257         32              66
    556          *  259         32              100
    557          */
    558         if ((phy_port == _TH2_PHY_PORT_MNG0 && port != _TH2_DEV_PORT_MNG0) ||
    559             (phy_port == _TH2_PHY_PORT_MNG1 && port != _TH2_DEV_PORT_MNG1)) {
    560             LOG_CLI((BSL_META_U(unit,
    561                                 "Management Port %d: Invalid port number %d\n"),
    562                      phy_port, port));
    563             rv = SOC_E_FAIL;
    564             continue;
    565         }
    566         /* Check device port number and physical port number of general port
    567          * are in the same pipeline range. */
    568         pipe = port/_TH2_DEV_PORTS_PER_PIPE;
    569         if ((port != _TH2_DEV_PORT_MNG0 && port != _TH2_DEV_PORT_MNG1) &&
    570             ((phy_port < (pipe * _TH2_GPHY_PORTS_PER_PIPE + 1)) ||
    571             (phy_port > (pipe + 1) * _TH2_GPHY_PORTS_PER_PIPE))) {
    572             LOG_CLI((BSL_META_U(unit,
    573                                 "Port %d, Physical port %d: "
    574                                 "Not in same pipeline range\n"),
    575                      port, phy_port));
    576             rv = SOC_E_FAIL;
    577             continue;
    578         }
    579         /* Skip HG ports if device is under latency mode */
    580         if ((!SOC_PBMP_MEMBER(eth_pbm, port)) &&
    581             (latency != SOC_SWITCH_BYPASS_MODE_NONE)) {
    582             LOG_CLI((BSL_META_U(unit,
    583                     "Skip port %d: HG not supported under latency mode\n"),
    584                      port));
    585             continue;
    586         }
    587         /* Skip ':' between physical port number and bandwidth */
    588         sub_str = sub_str_end;
    589         if (*sub_str != '\0') {
    590             if (*sub_str != ':') {
    591                 LOG_CLI((BSL_META_U(unit,
    592                                     "Port %d: Bad config string \"%s\"\n"),
    593                          port, config_str));
    594                 rv = SOC_E_FAIL;
    595                 continue;
    596             }
    597             sub_str++;
    598         }
    599 
    600         /* Parse bandwidth */
    601         for (index = 0; index < sizeof(str_2p5) - 1; index++) {
    602             if (sub_str[index] == '\0') {
    603                 break;
    604             }
    605             str_buf[index] = sub_str[index];
    606         }
    607         str_buf[index] = '\0';
    608         if (!sal_strcmp(str_buf, str_2p5)) {
    609             port_bandwidth = 2500;
    610             sub_str_end = &sub_str[sizeof(str_2p5) - 1];
    611         } else {
    612             port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000;
    613             if (sub_str == sub_str_end) {
    614                 LOG_CLI((BSL_META_U(unit,
    615                                     "Port %d: Missing bandwidth information "
    616                                     "\"%s\"\n"),
    617                          port, config_str));
    618                 rv = SOC_E_FAIL;
    619                 continue;
    620             }
    621             switch (port_bandwidth) {
    622             case 1000:
    623             case 10000:
    624             case 11000:
    625             case 20000:
    626             case 21000:
    627             case 25000:
    628             case 27000:
    629             case 40000:
    630             case 42000:
    631             case 50000:
    632             case 53000:
    633             case 100000:
    634             case 106000:
    635                 break;
    636             default:
    637                 LOG_CLI((BSL_META_U(unit,
    638                                     "Port %d: Invalid bandwidth %d Gb\n"),
    639                          port, port_bandwidth / 1000));
    640                 rv = SOC_E_FAIL;
    641                 continue;
    642             }
    643         }
    644 
    645         /* Check if option presents */
    646         option1 = 0; option2 = 0;
    647         sub_str = sub_str_end;
    648         if (*sub_str != '\0') {
    649             /* Skip ':' between bandwidth and cap or options */
    650             if (*sub_str != ':') {
    651                 LOG_CLI((BSL_META_U(unit,
    652                                     "Port %d: Bad config string \"%s\"\n"),
    653                          port, config_str));
    654                 rv = SOC_E_FAIL;
    655                 continue;
    656             }
    657             sub_str++;
    658 
    659             if (*sub_str != '\0') {
    660                 /* Parse bandwidth cap or options */
    661                 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000;
    662                 switch (bandwidth_cap) {
    663                 case 10000:
    664                 case 11000:
    665                 case 20000:
    666                 case 21000:
    667                 case 25000:
    668                 case 27000:
    669                 case 40000:
    670                 case 42000:
    671                 case 50000:
    672                 case 53000:
    673                 case 100000:
    674                 case 106000:
    675                     sub_str = sub_str_end;
    676                     _soc_th2_port_speed_cap[unit][port] = bandwidth_cap;
    677                     /* Flex config detected, port speed cap specified */
    678                     is_any_cap = TRUE;
    679                     break;
    680                 default:
    681                     if (!(*sub_str == 'i' || *sub_str == '1' ||
    682                           *sub_str == '2' || *sub_str == '4')) {
    683                         LOG_CLI((BSL_META_U(unit,
    684                                             "Port %d: Bad config string "
    685                                             "\"%s\"\n"),
    686                                  port, config_str));
    687                         rv = SOC_E_FAIL;
    688                         continue;
    689                     } else {
    690                         option1 = *sub_str;
    691                         sub_str++;
    692                     }
    693                 }
    694                 /* Check if more options present */
    695                 if (*sub_str != '\0') {
    696                     /* Skip ':' between options */
    697                     if (*sub_str != ':') {
    698                         LOG_CLI((BSL_META_U(unit,
    699                                             "Port %d: Bad config string "
    700                                             "\"%s\"\n"),
    701                                  port, config_str));
    702                         rv = SOC_E_FAIL;
    703                         continue;
    704                     }
    705                     sub_str++;
    706 
    707                     if (*sub_str != 'i') {
    708                         LOG_CLI((BSL_META_U(unit,
    709                                             "Port %d: Bad config string "
    710                                             "\"%s\"\n"),
    711                                  port, config_str));
    712                         rv = SOC_E_FAIL;
    713                         continue;
    714                     }
    715                     option2 = *sub_str;
    716                     sub_str++;
    717                 }
    718             }
    719         }
    720 
    721         /* Check trailing string */
    722         if (*sub_str != '\0') {
    723             LOG_CLI((BSL_META_U(unit,
    724                                 "Port %d: Bad config string \"%s\"\n"),
    725                      port, config_str));
    726             rv = SOC_E_FAIL;
    727             continue;
    728         }
    729 
    730         /* Update soc_info */
    731         si->port_l2p_mapping[port] = phy_port;
    732         si->port_p2l_mapping[phy_port] = port;
    733         si->port_speed_max[port] = port_bandwidth;
    734         si->port_init_speed[port] = port_bandwidth;
    735         if (option1 == 'i') {
    736             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
    737         } else {
    738             switch (option1) {
    739             case '1': si->port_num_lanes[port] = 1; break;
    740             case '2': si->port_num_lanes[port] = 2; break;
    741             case '4': si->port_num_lanes[port] = 4; break;
    742             default: break;
    743             }
    744         }
    745         if (option2 == 'i') {
    746             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
    747         }
    748     }
    749     
    750     /* Setup port_num_lanes */
    751     for (port = 0; port < _TH2_DEV_PORTS_PER_DEV; port++) {
    752         if (si->port_speed_max[port] > 53000) {
    753             si->port_num_lanes[port] = 4;
    754         } else if (si->port_speed_max[port] == 40000 ||
    755                    si->port_speed_max[port] == 42000) {
    756             /* Note: 40G, HG[42] can operate either in dual or quad lane mode 
    757                      Check if adjacent ports exist to set dual lane mode */
    758             phy_port = si->port_l2p_mapping[port];
    759             if (phy_port >= 1 && phy_port <= _TH2_PHY_PORTS_PER_DEV) {
    760                 int sis_port;
    761 
    762                 if (phy_port % 4 == 1) {
    763                     sis_port = si->port_p2l_mapping[phy_port+2];
    764                     if ((si->port_speed_max[sis_port] > 0) &&
    765                         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) {
    766                         si->port_num_lanes[port] = 2;
    767                     }
    768                 } else if (phy_port % 4 == 3) {
    769                     si->port_num_lanes[port] = 2;
    770                 }
    771             }
    772             /* Else set to quad lane mode by default if the user did not 
    773                specify anything and no sister ports existed */
    774             if (si->port_num_lanes[port] == -1) {
    775                 si->port_num_lanes[port] = 4;
    776             }
    777         } else if ((si->port_speed_max[port] >= 20000) && 
    778                     !(si->port_speed_max[port] == 25000 ||
    779                       si->port_speed_max[port] == 27000)) {
    780             /* 50G, HG[53], 20G MLD, HG[21] use 2 lanes */
    781             si->port_num_lanes[port] = 2;
    782         } else if (si->port_speed_max[port] > 0) {
    783             /* 10G XFI, HG[11], 25G XFI and HG[27] use 1 lane */
    784             if (si->port_num_lanes[port] == -1) {
    785                 /* But RXAUI and XAUI on mgmt ports use 2 and 4 lanes, which 
    786                  * can be provided via the portmap interface.
    787                  */
    788                 si->port_num_lanes[port] = 1;
    789             }
    790         }
    791     }
    792 
    793     /* check portmap */
    794     SOC_IF_ERROR_RETURN(_soc_tomahawk2_port_mapping_check(unit));
    795 
    796     /* get flex port properties */
    797     if (SOC_FAILURE(_soc_tomahawk2_port_flex_init(unit, is_any_cap))) {
    798         rv = SOC_E_FAIL;
    799     }
    800 
    801 #if defined(BCM_WARM_BOOT_SUPPORT)
    802     if (si->flex_eligible) {
    803         if (SOC_WARM_BOOT(unit)) {
    804             SOC_IF_ERROR_RETURN(
    805                 soc_th2_flexport_scache_recovery(unit));
    806         } else {
    807             SOC_IF_ERROR_RETURN(
    808                 soc_th2_flexport_scache_allocate(unit));
    809         }
    810     }
    811 #endif
    812 
    813     /* Setup high speed port (HSP) pbm */
    814     for (port = 0; port < _TH2_DEV_PORTS_PER_DEV; port++) {
    815         phy_port = si->port_l2p_mapping[port];
    816         if (phy_port <= 0 || phy_port > _TH2_PHY_PORT_MNG1) {
    817             continue;
    818         }
    819 
    820         pipe = port/_TH2_DEV_PORTS_PER_PIPE;
    821         if (phy_port == _TH2_PHY_PORT_MNG0) {
    822             si->port_l2i_mapping[port] = 32;
    823             si->port_p2m_mapping[phy_port] = 96;
    824             si->port_serdes[port] = 64;
    825             SOC_PBMP_PORT_ADD(si->management_pbm, port);
    826         } else if (phy_port == _TH2_PHY_PORT_MNG1) {
    827             si->port_l2i_mapping[port] = 32;
    828             si->port_p2m_mapping[phy_port] = 160;
    829             si->port_serdes[port] = 64;
    830             SOC_PBMP_PORT_ADD(si->management_pbm, port);
    831         } else {
    832             idb_port = (port % _TH2_DEV_PORTS_PER_PIPE) - (pipe == 0 ? 1 : 0);
    833             mmu_port = pipe * _TH2_MMU_PORTS_OFFSET_PER_PIPE + idb_port;
    834             si->port_l2i_mapping[port] = idb_port;
    835             si->port_p2m_mapping[phy_port] = mmu_port;
    836             si->port_serdes[port] = (phy_port - 1) / _TH2_PORTS_PER_PBLK;
    837         }
    838         si->port_pipe[port] = pipe;
    839         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
    840 
    841         if (phy_port == _TH2_PHY_PORT_MNG0 || phy_port == _TH2_PHY_PORT_MNG1) {
    842             continue;
    843         }
    844 
    845         /* In TH2, only the front panel ports can be oversubscription
    846          * ports, and they are on IDB port numbers 0 to 31
    847          */
    848         if (oversub_mode) {
    849             SOC_PBMP_PORT_ADD(si->oversub_pbm, port);
    850         }
    851 
    852         if (si->port_num_lanes[port] > 1) {
    853             SOC_PBMP_PORT_ADD(si->eq_pbm, port);
    854         }
    855     }
    856 
    857     /* Setup pipe/xpe mapping
    858      * XPE0 (SC_R/XPE_A): IP 0/3 EP 0/1
    859      * XPE1 (SC_S/XPE_A): IP 0/3 EP 2/3
    860      * XPE2 (SC_R/XPE_B): IP 1/2 EP 0/1
    861      * XPE3 (SC_S/XPE_B): IP 1/2 EP 2/3
    862      */
    863     pipe_map = 0;
    864     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    865         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
    866             continue;
    867         }
    868         pipe_map |= 1 << pipe;
    869     }
    870     xpe_map = 0;
    871     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
    872         ipipe_map = (xpe < 2 ? 0x9 : 0x6) & pipe_map;
    873         epipe_map = (xpe & 1 ? 0xc : 0x3) & pipe_map;
    874         if (ipipe_map == 0 || epipe_map == 0) {
    875             continue;
    876         }
    877         xpe_map |= 1 << xpe;
    878         si->xpe_ipipe_map[xpe] = ipipe_map;
    879         si->xpe_epipe_map[xpe] = epipe_map;
    880     }
    881     sc_map = 0;
    882     for (sc = 0; sc < NUM_SLICE(unit); sc++) {
    883         ipipe_map = pipe_map;
    884         epipe_map = (sc & 1 ? 0xc : 0x3) & pipe_map;
    885         if (ipipe_map == 0 || epipe_map == 0) {
    886             continue;
    887         }
    888         sc_map |= 1 << sc;
    889         si->sc_ipipe_map[sc] = ipipe_map;
    890         si->sc_epipe_map[sc] = epipe_map;
    891     }
    892     sed_map = 0;
    893     for (sed = 0; sed < NUM_SED(unit); sed++) {
    894         ipipe_map = pipe_map;
    895         epipe_map = (sed & 1 ? 0xc : 0x3) & pipe_map;
    896         if (ipipe_map == 0 || epipe_map == 0) {
    897             continue;
    898         }
    899         sed_map |= 1 << sed;
    900         si->sed_ipipe_map[sed] = ipipe_map;
    901         si->sed_epipe_map[sed] = epipe_map;
    902     }
    903     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    904         /* Number of pipes is 4 in Tomahawk2 */
    905         /* coverity[overrun-local : FALSE] */
    906         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
    907             continue;
    908         }
    909         /* coverity[overrun-local : FALSE] */
    910         si->ipipe_xpe_map[pipe] = (pipe == 0 || pipe == 3 ? 0x3 : 0xc) &
    911             xpe_map;
    912         /* coverity[overrun-local : FALSE] */
    913         si->epipe_xpe_map[pipe] = (pipe < 2 ? 0x5 : 0xa) & xpe_map;
    914         /* coverity[overrun-local : FALSE] */
    915         si->ipipe_sc_map[pipe] = sc_map;
    916         /* coverity[overrun-local : FALSE] */
    917         si->epipe_sc_map[pipe] = (pipe < 2 ? 0x1 : 0x2) & sc_map;
    918         /* coverity[overrun-local : FALSE] */
    919         si->ipipe_sed_map[pipe] = sed_map;
    920         /* coverity[overrun-local : FALSE] */
    921         si->epipe_sed_map[pipe] = (pipe < 2 ? 0x1 : 0x2) & sed_map;
    922     }
    923 
    924     /* Setup clport refclk master block bitmap.
    925      * In Tomahawk2, there are 8 port macros (clport 6,7,24,25,38,39,56,57 )that
    926      * will driven directly from the system board and they will act as the
    927      * refclk master to drive the other instances.
    928      */
    929     SHR_BITCLR_RANGE(si->pm_ref_master_bitmap, 0, SOC_MAX_NUM_BLKS);
    930     for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
    931         int blknum = SOC_BLOCK_NUMBER(unit, blk_idx);
    932         int blktype = SOC_BLOCK_TYPE(unit, blk_idx);
    933 
    934         if (blktype == SOC_BLK_CLPORT) {
    935             if ((blknum == 6 || blknum == 7 || blknum == 24 || blknum == 25 ||
    936               blknum == 38 ||blknum == 39 || blknum == 56 || blknum == 57)) {
    937                 SHR_BITSET(si->pm_ref_master_bitmap, blk_idx);
    938             }
    939 	}
    940     }
    941 
    942     return rv;
    943 }
    944 
    945 int
    946 _soc_tomahawk2_port_mapping_init(int unit)
    947 {
    948     soc_info_t *si;
    949     int port, phy_port, idb_port;
    950     int index;
    951     int num_port;
    952     soc_reg_t reg;
    953     soc_mem_t mem;
    954     uint32 rval;
    955     uint32 entry[SOC_MAX_MEM_WORDS];
    956     int pipe;
    957 
    958     /*
    959      * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT
    960      * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER
    961      */
    962 
    963     si = &SOC_INFO(unit);
    964 
    965     /* Ingress physical to IDB port mapping */
    966     sal_memset(&entry, 0, sizeof(entry));
    967 
    968     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    969         mem = SOC_MEM_UNIQUE_ACC(unit, ING_PHY_TO_IDB_PORT_MAPm)[pipe];
    970         for (index = 0; index < _TH2_GPHY_PORTS_PER_PIPE; index++) {
    971             phy_port = index + 1 + pipe * _TH2_GPHY_PORTS_PER_PIPE;
    972             port = si->port_p2l_mapping[phy_port];
    973             if (port != -1) {
    974                 idb_port = si->port_l2i_mapping[port];
    975                 soc_mem_field32_set(unit, mem, &entry, IDB_PORTf, idb_port);
    976                 soc_mem_field32_set(unit, mem, &entry, VALIDf, 1);
    977             } else {
    978                 soc_mem_field32_set(unit, mem, &entry, VALIDf, 0);
    979             }
    980             SOC_IF_ERROR_RETURN
    981             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
    982         }
    983     }
    984 
    985     num_port = soc_mem_index_count(unit, PORT_TABm) - 1;
    986 
    987     /* Ingress GPP port to device port mapping */
    988     mem = SYS_PORTMAPm;
    989     sal_memset(&entry, 0, sizeof(sys_portmap_entry_t));
    990     for (port = 0; port < num_port; port++) {
    991         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port);
    992         SOC_IF_ERROR_RETURN
    993             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry));
    994     }
    995 
    996     /* Ingress device port to GPP port mapping
    997      * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config
    998      * init routine _bcm_fb_port_cfg_init()
    999      */
   1000 
   1001     /* Egress device port to physical port mapping */
   1002     rval = 0;
   1003     reg = EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr;
   1004     PBMP_ALL_ITER(unit, port) {
   1005         soc_reg_field_set(unit, reg, &rval, PHYSICAL_PORT_NUMBERf,
   1006                           si->port_l2p_mapping[port]);
   1007         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   1008     }
   1009 
   1010     PBMP_ALL_ITER(unit, port) {
   1011         phy_port = si->port_l2p_mapping[port];
   1012 
   1013         /* MMU port to device port mapping */
   1014         rval = 0;
   1015         reg = MMU_PORT_TO_DEVICE_PORT_MAPPINGr;
   1016         soc_reg_field_set(unit, reg, &rval, DEVICE_PORTf, port);
   1017         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   1018 
   1019         /* MMU port to physical port mapping */
   1020         rval = 0;
   1021         reg = MMU_PORT_TO_PHY_PORT_MAPPINGr;
   1022         soc_reg_field_set(unit, reg, &rval, PHY_PORTf, phy_port);
   1023         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   1024 
   1025         /* MMU port to system port mapping */
   1026         rval = 0;
   1027         reg = MMU_PORT_TO_SYSTEM_PORT_MAPPINGr;
   1028         soc_reg_field_set(unit, reg, &rval, SYSTEM_PORTf, port);
   1029         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   1030     }
   1031     return SOC_E_NONE;
   1032 }
   1033 
   1034 void
   1035 _soc_th2_mmu_init_dev_config(int unit, _soc_mmu_device_info_t *devcfg,
   1036                             int lossless)
   1037 {
   1038     sal_memset(devcfg, 0, sizeof(_soc_mmu_device_info_t));
   1039 
   1040     devcfg->max_pkt_byte = _TH_MMU_MAX_PACKET_BYTES;
   1041     devcfg->mmu_hdr_byte = _TH_MMU_PACKET_HEADER_BYTES;
   1042     devcfg->jumbo_pkt_size = _TH_MMU_JUMBO_FRAME_BYTES;
   1043     devcfg->default_mtu_size = _TH_MMU_DEFAULT_MTU_BYTES;
   1044     devcfg->mmu_cell_size = _TH_MMU_BYTES_PER_CELL;
   1045     devcfg->mmu_total_cell = _TH2_MMU_TOTAL_CELLS_PER_XPE;
   1046     devcfg->num_pg = _TH_MMU_NUM_PG;
   1047     devcfg->num_service_pool = _TH_MMU_NUM_POOL;
   1048     devcfg->flags = SOC_MMU_CFG_F_PORT_MIN | SOC_MMU_CFG_F_PORT_POOL_MIN |
   1049                     SOC_MMU_CFG_F_RQE | SOC_MMU_CFG_F_EGR_MCQ_ENTRY;
   1050     devcfg->total_mcq_entry = _TH2_MMU_TOTAL_MCQ_ENTRY(unit);
   1051     devcfg->rqe_queue_num = _TH_MMU_NUM_RQE_QUEUES;
   1052 }
   1053 
   1054 STATIC int
   1055 _soc_th2_default_pg_headroom(int unit, soc_port_t port,
   1056                             int lossless)
   1057 {
   1058     int speed = 1000, hdrm = 0;
   1059     uint8 port_oversub = 0;
   1060 
   1061     if (IS_CPU_PORT(unit, port)) {
   1062         return 77;
   1063     } else if (!lossless) {
   1064         return 0;
   1065     } else if (IS_LB_PORT(unit, port)) {
   1066         return 150;
   1067     }
   1068 
   1069     speed = SOC_INFO(unit).port_speed_max[port];
   1070 
   1071     if (SOC_PBMP_MEMBER(SOC_INFO(unit).oversub_pbm, port)) {
   1072         port_oversub = 1;
   1073     }
   1074 
   1075     if ((speed >= 1000) && (speed < 20000)) {
   1076         hdrm = port_oversub ? 
   1077             _TH2_PG_HEADROOM_OVERSUB_10G : _TH2_PG_HEADROOM_LINERATE_10G;
   1078     } else if ((speed >= 20000) && (speed <= 30000)) {
   1079         hdrm = port_oversub ? 
   1080             _TH2_PG_HEADROOM_OVERSUB_25G : _TH2_PG_HEADROOM_LINERATE_25G;
   1081     } else if ((speed >= 30000) && (speed <= 42000)) {
   1082         hdrm = port_oversub ? 
   1083             _TH2_PG_HEADROOM_OVERSUB_40G : _TH2_PG_HEADROOM_LINERATE_40G;
   1084     } else if ((speed >= 50000) && (speed < 100000)) {
   1085         hdrm = port_oversub ? 
   1086             _TH2_PG_HEADROOM_OVERSUB_50G : _TH2_PG_HEADROOM_LINERATE_50G;
   1087     } else if (speed >= 100000) {
   1088         hdrm = port_oversub ? 
   1089             _TH2_PG_HEADROOM_OVERSUB_100G : _TH2_PG_HEADROOM_LINERATE_100G;
   1090     } else {
   1091         hdrm = port_oversub ? 
   1092             _TH2_PG_HEADROOM_OVERSUB_10G : _TH2_PG_HEADROOM_LINERATE_10G;
   1093     }
   1094     return hdrm;
   1095 }
   1096 
   1097 STATIC int
   1098 _soc_th2_default_mcq_guarantee(int unit, soc_port_t port,
   1099                                int lossless)
   1100 {
   1101     if (lossless) {
   1102         return 0;
   1103     } else if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   1104         return 8;
   1105     } else {
   1106         return 0;
   1107     }
   1108 }
   1109 
   1110 STATIC int
   1111 _soc_th2_mmu_config_buf_asf(int unit, 
   1112     _soc_mmu_cfg_buf_t *buf, int lossless)
   1113 {
   1114     int pipe, pipe_map, xpe, pm;
   1115     soc_info_t *si;
   1116     _soc_mmu_cfg_buf_pool_t *buf_pool;
   1117     int oversub, num_ports, ports[3], asf, cap;
   1118     int asf_profile;
   1119     int asf_reserved_cells[3][3][2] =     /* 1/2/4 port, asf profile, line/oversub*/
   1120         {
   1121             {{ 0,  0}, {16,  27}, { 46,  56}},     /* 1-port PM */
   1122             {{ 0,  0}, {30,  52}, { 92, 112}},     /* 2-ports PM */
   1123             {{ 0,  0}, {60, 104}, {184, 224}},     /* 3/4-ports PM */
   1124         };
   1125     int asf_reserved_cells_cap[3][2] =
   1126         {{ 0,  0}, {16, 27}, {46, 56}};
   1127 
   1128 
   1129     asf_profile = soc_property_get(unit, spn_ASF_MEM_PROFILE,
   1130         _SOC_TH_ASF_MEM_PROFILE_SIMILAR);
   1131     if ((asf_profile > _SOC_TH_ASF_MEM_PROFILE_EXTREME)
   1132         || (asf_profile < _SOC_TH_ASF_MEM_PROFILE_NONE)) {
   1133         asf_profile = _SOC_TH_ASF_MEM_PROFILE_NONE;
   1134     }
   1135 
   1136     si = &SOC_INFO(unit);
   1137     oversub = SOC_PBMP_IS_NULL(si->oversub_pbm) ? 0 : 1;
   1138     
   1139     for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1140         /* use pool 0 only */
   1141         buf_pool = &buf->pools_xpe[xpe][0];
   1142         asf = 0;
   1143         ports[0] = ports[1] = ports[2] = 0;
   1144         
   1145         pipe_map = si->xpe_epipe_map[xpe];
   1146         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe ++) {
   1147             if (pipe_map & (1 << pipe)) {
   1148                 for (pm = pipe * _TH2_PBLKS_PER_PIPE; 
   1149                     pm < (pipe + 1) * _TH2_PBLKS_PER_PIPE; pm ++) {
   1150                     num_ports = si->pm_max_ports[pm + 1];
   1151                     if (num_ports == 1) {
   1152                         ports[0] ++;
   1153                     } else if (num_ports == 2) {
   1154                         ports[1] ++;
   1155                     } else if ((num_ports == 4) || (num_ports == 3)) {
   1156                         ports[2] ++;
   1157                     }
   1158                 }
   1159             }
   1160         }
   1161 
   1162         asf = asf_reserved_cells[0][asf_profile][oversub] * ports[0]
   1163             + asf_reserved_cells[1][asf_profile][oversub] * ports[1]
   1164             + asf_reserved_cells[2][asf_profile][oversub] * ports[2];
   1165         cap = asf_reserved_cells_cap[asf_profile][oversub] * 64;
   1166         asf = ((asf < cap) ? asf : cap);
   1167         
   1168         buf_pool->asf_reserved = asf;
   1169     }
   1170 
   1171     return SOC_E_NONE;
   1172 }
   1173 
   1174 STATIC int 
   1175 _soc_th2_mmu_config_buf_queue_guarantee(int unit, 
   1176     _soc_mmu_cfg_buf_t *buf, _soc_mmu_device_info_t *devcfg, int lossless)
   1177 {
   1178     soc_info_t *si;
   1179     _soc_mmu_cfg_buf_pool_t *buf_pool;
   1180     int default_mtu_cells;
   1181     int cpu[] = {1, 0, 0, 0};
   1182     int lb[] = {1, 1, 1, 1};
   1183     int xpe, pipe, pipe_map;
   1184     int port_num;
   1185 
   1186     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   1187                                                    devcfg->mmu_hdr_byte,
   1188                                                    devcfg->mmu_cell_size);
   1189     si = &SOC_INFO(unit);
   1190 
   1191     for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1192         buf_pool = &buf->pools_xpe[xpe][0];
   1193         buf_pool->queue_guarantee = 0;
   1194         buf_pool->queue_group_guarantee = 0;
   1195         buf_pool->rqe_guarantee = _TH_MMU_NUM_RQE_QUEUES * 8;
   1196         if (lossless) {
   1197             continue;
   1198         }
   1199         
   1200         pipe_map = si->xpe_epipe_map[xpe];
   1201         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe ++) {
   1202             if (pipe_map & (1 << pipe)) {
   1203                 /* cosq guarantee, cpu and lb only */
   1204                 buf_pool->queue_guarantee +=
   1205                     (cpu[pipe] * 48 + lb[pipe] * 10) * default_mtu_cells;
   1206                 /* queue group guarantee, fp and mgmt */
   1207                 SOC_PBMP_COUNT(si->pipe_pbm[pipe], port_num);
   1208                 port_num = port_num - cpu[pipe] - lb[pipe];
   1209                 buf_pool->queue_group_guarantee +=
   1210                     port_num * default_mtu_cells * 2;
   1211             }
   1212         }
   1213     }
   1214 
   1215     return SOC_E_NONE;
   1216 }
   1217 
   1218 STATIC int 
   1219 _soc_th2_mmu_config_buf_flex_port(int unit, 
   1220     _soc_mmu_cfg_buf_t *buf, int lossless)
   1221 {
   1222     soc_info_t *si;
   1223     _soc_mmu_cfg_buf_pool_t *buf_pool;
   1224     int cpu[] = {1, 0, 0, 0};
   1225     int mgmt[] = {0, 1, 1, 0};
   1226     int lb[] = {1, 1, 1, 1};
   1227     int xpe, pipe, pipe_map, pm;
   1228     int num_ports, ports[3], cpu_ports, lb_ports, mgmt_ports;
   1229     int headroom, cap;
   1230     int headroom_cells[3] =     /* 1/2/4 port */
   1231         {_TH2_PG_HEADROOM_OVERSUB_100G, 
   1232          _TH2_PG_HEADROOM_OVERSUB_50G,
   1233          _TH2_PG_HEADROOM_OVERSUB_25G};
   1234 
   1235     si = &SOC_INFO(unit);
   1236     
   1237     for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1238         /* use pool 0 only */
   1239         buf_pool = &buf->pools_xpe[xpe][0];
   1240         
   1241         /* ingress */
   1242         /* count number of ports */
   1243         pipe_map = si->xpe_ipipe_map[xpe];
   1244         ports[0] = ports[1] = ports[2] = 0;
   1245         cpu_ports = lb_ports = mgmt_ports = 0;
   1246         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe ++) {
   1247             if (pipe_map & (1 << pipe)) {
   1248                 cpu_ports += cpu[pipe];
   1249                 lb_ports += lb[pipe];
   1250                 mgmt_ports += mgmt[pipe];
   1251                 for (pm = pipe * _TH2_PBLKS_PER_PIPE; 
   1252                     pm < (pipe + 1) * _TH2_PBLKS_PER_PIPE; pm ++) {
   1253                     num_ports = si->pm_max_ports[pm + 1];
   1254                     if (num_ports == 1) {
   1255                         ports[0] ++;
   1256                     } else if (num_ports == 2) {
   1257                         ports[1] ++;
   1258                     } else if ((num_ports == 4) || (num_ports == 3)) {
   1259                         ports[2] ++;
   1260                     }
   1261                 }
   1262             }
   1263         }
   1264         
   1265         if (lossless) {
   1266             headroom = headroom_cells[0] * ports[0]
   1267                 + headroom_cells[1] * ports[1] * 2
   1268                 + headroom_cells[2] * ports[2] * 4;
   1269             cap = headroom_cells[0] * ports[0] + 
   1270                 (64 - ports[0]) * _TH2_PG_HEADROOM_OVERSUB_50G;
   1271             /* pg headroom for fp, cpu, lb */
   1272             buf_pool->prigroup_headroom = 
   1273                 MIN(headroom, cap) + cpu_ports * 77 + lb_ports * 150;
   1274             /* pg min for fp, cpu, lb, mgmt, mmu_pg_min = 8 */
   1275             buf_pool->prigroup_guarantee = 
   1276                 (MIN((ports[0] + ports[1] * 2 + ports[2] * 4), 64) 
   1277                     + cpu_ports + lb_ports + mgmt_ports) * 8;
   1278         } else {
   1279             /* pg headroom for cpu */
   1280             buf_pool->prigroup_headroom = cpu_ports * 77;
   1281             /* mmu_pg_min = 0 */
   1282             buf_pool->prigroup_guarantee = 0;
   1283         }
   1284         
   1285         /* egress */
   1286         /* count number of ports */
   1287         pipe_map = si->xpe_epipe_map[xpe];
   1288         ports[0] = ports[1] = ports[2] = 0;
   1289         cpu_ports = lb_ports = mgmt_ports = 0;
   1290         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe ++) {
   1291             if (pipe_map & (1 << pipe)) {
   1292                 cpu_ports += cpu[pipe];
   1293                 lb_ports += lb[pipe];
   1294                 mgmt_ports += mgmt[pipe];
   1295                 for (pm = pipe * _TH2_PBLKS_PER_PIPE; 
   1296                     pm < (pipe + 1) * _TH2_PBLKS_PER_PIPE; pm ++) {
   1297                     num_ports = si->pm_max_ports[pm + 1];
   1298                     if (num_ports == 1) {
   1299                         ports[0] ++;
   1300                     } else if (num_ports == 2) {
   1301                         ports[1] ++;
   1302                     } else if ((num_ports == 4) || (num_ports == 3)) {
   1303                         ports[2] ++;
   1304                     }
   1305                 }
   1306             }
   1307         }
   1308         
   1309         if (lossless) {
   1310             /* mmu_egr_qgrp_min = 0  */
   1311             buf_pool->queue_group_guarantee = 0;
   1312         } else {
   1313             /* mmu_egr_qgrp_min = 16  */
   1314             buf_pool->queue_group_guarantee = 
   1315                (MIN((ports[0] + ports[1] * 2 + ports[2] * 4), 64) + mgmt_ports)
   1316                * 16;
   1317         }
   1318         
   1319         /* reserve 6 before buffer admission due to design restriction,
   1320            queue minimal guarantee for buffer admission is 0 per v2.2 */
   1321         buf_pool->mcq_entry_reserved = 
   1322             (MIN((ports[0] + ports[1] * 2 + ports[2] * 4), 64) * 10
   1323                 + mgmt_ports * 10 + lb_ports * 10 + cpu_ports * 48) 
   1324             * (6 + 0);
   1325         
   1326     }
   1327 
   1328     return SOC_E_NONE;
   1329 }
   1330 
   1331 STATIC int 
   1332 _soc_th2_mmu_config_buf_calculate(int unit, 
   1333     _soc_mmu_cfg_buf_t *buf, _soc_mmu_device_info_t *devcfg, int lossless)
   1334 {
   1335     soc_info_t *si;
   1336     int flex;
   1337     
   1338     si = &SOC_INFO(unit);
   1339     flex = si->flex_eligible;
   1340 
   1341     SOC_IF_ERROR_RETURN(
   1342         _soc_th2_mmu_config_buf_asf(unit, buf, lossless));
   1343     
   1344     SOC_IF_ERROR_RETURN(
   1345         _soc_th2_mmu_config_buf_queue_guarantee(unit, buf, devcfg, lossless));
   1346     
   1347     if (flex) {
   1348         SOC_IF_ERROR_RETURN(
   1349             _soc_th2_mmu_config_buf_flex_port(unit, buf, lossless));
   1350     }
   1351 
   1352     return SOC_E_NONE;
   1353 }
   1354 
   1355 /*
   1356  * Default class 1 MMU settings about headroom, guarantee, dynamic, color, ...
   1357  * which depend on single port/queue/qgroup/pg...
   1358  * Version 2.2
   1359  */
   1360 STATIC void
   1361 _soc_th2_mmu_config_buf_class1(int unit, _soc_mmu_cfg_buf_t *buf,
   1362                                _soc_mmu_device_info_t *devcfg, int lossless)
   1363 {
   1364     soc_info_t *si;
   1365     _soc_mmu_cfg_buf_pool_t *buf_pool;
   1366     _soc_mmu_cfg_buf_port_t *buf_port;
   1367     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   1368     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   1369     _soc_mmu_cfg_buf_queue_t *buf_queue;
   1370     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   1371     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   1372     int max_packet_cells, default_mtu_cells;
   1373     int port, xpe, idx;
   1374     int total_pool_size = 0;
   1375     int rqe_entry_shared_total;
   1376 
   1377     si = &SOC_INFO(unit);
   1378 
   1379     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1380                 (BSL_META_U(unit,
   1381                             "Initializing default MMU config class 1(u=%d)\n"), unit));
   1382     max_packet_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->max_pkt_byte +
   1383                                                    devcfg->mmu_hdr_byte,
   1384                                                    devcfg->mmu_cell_size);
   1385     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   1386                                                    devcfg->mmu_hdr_byte,
   1387                                                    devcfg->mmu_cell_size);
   1388 
   1389     total_pool_size = devcfg->mmu_total_cell; /* per XPE limit */
   1390     
   1391     buf->headroom = 2 * max_packet_cells;
   1392 
   1393     rqe_entry_shared_total = _TH2_MMU_TOTAL_RQE_ENTRY(unit) - 160 - 88;
   1394 
   1395     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   1396         buf_pool = &buf->pools[idx];
   1397         if (idx == 0) {  /* 100% scale up by 100 */
   1398             buf_pool->size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   1399             buf_pool->yellow_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   1400             buf_pool->red_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   1401             buf_pool->total_mcq_entry = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   1402             buf_pool->total_rqe_entry = rqe_entry_shared_total;
   1403         } else {
   1404             buf_pool->size = 0;
   1405             buf_pool->yellow_size = 0;
   1406             buf_pool->red_size = 0;
   1407             buf_pool->total_mcq_entry = 0;
   1408             buf_pool->total_rqe_entry = 0;
   1409         }
   1410         
   1411         for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1412             sal_memcpy(&buf->pools_xpe[xpe][idx], buf_pool, 
   1413                 sizeof(_soc_mmu_cfg_buf_pool_t));
   1414         }
   1415     }
   1416 
   1417     for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   1418         queue_grp = &buf->qgroups[idx];
   1419         /* resume limits - accounted for 8 cell granularity */
   1420         queue_grp->pool_resume = 16;
   1421         queue_grp->yellow_resume = 16;
   1422         queue_grp->red_resume = 16;
   1423         if (lossless) {
   1424             queue_grp->guarantee = 0;
   1425             queue_grp->discard_enable = 0;
   1426         } else {
   1427             queue_grp->guarantee = 16;
   1428             queue_grp->discard_enable = 1;
   1429         }
   1430     }
   1431 
   1432     PBMP_ALL_ITER(unit, port) {
   1433         if (port >= SOC_MMU_CFG_PORT_MAX) {
   1434             break;
   1435         }
   1436         buf_port = &buf->ports[port];
   1437 
   1438         /* internal priority to priority group mapping */
   1439         for (idx = 0; idx < 16; idx++) {
   1440             buf_port->pri_to_prigroup[idx] = 7;
   1441         }
   1442 
   1443         /* priority group to pool mapping */
   1444         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   1445             buf_port->prigroups[idx].pool_idx = 0;
   1446         }
   1447 
   1448         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   1449             buf_port_pool = &buf_port->pools[idx];
   1450             buf_port_pool->guarantee = 0;
   1451             buf_port_pool->pool_limit = 0;
   1452             buf_port_pool->pool_resume = 0;
   1453             if (idx == 0) {
   1454                 buf_port_pool->pool_limit = total_pool_size;
   1455                 buf_port_pool->pool_resume =
   1456                             total_pool_size - 16;
   1457             }
   1458         }
   1459 
   1460         buf_port->pkt_size = max_packet_cells;
   1461 
   1462         /* priority group */
   1463         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   1464             buf_prigroup = &buf_port->prigroups[idx];
   1465             buf_prigroup->guarantee = 0;
   1466             buf_prigroup->user_delay = -1;
   1467             buf_prigroup->switch_delay = -1;
   1468             buf_prigroup->pkt_size = max_packet_cells;
   1469             buf_prigroup->device_headroom_enable = 0;
   1470             buf_prigroup->pool_floor = 0;
   1471             buf_prigroup->headroom = 0;
   1472             buf_prigroup->pool_resume = 0;
   1473             buf_prigroup->flow_control_enable = 0;
   1474             if (idx == 7) {
   1475                 buf_prigroup->device_headroom_enable = 1;
   1476                 buf_prigroup->flow_control_enable = lossless;
   1477                 buf_prigroup->headroom =
   1478                     _soc_th2_default_pg_headroom(unit, port, lossless);
   1479                 if (lossless) {
   1480                     buf_prigroup->guarantee = default_mtu_cells;
   1481                 }
   1482             }
   1483         }
   1484 
   1485         /* multicast queue */
   1486         for (idx = 0; idx < si->port_num_cosq[port]; idx++) {
   1487             buf_queue = &buf_port->queues[idx];
   1488             buf_queue->qgroup_id = -1;
   1489             /* accroding to TH2 MMU setting, 
   1490                reserve 6 before buffer admission due to design restriction,
   1491                queue minimal guarantee for buffer admission is 0 per v2.2 */
   1492             buf_queue->mcq_entry_guarantee = 0;
   1493             buf_queue->mcq_entry_reserved = 6;
   1494             buf_queue->guarantee = 
   1495                 _soc_th2_default_mcq_guarantee(unit, port, lossless);
   1496             if (lossless) {
   1497                 buf_queue->discard_enable = 0;
   1498                 buf_queue->color_discard_enable = 0;
   1499                 /* resume limits - accounted for 8 cell granularity */
   1500                 buf_queue->pool_resume = 16;
   1501             } else {
   1502                 buf_queue->discard_enable = 1;
   1503                 buf_queue->color_discard_enable = 0;
   1504                 /* resume limits - accounted for 8 cell granularity */
   1505                 buf_queue->pool_resume = 16;
   1506             }
   1507         }
   1508 
   1509         /* unicast queue */
   1510         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   1511             buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];
   1512             buf_queue->qgroup_id = -1;
   1513             if (lossless) {
   1514                 buf_queue->guarantee = 0;
   1515                 buf_queue->discard_enable = 0;
   1516                 buf_queue->color_discard_enable = 0;
   1517                 /* resume limits - accounted for 8 cell granularity */
   1518                 buf_queue->pool_resume = 16;
   1519                 buf_queue->yellow_resume = 16;
   1520                 buf_queue->red_resume = 16;
   1521             } else {
   1522                 buf_queue->guarantee = 0;
   1523                 buf_queue->discard_enable = 1;
   1524                 buf_queue->color_discard_enable = 0;
   1525                 /* resume limits - accounted for 8 cell granularity */
   1526                 buf_queue->pool_resume = 16;
   1527                 buf_queue->yellow_resume = 16;
   1528                 buf_queue->red_resume = 16;
   1529                 /* Enable QGROUP in LOSSY MODE */
   1530                 buf_queue->qgroup_id = 0;
   1531                 buf_queue->qgroup_min_enable = 1;
   1532             }
   1533         }
   1534 
   1535         /* queue to pool mapping */
   1536         for (idx = 0;
   1537              idx < si->port_num_cosq[port] + si->port_num_uc_cosq[port]; idx++) {
   1538             buf_port->queues[idx].pool_idx = 0;
   1539         }
   1540     }
   1541 
   1542     /* RQE */
   1543     for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   1544         buf_rqe_queue = &buf->rqe_queues[idx];
   1545         buf_rqe_queue->pool_idx = 0;
   1546         if (lossless) {
   1547             buf_rqe_queue->guarantee = 8;
   1548             buf_rqe_queue->discard_enable = 0;
   1549         } else {
   1550             buf_rqe_queue->guarantee = 8;
   1551             buf_rqe_queue->discard_enable = 1;
   1552         }
   1553     }
   1554 
   1555 }
   1556 
   1557 /*
   1558  * Default class 2 MMU settings about shared buffer limit, which depend on 
   1559  * guaranteed/reserved/headroom buffers on all port/queue/qgroup/pg/...
   1560  * Version 2.2
   1561  */
   1562 STATIC void
   1563 _soc_th2_mmu_config_buf_class2(int unit, _soc_mmu_cfg_buf_t *buf,
   1564                                _soc_mmu_device_info_t *devcfg, int lossless)
   1565 {
   1566     soc_info_t *si;
   1567     _soc_mmu_cfg_buf_port_t *buf_port;
   1568     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   1569     _soc_mmu_cfg_buf_queue_t *buf_queue;
   1570     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   1571     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   1572     int port, xpe, idx;
   1573     int total_pool_size = 0;
   1574     int egr_shared_total, egr_shared_total_xpe;
   1575     int ing_shared_total, ing_shared_total_xpe;
   1576     uint32 color_limit = 0;
   1577 
   1578     si = &SOC_INFO(unit);
   1579 
   1580     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1581                 (BSL_META_U(unit,
   1582                             "Initializing default MMU config class 2(u=%d)\n"), unit));
   1583     
   1584     total_pool_size = devcfg->mmu_total_cell; /* per XPE limit */
   1585     
   1586     ing_shared_total = total_pool_size;
   1587     for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1588         ing_shared_total_xpe = total_pool_size
   1589             - buf->pools_xpe[xpe][0].asf_reserved
   1590             - buf->headroom
   1591             - buf->pools_xpe[xpe][0].prigroup_headroom
   1592             - buf->pools_xpe[xpe][0].prigroup_guarantee
   1593             - buf->pools_xpe[xpe][0].port_guarantee;
   1594         if (lossless) {
   1595             ing_shared_total_xpe = ing_shared_total_xpe
   1596                 - buf->pools_xpe[xpe][0].queue_guarantee
   1597                 - buf->pools_xpe[xpe][0].queue_group_guarantee
   1598                 - buf->pools_xpe[xpe][0].rqe_guarantee;
   1599         }
   1600 
   1601         if (ing_shared_total_xpe < ing_shared_total) {
   1602             ing_shared_total = ing_shared_total_xpe;
   1603         }
   1604     }
   1605     egr_shared_total = total_pool_size;
   1606     for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1607         egr_shared_total_xpe = total_pool_size
   1608             - buf->pools_xpe[xpe][0].asf_reserved
   1609             - buf->pools_xpe[xpe][0].queue_guarantee
   1610             - buf->pools_xpe[xpe][0].queue_group_guarantee
   1611             - buf->pools_xpe[xpe][0].rqe_guarantee;
   1612 
   1613         if (egr_shared_total_xpe < egr_shared_total) {
   1614             egr_shared_total = egr_shared_total_xpe;
   1615         }
   1616     }
   1617     LOG_VERBOSE(BSL_LS_SOC_MMU,
   1618                 (BSL_META_U(unit,
   1619                             "MMU config: Total Shared size: ingress %d egress %d\n"),
   1620                             ing_shared_total, egr_shared_total));
   1621 
   1622     color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG;
   1623     
   1624     for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   1625         queue_grp = &buf->qgroups[idx];
   1626         if (lossless) {
   1627             queue_grp->pool_limit = egr_shared_total;
   1628             queue_grp->pool_scale = -1;
   1629             queue_grp->red_limit = egr_shared_total;
   1630             queue_grp->yellow_limit = egr_shared_total;
   1631         } else {
   1632             queue_grp->pool_limit = 0;
   1633             queue_grp->pool_scale = 8;
   1634             queue_grp->red_limit = color_limit;
   1635             queue_grp->yellow_limit = color_limit;
   1636         }
   1637     }
   1638 
   1639     PBMP_ALL_ITER(unit, port) {
   1640         if (port >= SOC_MMU_CFG_PORT_MAX) {
   1641             break;
   1642         }
   1643         buf_port = &buf->ports[port];
   1644 
   1645         /* priority group */
   1646         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   1647             buf_prigroup = &buf_port->prigroups[idx];
   1648             buf_prigroup->pool_limit = 0;
   1649             buf_prigroup->pool_scale = -1;
   1650             if (idx == 7) {
   1651                 if (lossless) {
   1652                     buf_prigroup->pool_scale = 8;
   1653                 } else {
   1654                     buf_prigroup->pool_limit = ing_shared_total;
   1655                 }
   1656             }
   1657         }
   1658 
   1659         /* multicast queue */
   1660         for (idx = 0; idx < si->port_num_cosq[port]; idx++) {
   1661             buf_queue = &buf_port->queues[idx];
   1662             if (lossless) {
   1663                 buf_queue->pool_scale = -1;
   1664                 buf_queue->pool_limit = egr_shared_total;
   1665                 buf_queue->yellow_limit = egr_shared_total;
   1666                 buf_queue->red_limit = egr_shared_total;
   1667             } else {
   1668                 buf_queue->pool_scale = 8;
   1669                 buf_queue->pool_limit = 0;
   1670                 buf_queue->yellow_limit = color_limit
   1671                                           | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   1672                 buf_queue->red_limit = color_limit
   1673                                        | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   1674             }
   1675         }
   1676 
   1677         /* unicast queue */
   1678         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   1679             buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];
   1680             if (lossless) {
   1681                 buf_queue->pool_scale = -1;
   1682                 buf_queue->pool_limit = egr_shared_total;
   1683                 buf_queue->red_limit = egr_shared_total;
   1684                 buf_queue->yellow_limit = egr_shared_total;
   1685             } else {
   1686                 buf_queue->pool_scale = 8;
   1687                 buf_queue->pool_limit = 0;
   1688                 buf_queue->red_limit = color_limit
   1689                                        | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   1690                 buf_queue->yellow_limit = color_limit
   1691                                           | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   1692             }
   1693         }
   1694     }
   1695 
   1696     /* RQE */
   1697     for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   1698         buf_rqe_queue = &buf->rqe_queues[idx];
   1699         if (lossless) {
   1700             buf_rqe_queue->pool_scale = -1;
   1701             buf_rqe_queue->pool_limit = egr_shared_total;
   1702             buf_rqe_queue->red_limit = egr_shared_total;
   1703             buf_rqe_queue->yellow_limit = egr_shared_total;
   1704         } else {
   1705             buf_rqe_queue->pool_scale = 8;
   1706             buf_rqe_queue->pool_limit = 0;
   1707             buf_rqe_queue->red_limit = color_limit;
   1708             buf_rqe_queue->yellow_limit = color_limit;
   1709         }
   1710     }
   1711 
   1712 }
   1713 
   1714 STATIC int
   1715 _soc_th2_mmu_config_buf_set_hw_global(int unit, _soc_mmu_cfg_buf_t *buf,
   1716                               _soc_mmu_device_info_t *devcfg, int lossless)
   1717 {
   1718     _soc_mmu_cfg_buf_pool_t *buf_pool;
   1719     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   1720     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
   1721     mmu_thdo_offset_qgroup_entry_t offset_qgrp;
   1722     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   1723     soc_mem_t mem0, mem1;
   1724     uint32 fval, rval, rval2, rval3;
   1725     int rqlen;
   1726     int idx, pval;
   1727     int max_packet_cells, jumbo_frame_cells, default_mtu_cells, limit, limit_xpe;
   1728     int pipe, xpe;
   1729     int pool_resume = 0;
   1730     int pool_pg_headroom = 0;
   1731     static const soc_mem_t mmu_thdo_qgrp_uc_mem[] = {
   1732         MMU_THDU_CONFIG_QGROUPm,
   1733         MMU_THDU_OFFSET_QGROUPm
   1734     };
   1735 
   1736     max_packet_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->max_pkt_byte +
   1737                                                    devcfg->mmu_hdr_byte,
   1738                                                    devcfg->mmu_cell_size);
   1739     jumbo_frame_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->jumbo_pkt_size +
   1740                                                     devcfg->mmu_hdr_byte,
   1741                                                     devcfg->mmu_cell_size);
   1742     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   1743                                                    devcfg->mmu_hdr_byte,
   1744                                                    devcfg->mmu_cell_size);
   1745     pool_resume = 2 * jumbo_frame_cells;
   1746 
   1747     rval = 0;
   1748     fval = _TH2_MMU_PHYSICAL_CELLS_PER_XPE - _TH2_MMU_RSVD_CELLS_CFAP_PER_XPE;
   1749     soc_reg_field_set(unit, CFAPFULLTHRESHOLDSETr, &rval, CFAPFULLSETPOINTf,
   1750                       fval);
   1751     SOC_IF_ERROR_RETURN(
   1752         soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDSETr, -1, -1,
   1753                                    -1, rval));
   1754     
   1755     rval = 0;
   1756     soc_reg_field_set(unit, CFAPFULLTHRESHOLDRESETr, &rval,
   1757                       CFAPFULLRESETPOINTf, fval - (2 * jumbo_frame_cells));
   1758     SOC_IF_ERROR_RETURN(
   1759         soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDRESETr, -1, -1,
   1760                                    -1, rval));
   1761     
   1762     rval = 0;
   1763     soc_reg_field_set(unit, CFAPBANKFULLr, &rval, LIMITf, 
   1764         _TH2_CFAP_BANK_FULL_LIMIT);
   1765     for (idx = 0; idx < SOC_REG_NUMELS(unit, CFAPBANKFULLr); idx++) {
   1766         SOC_IF_ERROR_RETURN(
   1767             soc_tomahawk_xpe_reg32_set(unit, CFAPBANKFULLr, -1, -1,
   1768                                        idx, rval));
   1769     }
   1770 
   1771     rval = 0;
   1772     SOC_IF_ERROR_RETURN(READ_MMU_SCFG_TOQ_MC_CFG0r(unit, &rval));
   1773     soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG0r, &rval, 
   1774         MCQE_FULL_THRESHOLDf, 0);
   1775     SOC_IF_ERROR_RETURN(WRITE_MMU_SCFG_TOQ_MC_CFG0r(unit, rval));
   1776     
   1777     /* Input thresholds */
   1778     rval = 0;
   1779     soc_reg_field_set(unit, THDI_GLOBAL_HDRM_LIMITr,
   1780                       &rval, GLOBAL_HDRM_LIMITf, buf->headroom / 2);
   1781     /* Per XPE register */
   1782     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1783         THDI_GLOBAL_HDRM_LIMITr, -1, -1, 0, rval));
   1784 
   1785     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   1786         buf_pool = &buf->pools[idx];
   1787         if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) {
   1788             continue;
   1789         }
   1790 
   1791         pool_pg_headroom = 0;
   1792         limit = buf_pool->total;
   1793         for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1794             limit_xpe = buf_pool->total
   1795                 - buf->pools_xpe[xpe][idx].asf_reserved
   1796                 - buf->headroom
   1797                 - buf->pools_xpe[xpe][idx].prigroup_headroom
   1798                 - buf->pools_xpe[xpe][idx].prigroup_guarantee
   1799                 - buf->pools_xpe[xpe][idx].port_guarantee;
   1800             if (lossless) {
   1801                 limit_xpe = limit_xpe
   1802                     - buf->pools_xpe[xpe][idx].queue_guarantee
   1803                     - buf->pools_xpe[xpe][idx].queue_group_guarantee
   1804                     - buf->pools_xpe[xpe][idx].rqe_guarantee;
   1805             }
   1806 
   1807             if (limit_xpe < limit) {
   1808                 limit = limit_xpe;
   1809             }
   1810             if (buf->pools_xpe[xpe][idx].prigroup_headroom > pool_pg_headroom) {
   1811                 pool_pg_headroom = buf->pools_xpe[xpe][idx].prigroup_headroom;
   1812             }
   1813         }
   1814 
   1815         if (limit > 0) {
   1816             rval = 0;
   1817             soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf,
   1818                               limit);
   1819             SOC_IF_ERROR_RETURN(
   1820                 soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_SPr,
   1821                                            -1, -1, idx, rval));
   1822         }
   1823 
   1824         rval = 0;
   1825         soc_reg_field_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr, &rval,
   1826                           OFFSETf, pool_resume);
   1827         SOC_IF_ERROR_RETURN(
   1828             soc_tomahawk_xpe_reg32_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr,
   1829                                        -1, -1, idx, rval));
   1830 
   1831         rval = 0;
   1832         soc_reg_field_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr, &rval,
   1833                           LIMITf, pool_pg_headroom);
   1834         SOC_IF_ERROR_RETURN(
   1835             soc_tomahawk_xpe_reg32_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr,
   1836                                        -1, -1, idx, rval));
   1837     }
   1838     
   1839     rval = 0;
   1840     SOC_IF_ERROR_RETURN(
   1841         soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr,
   1842                                    -1, -1, 0, rval));
   1843 
   1844     rval = 0;
   1845     SOC_IF_ERROR_RETURN(
   1846         soc_tomahawk_xpe_reg32_set(unit, THDI_HDRM_POOL_CFGr,
   1847                                    -1, -1, 0, rval));
   1848 
   1849     rval = 0;
   1850     soc_reg_field_set(unit, THDI_PORT_MAX_PKT_SIZEr, &rval,
   1851                         PORT_MAX_PKT_SIZEf, max_packet_cells);
   1852     SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_MAX_PKT_SIZEr(unit, rval));
   1853 
   1854     /* output thresholds */
   1855     SOC_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval));
   1856     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
   1857                       ENABLE_QUEUE_AND_GROUP_TICKETf, 1);
   1858     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
   1859                       ENABLE_UPDATE_COLOR_RESUMEf, 0);
   1860     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Bf, 1);
   1861     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Af, 0);
   1862     SOC_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval));
   1863 
   1864     rval = 0;
   1865     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
   1866     soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
   1867                       MOP_POLICYf, 1);
   1868     SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
   1869 
   1870     SOC_IF_ERROR_RETURN(
   1871         WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0, 2));
   1872 
   1873     SOC_IF_ERROR_RETURN(
   1874         WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0, 2));
   1875 
   1876     SOC_IF_ERROR_RETURN(
   1877         WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0, 1));
   1878 
   1879     SOC_IF_ERROR_RETURN(
   1880         WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0, 1));
   1881 
   1882     /* per service pool settings */
   1883     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   1884         buf_pool = &buf->pools[idx];
   1885         if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) {
   1886             continue;
   1887         }
   1888 
   1889         limit = buf_pool->total;
   1890         for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1891             limit_xpe = buf_pool->total
   1892                 - buf->pools_xpe[xpe][idx].asf_reserved
   1893                 - buf->pools_xpe[xpe][idx].queue_guarantee
   1894                 - buf->pools_xpe[xpe][idx].queue_group_guarantee
   1895                 - buf->pools_xpe[xpe][idx].rqe_guarantee;
   1896             
   1897             if (limit_xpe < limit) {
   1898                 limit = limit_xpe;
   1899             }
   1900         }
   1901 
   1902         rval = 0;
   1903         soc_reg_field_set(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, &rval,
   1904                           SHARED_LIMITf, limit);
   1905         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1906             MMU_THDM_DB_POOL_SHARED_LIMITr, -1, -1, idx, rval));
   1907 
   1908         rval = 0;
   1909         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr,
   1910                           &rval, YELLOW_SHARED_LIMITf, CEIL(limit, 8));
   1911         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1912             MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval));
   1913 
   1914         rval = 0;
   1915         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_SHARED_LIMITr,
   1916                           &rval, RED_SHARED_LIMITf, CEIL(limit, 8));
   1917         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1918             MMU_THDM_DB_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval));
   1919 
   1920         rval = 0;
   1921         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RESUME_LIMITr,
   1922                           &rval, RESUME_LIMITf, CEIL(limit, 8));
   1923         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1924             MMU_THDM_DB_POOL_RESUME_LIMITr, -1, -1, idx, rval));
   1925 
   1926         rval = 0;
   1927         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr,
   1928                           &rval, YELLOW_RESUME_LIMITf, CEIL(limit, 8));
   1929         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1930             MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval));
   1931 
   1932         rval = 0;
   1933         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_RESUME_LIMITr,
   1934                           &rval, RED_RESUME_LIMITf, CEIL(limit, 8));
   1935         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1936             MMU_THDM_DB_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval));
   1937 
   1938         /* mcq entries, each XPE carries half the queues */
   1939         limit = buf_pool->total_mcq_entry;
   1940         for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   1941             limit_xpe = buf_pool->total_mcq_entry
   1942                 - buf->pools_xpe[xpe][idx].mcq_entry_reserved
   1943                 - SOC_TH2_MMU_MCQ_ENTRY_RESERVED_TDM_OVERSHOOT;
   1944             
   1945             if (limit_xpe < limit) {
   1946                 limit = limit_xpe;
   1947             }
   1948         }
   1949         if (limit <= 0) {
   1950             continue;
   1951         }
   1952 
   1953         rval = 0;
   1954         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
   1955                           &rval, SHARED_LIMITf, limit / 4);
   1956         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1957             MMU_THDM_MCQE_POOL_SHARED_LIMITr, -1, -1, idx, rval));
   1958 
   1959         rval = 0;
   1960         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr,
   1961                           &rval, YELLOW_SHARED_LIMITf, CEIL(limit, 8));
   1962         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1963             MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval));
   1964 
   1965         rval = 0;
   1966         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr,
   1967                           &rval, RED_SHARED_LIMITf, CEIL(limit, 8));
   1968         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1969             MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval));
   1970 
   1971         rval = 0;
   1972         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RESUME_LIMITr,
   1973                           &rval, RESUME_LIMITf, CEIL(limit, 8));
   1974         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1975             MMU_THDM_MCQE_POOL_RESUME_LIMITr, -1, -1, idx, rval));
   1976 
   1977         rval = 0;
   1978         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr,
   1979                           &rval, YELLOW_RESUME_LIMITf, CEIL(limit, 8));
   1980         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1981             MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval));
   1982 
   1983         rval = 0;
   1984         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr,
   1985                                        &rval, RED_RESUME_LIMITf, CEIL(limit, 8));
   1986         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   1987             MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval));
   1988     }
   1989 
   1990     rval = 0;
   1991     soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval, 
   1992                                     CLEAR_DROP_STATE_ON_CONFIG_UPDATEf, 1);
   1993     soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval, MOP_POLICY_1Bf, 1);
   1994     soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval, MOP_POLICY_1Af, 0);
   1995     SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIGr(unit, rval));
   1996 
   1997     /* configure Q-groups */
   1998     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   1999         for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   2000             mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[0])[pipe];
   2001             mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[1])[pipe];
   2002             if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
   2003                 continue;
   2004             }
   2005             queue_grp = &buf->qgroups[idx];
   2006 
   2007 
   2008             sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
   2009             sal_memset(&offset_qgrp, 0, sizeof(offset_qgrp));
   2010 
   2011             soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2012                                 Q_MIN_LIMIT_CELLf, queue_grp->guarantee);
   2013 
   2014             if (queue_grp->pool_scale != -1) {
   2015                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2016                                     Q_SHARED_ALPHA_CELLf,
   2017                                     queue_grp->pool_scale);
   2018                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2019                                     Q_LIMIT_DYNAMIC_CELLf, 1);
   2020             } else {
   2021                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2022                                     Q_SHARED_LIMIT_CELLf,
   2023                                     queue_grp->pool_limit);
   2024             }
   2025 
   2026             if ((queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   2027                 (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   2028                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2029                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
   2030             }
   2031 
   2032             if (queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
   2033                 pval = _TH2_POLL_SCALE_TO_LIMIT(queue_grp->pool_limit,
   2034                           queue_grp->red_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   2035                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2036                                     LIMIT_RED_CELLf, CEIL(pval, 8));
   2037 
   2038             } else {
   2039                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2040                                         LIMIT_RED_CELLf,
   2041                                         CEIL(queue_grp->red_limit, 8));
   2042             }
   2043 
   2044             if (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
   2045                 pval = _TH2_POLL_SCALE_TO_LIMIT(queue_grp->pool_limit,
   2046                           queue_grp->yellow_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   2047                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2048                                     LIMIT_YELLOW_CELLf, CEIL(pval,8));
   2049 
   2050             } else {
   2051                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   2052                                     LIMIT_YELLOW_CELLf,
   2053                                     CEIL(queue_grp->yellow_limit, 8));
   2054             }
   2055 
   2056             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   2057                                 RESET_OFFSET_CELLf,
   2058                                 queue_grp->pool_resume / 8);
   2059             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   2060                                 RESET_OFFSET_YELLOW_CELLf,
   2061                                 queue_grp->pool_resume / 8);
   2062             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   2063                                 RESET_OFFSET_RED_CELLf,
   2064                                 queue_grp->pool_resume / 8);
   2065             SOC_IF_ERROR_RETURN
   2066                     (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, idx, &cfg_qgrp));
   2067             SOC_IF_ERROR_RETURN
   2068                     (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, idx, &offset_qgrp));
   2069         }
   2070     }
   2071 
   2072     /* RQE */
   2073     for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   2074         buf_rqe_queue = &buf->rqe_queues[idx];
   2075 
   2076         rval = 0;
   2077         soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_MIN_PRIQr,
   2078                           &rval, MIN_LIMITf, buf_rqe_queue->guarantee);
   2079         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_MIN_PRIQr(unit, idx, rval));
   2080 
   2081         rval = 0;
   2082         rval2 = 0;
   2083         rval3 = 0;
   2084         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   2085                             &rval, SPIDf, buf_rqe_queue->pool_idx);
   2086 
   2087         if ((buf_rqe_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   2088             (buf_rqe_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   2089             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   2090                               &rval, COLOR_LIMIT_DYNAMICf, 1);
   2091             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   2092                 SHARED_RED_LIMITf,
   2093                 buf_rqe_queue->red_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   2094             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   2095                 SHARED_YELLOW_LIMITf,
   2096                 buf_rqe_queue->yellow_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   2097         } else {
   2098             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   2099                 SHARED_RED_LIMITf, CEIL(buf_rqe_queue->red_limit, 8));
   2100 
   2101             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   2102                 SHARED_YELLOW_LIMITf, CEIL(buf_rqe_queue->yellow_limit, 8));
   2103         }
   2104 
   2105         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf,
   2106                           (buf_rqe_queue->discard_enable ? 1 : 0));
   2107 
   2108         if (buf_rqe_queue->pool_scale != -1) {
   2109             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   2110                               &rval, DYNAMIC_ENABLEf, 1);
   2111             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   2112                               SHARED_ALPHAf, buf_rqe_queue->pool_scale);
   2113         } else {
   2114             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   2115                               SHARED_LIMITf, buf_rqe_queue->pool_limit);
   2116         }
   2117         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   2118                           RESET_OFFSETf, 2);
   2119 
   2120         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, rval));
   2121         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG_PRIQr_REG32(unit, idx, rval2));
   2122         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_COLOR_PRIQr(unit,
   2123                                                                 idx, rval3));
   2124 
   2125         rval = 0;
   2126         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
   2127                           &rval, RESET_OFFSET_REDf,
   2128                           (default_mtu_cells * 2)/8);
   2129         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
   2130                           &rval, RESET_OFFSET_YELLOWf,
   2131                           (default_mtu_cells * 2)/8);
   2132         SOC_IF_ERROR_RETURN(
   2133                   WRITE_MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
   2134 
   2135         /* queue entry */
   2136         rval = 0;
   2137         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_MIN_PRIQr,
   2138                           &rval, MIN_LIMITf, buf_rqe_queue->guarantee/8);
   2139         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_MIN_PRIQr(unit, idx, rval));
   2140 
   2141         rval = 0;
   2142         rval2 = 0;
   2143         rval3 = 0;
   2144         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   2145                           &rval, SPIDf, buf_rqe_queue->pool_idx);
   2146 
   2147         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, &rval,
   2148                           LIMIT_ENABLEf, (!lossless));
   2149         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   2150                           &rval, DYNAMIC_ENABLEf, (!lossless));
   2151         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, &rval,
   2152                           COLOR_ENABLEf, 0);
   2153         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   2154                           &rval, COLOR_LIMIT_DYNAMICf, (!lossless));
   2155 
   2156         limit = (lossless ?
   2157             CEIL(buf->pools[buf_rqe_queue->pool_idx].total_rqe_entry, 8*11) :
   2158             0);
   2159         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   2160                           &rval3, SHARED_RED_LIMITf, limit);
   2161         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   2162                           &rval3, SHARED_YELLOW_LIMITf, limit);
   2163 
   2164         limit = (lossless ?
   2165             CEIL(buf->pools[buf_rqe_queue->pool_idx].total_rqe_entry, 8*11) :
   2166             8);
   2167         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2,
   2168                           SHARED_LIMITf, limit);
   2169         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2,
   2170                           RESET_OFFSETf, 1);
   2171 
   2172         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG1_PRIQr(unit, idx, rval));
   2173         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_PRIQr(unit, idx, rval2));
   2174         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_COLOR_PRIQr(unit, idx, rval3));
   2175 
   2176         rval = 0;
   2177         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
   2178                           &rval, RESET_OFFSET_REDf, default_mtu_cells/8);
   2179         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
   2180                           &rval, RESET_OFFSET_YELLOWf, default_mtu_cells/8);
   2181         SOC_IF_ERROR_RETURN(
   2182                   WRITE_MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
   2183 
   2184     }
   2185 
   2186     /* per pool RQE settings */
   2187     for (idx = 0; idx < 4; idx++) {
   2188         buf_pool = &buf->pools[idx];
   2189         if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) ||
   2190             (buf_pool->total == 0)) {
   2191             continue;
   2192         }
   2193 
   2194         limit = buf_pool->total;
   2195         for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   2196             limit_xpe = buf_pool->total
   2197                 - buf->pools_xpe[xpe][idx].asf_reserved
   2198                 - buf->pools_xpe[xpe][idx].queue_guarantee
   2199                 - buf->pools_xpe[xpe][idx].queue_group_guarantee
   2200                 - buf->pools_xpe[xpe][idx].rqe_guarantee;
   2201 
   2202             if (limit_xpe < limit) {
   2203                 limit = limit_xpe;
   2204             }
   2205         }
   2206 
   2207         rval = 0;
   2208         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr,
   2209                           &rval, SHARED_LIMITf, limit);
   2210         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr, &rval, RESUME_LIMITf,
   2211                           CEIL((limit - default_mtu_cells * 2), 8));
   2212         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   2213             MMU_THDR_DB_CONFIG_SPr, -1, -1, idx, rval));
   2214 
   2215         rval = 0;
   2216         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
   2217                           SHARED_RED_LIMITf,
   2218                           CEIL(limit, 8));
   2219         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
   2220                           SHARED_YELLOW_LIMITf,
   2221                           CEIL(limit, 8));
   2222         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   2223             MMU_THDR_DB_SP_SHARED_LIMITr, -1, -1, idx, rval));
   2224 
   2225         rval = 0;
   2226         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
   2227                           RESUME_RED_LIMITf,
   2228                           CEIL((limit - default_mtu_cells * 2), 8));
   2229         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
   2230                           RESUME_YELLOW_LIMITf,
   2231                           CEIL((limit - default_mtu_cells * 2), 8));
   2232         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   2233             MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, -1, -1, idx, rval));
   2234 
   2235         rqlen = CEIL(buf_pool->total_rqe_entry, 8);
   2236         if (rqlen <= 0) {
   2237             continue;
   2238         }
   2239 
   2240         rval = 0;
   2241         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
   2242                           SHARED_LIMITf, rqlen);
   2243         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
   2244                           RESUME_LIMITf, rqlen - 1);
   2245         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_SPr(unit, idx, rval));
   2246 
   2247         rval = 0;
   2248         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
   2249                           SHARED_RED_LIMITf, rqlen);
   2250         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
   2251                           SHARED_YELLOW_LIMITf, rqlen);
   2252         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr(unit,
   2253                                                                      idx, rval));
   2254 
   2255         rval = 0;
   2256         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
   2257                           RESUME_RED_LIMITf, rqlen - 1);
   2258         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
   2259                           RESUME_YELLOW_LIMITf, rqlen - 1);
   2260         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr(unit,
   2261                                                                      idx, rval));
   2262     }
   2263 
   2264 
   2265    return SOC_E_NONE;
   2266 }
   2267 
   2268 STATIC int
   2269 _soc_th2_mmu_config_buf_set_hw_port(int unit, int port, _soc_mmu_cfg_buf_t *buf,
   2270                               _soc_mmu_device_info_t *devcfg, int lossless)
   2271 {
   2272     soc_info_t *si;
   2273     _soc_mmu_cfg_buf_port_t *buf_port;
   2274     _soc_mmu_cfg_buf_pool_t *buf_pool;
   2275     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   2276     thdi_port_sp_config_entry_t thdi_sp_config;
   2277     thdi_port_pg_config_entry_t pg_config_mem;
   2278     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   2279     _soc_mmu_cfg_buf_queue_t *buf_queue;
   2280     uint32 entry0[SOC_MAX_MEM_WORDS], entry1[SOC_MAX_MEM_WORDS];
   2281     soc_reg_t reg = INVALIDr;
   2282     soc_mem_t mem, mem0, mem1, mem2, mem3;
   2283     uint32 fval, rval;
   2284     int base, numq;
   2285     int idx, midx, pri;
   2286     int default_mtu_cells, limit, limit_xpe, rlimit;
   2287     int pipe, xpe;
   2288     static const soc_mem_t mmu_thdo_q_uc_mem[] = {
   2289         MMU_THDU_CONFIG_QUEUEm,
   2290         MMU_THDU_OFFSET_QUEUEm,
   2291         MMU_THDU_Q_TO_QGRP_MAPm
   2292     };
   2293     static const soc_mem_t mmu_thdo_port_uc_mem[] = {
   2294         MMU_THDU_CONFIG_PORTm,
   2295         MMU_THDU_RESUME_PORTm
   2296     };
   2297     static const soc_mem_t mmu_thdo_q_mc_mem[] = {
   2298         MMU_THDM_DB_QUEUE_CONFIGm,
   2299         MMU_THDM_DB_QUEUE_OFFSETm,
   2300         MMU_THDM_MCQE_QUEUE_CONFIGm,
   2301         MMU_THDM_MCQE_QUEUE_OFFSETm
   2302     };
   2303     static const soc_mem_t mmu_thdo_port_mc_mem[] = {
   2304         MMU_THDM_DB_PORTSP_CONFIGm,
   2305         MMU_THDM_MCQE_PORTSP_CONFIGm
   2306     };
   2307     static const soc_field_t prigroup_reg[] = {
   2308         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   2309     };
   2310     static const soc_field_t prigroup_field[] = {
   2311         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   2312         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   2313         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   2314         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   2315     };
   2316     static const soc_field_t prigroup_spid_field[] = {
   2317         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   2318         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   2319     };
   2320 
   2321     si = &SOC_INFO(unit);
   2322     pipe = si->port_pipe[port];
   2323     buf_port = &buf->ports[port];
   2324     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   2325                                                    devcfg->mmu_hdr_byte,
   2326                                                    devcfg->mmu_cell_size);
   2327 
   2328     /*==================== THDI ====================*/
   2329 
   2330     /********************************
   2331      * Input port per port settings *
   2332  */
   2333 
   2334     /* Internal priority to priority group mapping */
   2335     for (idx = 0; idx < 16; idx++) {
   2336         if (idx % 8 == 0) { /* 8 fields per register */
   2337             reg = prigroup_reg[idx / 8];
   2338             rval = 0;
   2339         }
   2340         soc_reg_field_set(unit, reg, &rval, prigroup_field[idx],
   2341                           buf_port->pri_to_prigroup[idx]);
   2342         if (idx % 8 == 7) { /* 8 fields per register */
   2343             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   2344         }
   2345     }
   2346 
   2347     /* Ingress priority group to ingress service pool mapping */
   2348     rval = 0;
   2349     for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   2350         soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval,
   2351                           prigroup_spid_field[idx],
   2352                           buf_port->prigroups[idx].pool_idx);
   2353     }
   2354     SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, port, rval));
   2355 
   2356     /* Enables for port receive, pause, PFC, SAFC */
   2357     fval = 0;
   2358     rval = 0;
   2359     for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   2360         if (buf_port->prigroups[idx].flow_control_enable != 0) {
   2361             for (pri=0; pri < 16; pri++) {
   2362                 if (buf_port->pri_to_prigroup[pri] == idx) {
   2363                     fval |= 1 << pri;
   2364                 }
   2365             }
   2366         }
   2367     }
   2368     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   2369                       INPUT_PORT_RX_ENABLEf, 1);
   2370     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   2371                       PORT_PRI_XON_ENABLEf, fval);
   2372     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   2373                       PORT_PAUSE_ENABLEf, fval ? 1 : 0);
   2374     SOC_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit, port, rval));
   2375 
   2376     /*****************************************
   2377      * Input port per port per pool settings *
   2378  */
   2379     mem = SOC_MEM_UNIQUE_ACC(unit, THDI_PORT_SP_CONFIGm)[pipe];
   2380     if (mem != INVALIDm) {
   2381         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   2382             buf_port_pool = &buf_port->pools[idx];
   2383             midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, THDI_PORT_SP_CONFIGm,
   2384                                               idx);
   2385             sal_memset(&thdi_sp_config, 0, sizeof(thdi_sp_config));
   2386             soc_mem_field32_set(unit, mem, &thdi_sp_config,
   2387                                 PORT_SP_MIN_LIMITf, buf_port_pool->guarantee);
   2388             soc_mem_field32_set(unit, mem, &thdi_sp_config,
   2389                            PORT_SP_RESUME_LIMITf, buf_port_pool->pool_resume);
   2390             soc_mem_field32_set(unit, mem, &thdi_sp_config,
   2391                                PORT_SP_MAX_LIMITf, buf_port_pool->pool_limit);
   2392             SOC_IF_ERROR_RETURN
   2393                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2394                                midx, &thdi_sp_config));
   2395         }
   2396     }
   2397 
   2398     /***************************************************
   2399      * Input port per port per priority group settings *
   2400  */
   2401     mem = SOC_MEM_UNIQUE_ACC(unit, THDI_PORT_PG_CONFIGm)[pipe];
   2402     if (mem != INVALIDm) {
   2403         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   2404             buf_prigroup = &buf->ports[port].prigroups[idx];
   2405 
   2406             midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, THDI_PORT_PG_CONFIGm,
   2407                                               idx);
   2408             sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
   2409             soc_mem_field32_set(unit, mem, &pg_config_mem,
   2410                                 PG_MIN_LIMITf, buf_prigroup->guarantee);
   2411 
   2412             if (buf_prigroup->pool_scale != -1) {
   2413                 soc_mem_field32_set(unit, mem, &pg_config_mem,
   2414                                     PG_SHARED_DYNAMICf, 1);
   2415                 soc_mem_field32_set(unit, mem, &pg_config_mem,
   2416                                     PG_SHARED_LIMITf,
   2417                                     buf_prigroup->pool_scale);
   2418             } else {
   2419                 soc_mem_field32_set(unit, mem, &pg_config_mem,
   2420                                     PG_SHARED_LIMITf,
   2421                                     buf_prigroup->pool_limit);
   2422             }
   2423 
   2424             soc_mem_field32_set(unit, mem, &pg_config_mem,
   2425                                 PG_GBL_HDRM_ENf,
   2426                                 buf_prigroup->device_headroom_enable);
   2427             soc_mem_field32_set(unit, mem, &pg_config_mem,
   2428                                 PG_HDRM_LIMITf, buf_prigroup->headroom);
   2429 
   2430             soc_mem_field32_set(unit, mem, &pg_config_mem,
   2431                                 PG_RESET_OFFSETf, buf_prigroup->pool_resume / 8);
   2432 
   2433             soc_mem_field32_set(unit, mem, &pg_config_mem,
   2434                                 PG_RESET_FLOORf, buf_prigroup->pool_floor);
   2435 
   2436             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem,
   2437                                               MEM_BLOCK_ALL, midx,
   2438                                               &pg_config_mem));
   2439         }
   2440     }
   2441 
   2442     /*==================== THDO ====================*/
   2443 
   2444     /*******************************************
   2445      *  Output port per port per queue setting *
   2446  */
   2447 
   2448     /* MC */
   2449     numq = si->port_num_cosq[port];
   2450     base = si->port_cosq_base[port];
   2451 
   2452     mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[0])[pipe];
   2453     mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[1])[pipe];
   2454     if ((numq != 0) && (mem0 != INVALIDm) && (mem1 != INVALIDm)) {
   2455         for (idx = 0; idx < numq; idx++) {
   2456             buf_queue = &buf->ports[port].queues[idx];
   2457 
   2458             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_0_entry_t));
   2459 
   2460             soc_mem_field32_set(unit, mem0, entry0,
   2461                                 Q_MIN_LIMITf, buf_queue->guarantee);
   2462             if (buf_queue->discard_enable) {
   2463                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_ENABLEf, 1);
   2464             }
   2465             if (buf_queue->color_discard_enable) {
   2466                 soc_mem_field32_set(unit, mem0, entry0, Q_COLOR_LIMIT_ENABLEf,
   2467                                     1);
   2468             }
   2469             if (buf_queue->pool_scale != -1) {
   2470                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMICf, 1);
   2471                 soc_mem_field32_set(unit, mem0, entry0,
   2472                            Q_SHARED_ALPHAf, buf_queue->pool_scale);
   2473             } else {
   2474                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   2475                 soc_mem_field32_set(unit, mem0, entry0,
   2476                                     Q_SHARED_LIMITf, buf_queue->pool_limit);
   2477             }
   2478             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   2479                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   2480                 soc_mem_field32_set(unit, mem0, entry0,
   2481                                     Q_COLOR_LIMIT_DYNAMICf, 1);
   2482                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   2483                      buf_queue->yellow_limit
   2484                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2485                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2486                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   2487                      buf_queue->red_limit
   2488                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2489                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2490             } else {
   2491                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   2492                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   2493                      CEIL(buf_queue->yellow_limit, 8));
   2494                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   2495                      CEIL(buf_queue->red_limit, 8));
   2496             }
   2497 
   2498             soc_mem_field32_set(unit, mem0, entry0,
   2499                                 Q_SPIDf, buf_queue->pool_idx);
   2500 
   2501             SOC_IF_ERROR_RETURN
   2502                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx,
   2503                                entry0));
   2504 
   2505             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_offset_entry_t));
   2506 
   2507             soc_mem_field32_set(unit, mem1, entry0,
   2508                                 RESUME_OFFSETf, (default_mtu_cells * 2)/8);
   2509             soc_mem_field32_set(unit, mem1, entry0,
   2510                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
   2511             soc_mem_field32_set(unit, mem1, entry0,
   2512                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
   2513             SOC_IF_ERROR_RETURN
   2514                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx,
   2515                                entry0));
   2516 
   2517         }
   2518     }
   2519 
   2520     mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[2])[pipe];
   2521     mem3 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[3])[pipe];
   2522     if ((numq != 0) && (mem2 != INVALIDm) && (mem3 != INVALIDm)) {
   2523         for (idx = 0; idx < numq; idx++) {
   2524             buf_queue = &buf->ports[port].queues[idx];
   2525             buf_pool = &buf->pools[buf_queue->pool_idx];
   2526             if (buf_pool->total == 0) {
   2527                 continue;
   2528             }
   2529             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
   2530 
   2531             soc_mem_field32_set(unit, mem2, entry0,
   2532                                 Q_MIN_LIMITf,
   2533                                 buf_queue->mcq_entry_guarantee/4);
   2534             
   2535             /* each XPE carries half the queues */
   2536             limit = buf_pool->total_mcq_entry;
   2537             for (xpe = 0; xpe < _TH2_XPES_PER_DEV; xpe ++) {
   2538                 limit_xpe = buf_pool->total_mcq_entry
   2539                     - buf->pools_xpe[xpe][buf_queue->pool_idx].mcq_entry_reserved
   2540                     - SOC_TH2_MMU_MCQ_ENTRY_RESERVED_TDM_OVERSHOOT;
   2541                 
   2542                 if (limit_xpe < limit) {
   2543                     limit = limit_xpe;
   2544                 }
   2545             }
   2546             if (limit <= 0) {
   2547                 continue;
   2548             }
   2549 
   2550             if (buf_queue->discard_enable) {
   2551                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_ENABLEf, 1);
   2552             }
   2553             if (buf_queue->color_discard_enable) {
   2554                 soc_mem_field32_set(unit, mem2, entry0, Q_COLOR_LIMIT_ENABLEf,
   2555                                     1);
   2556             }
   2557             if (buf_queue->pool_scale != -1) {
   2558                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_DYNAMICf, 1);
   2559                 soc_mem_field32_set(unit, mem2, entry0,
   2560                                     Q_SHARED_ALPHAf,
   2561                                     buf_queue->pool_scale);
   2562             } else {
   2563                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   2564                 soc_mem_field32_set(unit, mem2, entry0,
   2565                                     Q_SHARED_LIMITf, CEIL(limit, 4));
   2566             }
   2567             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   2568                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   2569                 soc_mem_field32_set(unit, mem2, entry0,
   2570                                     Q_COLOR_LIMIT_DYNAMICf, 1);
   2571                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
   2572                      buf_queue->yellow_limit
   2573                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2574                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2575                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
   2576                      buf_queue->red_limit
   2577                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2578                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2579             } else {
   2580                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   2581                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
   2582                                     CEIL(limit, 8));
   2583                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
   2584                                     CEIL(limit, 8));
   2585 
   2586             }
   2587 
   2588             soc_mem_field32_set(unit, mem2, entry0,
   2589                                 Q_SPIDf, buf_queue->pool_idx);
   2590 
   2591             SOC_IF_ERROR_RETURN
   2592                 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, base + idx,
   2593                                entry0));
   2594 
   2595             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_offset_entry_t));
   2596 
   2597             soc_mem_field32_set(unit, mem3, entry0, RESUME_OFFSETf, 1);
   2598             soc_mem_field32_set(unit, mem3, entry0,
   2599                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
   2600             soc_mem_field32_set(unit, mem3, entry0,
   2601                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
   2602             SOC_IF_ERROR_RETURN
   2603                 (soc_mem_write(unit, mem3, MEM_BLOCK_ALL, base + idx,
   2604                                entry0));
   2605 
   2606         }
   2607     }
   2608 
   2609     /* Per port per pool */
   2610     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   2611         buf_port_pool = &buf->ports[port].pools[idx];
   2612         if (buf_port_pool->pool_limit == 0) {
   2613             continue;
   2614         }
   2615 
   2616         limit = buf_port_pool->pool_limit;
   2617         rlimit = limit - (default_mtu_cells * 2);
   2618 
   2619         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[0])[pipe];
   2620         if (mem0 == INVALIDm) {
   2621             continue;
   2622         }
   2623 
   2624         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port,
   2625                                             mmu_thdo_port_mc_mem[0],
   2626                                             idx);
   2627         sal_memset(entry0, 0, sizeof(mmu_thdm_db_portsp_config_entry_t));
   2628 
   2629         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
   2630         soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   2631                             CEIL(limit, 8));
   2632         soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   2633                             CEIL(limit, 8));
   2634 
   2635         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMIT_ENABLEf,
   2636                             !lossless);
   2637 
   2638         soc_mem_field32_set(unit, mem0, entry0, SHARED_RESUME_LIMITf,
   2639                             CEIL(rlimit, 8));
   2640         soc_mem_field32_set(unit, mem0, entry0, YELLOW_RESUME_LIMITf,
   2641                             CEIL(rlimit, 8));
   2642         soc_mem_field32_set(unit, mem0, entry0, RED_RESUME_LIMITf,
   2643                             CEIL(rlimit, 8));
   2644 
   2645         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   2646                             midx, entry0));
   2647 
   2648         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[1])[pipe];
   2649         if (mem1 == INVALIDm) {
   2650             continue;
   2651         }
   2652         buf_pool = &buf->pools[idx];
   2653         sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_portsp_config_entry_t));
   2654 
   2655         limit = buf_pool->total_mcq_entry;
   2656         if (limit <= 0) {
   2657             continue;
   2658         }
   2659 
   2660         soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMITf,
   2661                             CEIL(limit, 4) - 1);
   2662         soc_mem_field32_set(unit, mem1, entry0, YELLOW_SHARED_LIMITf,
   2663                             CEIL(limit, 8) - 1);
   2664         soc_mem_field32_set(unit, mem1, entry0, RED_SHARED_LIMITf,
   2665                             CEIL(limit, 8) - 1);
   2666 
   2667         soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMIT_ENABLEf,
   2668                             !lossless);
   2669 
   2670         soc_mem_field32_set(unit, mem1, entry0, SHARED_RESUME_LIMITf,
   2671                             CEIL(limit, 8) - 2);
   2672         soc_mem_field32_set(unit, mem1, entry0, YELLOW_RESUME_LIMITf,
   2673                             CEIL(limit, 8) - 2);
   2674         soc_mem_field32_set(unit, mem1, entry0, RED_RESUME_LIMITf,
   2675                             CEIL(limit, 8) - 2);
   2676 
   2677         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
   2678                             midx, entry0));
   2679     }
   2680 
   2681     /* UC */
   2682     numq = si->port_num_uc_cosq[port];
   2683     base = si->port_uc_cosq_base[port];
   2684 
   2685     mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[0])[pipe];
   2686     mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[1])[pipe];
   2687     mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[2])[pipe];
   2688     if ((numq != 0) &&
   2689         (mem0 != INVALIDm) && (mem1 != INVALIDm) && (mem2 != INVALIDm)) {
   2690         for (idx = 0; idx < numq; idx++) {
   2691             buf_queue = &buf->ports[port].queues[si->port_num_cosq[port] + idx];
   2692 
   2693             sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
   2694             sal_memset(entry1, 0, sizeof(mmu_thdu_offset_queue_entry_t));
   2695 
   2696             soc_mem_field32_set(unit, mem0, entry0,
   2697                                 Q_MIN_LIMIT_CELLf, buf_queue->guarantee);
   2698             if (buf_queue->pool_scale != -1) {
   2699                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMIC_CELLf,
   2700                                     1);
   2701                 soc_mem_field32_set(unit, mem0, entry0,
   2702                                     Q_SHARED_ALPHA_CELLf,
   2703                                     buf_queue->pool_scale);
   2704             } else {
   2705                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   2706                 soc_mem_field32_set(unit, mem0, entry0,
   2707                                     Q_SHARED_LIMIT_CELLf,
   2708                                     buf_queue->pool_limit);
   2709             }
   2710             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_CELLf,
   2711                                 buf_queue->pool_resume / 8);
   2712 
   2713             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   2714                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   2715                 soc_mem_field32_set(unit, mem0, entry0,
   2716                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
   2717                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
   2718                      buf_queue->yellow_limit
   2719                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2720                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2721                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
   2722                      buf_queue->red_limit
   2723                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   2724                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   2725             } else {
   2726                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   2727                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
   2728                                     CEIL(buf_queue->yellow_limit, 8));
   2729                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
   2730                                     CEIL(buf_queue->red_limit, 8));
   2731             }
   2732             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_YELLOW_CELLf,
   2733                                 buf_queue->yellow_resume / 8);
   2734             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_RED_CELLf,
   2735                                 buf_queue->red_resume / 8);
   2736             SOC_IF_ERROR_RETURN
   2737                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0));
   2738 
   2739             SOC_IF_ERROR_RETURN
   2740                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, entry1));
   2741 
   2742             sal_memset(entry0, 0, sizeof(mmu_thdo_q_to_qgrp_map_entry_t));
   2743             soc_mem_field32_set(unit, mem2, entry0,
   2744                                 Q_SPIDf, buf_queue->pool_idx);
   2745 
   2746             if (buf_queue->discard_enable) {
   2747                 soc_mem_field32_set(unit, mem2, entry0,
   2748                                     Q_LIMIT_ENABLEf, 1);
   2749             }
   2750             if (buf_queue->color_discard_enable) {
   2751                 soc_mem_field32_set(unit, mem2, entry0,
   2752                                     Q_COLOR_ENABLE_CELLf, 1);
   2753             }
   2754 
   2755 
   2756             if (buf_queue->qgroup_id >= 0) {
   2757                 soc_mem_field32_set(unit, mem2, entry0, QGROUP_VALIDf, 1);
   2758                 if (buf_queue->qgroup_min_enable) {
   2759                     soc_mem_field32_set(unit, mem2, entry0, USE_QGROUP_MINf, 1);
   2760                 }
   2761             }
   2762 
   2763             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL,
   2764                                               base + idx, entry0));
   2765         }
   2766     }
   2767 
   2768     /* Per  port per pool unicast */
   2769     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   2770         buf_pool = &buf->pools[idx];
   2771 
   2772         if (buf_pool->total == 0) {
   2773             continue;
   2774         }
   2775 
   2776         limit = buf_pool->total;
   2777 
   2778         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[0])[pipe];
   2779         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[1])[pipe];
   2780         if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
   2781             continue;
   2782         }
   2783         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port,
   2784                                           mmu_thdo_port_uc_mem[0],
   2785                                           idx);
   2786         sal_memset(entry0, 0, sizeof(mmu_thdu_config_port_entry_t));
   2787         sal_memset(entry1, 0, sizeof(mmu_thdu_resume_port_entry_t));
   2788 
   2789         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
   2790         soc_mem_field32_set(unit, mem1, entry1,
   2791                             SHARED_RESUMEf,
   2792                             CEIL((limit - default_mtu_cells*2), 8));
   2793 
   2794         soc_mem_field32_set(unit, mem0, entry0, YELLOW_LIMITf, 
   2795                             CEIL(limit, 8));
   2796         soc_mem_field32_set(unit, mem1, entry1,
   2797                             YELLOW_RESUMEf,
   2798                             CEIL((limit - default_mtu_cells*2), 8));
   2799 
   2800         soc_mem_field32_set(unit, mem0, entry0, RED_LIMITf, 
   2801                             CEIL(limit, 8));
   2802         soc_mem_field32_set(unit, mem1, entry1,
   2803                             RED_RESUMEf,
   2804                             CEIL((limit - default_mtu_cells*2), 8));
   2805 
   2806         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   2807                             midx, entry0));
   2808         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
   2809                             midx, entry1));
   2810     }
   2811 
   2812    return SOC_E_NONE;
   2813 }
   2814 
   2815 STATIC int
   2816 _soc_th2_mmu_config_buf_set_hw(int unit, _soc_mmu_cfg_buf_t *buf,
   2817                               _soc_mmu_device_info_t *devcfg, int lossless)
   2818 {
   2819     int port;
   2820 
   2821     SOC_IF_ERROR_RETURN
   2822         (_soc_th2_mmu_config_buf_set_hw_global(unit, buf, devcfg, lossless));
   2823 
   2824     PBMP_ALL_ITER(unit, port) {
   2825         SOC_IF_ERROR_RETURN
   2826             (_soc_th2_mmu_config_buf_set_hw_port(unit, port, buf, devcfg,
   2827                                                  lossless));
   2828     }
   2829     return SOC_E_NONE;
   2830 }
   2831 
   2832 int
   2833 soc_th2_mmu_config_init_port(int unit, int port)
   2834 {
   2835     _soc_mmu_cfg_buf_t *buf;
   2836     _soc_mmu_device_info_t devcfg;
   2837     int lossless = 1;
   2838     int rv;
   2839 
   2840     buf = soc_mmu_cfg_alloc(unit);
   2841     if (!buf) {
   2842         return SOC_E_MEMORY;
   2843     }
   2844 
   2845     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
   2846 
   2847     _soc_th2_mmu_init_dev_config(unit, &devcfg, lossless);
   2848     /* Calculate the buf - global as well as per port
   2849      * but _soc_th2_mmu_config_buf_set_hw_port is only made
   2850      * for that port - since it is flex operation - we don't
   2851      * touch any other port */
   2852     /* Class 1 config */
   2853     _soc_th2_mmu_config_buf_class1(unit, buf, &devcfg, lossless);
   2854     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   2855         /* Override default class 1 config */
   2856         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   2857     }
   2858     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
   2859     if (SOC_FAILURE(rv)) {
   2860         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2861                 (BSL_META_U(unit,
   2862                             "MMU config: Use default setting\n")));
   2863         _soc_th2_mmu_config_buf_class1(unit, buf, &devcfg, lossless);
   2864         _soc_mmu_cfg_buf_calculate(unit, buf, &devcfg);
   2865     }
   2866 
   2867     /* TH2 buffer special calculation */
   2868     _soc_th2_mmu_config_buf_calculate(unit, buf, &devcfg, lossless);
   2869     /* Default class 2 config */
   2870     _soc_th2_mmu_config_buf_class2(unit, buf, &devcfg, lossless);
   2871     /* Override default class 2 config */
   2872     if (SOC_SUCCESS(rv)) {
   2873         if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   2874             _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   2875         }
   2876     }
   2877     
   2878     rv = _soc_th2_mmu_config_buf_set_hw_port(unit, port, buf, &devcfg, lossless);
   2879 
   2880     soc_mmu_cfg_free(unit, buf);
   2881 
   2882     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2883                 (BSL_META_U(unit,
   2884                             "MMU THDI/THDO init done\n")));
   2885     return rv;
   2886 }
   2887 
   2888 int
   2889 soc_th2_mmu_config_init(int unit, int test_only)
   2890 {
   2891     int rv;
   2892     int lossless = 1;
   2893     _soc_mmu_cfg_buf_t *buf;
   2894     _soc_mmu_device_info_t devcfg;
   2895 
   2896     buf = soc_mmu_cfg_alloc(unit);
   2897     if (!buf) {
   2898         return SOC_E_MEMORY;
   2899     }
   2900 
   2901     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
   2902 
   2903     /* Update the soc_info mmu_lossless to the updated value */
   2904     SOC_INFO(unit).mmu_lossless = lossless;
   2905 
   2906     _soc_th2_mmu_init_dev_config(unit, &devcfg, lossless);
   2907     
   2908     /* Default class 1 config */
   2909     _soc_th2_mmu_config_buf_class1(unit, buf, &devcfg, lossless);
   2910     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   2911         /* Override default class 1 config */
   2912         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   2913     }
   2914     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
   2915     if (!test_only) {
   2916         if (SOC_FAILURE(rv)) {
   2917             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2918                         (BSL_META_U(unit,
   2919                                     "MMU config: Use default setting\n")));
   2920             _soc_th2_mmu_config_buf_class1(unit, buf, &devcfg, lossless);
   2921             _soc_mmu_cfg_buf_calculate(unit, buf, &devcfg);
   2922         }
   2923         /* TH2 buffer special calculation */
   2924         _soc_th2_mmu_config_buf_calculate(unit, buf, &devcfg, lossless);
   2925         /* Default class 2 config */
   2926         _soc_th2_mmu_config_buf_class2(unit, buf, &devcfg, lossless);
   2927         /* Override default class 2 config */
   2928         if (SOC_SUCCESS(rv)) {
   2929             if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   2930                 _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   2931             }
   2932         }
   2933 
   2934         rv = _soc_th2_mmu_config_buf_set_hw(unit, buf, &devcfg, lossless);
   2935     }
   2936 
   2937     soc_mmu_cfg_free(unit, buf);
   2938 
   2939     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2940                 (BSL_META_U(unit,
   2941                             "MMU THDI/THDO init done\n")));
   2942     return rv;
   2943 }
   2944 
   2945 /*
   2946  * Check and set threshold to register
   2947  * 
   2948  * Parameter:
   2949  *   reg/mem    - reg or mem
   2950  *   field      - threshold field
   2951  *   unique     - if the acc_type is unique or duplicate
   2952  *   xpe        - if unique, inidicate the xpe #
   2953  *   val        - threshold value
   2954  *   decrease   - 1: only new val < current val will be set to reg
   2955  *                0: only new val > current val will be set to reg
   2956  *   chk_zero   - only non-zero val could be set to reg
   2957  */
   2958 int
   2959 _soc_th2_mmu_config_shared_limit_chk_set(int unit, 
   2960         soc_reg_t reg, soc_mem_t mem, soc_field_t field, int index, 
   2961         int xpe, uint32 val, int decrease, int chk_zero)
   2962 {
   2963     uint32 rval, entry[SOC_MAX_MEM_WORDS];
   2964     uint32 cur_val;
   2965 
   2966     if (reg != INVALIDr) {
   2967         rval = 0;
   2968         SOC_IF_ERROR_RETURN
   2969             (soc_tomahawk_xpe_reg32_get(unit, reg, xpe, -1, index, &rval));
   2970         
   2971         cur_val = soc_reg_field_get(unit, reg, rval, field);
   2972         if (((!chk_zero) || (chk_zero && (cur_val != 0))) &&
   2973             TH2_MMU_SHARED_LIMIT_CHK(cur_val, val, decrease)) {
   2974             soc_reg_field_set(unit, reg, &rval, field, val);
   2975             SOC_IF_ERROR_RETURN
   2976                 (soc_tomahawk_xpe_reg32_set(unit, reg, xpe, -1, index, rval));
   2977         }
   2978     } else if (mem != INVALIDm) {
   2979         sal_memset(entry, 0, sizeof(entry));
   2980         SOC_IF_ERROR_RETURN
   2981             (soc_tomahawk_xpe_mem_read(unit, mem, xpe, -1, 
   2982                 MEM_BLOCK_ALL, index, entry));
   2983         
   2984         cur_val = soc_mem_field32_get(unit, mem, entry, field);
   2985         if (((!chk_zero) || (chk_zero && (cur_val != 0))) &&
   2986             TH2_MMU_SHARED_LIMIT_CHK(cur_val, val, decrease)) {
   2987             soc_mem_field32_set(unit, mem, entry, field, val);
   2988             SOC_IF_ERROR_RETURN
   2989                 (soc_tomahawk_xpe_mem_write(unit, mem, xpe, -1, 
   2990                     MEM_BLOCK_ALL, index, entry));
   2991         }
   2992     } else {
   2993         return SOC_E_INTERNAL;
   2994     }
   2995     
   2996     return SOC_E_NONE;
   2997 }
   2998 
   2999 int
   3000 soc_th2_mmu_config_shared_buf_set_hw(int unit, int res, 
   3001                         int *thdi_shd, int *thdo_db_shd, int *thdo_qe_shd,
   3002                         int post_update)
   3003 {
   3004     soc_info_t *si;
   3005     _soc_mmu_device_info_t devcfg;
   3006     int pipe, xpe, xpe_map;
   3007     uint32 entry0[SOC_MAX_MEM_WORDS], new_limit, rval = 0;
   3008     thdi_port_pg_config_entry_t pg_config_mem;
   3009     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
   3010     int port, base, numq, idx, midx;
   3011     soc_mem_t base_mem = INVALIDm;
   3012     soc_mem_t mem = INVALIDm;
   3013     soc_reg_t reg = INVALIDr;
   3014     soc_field_t field = INVALIDf;
   3015     int granularity;
   3016     int thdi_shd_min, thdo_db_shd_min, thdo_qe_shd_min;
   3017     int default_mtu_cells;
   3018 
   3019     si = &SOC_INFO(unit);
   3020 
   3021     xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3022     
   3023     _soc_th2_mmu_init_dev_config(unit, &devcfg, 0);
   3024     
   3025     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg.default_mtu_size +
   3026                                                    devcfg.mmu_hdr_byte,
   3027                                                    devcfg.mmu_cell_size);
   3028     
   3029     _TH_ARRAY_MIN(thdi_shd, NUM_XPE(unit), xpe_map, thdi_shd_min);
   3030     _TH_ARRAY_MIN(thdo_db_shd, NUM_XPE(unit), xpe_map, thdo_db_shd_min);
   3031     _TH_ARRAY_MIN(thdo_qe_shd, NUM_XPE(unit), xpe_map, thdo_qe_shd_min);
   3032     
   3033     /***********************************
   3034      * THDI
   3035  */
   3036     if (res & 0x1) { /* if (res & THDI) { */
   3037 
   3038         /* THDI SP entries */
   3039         rval = 0;
   3040         reg = THDI_BUFFER_CELL_LIMIT_SPr;
   3041         field = LIMITf;
   3042         granularity = 1;
   3043         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   3044             if (!(xpe_map & (1 << xpe))) {
   3045                 continue;
   3046             }
   3047             
   3048             new_limit = CEIL(thdi_shd[xpe], granularity);
   3049             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   3050                 SOC_IF_ERROR_RETURN
   3051                     (_soc_th2_mmu_config_shared_limit_chk_set
   3052                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3053                          post_update, 1));
   3054             }
   3055         }
   3056 
   3057         /* Input per port settings */
   3058         base_mem = THDI_PORT_PG_CONFIGm;
   3059         PBMP_ALL_ITER(unit, port) {
   3060             pipe = si->port_pipe[port];
   3061             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   3062             field = PG_SHARED_LIMITf;
   3063             granularity = 1;
   3064             new_limit = CEIL(thdi_shd_min, granularity);
   3065             /* Input port per Port-PG settings */
   3066             for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   3067                 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, base_mem, idx);
   3068                 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
   3069                 SOC_IF_ERROR_RETURN
   3070                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   3071                                   midx, &pg_config_mem));
   3072                 if (!soc_mem_field32_get(unit, mem, &pg_config_mem,
   3073                                          PG_SHARED_DYNAMICf)) {
   3074                     SOC_IF_ERROR_RETURN
   3075                         (_soc_th2_mmu_config_shared_limit_chk_set
   3076                             (unit, INVALIDr, mem, field, midx, -1, new_limit, 
   3077                              post_update, 1));
   3078                 }
   3079             }
   3080         }
   3081     }
   3082 
   3083     /***********************************
   3084      * THDO
   3085  */
   3086     if (res & 0x2) { /* if (res & THDO) { */
   3087         /* Per SP settings */
   3088         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   3089             if (!(xpe_map & (1 << xpe))) {
   3090                 continue;
   3091             }
   3092             
   3093             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   3094                 /* Data Buffer */
   3095                 rval = 0;
   3096                 reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
   3097                 field = SHARED_LIMITf;
   3098                 granularity = 1;
   3099                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3100                 SOC_IF_ERROR_RETURN
   3101                     (_soc_th2_mmu_config_shared_limit_chk_set
   3102                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3103                          post_update, 1));
   3104             
   3105                 rval = 0;
   3106                 reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
   3107                 field = RESUME_LIMITf;
   3108                 granularity = 8;
   3109                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3110                 SOC_IF_ERROR_RETURN
   3111                     (_soc_th2_mmu_config_shared_limit_chk_set
   3112                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3113                          post_update, 1));
   3114             
   3115                 rval = 0;
   3116                 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
   3117                 field = YELLOW_SHARED_LIMITf;
   3118                 granularity = 8;
   3119                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3120                 SOC_IF_ERROR_RETURN
   3121                     (_soc_th2_mmu_config_shared_limit_chk_set
   3122                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3123                          post_update, 1));
   3124             
   3125                 rval = 0;
   3126                 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
   3127                 field = YELLOW_RESUME_LIMITf;
   3128                 granularity = 8;
   3129                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3130                 SOC_IF_ERROR_RETURN
   3131                     (_soc_th2_mmu_config_shared_limit_chk_set
   3132                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3133                          post_update, 1));
   3134             
   3135                 rval = 0;
   3136                 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
   3137                 field = RED_SHARED_LIMITf;
   3138                 granularity = 8;
   3139                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3140                 SOC_IF_ERROR_RETURN
   3141                     (_soc_th2_mmu_config_shared_limit_chk_set
   3142                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3143                          post_update, 1));
   3144             
   3145                 rval = 0;
   3146                 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
   3147                 field = RED_RESUME_LIMITf;
   3148                 granularity = 8;
   3149                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3150                 SOC_IF_ERROR_RETURN
   3151                     (_soc_th2_mmu_config_shared_limit_chk_set
   3152                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3153                          post_update, 1));
   3154             
   3155                 /* MCQE */
   3156                 rval = 0;
   3157                 reg = MMU_THDM_MCQE_POOL_SHARED_LIMITr;
   3158                 field = SHARED_LIMITf;
   3159                 granularity = 4;
   3160                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3161                 SOC_IF_ERROR_RETURN
   3162                     (_soc_th2_mmu_config_shared_limit_chk_set
   3163                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3164                          post_update, 1));
   3165             
   3166                 rval = 0;
   3167                 reg = MMU_THDM_MCQE_POOL_RESUME_LIMITr;
   3168                 field = RESUME_LIMITf;
   3169                 granularity = 8;
   3170                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3171                 SOC_IF_ERROR_RETURN
   3172                     (_soc_th2_mmu_config_shared_limit_chk_set
   3173                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3174                          post_update, 1));
   3175             
   3176                 rval = 0;
   3177                 reg = MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr;
   3178                 field = YELLOW_SHARED_LIMITf;
   3179                 granularity = 8;
   3180                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3181                 SOC_IF_ERROR_RETURN
   3182                     (_soc_th2_mmu_config_shared_limit_chk_set
   3183                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3184                          post_update, 1));
   3185             
   3186                 rval = 0;
   3187                 reg = MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr;
   3188                 field = YELLOW_RESUME_LIMITf;
   3189                 granularity = 8;
   3190                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3191                 SOC_IF_ERROR_RETURN
   3192                     (_soc_th2_mmu_config_shared_limit_chk_set
   3193                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3194                          post_update, 1));
   3195             
   3196                 rval = 0;
   3197                 reg = MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr;
   3198                 field = RED_SHARED_LIMITf;
   3199                 granularity = 8;
   3200                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3201                 SOC_IF_ERROR_RETURN
   3202                     (_soc_th2_mmu_config_shared_limit_chk_set
   3203                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3204                          post_update, 1));
   3205             
   3206                 rval = 0;
   3207                 reg = MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr;
   3208                 field = RED_RESUME_LIMITf;
   3209                 granularity = 8;
   3210                 new_limit = CEIL(thdo_qe_shd[xpe], granularity);
   3211                 SOC_IF_ERROR_RETURN
   3212                     (_soc_th2_mmu_config_shared_limit_chk_set
   3213                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3214                          post_update, 1));
   3215             }
   3216         }
   3217 
   3218         /* configure Q-groups */
   3219         base_mem = MMU_THDU_CONFIG_QGROUPm;
   3220         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   3221             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   3222             for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   3223                 sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
   3224 
   3225                 SOC_IF_ERROR_RETURN
   3226                         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp));
   3227 
   3228                 field = Q_SHARED_LIMIT_CELLf;
   3229                 granularity = 1;
   3230                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp, Q_LIMIT_DYNAMIC_CELLf)) {
   3231                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3232                     SOC_IF_ERROR_RETURN
   3233                         (_soc_th2_mmu_config_shared_limit_chk_set
   3234                             (unit, INVALIDr, mem, field, idx, -1, new_limit, 
   3235                              post_update, 0));
   3236                 }
   3237 
   3238                 granularity = 8;
   3239                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp,
   3240                                          Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
   3241                     field = LIMIT_RED_CELLf;
   3242                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3243                     SOC_IF_ERROR_RETURN
   3244                         (_soc_th2_mmu_config_shared_limit_chk_set
   3245                             (unit, INVALIDr, mem, field, idx, -1, new_limit, 
   3246                              post_update, 0));
   3247 
   3248                     field = LIMIT_YELLOW_CELLf;
   3249                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3250                     SOC_IF_ERROR_RETURN
   3251                         (_soc_th2_mmu_config_shared_limit_chk_set
   3252                             (unit, INVALIDr, mem, field, idx, -1, new_limit, 
   3253                              post_update, 0));
   3254                 }
   3255             }
   3256         }
   3257 
   3258         /* Output port per port per queue setting for UC queue */
   3259         PBMP_PORT_ITER(unit, port) {
   3260             base_mem = MMU_THDU_CONFIG_QUEUEm;
   3261             pipe = si->port_pipe[port];
   3262 
   3263             /* per port UC queue */
   3264             numq = si->port_num_uc_cosq[port];
   3265             base = si->port_uc_cosq_base[port];
   3266 
   3267             if (numq == 0) {
   3268                 continue;
   3269             }
   3270             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   3271             for (idx = 0; idx < numq; idx++) {
   3272                 sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
   3273 
   3274                 SOC_IF_ERROR_RETURN
   3275                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
   3276 
   3277                 field = Q_SHARED_LIMIT_CELLf;
   3278                 granularity = 1;
   3279                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMIC_CELLf)) {
   3280                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3281                     SOC_IF_ERROR_RETURN
   3282                         (_soc_th2_mmu_config_shared_limit_chk_set
   3283                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3284                              post_update, 0));
   3285                 }
   3286 
   3287                 granularity = 8;
   3288                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
   3289                     field = LIMIT_YELLOW_CELLf;
   3290                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3291                     SOC_IF_ERROR_RETURN
   3292                         (_soc_th2_mmu_config_shared_limit_chk_set
   3293                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3294                              post_update, 0));
   3295                     
   3296                     field = LIMIT_RED_CELLf;
   3297                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3298                     SOC_IF_ERROR_RETURN
   3299                         (_soc_th2_mmu_config_shared_limit_chk_set
   3300                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3301                              post_update, 0));
   3302                 }
   3303             }
   3304         }
   3305 
   3306         /* Output port per port per queue setting for MC queue */
   3307         PBMP_PORT_ITER(unit, port) {
   3308             /* DB entries - Queue */
   3309             numq = si->port_num_cosq[port];
   3310             base = si->port_cosq_base[port];
   3311             pipe = si->port_pipe[port];
   3312             if (numq == 0) {
   3313                 continue;
   3314             }
   3315 
   3316             base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   3317             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   3318 
   3319             for (idx = 0; idx < numq; idx++) {
   3320                 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_entry_t));
   3321 
   3322                 SOC_IF_ERROR_RETURN
   3323                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
   3324 
   3325                 field = Q_SHARED_LIMITf;
   3326                 granularity = 1;
   3327                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
   3328                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3329                     SOC_IF_ERROR_RETURN
   3330                         (_soc_th2_mmu_config_shared_limit_chk_set
   3331                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3332                              post_update, 0));
   3333                 }
   3334 
   3335                 granularity = 8;
   3336                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
   3337                     field = YELLOW_SHARED_LIMITf;
   3338                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3339                     SOC_IF_ERROR_RETURN
   3340                         (_soc_th2_mmu_config_shared_limit_chk_set
   3341                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3342                              post_update, 0));
   3343                     
   3344                     field = RED_SHARED_LIMITf;
   3345                     new_limit = CEIL(thdo_db_shd_min, granularity);
   3346                     SOC_IF_ERROR_RETURN
   3347                         (_soc_th2_mmu_config_shared_limit_chk_set
   3348                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3349                              post_update, 0));
   3350                 }
   3351             }
   3352 
   3353             /* MCQE - Queue */
   3354             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   3355             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   3356             for (idx = 0; idx < numq; idx++) {
   3357                 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
   3358 
   3359                 SOC_IF_ERROR_RETURN
   3360                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
   3361 
   3362                 field = Q_SHARED_LIMITf;
   3363                 granularity = 4;
   3364                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
   3365                     new_limit = CEIL(thdo_qe_shd_min, granularity);
   3366                     SOC_IF_ERROR_RETURN
   3367                         (_soc_th2_mmu_config_shared_limit_chk_set
   3368                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3369                              post_update, 0));
   3370                 }
   3371 
   3372                 granularity = 8;
   3373                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
   3374                     field = YELLOW_SHARED_LIMITf;
   3375                     new_limit = CEIL(thdo_qe_shd_min, granularity);
   3376                     SOC_IF_ERROR_RETURN
   3377                         (_soc_th2_mmu_config_shared_limit_chk_set
   3378                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3379                              post_update, 0));
   3380                     
   3381                     field = RED_SHARED_LIMITf;
   3382                     new_limit = CEIL(thdo_qe_shd_min, granularity);
   3383                     SOC_IF_ERROR_RETURN
   3384                         (_soc_th2_mmu_config_shared_limit_chk_set
   3385                             (unit, INVALIDr, mem, field, base + idx, -1, new_limit, 
   3386                              post_update, 0));
   3387                 }
   3388             }
   3389         }
   3390 
   3391         /* RQE */
   3392         for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   3393             rval = 0;
   3394             SOC_IF_ERROR_RETURN
   3395                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, &rval));
   3396 
   3397             reg = MMU_THDR_DB_CONFIG_PRIQr;
   3398             field = SHARED_LIMITf;
   3399             granularity = 1;
   3400             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   3401                                    DYNAMIC_ENABLEf)) {
   3402                 new_limit = CEIL(thdo_db_shd_min, granularity);
   3403                 SOC_IF_ERROR_RETURN
   3404                     (_soc_th2_mmu_config_shared_limit_chk_set
   3405                         (unit, reg, INVALIDm, field, idx, -1, new_limit, 
   3406                          post_update, 0));
   3407             }
   3408 
   3409             reg = MMU_THDR_DB_LIMIT_COLOR_PRIQr;
   3410             granularity = 8;
   3411             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   3412                                    COLOR_LIMIT_DYNAMICf)) {
   3413                 field = SHARED_RED_LIMITf;
   3414                 new_limit = CEIL(thdo_db_shd_min, granularity);
   3415                 SOC_IF_ERROR_RETURN
   3416                     (_soc_th2_mmu_config_shared_limit_chk_set
   3417                         (unit, reg, INVALIDm, field, idx, -1, new_limit, 
   3418                          post_update, 0));
   3419 
   3420                 field = SHARED_YELLOW_LIMITf;
   3421                 new_limit = CEIL(thdo_db_shd_min, granularity);
   3422                 SOC_IF_ERROR_RETURN
   3423                     (_soc_th2_mmu_config_shared_limit_chk_set
   3424                         (unit, reg, INVALIDm, field, idx, -1, new_limit, 
   3425                          post_update, 0));
   3426             }
   3427         }
   3428         
   3429         /* per pool RQE settings */
   3430         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   3431             if (!(xpe_map & (1 << xpe))) {
   3432                 continue;
   3433             }
   3434             
   3435             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   3436                 reg = MMU_THDR_DB_CONFIG_SPr;
   3437                 field = SHARED_LIMITf;
   3438                 granularity = 1;
   3439                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3440                 SOC_IF_ERROR_RETURN
   3441                     (_soc_th2_mmu_config_shared_limit_chk_set
   3442                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3443                          post_update, 1));
   3444                 
   3445                 field = RESUME_LIMITf;
   3446                 new_limit = CEIL((thdo_db_shd[xpe] - default_mtu_cells * 2), 8);
   3447                 SOC_IF_ERROR_RETURN
   3448                     (_soc_th2_mmu_config_shared_limit_chk_set
   3449                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3450                          post_update, 1));
   3451             
   3452                 reg = MMU_THDR_DB_SP_SHARED_LIMITr;
   3453                 field = SHARED_YELLOW_LIMITf;
   3454                 granularity = 8;
   3455                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3456                 SOC_IF_ERROR_RETURN
   3457                     (_soc_th2_mmu_config_shared_limit_chk_set
   3458                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3459                          post_update, 1));
   3460                 
   3461                 field = SHARED_RED_LIMITf;
   3462                 granularity = 8;
   3463                 new_limit = CEIL(thdo_db_shd[xpe], granularity);
   3464                 SOC_IF_ERROR_RETURN
   3465                     (_soc_th2_mmu_config_shared_limit_chk_set
   3466                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3467                          post_update, 1));
   3468             
   3469                 reg = MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr;
   3470                 field = RESUME_YELLOW_LIMITf;
   3471                 new_limit = CEIL((thdo_db_shd[xpe] - default_mtu_cells * 2), 8);
   3472                 SOC_IF_ERROR_RETURN
   3473                     (_soc_th2_mmu_config_shared_limit_chk_set
   3474                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3475                          post_update, 1));
   3476                 
   3477                 field = RESUME_RED_LIMITf;
   3478                 new_limit = CEIL((thdo_db_shd[xpe] - default_mtu_cells * 2), 8);
   3479                 SOC_IF_ERROR_RETURN
   3480                     (_soc_th2_mmu_config_shared_limit_chk_set
   3481                         (unit, reg, INVALIDm, field, idx, xpe, new_limit, 
   3482                          post_update, 1));
   3483             }
   3484         }
   3485     }
   3486 
   3487     return SOC_E_NONE;
   3488 }
   3489 
   3490 /*
   3491  * Function:
   3492  *      soc_th2_mmu_config_shared_buf_set_hw_port
   3493  * Purpose:
   3494  *      Update shared limit setting of port.
   3495  * Parameters:
   3496  *      unit        - (IN) Unit number.
   3497  *      port        - (IN) Logical port.
   3498  *      thdi_shd    - (IN) Ingress shared limit
   3499  *      thdo_db_shd - (IN) Egress shared limit
   3500  *      thdo_qe_shd - (IN) Egress shared limit for MCQE
   3501  * Returns:
   3502  *      SOC_E_XXX
   3503  */
   3504 int
   3505 soc_th2_mmu_config_shared_buf_set_hw_port(int unit, int port, int *thdi_shd,
   3506                                           int *thdo_db_shd, int *thdo_qe_shd)
   3507 {
   3508     soc_info_t *si;
   3509     int pipe, xpe_map, base, numq, idx, midx, dynamic_q, update, granularity;
   3510     int thdi_shd_min, thdo_db_shd_min, thdo_qe_shd_min;
   3511     uint32  new_limit, cur_limit, cur_limit1;
   3512     thdi_port_pg_config_entry_t pg_cfg;
   3513     mmu_thdu_config_queue_entry_t cfg_queue;
   3514     mmu_thdm_db_queue_config_entry_t dbq_cfg;
   3515     mmu_thdm_mcqe_queue_config_entry_t mcqe_cfg;
   3516     soc_mem_t mem = INVALIDm;
   3517     soc_field_t field[3];
   3518 
   3519     si = &SOC_INFO(unit);
   3520     pipe = si->port_pipe[port];
   3521     xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3522     _TH_ARRAY_MIN(thdi_shd, NUM_XPE(unit), xpe_map, thdi_shd_min);
   3523     _TH_ARRAY_MIN(thdo_db_shd, NUM_XPE(unit), xpe_map, thdo_db_shd_min);
   3524     _TH_ARRAY_MIN(thdo_qe_shd, NUM_XPE(unit), xpe_map, thdo_qe_shd_min);
   3525 
   3526 
   3527     /***********************************
   3528      * THDI
   3529  */
   3530 
   3531     /* Input per port settings */
   3532     mem = SOC_MEM_UNIQUE_ACC(unit, THDI_PORT_PG_CONFIGm)[pipe];
   3533     field[0] = PG_SHARED_LIMITf;
   3534     granularity = 1;
   3535     new_limit = CEIL(thdi_shd_min, granularity);
   3536     /* Input port per Port-PG settings */
   3537     for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   3538         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, THDI_PORT_PG_CONFIGm,
   3539                                           idx);
   3540         sal_memset(&pg_cfg, 0, sizeof(pg_cfg));
   3541         SOC_IF_ERROR_RETURN
   3542             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &pg_cfg));
   3543         if (!soc_mem_field32_get(unit, mem, &pg_cfg, PG_SHARED_DYNAMICf)) {
   3544             cur_limit = soc_mem_field32_get(unit, mem, &pg_cfg, field[0]);
   3545             if ((cur_limit != 0) && (cur_limit != new_limit)) {
   3546                 soc_mem_field32_set(unit, mem, &pg_cfg, field[0], new_limit);
   3547                 SOC_IF_ERROR_RETURN
   3548                     (soc_tomahawk_xpe_mem_write(unit, mem, -1, -1,
   3549                                                 MEM_BLOCK_ALL, midx, &pg_cfg));
   3550             }
   3551         }
   3552     }
   3553 
   3554     /***********************************
   3555      * THDO
   3556  */
   3557 
   3558     /* per port UC queue */
   3559     numq = si->port_num_uc_cosq[port];
   3560     base = si->port_uc_cosq_base[port];
   3561     if (numq != 0) {
   3562         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
   3563         field[0] = Q_SHARED_LIMIT_CELLf;
   3564         field[1] = LIMIT_YELLOW_CELLf;
   3565         field[2] = LIMIT_RED_CELLf;
   3566 
   3567         for (idx = 0; idx < numq; idx++) {
   3568             midx = base + idx;
   3569             sal_memset(&cfg_queue, 0, sizeof(cfg_queue));
   3570             update = 0;
   3571 
   3572             SOC_IF_ERROR_RETURN
   3573                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &cfg_queue));
   3574 
   3575             granularity = 1;
   3576             new_limit = CEIL(thdo_db_shd_min, granularity);
   3577             cur_limit = soc_mem_field32_get(unit, mem, &cfg_queue, field[0]);
   3578             dynamic_q = soc_mem_field32_get(unit, mem, &cfg_queue,
   3579                                             Q_LIMIT_DYNAMIC_CELLf);
   3580             if ((new_limit != cur_limit) && !dynamic_q) {
   3581                 soc_mem_field32_set(unit, mem, &cfg_queue, field[0], new_limit);
   3582                 update = 1;
   3583             }
   3584 
   3585             granularity = 8;
   3586             new_limit = CEIL(thdo_db_shd_min, granularity);
   3587             cur_limit = soc_mem_field32_get(unit, mem, &cfg_queue, field[1]);
   3588             cur_limit1 = soc_mem_field32_get(unit, mem, &cfg_queue, field[2]);
   3589             dynamic_q = soc_mem_field32_get(unit, mem, &cfg_queue,
   3590                                             Q_COLOR_LIMIT_DYNAMIC_CELLf);
   3591             if (((new_limit != cur_limit) || (new_limit != cur_limit1)) &&
   3592                 !dynamic_q) {
   3593                 soc_mem_field32_set(unit, mem, &cfg_queue, field[1], new_limit);
   3594                 soc_mem_field32_set(unit, mem, &cfg_queue, field[2], new_limit);
   3595                 update = 1;
   3596             }
   3597 
   3598             if (update) {
   3599                 SOC_IF_ERROR_RETURN
   3600                     (soc_tomahawk_xpe_mem_write(unit, mem, -1, -1,
   3601                                                 MEM_BLOCK_ALL, midx,
   3602                                                 &cfg_queue));
   3603             }
   3604         }
   3605     }
   3606 
   3607     /* per port per MC queue */
   3608     numq = si->port_num_cosq[port];
   3609     base = si->port_cosq_base[port];
   3610     if (numq != 0) {
   3611         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
   3612         field[0] = Q_SHARED_LIMITf;
   3613         field[1] = YELLOW_SHARED_LIMITf;
   3614         field[2] = RED_SHARED_LIMITf;
   3615 
   3616         for (idx = 0; idx < numq; idx++) {
   3617             midx = base + idx;
   3618             sal_memset(&dbq_cfg, 0, sizeof(dbq_cfg));
   3619             update = 0;
   3620 
   3621             SOC_IF_ERROR_RETURN
   3622                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &dbq_cfg));
   3623 
   3624             granularity = 1;
   3625             new_limit = CEIL(thdo_db_shd_min, granularity);
   3626             cur_limit = soc_mem_field32_get(unit, mem, &dbq_cfg, field[0]);
   3627             dynamic_q = soc_mem_field32_get(unit, mem, &dbq_cfg,
   3628                                             Q_LIMIT_DYNAMICf);
   3629             if ((new_limit != cur_limit) && !dynamic_q) {
   3630                 soc_mem_field32_set(unit, mem, &dbq_cfg, field[0], new_limit);
   3631                 update = 1;
   3632             }
   3633 
   3634             granularity = 8;
   3635             new_limit = CEIL(thdo_db_shd_min, granularity);
   3636             cur_limit = soc_mem_field32_get(unit, mem, &dbq_cfg, field[1]);
   3637             cur_limit1 = soc_mem_field32_get(unit, mem, &dbq_cfg, field[2]);
   3638             dynamic_q = soc_mem_field32_get(unit, mem, &dbq_cfg,
   3639                                             Q_COLOR_LIMIT_DYNAMICf);
   3640             if (((new_limit != cur_limit) || (new_limit != cur_limit1)) &&
   3641                 !dynamic_q) {
   3642                 soc_mem_field32_set(unit, mem, &dbq_cfg, field[1], new_limit);
   3643                 soc_mem_field32_set(unit, mem, &dbq_cfg, field[2], new_limit);
   3644                 update = 1;
   3645             }
   3646 
   3647             if (update) {
   3648                 SOC_IF_ERROR_RETURN
   3649                     (soc_tomahawk_xpe_mem_write(unit, mem, -1, -1,
   3650                                                 MEM_BLOCK_ALL, midx,
   3651                                                 &dbq_cfg));
   3652             }
   3653         }
   3654 
   3655         /* MCQE - Queue */
   3656         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_MCQE_QUEUE_CONFIGm)[pipe];
   3657         field[0] = Q_SHARED_LIMITf;
   3658         field[1] = YELLOW_SHARED_LIMITf;
   3659         field[2] = RED_SHARED_LIMITf;
   3660         for (idx = 0; idx < numq; idx++) {
   3661             midx = base + idx;
   3662             sal_memset(&mcqe_cfg, 0, sizeof(mcqe_cfg));
   3663             update = 0;
   3664 
   3665             SOC_IF_ERROR_RETURN
   3666                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &mcqe_cfg));
   3667 
   3668             granularity = 4;
   3669             new_limit = CEIL(thdo_qe_shd_min, granularity);
   3670             cur_limit = soc_mem_field32_get(unit, mem, &mcqe_cfg, field[0]);
   3671             dynamic_q = soc_mem_field32_get(unit, mem, &mcqe_cfg,
   3672                                             Q_LIMIT_DYNAMICf);
   3673             if ((new_limit != cur_limit) && !dynamic_q) {
   3674                 soc_mem_field32_set(unit, mem, &mcqe_cfg, field[0], new_limit);
   3675                 update = 1;
   3676             }
   3677 
   3678             granularity = 8;
   3679             new_limit = CEIL(thdo_qe_shd_min, granularity);
   3680             cur_limit = soc_mem_field32_get(unit, mem, &mcqe_cfg, field[1]);
   3681             cur_limit1 = soc_mem_field32_get(unit, mem, &mcqe_cfg, field[2]);
   3682             dynamic_q = soc_mem_field32_get(unit, mem, &mcqe_cfg,
   3683                                             Q_COLOR_LIMIT_DYNAMICf);
   3684             if (((new_limit != cur_limit) || (new_limit != cur_limit1)) &&
   3685                 !dynamic_q) {
   3686                 soc_mem_field32_set(unit, mem, &mcqe_cfg, field[1], new_limit);
   3687                 soc_mem_field32_set(unit, mem, &mcqe_cfg, field[2], new_limit);
   3688                 update = 1;
   3689             }
   3690 
   3691             if (update) {
   3692                 SOC_IF_ERROR_RETURN
   3693                     (soc_tomahawk_xpe_mem_write(unit, mem, -1, -1,
   3694                                                 MEM_BLOCK_ALL, midx,
   3695                                                 &mcqe_cfg));
   3696             }
   3697         }
   3698     }
   3699 
   3700     return SOC_E_NONE;
   3701 }
   3702 
   3703 static int
   3704 _soc_th2_dpp_ratio_sel(int ratiox10)
   3705 {
   3706     switch (ratiox10) {
   3707     case 15:
   3708         /* core : dpp is 3:2 */
   3709         return 1;
   3710     case 20:
   3711         /* core : dpp is 2:1 */
   3712         return 2;
   3713     case 10:
   3714         /* core : dpp is 1:1 */
   3715         return 3;
   3716     default:
   3717         return 1;
   3718     }
   3719 }
   3720 
   3721 /*
   3722  * Recommended Min. Slot Pipeline Latency Value
   3723  * CORE/DPP Ratio (R) |  Modes
   3724  * --------------------------------------------
   3725  *	              |  FULL | L2+L3 | L2
   3726  * --------------------------------------------
   3727  *          1         |  189  | 144   |  85
   3728  * --------------------------------------------
   3729  *          1.5       |  309  | 241   | 153
   3730  * --------------------------------------------
   3731  *          2         |  423  | 333   | 215
   3732  * --------------------------------------------
   3733  */
   3734 int
   3735 soc_th2_slot_pipeline_latency_get(int dpp_ratio_x10, int lmode)
   3736 {
   3737     int dpr_id;
   3738     int latency[3][3] = {
   3739         {189, 144,  85},
   3740         {309, 241, 153},
   3741         {423, 333, 215},
   3742     };
   3743 
   3744     dpr_id = (dpp_ratio_x10 == 20 ? 2 : 
   3745              (dpp_ratio_x10 == 15 ? 1 : 0));
   3746 
   3747     if ((lmode > SOC_SWITCH_BYPASS_MODE_LOW) || 
   3748         (lmode < SOC_SWITCH_BYPASS_MODE_NONE)) {
   3749          lmode = SOC_SWITCH_BYPASS_MODE_NONE;
   3750     }
   3751 
   3752     return latency[dpr_id][lmode];
   3753 }
   3754 
   3755 STATIC int
   3756 _soc_tomahawk2_init_ipep_memory(int unit)
   3757 {
   3758     uint32 pipe_map;
   3759     soc_reg_t reg;
   3760     int pipe, count;
   3761     uint32 rval, in_progress;
   3762     int pipe_init_usec;
   3763     soc_timeout_t to;
   3764 
   3765     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   3766 
   3767     /* Initial IPIPE memory */
   3768     rval = 0;
   3769     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval));
   3770     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   3771     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   3772     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 0);
   3773     /* Set count to # entries of largest IPIPE table */
   3774     count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm);
   3775     if (count < soc_mem_index_count(unit, L2Xm)) {
   3776         count = soc_mem_index_count(unit, L2Xm);
   3777     }
   3778     if (count < soc_mem_index_count(unit, L3_ENTRY_ONLYm)) {
   3779         count = soc_mem_index_count(unit, L3_ENTRY_ONLYm);
   3780     }
   3781     if (count < soc_mem_index_count(unit, FPEM_ECCm)) {
   3782         count = soc_mem_index_count(unit, FPEM_ECCm);
   3783     }
   3784     if (count < soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   3785         count = soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m);
   3786     }
   3787     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, count);
   3788     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3789 
   3790     /* Initial EPIPE memory */
   3791     rval = 0;
   3792     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval));
   3793     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   3794     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   3795     /* Set count to # entries in largest EPIPE table (EGR_L3_NEXT_HOP) */
   3796     count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   3797     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
   3798     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   3799 
   3800     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   3801     if (SAL_BOOT_SIMULATION) {
   3802         pipe_init_usec = 10000000;
   3803     } else {
   3804         pipe_init_usec = 50000;
   3805     }
   3806     soc_timeout_init(&to, pipe_init_usec, 0);
   3807 
   3808     /* Wait for IPIPE memory initialization done */
   3809     in_progress = pipe_map;
   3810     do {
   3811         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV && in_progress; pipe++) {
   3812             reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   3813             if (in_progress & (1 << pipe)) { /* not done yet */
   3814                 SOC_IF_ERROR_RETURN
   3815                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3816                 if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3817                     in_progress ^= (1 << pipe);
   3818                 }
   3819             }
   3820         }
   3821         if (soc_timeout_check(&to)) {
   3822             LOG_WARN(BSL_LS_SOC_COMMON,
   3823                      (BSL_META_U(unit,
   3824                                  "unit %d : ING_HW_RESET timeout\n"), unit));
   3825             break;
   3826         }
   3827     } while (in_progress != 0);
   3828 
   3829     /* Wait for EPIPE memory initialization done */
   3830     in_progress = pipe_map;
   3831     do {
   3832         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV && in_progress; pipe++) {
   3833             reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe];
   3834             if (in_progress & (1 << pipe)) { /* not done yet */
   3835                 SOC_IF_ERROR_RETURN
   3836                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3837                 if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3838                     in_progress ^= (1 << pipe);
   3839                 }
   3840             }
   3841         }
   3842         if (soc_timeout_check(&to)) {
   3843             LOG_WARN(BSL_LS_SOC_COMMON,
   3844                      (BSL_META_U(unit,
   3845                                  "unit %d : EGR_HW_RESET timeout\n"), unit));
   3846             break;
   3847         }
   3848     } while (in_progress != 0);
   3849 
   3850     rval = 0;
   3851     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3852     rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo;
   3853     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   3854 
   3855     return SOC_E_NONE;
   3856 }
   3857 
   3858 static int
   3859 _soc_tomahawk2_clear_l2_mod_fifo(int unit) {
   3860     uint32 rval;
   3861     sal_usecs_t clear_l2mod_usec, sleep_usec = 10000;
   3862     soc_timeout_t to;
   3863     soc_reg_t reg;
   3864     int count;
   3865     /* Initial L2_MGT memories */
   3866     rval = 0;
   3867     SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_0r(unit, rval));
   3868     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   3869     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   3870     count = soc_mem_index_count(unit, L2_MOD_FIFOm);
   3871     if (count < soc_mem_index_count(unit, L2_MGMT_SER_FIFOm)) {
   3872         count = soc_mem_index_count(unit, L2_MGMT_SER_FIFOm);
   3873     }
   3874     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
   3875     SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, rval));
   3876 
   3877     if (SAL_BOOT_SIMULATION) {
   3878         clear_l2mod_usec = 1000000;
   3879     } else {
   3880         clear_l2mod_usec = 500000;
   3881     }
   3882     soc_timeout_init(&to, clear_l2mod_usec, 0);
   3883     do {
   3884         sal_usleep(sleep_usec);
   3885         /* Make sure L2_MGMT memories are all clean */
   3886         reg = L2_MGMT_HW_RESET_CONTROL_1r;
   3887         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3888         if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3889             return WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, 0);
   3890         }
   3891 
   3892         if (soc_timeout_check(&to)) {
   3893             break;
   3894         }
   3895     } while (1);
   3896 
   3897     LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   3898         "unit %d : L2_MGMT_HW_RESET not done (reg val: 0x%x) !! \n"),
   3899         unit, rval));
   3900 
   3901     return SOC_E_TIMEOUT;
   3902 }
   3903 
   3904 STATIC int
   3905 _soc_tomahawk2_init_idb_memory(int unit)
   3906 {
   3907     uint32 pipe_map;
   3908     soc_reg_t reg;
   3909     int pipe;
   3910     uint32 rval, in_progress;
   3911     int pipe_init_usec;
   3912     soc_timeout_t to;
   3913 
   3914     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   3915 
   3916     /* Initialize IDB memory */
   3917     rval = 0;
   3918     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   3919     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   3920     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 1);
   3921     
   3922     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x100);
   3923     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3924 
   3925     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   3926     if (SAL_BOOT_SIMULATION) {
   3927         pipe_init_usec = 10000000;
   3928     } else {
   3929         pipe_init_usec = 50000;
   3930     }
   3931     soc_timeout_init(&to, pipe_init_usec, 0);
   3932 
   3933     /* Wait for IDB memory initialization done */
   3934     in_progress = pipe_map;
   3935     do {
   3936         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV && in_progress; pipe++) {
   3937             reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   3938             if (in_progress & (1 << pipe)) { /* not done yet */
   3939                 SOC_IF_ERROR_RETURN
   3940                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3941                 if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3942                     in_progress ^= (1 << pipe);
   3943                 }
   3944             }
   3945         }
   3946         if (soc_timeout_check(&to)) {
   3947             LOG_WARN(BSL_LS_SOC_COMMON,
   3948                      (BSL_META_U(unit,
   3949                                  "unit %d : ING_HW_RESET timeout\n"), unit));
   3950             break;
   3951         }
   3952     } while (in_progress != 0);
   3953     rval = 0;
   3954     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 1);
   3955     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3956 
   3957     return SOC_E_NONE;
   3958 }
   3959 
   3960 int
   3961 soc_tomahawk2_init_mmu_memory(int unit)
   3962 {
   3963     uint32 rval = 0;
   3964 
   3965     /* Initialize MMU memory */
   3966     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0));
   3967     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, PARITY_ENf, 1);
   3968     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 1);
   3969     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   3970     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 0);
   3971     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   3972     sal_usleep(20);
   3973     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, PARITY_ENf, 0);
   3974     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   3975 
   3976     return SOC_E_NONE;
   3977 }
   3978 
   3979 int
   3980 soc_tomahawk2_clear_mmu_memory(int unit)
   3981 {
   3982 #define SOC_MMU_BASE_TYPE_IPORT 0
   3983 #define SOC_MMU_BASE_TYPE_EPORT 1
   3984 #define SOC_MMU_BASE_TYPE_IPIPE 2
   3985 #define SOC_MMU_BASE_TYPE_EPIPE 3
   3986 #define SOC_MMU_BASE_TYPE_CHIP 4
   3987 #define SOC_MMU_BASE_TYPE_XPE 5
   3988 #define SOC_MMU_BASE_TYPE_SC 6
   3989 #define SOC_MMU_BASE_TYPE_LAYER 7
   3990     int i, j, use_base_type_views, base_type, index, num_views;
   3991     uint32 entry[SOC_MAX_MEM_WORDS];
   3992     soc_mem_t mem;
   3993     static const struct {
   3994         soc_mem_t mem; /* base view */
   3995         int use_base_type_views; /* 1 means use xpe/sc/etc views */
   3996         int index; /* -1 means clear entire mem */
   3997     } mem_list[] = {
   3998         { MMU_CBPDATA0m, 1, 0 },
   3999         { MMU_CBPDATA1m, 1, 0 },
   4000         { MMU_CBPDATA2m, 1, 0 },
   4001         { MMU_CBPDATA3m, 1, 0 },
   4002         { MMU_CBPDATA4m, 1, 0 },
   4003         { MMU_CBPDATA5m, 1, 0 },
   4004         { MMU_CBPDATA6m, 1, 0 },
   4005         { MMU_CBPDATA7m, 1, 0 },
   4006         { INVALIDm, 0, -1 }
   4007     };
   4008     for (i = 0; mem_list[i].mem != INVALIDm; i++) {
   4009         mem = mem_list[i].mem;
   4010         index = mem_list[i].index;
   4011         use_base_type_views = mem_list[i].use_base_type_views;
   4012         if (use_base_type_views) {
   4013             base_type = soc_tomahawk_mem_basetype_get(unit, mem);
   4014             switch (base_type) {
   4015             case SOC_MMU_BASE_TYPE_XPE:
   4016                 num_views = NUM_XPE(unit);
   4017                 break;
   4018             case SOC_MMU_BASE_TYPE_SC:
   4019                 num_views = NUM_SLICE(unit);
   4020                 break;
   4021             case SOC_MMU_BASE_TYPE_LAYER:
   4022                 num_views = NUM_LAYER(unit);
   4023                 break;
   4024             case SOC_MMU_BASE_TYPE_IPIPE:
   4025             case SOC_MMU_BASE_TYPE_EPIPE:
   4026                 num_views = NUM_PIPE(unit);
   4027                 break;
   4028             default:
   4029                 num_views = -1; /* not supported */
   4030                 break;
   4031             }
   4032             if (num_views < 0) {
   4033                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4034                           (BSL_META_U(unit,
   4035                                       "mmu_mem %s, base_type %d will not be"
   4036                                       "cleared \n"),
   4037                            SOC_MEM_NAME(unit,mem), base_type));
   4038                 continue;
   4039             }
   4040         } else {
   4041             num_views = 0; /* dont_care */
   4042         }
   4043 
   4044         sal_memset(entry, 0x0,
   4045                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   4046         if (use_base_type_views) {
   4047             for (j = 0; j < num_views; j++) {
   4048                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4049                             (BSL_META_U(unit,
   4050                                         "mmu_mem %s, index %d will be "
   4051                                         "cleared \n"),
   4052                             SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]),
   4053                             index));
   4054                 if (index >= 0) {
   4055                     SOC_IF_ERROR_RETURN
   4056                         (soc_mem_write(unit,
   4057                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   4058                                        MEM_BLOCK_ALL, index, entry));
   4059                 } else {
   4060                     SOC_IF_ERROR_RETURN
   4061                         (soc_mem_clear(unit,
   4062                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   4063                                        COPYNO_ALL, TRUE));
   4064                 }
   4065             }
   4066         } else {
   4067             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4068                         (BSL_META_U(unit,
   4069                                     "mmu_mem %s, index %d will be "
   4070                                     "cleared \n"),
   4071                         SOC_MEM_NAME(unit, mem), index));
   4072             if (index >= 0) {
   4073                 SOC_IF_ERROR_RETURN
   4074                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   4075                                    entry));
   4076             } else {
   4077                 SOC_IF_ERROR_RETURN
   4078                     (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE));
   4079             }
   4080         }
   4081     }
   4082     return SOC_E_NONE;
   4083 }
   4084 
   4085 int
   4086 soc_tomahawk2_clear_enabled_port_data (int unit)
   4087 {
   4088     uint64 rval64;
   4089     int    port;
   4090 
   4091     /* Some registers are implemented in memory, need to clear them in order
   4092      * to have correct parity value */
   4093     COMPILER_64_ZERO(rval64);
   4094     PBMP_ALL_ITER(unit, port) {
   4095         if (SOC_REG_IS_VALID(unit, EGR_1588_LINK_DELAY_64r)) {
   4096             SOC_IF_ERROR_RETURN(WRITE_EGR_1588_LINK_DELAY_64r(unit, port, rval64));
   4097         }
   4098     }
   4099 
   4100     return SOC_E_NONE;
   4101 }
   4102 
   4103 /*
   4104  * FUNCTION : soc_th2_bypass_unused_pm
   4105  * ARGS:
   4106  *         unit    -    IN, unit number
   4107  * Description :
   4108  * Bypass unused port blocks, by programming TOP_TSC_ENABLEr and TOP_TSC_ENABLE_1r
   4109  * appropriately.
   4110  */
   4111 soc_error_t
   4112 soc_th2_bypass_unused_pm(int unit)
   4113 {
   4114     int port, phy_port, pm, block, bn, i, port_macro;
   4115     uint32 rval = 0, orval, xrval;
   4116     soc_info_t *si = &SOC_INFO(unit);
   4117     uint8 used_pm_map[_TH2_PBLKS_PER_DEV + 1]; /* #CLPORT + #XLPORT */
   4118     soc_reg_t reg[2] = {TOP_TSC_ENABLEr, TOP_TSC_ENABLE_1r};
   4119     soc_field_t reg_field[_TH2_PBLKS_PER_DEV] = {
   4120         TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf,
   4121         TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf,
   4122         TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf,
   4123         TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf,
   4124         TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf,
   4125         TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf,
   4126         TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf,
   4127         TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf,
   4128         TSC_32_ENABLEf, TSC_33_ENABLEf, TSC_34_ENABLEf, TSC_35_ENABLEf,
   4129         TSC_36_ENABLEf, TSC_37_ENABLEf, TSC_38_ENABLEf, TSC_39_ENABLEf,
   4130         TSC_40_ENABLEf, TSC_41_ENABLEf, TSC_42_ENABLEf, TSC_43_ENABLEf,
   4131         TSC_44_ENABLEf, TSC_45_ENABLEf, TSC_46_ENABLEf, TSC_47_ENABLEf,
   4132         TSC_48_ENABLEf, TSC_49_ENABLEf, TSC_50_ENABLEf, TSC_51_ENABLEf,
   4133         TSC_52_ENABLEf, TSC_53_ENABLEf, TSC_54_ENABLEf, TSC_55_ENABLEf,
   4134         TSC_56_ENABLEf, TSC_57_ENABLEf, TSC_58_ENABLEf, TSC_59_ENABLEf,
   4135         TSC_60_ENABLEf, TSC_61_ENABLEf, TSC_62_ENABLEf, TSC_63_ENABLEf
   4136     };
   4137 
   4138     sal_memset(used_pm_map, 0, sizeof(used_pm_map));
   4139     for (phy_port = 1; phy_port <= _TH2_PORTS_PER_DEV; phy_port++) {
   4140         port = si->port_p2l_mapping[phy_port];
   4141         if (port > 0) {
   4142             pm = si->port_serdes[port];
   4143             if ((-1 != pm) && (0 == used_pm_map[pm])) {
   4144                 used_pm_map[pm] = 1;
   4145             }
   4146         }
   4147     }
   4148 
   4149     for (i = 0; i < 2; i++) {
   4150         SOC_IF_ERROR_RETURN(
   4151             soc_reg32_get(unit, reg[i], REG_PORT_ANY, 0, &rval));
   4152         orval = rval;
   4153         /* Upper loop bound omits XLPORT block intentionally */
   4154         for (port_macro = 0; port_macro < _TH2_PBLKS_PER_DEV / 2; port_macro++) {
   4155             pm = port_macro + 32 * i;
   4156             /* In Tomahawk2, there are 8 port macros (clport 6,7,24,25,38,39,56,57 )that
   4157              * will driven directly from the system board and they will act as the
   4158              * refclk master to drive the other instances.
   4159              */
   4160             if ((pm == 6 || pm == 7 || pm == 24 || pm == 25 ||
   4161               pm == 38 ||pm == 39 || pm == 56 || pm == 57)) {
   4162                 continue;
   4163             }
   4164             /* If PM is not used, bypass it */
   4165             if (0 == used_pm_map[pm]) {
   4166                 soc_reg_field_set(unit, reg[i], &rval, reg_field[pm], 0);
   4167                 phy_port = 1 + (pm * _TH_PORTS_PER_PBLK);
   4168                 block = SOC_PORT_BLOCK(unit, phy_port);
   4169                 /* Invalidate port block in soc info */
   4170                 if (SOC_BLK_CLPORT == SOC_BLOCK_INFO(unit, block).type) {
   4171                     si->block_valid[block] = 0;
   4172                 }
   4173             }
   4174         }
   4175         if (rval != orval) {
   4176             /*Calculate different bits number between old and new*/
   4177             xrval = rval ^ orval;
   4178             for (bn = 0; xrval != 0; bn++) {
   4179                 xrval &= (xrval - 1);
   4180             }
   4181 
   4182             /*Do two steps configuration change for the case of different bits number beyond 10*/
   4183             if (bn > 10) {
   4184                 /*Change half of those different bits to new at first*/
   4185                 bn /= 2;
   4186                 xrval = rval ^ orval;
   4187                 do {
   4188                     xrval &= (xrval-1);
   4189                 } while (bn-- > 0);
   4190                 xrval ^= rval;
   4191                 SOC_IF_ERROR_RETURN(
   4192                     soc_reg32_set(unit, reg[i], REG_PORT_ANY, 0, xrval));
   4193                 sal_usleep(100000);
   4194             }
   4195             SOC_IF_ERROR_RETURN(
   4196                     soc_reg32_set(unit, reg[i], REG_PORT_ANY, 0, rval));
   4197             sal_usleep(100000);
   4198         }
   4199     }
   4200 
   4201     return SOC_E_NONE;
   4202 }
   4203 
   4204 void
   4205 soc_tomahawk2_sbus_ring_map_config(int unit)
   4206 {
   4207     /*
   4208      * SBUS ring and block number:
   4209      * ring 0: IP(1), LBPORT0(79), LBPORT1(80), LBPORT2(81), LBPORT3(82)
   4210      * ring 1: EP(2)
   4211      * ring 2: MMU_XPE(3), MMU_SC(4), MMU_GLB(5), MMU_SED(12)
   4212      * ring 3: PM64XLPORT0(11), PM0(15), PM1(16), PM2(17), PM3(18), PM4(19), PM5(20), 
   4213      *         PM6(21), PM7(22), PM8(23), PM9(24), PM10(25), PM11(26), PM12(27),
   4214      *         PM13(28), PM14(29), PM15(30), PM16(31), PM17(32), PM18(33), PM19(34), 
   4215      *         PM20(35), PM21(36), PM22(37), PM23(38), PM24(39), PM25(40), PM26(41), 
   4216      *         PM27(42), PM28(43), PM29(44), PM30(45), PM31(46), CLPORT64(83)
   4217      * ring 4: PM32(47), PM33(48), PM34(49), PM35(50), PM36(51),
   4218      *         PM37(52), PM38(53), PM39(54), PM40(55), PM41(56), PM42(57), PM43(58),
   4219      *         PM44(59), PM45(60), PM46(61), PM47(62), PM48(63), PM49(64), PM50(65),
   4220      *         PM51(66), PM52(67), PM53(68), PM54(69), PM55(70), PM56(71), PM57(72),
   4221      *         PM58(73), PM59(74), PM60(75), PM61(76), PM62(77), PM63(78)
   4222      * ring 5: OTPC(6), OTPC1(13), AVS(87), TOP(7), SER(8)
   4223      */
   4224     WRITE_CMIC_SBUS_RING_MAP_0_7r(unit, 0x55222100);
   4225     WRITE_CMIC_SBUS_RING_MAP_8_15r(unit, 0x30523005);
   4226     WRITE_CMIC_SBUS_RING_MAP_16_23r(unit, 0x33333333);
   4227     WRITE_CMIC_SBUS_RING_MAP_24_31r(unit, 0x33333333);
   4228     WRITE_CMIC_SBUS_RING_MAP_32_39r(unit, 0x33333333);
   4229     WRITE_CMIC_SBUS_RING_MAP_40_47r(unit, 0x43333333);
   4230     WRITE_CMIC_SBUS_RING_MAP_48_55r(unit, 0X44444444);
   4231     WRITE_CMIC_SBUS_RING_MAP_56_63r(unit, 0x44444444);
   4232     WRITE_CMIC_SBUS_RING_MAP_64_71r(unit, 0x44444444);
   4233     WRITE_CMIC_SBUS_RING_MAP_72_79r(unit, 0x04444444);
   4234     WRITE_CMIC_SBUS_RING_MAP_80_87r(unit, 0x50003000);
   4235 #ifdef FW_BCAST_DOWNLOAD
   4236     /*
   4237      * program SBUS agent with SBUS ID 126 to SBUS ring 3, SBUS ring 3 use 126 as its broadcast ID
   4238      * program SBUS agent with SBUS ID 125 to SBUS ring 4, SBUS ring 4 use 125 as its broadcast ID
   4239      */
   4240     WRITE_CMIC_SBUS_RING_MAP_120_127r(unit, 0x03400000);
   4241 #endif
   4242     if (!SAL_BOOT_QUICKTURN) {
   4243         WRITE_CMIC_SBUS_TIMEOUTr(unit, 0x1000);
   4244     }
   4245 
   4246     return;
   4247 }
   4248 
   4249 int
   4250 soc_tomahawk2_chip_reset(int unit)
   4251 {
   4252 #define _SOC_TH2_PLL_CFG_FIELDS 4
   4253 #define _SOC_TH2_BSPLL_COUNT    2
   4254 #define _SOC_TH2_HW_TEMP_MAX       125
   4255 #define _SOC_TH2_DEF_SW_TEMP_MAX   110
   4256 
   4257     soc_info_t *si;
   4258     soc_reg_t reg;
   4259     int freq_sel, max_freq_sel, def_freq_sel, freq_list_len, max_freq, def_freq;
   4260     int def_dpp_ratio_x10, ratio_sel, ratio_list_len, field_count, pipe;
   4261     uint32 to_usec, rval;
   4262     uint32 sw_temp_mask, hw_temp_mask, temp_thr, sw_temp_thr, hw_temp_thr;
   4263     soc_field_t fields[_SOC_TH2_PLL_CFG_FIELDS];
   4264     uint32 values[_SOC_TH2_PLL_CFG_FIELDS];
   4265     int num_banks, index, shared_bank, shared_bank_offset = 0;
   4266     int num_shared_l2_banks, num_shared_l3_banks, num_shared_fpem_banks;
   4267     uint32 config = 0, map = 0, fpmap = 0;
   4268     uint32 pipe_map;
   4269     int parity_enable;
   4270     int num_share_banks_enabled = 4;
   4271     int share_banks_bitmap_enabled = 0xf;    
   4272     static soc_field_t l2_fields[] = {
   4273         L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
   4274         L2_ENTRY_BANK_5f
   4275     };
   4276     static soc_field_t l3_fields[] = {
   4277         L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f,
   4278         L3_ENTRY_BANK_7f
   4279     };
   4280     static soc_field_t fpem_fields[] = {
   4281         FPEM_ENTRY_BANK_0f, FPEM_ENTRY_BANK_1f, FPEM_ENTRY_BANK_2f,
   4282         FPEM_ENTRY_BANK_3f
   4283     };
   4284     static const soc_reg_t bspll_status_reg[] = {
   4285         TOP_BS_PLL0_STATUSr, TOP_BS_PLL1_STATUSr,
   4286     };
   4287     static const soc_reg_t temp_thr_reg[] = {
   4288         TOP_PVTMON_0_INTR_THRESHOLDr, TOP_PVTMON_1_INTR_THRESHOLDr,
   4289         TOP_PVTMON_2_INTR_THRESHOLDr, TOP_PVTMON_3_INTR_THRESHOLDr,
   4290         TOP_PVTMON_4_INTR_THRESHOLDr, TOP_PVTMON_5_INTR_THRESHOLDr,
   4291         TOP_PVTMON_6_INTR_THRESHOLDr, TOP_PVTMON_7_INTR_THRESHOLDr
   4292     };
   4293     static const char *temp_thr_prop[] = {
   4294         "temp0_threshold", "temp1_threshold", "temp2_threshold",
   4295         "temp3_threshold", "temp4_threshold", "temp5_threshold",
   4296         "temp6_threshold", "temp7_threshold"
   4297     };
   4298     static const int freq_list[] = { 1700, 1625, 1525, 1425, 1325, 1275,
   4299                                      1225, 1125, 1050, 950, 850 };
   4300     static const int dpp_ratio_x10_list[] = {
   4301         15, /* core clk : pp clk ratio is 3:2 (default) */
   4302         20, /* core clk : pp clk ratio is 2:1 */
   4303         10  /* core clk : pp clk ratio is 1:1 */
   4304     };
   4305     const char *ratio_str[] = {"2:3", "1:2", "1:1"};
   4306     uint16 dev_id;
   4307     uint8 rev_id;
   4308     
   4309 
   4310    /* Settings for 500 MHz TSPLL output clock. */
   4311     unsigned ts_ref_freq = 0;
   4312     unsigned ts_idx = 0;
   4313 
   4314     static const soc_pll_param_t ts_pll[] = {
   4315     /*     Fref, Ndiv_int, Ndiv_frac,  Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */
   4316       {25000000,      100,         0,     1,    5, 10,  3, 10,       1},
   4317       {50000000,      100,         0,     2,    5, 10,  3, 10,       1}, /* 50 MHz external reference. */
   4318       {       0,      100,         0,     2,    5, 10,  3, 10,       1} /* 50 MHz internal reference. */
   4319     };
   4320 
   4321     /* Settings for 20 MHz BSPLL output clock. */
   4322     unsigned bs_ref_freq = 0;
   4323     unsigned bs_idx = 0;
   4324 
   4325     static const soc_pll_param_t bs_pll[] = {
   4326     /*     Fref, Ndiv_int, Ndiv_frac,  Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */
   4327       {12800000,      195,   0x50000,     1,  125, 10,  3, 10,      1},
   4328       {20000000,      125,         0,     1,  125, 10,  3, 10,      1},
   4329       {25000000,      100,         0,     1,  125, 10,  3, 10,      1},
   4330       {32000000,       78,   0x20000,     1,  125, 10,  3, 10,      1},
   4331       {50000000,      100,         0,     2,  125, 10,  3, 10,      1},
   4332       {       0,      100,         0,     2,  125, 10,  3, 10,      1} /* 50 MHz internal reference. */
   4333     };
   4334 
   4335     si = &SOC_INFO(unit);
   4336     soc_cm_get_id(unit, &dev_id, &rev_id);
   4337     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
   4338                                    (10 * MILLISECOND_USEC);
   4339 
   4340     soc_tomahawk2_sbus_ring_map_config(unit);
   4341 
   4342     sal_usleep(to_usec);
   4343 
   4344     field_count = 0;
   4345 
   4346     /* Core frequency */
   4347     SOC_IF_ERROR_RETURN
   4348         (soc_tomahawk2_frequency_get(unit, &max_freq, &def_freq));
   4349     max_freq_sel = 0;
   4350     def_freq_sel = 0;
   4351     freq_list_len = COUNTOF(freq_list);
   4352     for (freq_sel = 0; freq_sel < freq_list_len; freq_sel++) {
   4353         if (max_freq == freq_list[freq_sel]) {
   4354             max_freq_sel = freq_sel;
   4355         }
   4356         if (def_freq == freq_list[freq_sel]) {
   4357             def_freq_sel = freq_sel;
   4358         }
   4359     }
   4360     if ((si->frequency != def_freq) && (si->frequency < max_freq)) {
   4361         for (freq_sel = max_freq_sel + 1; freq_sel < freq_list_len;
   4362              freq_sel++) {
   4363             if (si->frequency == freq_list[freq_sel]) {
   4364                 break;
   4365             }
   4366         }
   4367         if (freq_sel < freq_list_len) {
   4368             LOG_CLI((BSL_META_U(unit,
   4369                                 "*** change core clock frequency to %dMHz\n"),
   4370                                 si->frequency));
   4371             fields[field_count] = CORE_CLK_0_FREQ_SELf;
   4372             values[field_count] = freq_sel;
   4373             field_count++;
   4374         }
   4375     }
   4376 
   4377     if (soc_feature(unit, soc_feature_untethered_otp)) {
   4378         def_dpp_ratio_x10 = SOC_BOND_INFO(unit)->dpp_clk_ratio;
   4379     } else {
   4380         def_dpp_ratio_x10 = dpp_ratio_x10_list[0];
   4381     }
   4382 
   4383     /* DPP ratio */
   4384     if (si->dpp_clk_ratio_x10 != def_dpp_ratio_x10) {
   4385         ratio_list_len = COUNTOF(dpp_ratio_x10_list);
   4386         for (ratio_sel = 1; ratio_sel < ratio_list_len; ratio_sel++) {
   4387             if (si->dpp_clk_ratio_x10 == dpp_ratio_x10_list[ratio_sel]) {
   4388                 break;
   4389             }
   4390         }
   4391         if (ratio_sel < ratio_list_len) {
   4392             LOG_CLI((BSL_META_U(unit,
   4393                                 "*** change dpp_clk : core_clk ratio to %s\n"),
   4394                                 ratio_str[ratio_sel]));
   4395             ratio_sel = _soc_th2_dpp_ratio_sel(si->dpp_clk_ratio_x10);
   4396             fields[field_count] = DPP_CLK_RATIO_SELf;
   4397             values[field_count] = ratio_sel;
   4398             field_count++;
   4399         }
   4400     }
   4401     if (field_count) {
   4402         fields[field_count] = SW_CORE_CLK_0_SEL_ENf;
   4403         values[field_count] = 1;
   4404         field_count++;
   4405         SOC_IF_ERROR_RETURN
   4406             (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr, REG_PORT_ANY,
   4407                                     field_count, fields, values));
   4408         sal_usleep(to_usec);
   4409     } else {
   4410         /* Set correct frequency in non OTP'd SKUs */
   4411         SOC_IF_ERROR_RETURN(READ_TOP_DEV_REV_IDr(unit, &rval));
   4412         if (!(soc_reg_field_get(unit, TOP_DEV_REV_IDr, rval, DEVICE_SKEWf) & 0x8)) {
   4413             LOG_CLI((BSL_META_U(unit,
   4414                                 "*** change core clock frequency to %dMHz, "
   4415                                 "change dpp ratio to %s\n"),
   4416                                 def_freq, "2:3"));
   4417             field_count = 0;
   4418             fields[field_count] = CORE_CLK_0_FREQ_SELf;
   4419             values[field_count] = def_freq_sel;
   4420             field_count++;
   4421 
   4422             ratio_sel = _soc_th2_dpp_ratio_sel(dpp_ratio_x10_list[0]);
   4423             fields[field_count] = DPP_CLK_RATIO_SELf;
   4424             values[field_count] = ratio_sel;
   4425             field_count++;
   4426 
   4427             fields[field_count] = SW_CORE_CLK_0_SEL_ENf;
   4428             values[field_count] = 1;
   4429             field_count++;
   4430             SOC_IF_ERROR_RETURN
   4431                 (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr,
   4432                                     REG_PORT_ANY, field_count, fields, values));
   4433             sal_usleep(to_usec);
   4434         }
   4435     }
   4436 
   4437     /* Configure TS PLL */
   4438     ts_ref_freq = soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0);  /* 0->internal reference */
   4439 
   4440     for (ts_idx = 0; ts_idx < sizeof(ts_pll)/sizeof(ts_pll[0]); ++ts_idx) {
   4441         if (ts_pll[ts_idx].ref_freq == ts_ref_freq) {
   4442             break;
   4443         }
   4444     }
   4445 
   4446     if (ts_idx == sizeof(ts_pll)/sizeof(ts_pll[0])) {
   4447         /* Valid configuration lookup failed. Use internal reference. */
   4448         ts_idx = 5;
   4449         ts_ref_freq = 0;
   4450     }
   4451 
   4452     /* Do not change PLL settings for internal reference */
   4453     if(ts_ref_freq) {
   4454         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_3r(unit, &rval));
   4455         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_3r, &rval, REFCLK_SOURCE_SELf, (ts_ref_freq != 0));
   4456         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_3r(unit, rval));
   4457 
   4458         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_0r(unit,&rval));
   4459         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_0r, &rval, CH0_MDIVf,
   4460                           soc_property_get(unit, spn_PTP_TS_PLL_MNDIV, ts_pll[ts_idx].mdiv));
   4461         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_0r(unit, rval));
   4462 
   4463 
   4464         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit,&rval));
   4465         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, PDIVf,
   4466                           soc_property_get(unit, spn_PTP_TS_PLL_PDIV, ts_pll[ts_idx].pdiv));
   4467         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, NDIV_INTf,
   4468                           soc_property_get(unit, spn_PTP_TS_PLL_N, ts_pll[ts_idx].ndiv_int));
   4469         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval));
   4470 
   4471 
   4472         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_2r(unit,&rval));
   4473         /* TBD */
   4474         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_2r(unit, rval));
   4475 
   4476         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_4r(unit,&rval));
   4477         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KAf,
   4478                           soc_property_get(unit, spn_PTP_TS_KA, ts_pll[ts_idx].ka));
   4479         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KIf,
   4480                           soc_property_get(unit, spn_PTP_TS_KI, ts_pll[ts_idx].ki));
   4481         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KPf,
   4482                           soc_property_get(unit, spn_PTP_TS_KP, ts_pll[ts_idx].kp));
   4483         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_4r(unit, rval));
   4484     }
   4485 
   4486     /* Set 250Mhz (implies 4ns resolution) default timesync clock to
   4487        calculate assymentric delays */
   4488     SOC_TIMESYNC_PLL_CLOCK_NS(unit) = (1/250 * 1000); /* clock period in nanoseconds */
   4489 
   4490     /* Configure BroadSync PLLs. */
   4491     bs_ref_freq = soc_property_get(unit, spn_PTP_BS_FREF, 0);  /* 0->internal reference */
   4492     
   4493     for (bs_idx = 0; bs_idx < sizeof(bs_pll)/sizeof(bs_pll[0]); ++bs_idx) {
   4494         if (bs_pll[bs_idx].ref_freq == bs_ref_freq) {
   4495             break;
   4496         }
   4497     }
   4498     if (bs_idx == sizeof(bs_pll)/sizeof(bs_pll[0])) {
   4499         /* Valid configuration lookup failed. Use internal reference. */
   4500         bs_idx = 5;
   4501         bs_ref_freq = 0;
   4502     }
   4503 
   4504     if (bs_ref_freq) {
   4505         /* PLL settings for external reference */
   4506         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_3r(unit, &rval));
   4507         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_3r, &rval, REFCLK_SOURCE_SELf, (bs_ref_freq != 0));
   4508         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_3r(unit, rval));
   4509 
   4510         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_0r(unit, &rval));
   4511         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_0r, &rval, CH0_MDIVf,
   4512                           soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv));
   4513         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_0r(unit, rval));
   4514 
   4515         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval));
   4516         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, PDIVf,
   4517                           soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv));
   4518         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, NDIV_INTf,
   4519                           soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int));
   4520         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval));
   4521 
   4522         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_2r(unit, &rval));
   4523         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_2r(unit, rval));
   4524 
   4525         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_4r(unit, &rval));
   4526         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KAf,
   4527                           soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka));
   4528         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KIf,
   4529                           soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki));
   4530         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KPf,
   4531                           soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp));
   4532         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_4r(unit, rval));
   4533 
   4534     /* Configure BS PLL1 */
   4535         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_3r(unit, &rval));
   4536         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_3r, &rval, REFCLK_SOURCE_SELf, (bs_ref_freq != 0));
   4537         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_3r(unit, rval));
   4538 
   4539         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_0r(unit, &rval));
   4540         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_0r, &rval, CH0_MDIVf,
   4541                           soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv));
   4542         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_0r(unit, rval));
   4543 
   4544         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval));
   4545         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, PDIVf,
   4546                           soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv));
   4547         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, NDIV_INTf,
   4548                           soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int));
   4549         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval));
   4550 
   4551         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_2r(unit, &rval));
   4552         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_2r(unit, rval));
   4553 
   4554         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_4r(unit, &rval));
   4555         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KAf,
   4556                           soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka));
   4557         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KIf,
   4558                           soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki));
   4559         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KPf,
   4560                           soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp));
   4561         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_4r(unit, rval));
   4562 
   4563     }
   4564  /* Bring XG PLL0, TS PLL, BS PLL0/1, AVS out of reset */
   4565     SOC_IF_ERROR_RETURN(READ_TOP_XG_PLL0_CTRL_5r(unit, &rval));
   4566     soc_reg_field_set(unit, TOP_XG_PLL0_CTRL_5r, &rval, ROUTE_CTRLf, 0);
   4567     soc_reg_field_set(unit, TOP_XG_PLL0_CTRL_5r, &rval, EN_CTRLf, 1);
   4568     SOC_IF_ERROR_RETURN(WRITE_TOP_XG_PLL0_CTRL_5r(unit, rval));
   4569 
   4570     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   4571     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf,
   4572                       1);
   4573     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf,
   4574                       1);
   4575     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
   4576                       1);
   4577     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
   4578                       1);
   4579     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf,
   4580                       1);
   4581     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   4582     
   4583     sal_usleep(to_usec);
   4584     
   4585     if (!SAL_BOOT_SIMULATION) {
   4586         /* Check XG PLL0 lock status */
   4587         reg = TOP_XG_PLL0_STATUSr;
   4588         SOC_IF_ERROR_RETURN
   4589             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4590         if (!soc_reg_field_get(unit, reg, rval, TOP_XGPLL_LOCKf)) {
   4591             LOG_ERROR(BSL_LS_SOC_COMMON,
   4592                       (BSL_META_U(unit,
   4593                                   "XG_PLL0 not locked on unit %d "
   4594                                   "status = 0x%08x\n"), unit, rval));
   4595         }
   4596         
   4597         /* Check TS PLL lock status */
   4598         reg = TOP_TS_PLL_STATUSr;
   4599         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4600         if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4601             LOG_ERROR(BSL_LS_SOC_COMMON,
   4602                       (BSL_META_U(unit,
   4603                                   "TS_PLL not locked on unit %d "
   4604                                   "status = 0x%08x\n"), unit, rval));
   4605         }
   4606         
   4607         /* Check BS PLL lock status */
   4608         for (index = 0; index < _SOC_TH2_BSPLL_COUNT; index++) {
   4609             reg = bspll_status_reg[index];
   4610             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4611             if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4612                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4613                           (BSL_META_U(unit,
   4614                                       "BS_PLL%d not locked on unit %d "
   4615                                       "status = 0x%08x\n"), index, unit, rval));
   4616             }
   4617         }
   4618 
   4619         /* Check Core PLL lock status, only valid for TH2 B0 revision */
   4620         if (((BCM56970_DEVICE_ID & 0xFFF0) == (dev_id & 0xFFF0)) &&
   4621             (BCM56970_B0_REV_ID == rev_id)) {
   4622             reg = TOP_CORE_PLL0_STATUSr;
   4623             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4624             if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4625                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4626                         (BSL_META_U(unit,
   4627                                     "CORE_PLL not locked on unit %d "
   4628                                     "status = 0x%08x\n"), unit, rval));
   4629             }
   4630         }
   4631     }
   4632     
   4633     /* De-assert XG PLL0, TS PLL, BS PLL0/1 post reset */
   4634     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   4635     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4636                       TOP_XG_PLL0_POST_RST_Lf, 1);
   4637     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4638                       TOP_TS_PLL_POST_RST_Lf, 1);
   4639     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4640                       TOP_BS_PLL0_POST_RST_Lf, 1);
   4641     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4642                       TOP_BS_PLL1_POST_RST_Lf, 1);
   4643     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   4644     
   4645     sal_usleep(to_usec);
   4646 
   4647     if (rev_id == BCM56970_A0_REV_ID) {
   4648         /* TH2 A0 need to set correct value 0 for BG_ADJ, 
   4649          * TH2 B0 default value has been changed to 0.
   4650          */
   4651         SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_0r(unit, &rval));
   4652         soc_reg_field_set(unit, TOP_PVTMON_CTRL_0r, &rval, BG_ADJf, 0);
   4653         SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_0r(unit, rval));
   4654     }
   4655 
   4656     /* Check the the sticky bit whether HW PVTMON High Temperature Protection 
   4657     * happened in system's previous running or not. Halt the current bootup, print error  
   4658     * message, and ask for a system reboot if the sticky bit was set. */
   4659     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_RESULT_0r(unit, &rval));
   4660     if (soc_reg_field_get(unit, TOP_PVTMON_RESULT_0r, 
   4661                           rval, PVTMON_HIGHTEMP_STATUSf)) {
   4662         LOG_ERROR(BSL_LS_SOC_COMMON,
   4663                   (BSL_META_U(unit,
   4664                               "HW PVTMON High Temperature Protection "
   4665                               "was invoked during last system run. "
   4666                               "Please correct the temperature problem "
   4667                               "and cycle power to continue.\n")));
   4668         (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM,
   4669                                  SOC_SWITCH_EVENT_ALARM_125C_TEMP, 
   4670                                  -1, -1);
   4671         return SOC_E_FAIL;
   4672     }
   4673 
   4674     /* Enable high temperature interrupt monitoring.
   4675      * Default on: pvtmon5 (close to core_plls at center of die).
   4676      * Default threshold for pvtmon5: 110C.     
   4677      * Enable HW PVTMON High Temperature Protection.
   4678      * Default on: pvtmon[0-4, 6-7] .
   4679      * Default threshold : 125C.   */
   4680     sw_temp_mask = soc_property_get(unit, "temp_monitor_select", 1<<5);
   4681     sw_temp_mask = sw_temp_mask & ((1 << 8) - 1);
   4682     hw_temp_mask = soc_property_get(unit, "hw_temp_monitor_select", 
   4683                                     ((1 << 8) - 1));
   4684     hw_temp_mask = hw_temp_mask & ((1 << 8) - 1);
   4685     hw_temp_mask = hw_temp_mask & (~ sw_temp_mask);
   4686     /* sw_temp_mask is a 8 bit mask to indicate which temp sensor to hook up to
   4687      * the interrupt. */
   4688 
   4689     sw_temp_thr = soc_property_get(unit, spn_SW_TEMP_THRESHOLD, 
   4690                                    _SOC_TH2_DEF_SW_TEMP_MAX);
   4691     if (sw_temp_thr > _SOC_TH2_DEF_SW_TEMP_MAX) {
   4692         LOG_ERROR(BSL_LS_SOC_COMMON,
   4693                   (BSL_META_U(unit,
   4694                               "Unsupported temp value %d !! Max %d. Using %d.\n"),
   4695                   sw_temp_thr, _SOC_TH2_DEF_SW_TEMP_MAX, _SOC_TH2_DEF_SW_TEMP_MAX));
   4696         sw_temp_thr = _SOC_TH2_DEF_SW_TEMP_MAX;
   4697     }
   4698     
   4699     rval = 0;
   4700     for (index = 0; index <COUNTOF(temp_thr_reg); index++) {
   4701         uint32 trval;
   4702 
   4703         /* Temp = 434.10 - o_ADC_data * 0.53504
   4704          * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535
   4705          * Note: Since this is a high temp value we can safely assume it to
   4706          * always be a +ive number. This is in degrees celcius.
   4707          */
   4708         if (hw_temp_mask & (1 << index)) {
   4709             hw_temp_thr = soc_property_get(unit, temp_thr_prop[index], 
   4710                                            _SOC_TH2_HW_TEMP_MAX);
   4711             if (hw_temp_thr > _SOC_TH2_HW_TEMP_MAX) {
   4712                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4713                           (BSL_META_U(unit,
   4714                                       "Unsupported temp value %d !! Max %d. "
   4715                                       "Using %d.\n"), hw_temp_thr, 
   4716                                       _SOC_TH2_HW_TEMP_MAX, 
   4717                                       _SOC_TH2_HW_TEMP_MAX));
   4718                 hw_temp_thr = _SOC_TH2_HW_TEMP_MAX;
   4719             }
   4720             temp_thr = hw_temp_thr;
   4721         } else {
   4722             temp_thr = sw_temp_thr;
   4723         }
   4724         /* Convert temperature to config data */
   4725         temp_thr = (434100-(temp_thr*1000))/535;
   4726         SOC_IF_ERROR_RETURN
   4727             (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval));
   4728         soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf,
   4729                           temp_thr);
   4730         SOC_IF_ERROR_RETURN
   4731             (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval));
   4732         if (sw_temp_mask & (1 << index)) {
   4733             rval |= (1 << ((index * 2) + 1)); /* 2 bits per pvtmon, using min */
   4734         }
   4735     }
   4736     _soc_th_temp_mon_mask[unit] = sw_temp_mask;
   4737 
   4738     /* Enable high temperature interrupt monitoring.*/
   4739     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASKr(unit, rval));
   4740 
   4741     /* Enable HW PVTMON High Temperature Protection */
   4742     rval = 0;
   4743     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval));
   4744     rval = (rval & (~((1 << 8) - 1))) | hw_temp_mask;
   4745     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
   4746 
   4747 
   4748     /* Enable temp mon interrupt */
   4749     (void)soc_cmicm_intr3_enable(unit, 0x4); /* PVTMON_INTR bit 2 */
   4750 
   4751     /* Bring port blocks out of reset */
   4752     rval = 0;
   4753     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM64_RST_Lf, 1);
   4754     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1);
   4755     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   4756     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff));
   4757     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_4r(unit, 0xffffffff));
   4758     sal_usleep(to_usec);
   4759 
   4760     /* Per DE, need set PSG/PCG to 0 before de-assert IP/EP/MMU SOFT reset */
   4761     SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PSGr(unit, 0));
   4762     SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PCGr(unit, 0));
   4763 
   4764     /* Bring IP, EP, and MMU blocks out of reset */
   4765     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval));
   4766     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1);
   4767     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1);
   4768     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1);
   4769     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   4770     sal_usleep(to_usec);
   4771 
   4772     /* Enable IS_TDM_CALENDAR0,1 SER protection. 
   4773     * They can't be auto-generated by regFile.*/
   4774     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   4775     if (parity_enable) {	
   4776         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IDB_SER_CONTROLr,
   4777                                                    REG_PORT_ANY,
   4778                                                    IS_TDM_ECC_ENf,1));
   4779     }
   4780 
   4781     SOC_IF_ERROR_RETURN(_soc_tomahawk2_init_idb_memory(unit));
   4782 
   4783     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   4784 
   4785     /* Enable scheduler for SBUS accesses to PP IPIPE */
   4786     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
   4787         if (!(pipe_map & (1 << pipe))) {
   4788             continue;
   4789         }
   4790         reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_CONFIGr)[pipe];
   4791         rval = 0;
   4792         soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   4793         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   4794 
   4795         reg = SOC_REG_UNIQUE_ACC(unit, IS_OPP_SCHED_CFGr)[pipe];
   4796         rval = 0;
   4797         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, 1);
   4798         soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 6);
   4799         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   4800     }
   4801 
   4802     /* Must do this before setting low-latency mode */
   4803     SOC_IF_ERROR_RETURN(_soc_tomahawk2_init_ipep_memory(unit));
   4804     SOC_IF_ERROR_RETURN(_soc_tomahawk2_clear_l2_mod_fifo(unit));
   4805     /* Configure Switch Latency Bypass Mode */
   4806     SOC_IF_ERROR_RETURN(soc_th_latency_init(unit));
   4807     if (soc_feature(unit, soc_feature_untethered_otp)) {
   4808         soc_th2_uft_otp_info_get(unit, &num_share_banks_enabled,
   4809             &share_banks_bitmap_enabled);  
   4810     }
   4811 
   4812     if (soc_feature(unit, soc_feature_untethered_otp)
   4813         && num_share_banks_enabled < 4) {
   4814         SOC_IF_ERROR_RETURN
   4815             (soc_th2_set_uft_bank_map(unit));    
   4816     } else {
   4817 
   4818         SOC_IF_ERROR_RETURN
   4819             (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   4820         num_shared_l2_banks = num_banks - 2; /* minus 2 dedicated L2 banks */
   4821         SOC_IF_ERROR_RETURN
   4822             (soc_tomahawk_hash_bank_count_get(unit, L3_ENTRY_ONLYm, &num_banks));
   4823         num_shared_l3_banks = num_banks - 4; /* minus 4 dedicated L3 banks */
   4824         SOC_IF_ERROR_RETURN
   4825             (soc_tomahawk_hash_bank_count_get(unit, EXACT_MATCH_2m,
   4826                                               &num_shared_fpem_banks));
   4827 
   4828         if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   4829             int non_alpm = num_shared_fpem_banks + num_shared_l3_banks +
   4830                 num_shared_l2_banks;
   4831             if ((non_alpm) && (non_alpm <= 2)) {
   4832                 /* If Shared banks are used between ALPM and non-ALPM memories,
   4833                  * then ALPM uses Shared Bank B2, B3 and non-ALPM uses B4, B5 banks
   4834                  */
   4835                 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   4836                                   ALPM_ENTRY_BANK_CONFIGf, 0x3);
   4837                 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   4838                                   ALPM_BANK_MODEf, 1);
   4839                 SOC_IF_ERROR_RETURN
   4840                     (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   4841                                             REG_PORT_ANY, ALPM_BANK_MODEf, 1));
   4842                 SOC_IF_ERROR_RETURN
   4843                     (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   4844                                             REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0x3));
   4845                 soc_th_set_alpm_banks(unit, 2);
   4846                 shared_bank_offset = 2;
   4847             } else {
   4848                 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   4849                                   ALPM_ENTRY_BANK_CONFIGf, 0xf);
   4850                 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   4851                                   ALPM_BANK_MODEf, 0);
   4852                 SOC_IF_ERROR_RETURN
   4853                     (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   4854                                             REG_PORT_ANY, ALPM_BANK_MODEf, 0));
   4855                 SOC_IF_ERROR_RETURN
   4856                     (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   4857                                             REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0xf));
   4858                 soc_th_set_alpm_banks(unit, 4);
   4859             }
   4860         }
   4861 
   4862         soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L2_ENTRY_BANK_CONFIGf,
   4863                           ((1 << num_shared_l2_banks) - 1) << shared_bank_offset);
   4864         for (index = 0; index < num_shared_l2_banks; index++) {
   4865             shared_bank = index + shared_bank_offset;
   4866             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   4867                               l2_fields[index], shared_bank);
   4868         }
   4869         shared_bank_offset += num_shared_l2_banks;
   4870 
   4871         soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L3_ENTRY_BANK_CONFIGf,
   4872                           ((1 << num_shared_l3_banks) - 1) << shared_bank_offset);
   4873         for (index = 0; index < num_shared_l3_banks; index++) {
   4874             shared_bank = index + shared_bank_offset;;
   4875             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   4876                               l3_fields[index], shared_bank);
   4877         }
   4878         shared_bank_offset += num_shared_l3_banks;
   4879 
   4880         soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   4881                           FPEM_ENTRY_BANK_CONFIGf,
   4882                           ((1 << num_shared_fpem_banks) - 1) << shared_bank_offset);
   4883         for (index = 0; index < num_shared_fpem_banks; index++) {
   4884             shared_bank = index + shared_bank_offset;
   4885             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   4886                               fpem_fields[index], shared_bank);
   4887             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, &fpmap,
   4888                               fpem_fields[index], shared_bank);
   4889         }
   4890 
   4891         SOC_IF_ERROR_RETURN
   4892             (soc_reg32_set(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, config));
   4893         SOC_IF_ERROR_RETURN
   4894             (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, map));
   4895         SOC_IF_ERROR_RETURN
   4896             (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map));
   4897         SOC_IF_ERROR_RETURN
   4898             (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, REG_PORT_ANY, 0, fpmap));
   4899     }
   4900     /* Bypass unused Port Blocks */
   4901     if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) {
   4902         SOC_IF_ERROR_RETURN(soc_th2_bypass_unused_pm(unit));
   4903     }
   4904 
   4905     if (soc_feature(unit, soc_feature_turbo_boot)) {
   4906         if (soc_property_get(unit, "clear_on_hw_resetting", 
   4907                              (!(SOC_CONTROL(unit)->soc_flags &
   4908                                 SOC_F_ALL_MODULES_INITED) ||
   4909                               SAL_BOOT_BCMSIM))) {
   4910             SOC_HW_RESET_START(unit);
   4911         }
   4912     }
   4913 
   4914     return SOC_E_NONE;
   4915 }
   4916 
   4917 #ifdef BCM_WARM_BOOT_SUPPORT
   4918 /*
   4919  * Function:
   4920  *      soc_tomahawk2_chip_warmboot_reset
   4921  * Purpose:
   4922  *      Special re-init sequencing for BCM56970 during warmboot
   4923  */
   4924 int
   4925 soc_tomahawk2_chip_warmboot_reset(int unit)
   4926 {
   4927     uint32 map = 0;
   4928 
   4929     SOC_IF_ERROR_RETURN
   4930         (soc_reg32_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, &map));
   4931     SOC_IF_ERROR_RETURN
   4932         (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map));
   4933 
   4934     return SOC_E_NONE;
   4935 }
   4936 #endif
   4937 
   4938 int
   4939 soc_tomahawk2_sed_base_index_check(int unit, int base_type, int sed,
   4940                                  int base_index, char *msg)
   4941 {
   4942     soc_info_t *si;
   4943     int pipe;
   4944     uint32 map;
   4945     char *base_name;
   4946 
   4947     si = &SOC_INFO(unit);
   4948 
   4949     if (sed == -1 || base_index == -1) {
   4950         return SOC_E_NONE;
   4951     }
   4952 
   4953     if (sed < NUM_SED(unit) && si->sed_ipipe_map[sed] == 0) {
   4954         if (msg) {
   4955             LOG_CLI((BSL_META_U(unit,
   4956                                 "%s: SED%d is not in config\n"),
   4957                      msg, sed));
   4958         }
   4959         return SOC_E_PARAM;
   4960     }
   4961 
   4962     switch (base_type) {
   4963     case 0: /* IPORT */
   4964     case 1: /* EPORT */
   4965         base_name = base_type == 0 ? "IPORT" : "EPORT";
   4966         pipe = si->port_pipe[base_index];
   4967         if (pipe == -1) {
   4968             if (msg) {
   4969                 LOG_CLI((BSL_META_U(unit,
   4970                                     "%s: %s%d is not in config\n"),
   4971                          msg, base_name, base_index));
   4972             }
   4973         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   4974             map = base_type == 0 ?
   4975                 si->ipipe_sed_map[pipe] : si->epipe_sed_map[pipe];
   4976             if (map & (1 << sed)) {
   4977                 break;
   4978             }
   4979             if (msg != NULL) {
   4980                 LOG_CLI((BSL_META_U(unit,
   4981                                     "%s: %s%d is not in SED%d\n"),
   4982                          msg, base_name, base_index, sed));
   4983             }
   4984         } else {
   4985             break;
   4986         }
   4987         return SOC_E_PARAM;
   4988     case 2: /* IPIPE */
   4989     case 3: /* EPIPE */
   4990         if (base_type == 2) {
   4991             base_name = "IPIPE";
   4992             map = si->ipipe_sed_map[base_index];
   4993         } else {
   4994             base_name = "EPIPE";
   4995             map = si->epipe_sed_map[base_index]; 
   4996         }
   4997         if (map == 0) {
   4998             if (msg) {
   4999                 LOG_CLI((BSL_META_U(unit,
   5000                                     "%s: %s%d is not in config\n"),
   5001                          msg, base_name, base_index));
   5002             }
   5003         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   5004             if (map & (1 << sed)) {
   5005                 break;
   5006             }
   5007             if (msg != NULL) {
   5008                 LOG_CLI((BSL_META_U(unit,
   5009                                     "%s: %s%d is not in SED%d\n"),
   5010                          msg, base_name, base_index, sed));
   5011             }
   5012         } else {
   5013             break;
   5014         }
   5015         return SOC_E_PARAM;
   5016     case 4: /* CHIP */
   5017         break;
   5018     case 5: /* XPE */
   5019         if (si->xpe_ipipe_map[base_index] == 0) {
   5020             if (msg != NULL) {
   5021                 LOG_CLI((BSL_META_U(unit,
   5022                                     "%s: XPE%d is not in config\n"),
   5023                          msg, base_index));
   5024             }
   5025         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   5026             if (sed == 0) { /* XPE 0 and 2 are in slice 0 */
   5027                 if (base_index == 0 || base_index == 2) {
   5028                     break;
   5029                 }
   5030             } else { /* XPE 1 and 3 are in slice 1 */
   5031                 if (base_index == 1 || base_index == 3) {
   5032                     break;
   5033                 }
   5034             }
   5035             if (msg != NULL) {
   5036                 LOG_CLI((BSL_META_U(unit,
   5037                                     "%s: XPE%d is not in SLICE%d\n"),
   5038                          msg, base_index, sed));
   5039             }
   5040         } else {
   5041             break;
   5042         }
   5043         return SOC_E_PARAM;
   5044     case 6: /* SLICE */
   5045     case 7: /* LAYER, not used */
   5046         break;
   5047     }
   5048 
   5049     return SOC_E_NONE;
   5050 }
   5051 
   5052 STATIC int
   5053 _soc_tomahawk2_sed_reg_check(int unit, soc_reg_t reg, int sed, int base_index)
   5054 {
   5055     int acc_type, base_type;
   5056 
   5057     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_SED)) {
   5058         LOG_CLI((BSL_META_U(unit,
   5059                             "%s is not SED register\n"), SOC_REG_NAME(unit, reg)));
   5060         return SOC_E_PARAM;
   5061     }
   5062 
   5063     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   5064         if (sed == -1 || sed >= NUM_SED(unit)) {
   5065             LOG_CLI((BSL_META_U(unit,
   5066                                 "%s bad SED value %d\n"),
   5067                      SOC_REG_NAME(unit, reg), sed));
   5068             return SOC_E_PARAM;
   5069         }
   5070     } else {
   5071         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   5072         if (acc_type < NUM_SED(unit)) { /* UNIQUE per SED register */
   5073             if (sed != acc_type) {
   5074                 LOG_CLI((BSL_META_U(unit,
   5075                                     "Override SED value %d with ACC_TYPE of %s\n"),
   5076                          sed, SOC_REG_NAME(unit, reg)));
   5077             }
   5078             sed = acc_type;
   5079         } else { /* non-UNIQUE register */
   5080             return SOC_E_NONE;
   5081         }
   5082     }
   5083     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5084 
   5085     return soc_tomahawk2_sed_base_index_check(unit, base_type, sed, base_index,
   5086                                             SOC_REG_NAME(unit, reg));
   5087 }
   5088 
   5089 STATIC int
   5090 _soc_tomahawk2_sed_reg_access(int unit, soc_reg_t reg, int sed, int base_index,
   5091                             int index, uint64 *data, int write)
   5092 {
   5093     soc_info_t *si;
   5094     int port;
   5095     int base_type;
   5096     uint32 base_index_map;
   5097     soc_pbmp_t base_index_pbmp;
   5098     uint32 inst;
   5099 
   5100     si = &SOC_INFO(unit);
   5101     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5102 
   5103     if (sed >= 0 && base_index >= 0) {
   5104         SOC_IF_ERROR_RETURN
   5105             (_soc_tomahawk2_sed_reg_check(unit, reg, sed, base_index));
   5106     }
   5107 
   5108     switch (base_type) {
   5109     case 0: /* IPORT */
   5110     case 1: /* EPORT */
   5111         /* No unique access type for such base_type */
   5112         if (base_index == -1) {
   5113             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   5114         } else {
   5115             /* This argument is logical port, same as soc_reg_get/set */
   5116             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   5117         }
   5118 
   5119         SOC_PBMP_ITER(base_index_pbmp, port) {
   5120             if (write) {
   5121                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data));
   5122             } else {
   5123                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data));
   5124             }
   5125         }
   5126         break;
   5127     case 2: /* IPIPE */
   5128     case 3: /* EPIPE */
   5129         /* No unique access type for such base_type */
   5130         soc_tomahawk_pipe_map_get(unit, &base_index_map);
   5131         if (base_index != -1) {
   5132             base_index_map &= 1 << base_index;
   5133             if (base_index_map == 0) {
   5134                 return SOC_E_PARAM;
   5135             }
   5136         }
   5137 
   5138         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   5139             if (!(base_index_map & (1 << base_index))) {
   5140                 continue;
   5141             }
   5142             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5143             if (write) {
   5144                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5145             } else {
   5146                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5147             }
   5148         }
   5149         break;
   5150     case 4: /* CHIP */
   5151         if (write) {
   5152             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   5153         } else {
   5154             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   5155         }
   5156         break;
   5157     case 5: /* XPE */
   5158         /* No unique access type for such base_type */
   5159         if (base_index == -1) {
   5160             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5161         } else {
   5162             base_index_map = 1 << base_index;
   5163         }
   5164 
   5165         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   5166             if (!(base_index_map & (1 << base_index))) {
   5167                 continue;
   5168             }
   5169             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5170             if (write) {
   5171                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5172             } else {
   5173                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5174             }
   5175         }
   5176         break;
   5177     case 6: /* SLICE */
   5178         /* No unique access type for such base_type */
   5179         if (base_index == -1) {
   5180             base_index_map = si->ipipe_sed_map[0];;
   5181         } else {
   5182             base_index_map = 1 << base_index;
   5183         }
   5184         for (base_index = 0; base_index < NUM_SED(unit); base_index++) {
   5185             if (!(base_index_map & (1 << base_index))) {
   5186                 continue;
   5187             }
   5188             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5189             if (write) {
   5190                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5191             } else {
   5192                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5193             }
   5194         }
   5195         break;
   5196     case 7: /* LAYER */
   5197     default:
   5198         return SOC_E_INTERNAL;
   5199     }
   5200 
   5201     return SOC_E_NONE;
   5202 }
   5203 
   5204 int
   5205 soc_tomahawk2_sed_reg32_set(int unit, soc_reg_t reg, int sed, int base_index,
   5206                           int index, uint32 data)
   5207 {
   5208     uint64 data64;
   5209 
   5210     COMPILER_64_SET(data64, 0, data);
   5211     SOC_IF_ERROR_RETURN(_soc_tomahawk2_sed_reg_access(unit, reg, sed, base_index,
   5212                                                     index, &data64, TRUE));
   5213 
   5214     return SOC_E_NONE;
   5215 }
   5216 
   5217 int
   5218 soc_tomahawk2_sed_reg32_get(int unit, soc_reg_t reg, int sed, int base_index,
   5219                           int index, uint32 *data)
   5220 {
   5221     uint64 data64;
   5222 
   5223     COMPILER_64_SET(data64, 0, *data);
   5224     SOC_IF_ERROR_RETURN(_soc_tomahawk2_sed_reg_access(unit, reg, sed, base_index,
   5225                                                     index, &data64, FALSE));
   5226     *data = COMPILER_64_LO(data64);
   5227 
   5228     return SOC_E_NONE;
   5229 }
   5230 
   5231 int
   5232 soc_tomahawk2_sed_reg_set(int unit, soc_reg_t reg, int sed, int base_index,
   5233                         int index, uint64 data)
   5234 {
   5235     return _soc_tomahawk2_sed_reg_access(unit, reg, sed, base_index,
   5236                                        index, &data, TRUE);
   5237 }
   5238 
   5239 int
   5240 soc_tomahawk2_sed_reg_get(int unit, soc_reg_t reg, int sed, int base_index,
   5241                         int index, uint64 *data)
   5242 {
   5243     return _soc_tomahawk2_sed_reg_access(unit, reg, sed, base_index,
   5244                                        index, data, FALSE);
   5245 }
   5246 
   5247 soc_pstats_tbl_desc_t
   5248 _soc_th2_pstats_tbl_desc_all = {SOC_BLK_NONE, INVALIDm, FALSE, FALSE};
   5249 soc_pstats_tbl_desc_t _soc_th2_pstats_tbl_desc[] = {
   5250     /* List all the potential memories */
   5251 #ifdef BCM_PSTATS_MEASURE
   5252     {
   5253         SOC_BLK_MMU_GLB,
   5254         INVALIDm,
   5255         FALSE, FALSE,
   5256         {
   5257             {MMU_INTFO_TIMESTAMPm},
   5258             {INVALIDm}
   5259         }
   5260     },
   5261 #endif
   5262     {
   5263         SOC_BLK_MMU_GLB,
   5264         INVALIDm,
   5265         FALSE, FALSE,
   5266         {
   5267             {MMU_INTFO_UTC_TIMESTAMPm},
   5268             {INVALIDm}
   5269         }
   5270     },
   5271     {
   5272         SOC_BLK_MMU_XPE,
   5273         MMU_THDU_UCQ_STATS_TABLEm,
   5274         TRUE, TRUE
   5275     },
   5276     {
   5277         SOC_BLK_MMU_XPE,
   5278         THDI_PKT_STAT_SP_SHARED_COUNTm,
   5279         FALSE, FALSE
   5280     },
   5281     {
   5282         SOC_BLK_MMU_XPE,
   5283         MMU_THDM_DB_POOL_MCUC_PKSTATm,
   5284         FALSE, FALSE
   5285 #ifdef BCM_PSTATS_MEASURE
   5286     },
   5287     {
   5288         SOC_BLK_MMU_GLB,
   5289         INVALIDm,
   5290         FALSE, FALSE,
   5291         {
   5292             {MMU_INTFO_TIMESTAMPm},
   5293             {INVALIDm}
   5294         }
   5295 #endif
   5296     }
   5297 };
   5298 
   5299 void
   5300 soc_tomahawk2_mmu_pstats_tbl_config_all(int unit)
   5301 {
   5302     soc_control_t *soc = SOC_CONTROL(unit);
   5303     soc_pstats_mem_desc_t *desc, *desc_all;
   5304     int ti, mi, di = 0;
   5305 
   5306     desc_all = _soc_th2_pstats_tbl_desc_all.desc;
   5307     /* Check and strip invalid memories */
   5308     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
   5309         mi = 0;
   5310         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
   5311         while (desc[mi].mem != INVALIDm) {
   5312             desc_all[di] = desc[mi];
   5313             di++;
   5314             mi++;
   5315         }
   5316     }
   5317     desc_all[di].mem = INVALIDm;
   5318 
   5319     soc->pstats_tbl_desc = &_soc_th2_pstats_tbl_desc_all;
   5320     soc->pstats_tbl_desc_count = 1;
   5321 }
   5322 
   5323 void
   5324 soc_tomahawk2_mmu_pstats_tbl_config(int unit)
   5325 {
   5326     soc_control_t *soc = SOC_CONTROL(unit);
   5327     soc_pstats_mem_desc_t *desc;
   5328     soc_mem_t bmem;
   5329     int pe, mor_dma;
   5330     int ti, mi, xpe, pipe;
   5331 
   5332     soc->pstats_tbl_desc = _soc_th2_pstats_tbl_desc;
   5333     soc->pstats_tbl_desc_count = COUNTOF(_soc_th2_pstats_tbl_desc);
   5334     soc->pstats_mode = PSTATS_MODE_NULL;
   5335 
   5336     /* Check and strip invalid memories */
   5337     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
   5338         mi = 0;
   5339         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
   5340         bmem = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].bmem;
   5341         if (bmem == INVALIDm) {
   5342             while (desc[mi].mem != INVALIDm) {
   5343                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
   5344                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
   5345                 mi++;
   5346             }
   5347             continue;
   5348         }
   5349         pe = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].pipe_enum;
   5350         mor_dma = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].mor_dma;
   5351         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5352             for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   5353                 desc[mi].mem = pe ? SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, bmem, xpe, pipe) :
   5354                                     SOC_MEM_UNIQUE_ACC(unit, bmem)[xpe];
   5355                 if (desc[mi].mem == INVALIDm) {
   5356                     continue;
   5357                 }
   5358                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
   5359                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
   5360                 if (mor_dma) {
   5361                     desc[mi].mor_dma = TRUE;
   5362                 }
   5363                 mi++;
   5364                 if (!pe) {
   5365                     break;
   5366                 }
   5367             }
   5368         }
   5369         desc[mi].mem = INVALIDm;
   5370     }
   5371 
   5372     if (soc_property_get(unit, "pstats_desc_all", 1)) {
   5373         /* Use single desc chain */
   5374         soc_tomahawk2_mmu_pstats_tbl_config_all(unit);
   5375     }
   5376 }
   5377 
   5378 int
   5379 soc_tomahawk2_mmu_pstats_mode_set(int unit, uint32 flags)
   5380 {
   5381     soc_control_t *soc = SOC_CONTROL(unit);
   5382     int pf = 0;
   5383     uint32 rval = 0;
   5384     int rv;
   5385 
   5386     SOC_PSTATS_LOCK(unit);
   5387 
   5388     if (flags & _TH2_MMU_PSTATS_HWM_MOD) {
   5389         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
   5390                           HWM_MODEf, 1);
   5391         pf |= _TH2_MMU_PSTATS_HWM_MOD;
   5392         if (flags & _TH2_MMU_PSTATS_RESET_ON_READ) {
   5393             soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
   5394                               HWM_RESET_ON_READf, 1);
   5395             pf |= _TH2_MMU_PSTATS_RESET_ON_READ;
   5396         }
   5397     }
   5398 
   5399     if (flags & _TH2_MMU_PSTATS_PKT_MOD) {
   5400         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
   5401                           SELECTf, 1);
   5402         pf |= _TH2_MMU_PSTATS_PKT_MOD;
   5403         if (soc_feature(unit, soc_feature_mor_dma) &&
   5404             (flags & _TH2_MMU_PSTATS_MOR_EN)) {
   5405             soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
   5406                               MOR_ENf, 1);
   5407         }
   5408         if (flags & _TH2_MMU_PSTATS_MOR_EN) {
   5409             pf |= _TH2_MMU_PSTATS_MOR_EN;
   5410         }
   5411     }
   5412 
   5413     if (flags & _TH2_MMU_PSTATS_ENABLE) {
   5414         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
   5415                           ENABLEf, 1);
   5416         pf |= _TH2_MMU_PSTATS_ENABLE;
   5417         if (flags & _TH2_MMU_PSTATS_PKT_MOD) {
   5418             if ((flags & _TH2_MMU_PSTATS_SYNC) ||
   5419                 (flags & _TH2_MMU_PSTATS_HWM_MOD &&
   5420                  flags & _TH2_MMU_PSTATS_RESET_ON_READ)) {
   5421                 soc->pstats_mode = PSTATS_MODE_PKT_SYNC;
   5422                 pf |= _TH2_MMU_PSTATS_SYNC;
   5423             } else {
   5424                 soc->pstats_mode = PSTATS_MODE_PKT_BUFF;
   5425             }
   5426         } else {
   5427             soc->pstats_mode = PSTATS_MODE_OOB;
   5428         }
   5429     } else {
   5430         soc->pstats_mode = PSTATS_MODE_NULL;
   5431     }
   5432 
   5433     soc->pstats_flags = pf;
   5434 
   5435     rv = WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval);
   5436 
   5437     SOC_PSTATS_UNLOCK(unit);
   5438 
   5439     return rv;
   5440 }
   5441 
   5442 int
   5443 soc_tomahawk2_mmu_pstats_mode_get(int unit, uint32 *flags)
   5444 {
   5445     int pf = 0;
   5446     uint32 rval = 0;
   5447     int rv;
   5448     soc_reg_t reg = MMU_GCFG_PKTSTAT_OOBSTATr;
   5449 
   5450     SOC_PSTATS_LOCK(unit);
   5451 
   5452     rv = READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval);
   5453     if (SOC_FAILURE(rv)) {
   5454         SOC_PSTATS_UNLOCK(unit);
   5455         return rv;
   5456     }
   5457 
   5458     if (soc_reg_field_get(unit, reg, rval, ENABLEf)) {
   5459         pf |= _TH2_MMU_PSTATS_ENABLE;
   5460         if (soc_reg_field_get(unit, reg, rval, SELECTf)) {
   5461             pf |= _TH2_MMU_PSTATS_PKT_MOD;
   5462         }
   5463     }
   5464     if (soc_reg_field_get(unit, reg, rval, HWM_MODEf)) {
   5465         pf |= _TH2_MMU_PSTATS_HWM_MOD;
   5466         if (soc_reg_field_get(unit, reg, rval, HWM_RESET_ON_READf)) {
   5467             pf |= _TH2_MMU_PSTATS_RESET_ON_READ;
   5468         }
   5469     }
   5470 
   5471     SOC_PSTATS_UNLOCK(unit);
   5472 
   5473     *flags = pf;
   5474 
   5475     return SOC_E_NONE;
   5476 }
   5477 
   5478 int
   5479 soc_tomahawk2_mmu_pstats_mor_enable(int unit)
   5480 {
   5481     soc_control_t *soc = SOC_CONTROL(unit);
   5482     uint32 rval;
   5483     sal_usecs_t stime = sal_time_usecs();
   5484 
   5485 
   5486     if (soc->pstats_flags & _TH2_MMU_PSTATS_MOR_EN) {
   5487         SOC_IF_ERROR_RETURN(READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval));
   5488         if ( ! soc_reg_field_get(unit, 
   5489                                  MMU_GCFG_PKTSTAT_OOBSTATr, rval, MOR_ENf)) {
   5490             soc_reg_field_set(unit, 
   5491                               MMU_GCFG_PKTSTAT_OOBSTATr, &rval, MOR_ENf, 1);
   5492             SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval));
   5493         }
   5494     }
   5495 
   5496     LOG_INFO(BSL_LS_SOC_COMMON,
   5497              (BSL_META_U(unit,
   5498                          "pstats dma pc done in %d usecs\n"),
   5499               SAL_USECS_SUB(sal_time_usecs(), stime)));
   5500 
   5501     return SOC_E_NONE;
   5502 }
   5503 
   5504 int
   5505 soc_tomahawk2_mmu_pstats_mor_disable(int unit)
   5506 {
   5507     soc_control_t *soc = SOC_CONTROL(unit);
   5508     uint32 rval;
   5509     sal_usecs_t stime = sal_time_usecs();
   5510 
   5511     if (!soc_feature(unit, soc_feature_mor_dma) &&
   5512         (soc->pstats_flags & _TH2_MMU_PSTATS_MOR_EN)) {
   5513         SOC_IF_ERROR_RETURN(READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval));
   5514         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval, MOR_ENf, 0);
   5515         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval));
   5516     }
   5517 
   5518     LOG_INFO(BSL_LS_SOC_COMMON,
   5519              (BSL_META_U(unit,
   5520                          "pstats dma cb done in %d usecs\n"),
   5521               SAL_USECS_SUB(sal_time_usecs(), stime)));
   5522 
   5523     return SOC_E_NONE;
   5524 }
   5525 
   5526 int
   5527 soc_tomahawk2_mmu_splitter_reset(int unit)
   5528 {
   5529     uint32 rval;
   5530 
   5531     SOC_IF_ERROR_RETURN(READ_MMU_GCFG_SPLITTERr(unit, &rval));
   5532     soc_reg_field_set(unit, MMU_GCFG_SPLITTERr, &rval, RESET_SBUSf, 1);
   5533     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_SPLITTERr(unit, rval));
   5534 
   5535     return SOC_E_NONE;
   5536 }
   5537 
   5538 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad) \
   5539                             ((_phy_reg) |= ((_phyad) & 0x1f) << 19)
   5540 
   5541 int
   5542 soc_tomahawk2_mdio_addr_to_port(uint32 phy_addr)
   5543 {
   5544     int bus, offset;
   5545 
   5546     /* Must be internal MDIO address */
   5547     if ((phy_addr & 0x80) == 0) {
   5548         return 0;
   5549     }
   5550 
   5551     /*
   5552      * Internal phy address:
   5553      * bus 0 phy 1 to 28 are mapped to Physical port 1 to 28
   5554      * bus 1 phy 1 to 28 are mapped to Physical port 29 to 56
   5555      * bus 2 phy 1 to 16 are mapped to Physical port 57 to 72
   5556      * bus 3 phy 1 to 28 are mapped to Physical port 73 to 100
   5557      * bus 4 phy 1 to 28 are mapped to Physical port 101 to 128
   5558      * bus 5 phy 1 to 28 are mapped to Physical port 129 to 156
   5559      * bus 6 phy 1 to 28 are mapped to Physical port 157 to 184
   5560      * bus 7 phy 1 to 16 are mapped to Physical port 185 to 200
   5561      * bus 8 phy 1 to 28 are mapped to Physical port 201 to 228
   5562      * bus 9 phy 1 to 28 are mapped to Physical port 229 to 256
   5563      * bus 10 phy 1 is mapped to Physical port 257 and 
   5564      *        phy 3 is mapped to Physical port 259
   5565      */
   5566     bus = PHY_ID_BUS_NUM(phy_addr);
   5567     if (bus > 10) {
   5568         return 0;
   5569     }
   5570 
   5571     switch (bus) {
   5572     case 0: offset = 0;
   5573         break;
   5574     case 1: offset = 28;
   5575         break;
   5576     case 2: offset = 56;
   5577         break;
   5578     case 3: offset = 72;
   5579         break;
   5580     case 4: offset = 100;
   5581         break;
   5582     case 5: offset = 128;
   5583         break;
   5584     case 6: offset = 156;
   5585         break;
   5586     case 7: offset = 184;
   5587         break;
   5588     case 8: offset = 200;
   5589         break;
   5590     case 9: offset = 228;
   5591         break;
   5592     case 10: offset = 256;
   5593         if ((phy_addr & 0x1f) == 2 || (phy_addr & 0x1f) > 3) {
   5594             return 0;
   5595         }
   5596         break;
   5597     default:
   5598         return 0;
   5599     }
   5600 
   5601     return (phy_addr & 0x1f) + offset;
   5602 }
   5603 
   5604 int
   5605 soc_th2_ledup_init(int unit)
   5606 {
   5607     soc_reg_t led_reg[][16] = {
   5608         {
   5609             CMIC_LEDUP0_PORT_ORDER_REMAP_0_3r,
   5610             CMIC_LEDUP0_PORT_ORDER_REMAP_4_7r,
   5611             CMIC_LEDUP0_PORT_ORDER_REMAP_8_11r,
   5612             CMIC_LEDUP0_PORT_ORDER_REMAP_12_15r,
   5613             CMIC_LEDUP0_PORT_ORDER_REMAP_16_19r,
   5614             CMIC_LEDUP0_PORT_ORDER_REMAP_20_23r,
   5615             CMIC_LEDUP0_PORT_ORDER_REMAP_24_27r,
   5616             CMIC_LEDUP0_PORT_ORDER_REMAP_28_31r,
   5617             CMIC_LEDUP0_PORT_ORDER_REMAP_32_35r,
   5618             CMIC_LEDUP0_PORT_ORDER_REMAP_36_39r,
   5619             CMIC_LEDUP0_PORT_ORDER_REMAP_40_43r,
   5620             CMIC_LEDUP0_PORT_ORDER_REMAP_44_47r,
   5621             CMIC_LEDUP0_PORT_ORDER_REMAP_48_51r,
   5622             CMIC_LEDUP0_PORT_ORDER_REMAP_52_55r,
   5623             CMIC_LEDUP0_PORT_ORDER_REMAP_56_59r,
   5624             CMIC_LEDUP0_PORT_ORDER_REMAP_60_63r
   5625         },
   5626         {
   5627             CMIC_LEDUP1_PORT_ORDER_REMAP_0_3r,
   5628             CMIC_LEDUP1_PORT_ORDER_REMAP_4_7r,
   5629             CMIC_LEDUP1_PORT_ORDER_REMAP_8_11r,
   5630             CMIC_LEDUP1_PORT_ORDER_REMAP_12_15r,
   5631             CMIC_LEDUP1_PORT_ORDER_REMAP_16_19r,
   5632             CMIC_LEDUP1_PORT_ORDER_REMAP_20_23r,
   5633             CMIC_LEDUP1_PORT_ORDER_REMAP_24_27r,
   5634             CMIC_LEDUP1_PORT_ORDER_REMAP_28_31r,
   5635             CMIC_LEDUP1_PORT_ORDER_REMAP_32_35r,
   5636             CMIC_LEDUP1_PORT_ORDER_REMAP_36_39r,
   5637             CMIC_LEDUP1_PORT_ORDER_REMAP_40_43r,
   5638             CMIC_LEDUP1_PORT_ORDER_REMAP_44_47r,
   5639             CMIC_LEDUP1_PORT_ORDER_REMAP_48_51r,
   5640             CMIC_LEDUP1_PORT_ORDER_REMAP_52_55r,
   5641             CMIC_LEDUP1_PORT_ORDER_REMAP_56_59r,
   5642             CMIC_LEDUP1_PORT_ORDER_REMAP_60_63r
   5643         },
   5644         {
   5645             CMIC_LEDUP2_PORT_ORDER_REMAP_0_3r,
   5646             CMIC_LEDUP2_PORT_ORDER_REMAP_4_7r,
   5647             CMIC_LEDUP2_PORT_ORDER_REMAP_8_11r,
   5648             CMIC_LEDUP2_PORT_ORDER_REMAP_12_15r,
   5649             CMIC_LEDUP2_PORT_ORDER_REMAP_16_19r,
   5650             CMIC_LEDUP2_PORT_ORDER_REMAP_20_23r,
   5651             CMIC_LEDUP2_PORT_ORDER_REMAP_24_27r,
   5652             CMIC_LEDUP2_PORT_ORDER_REMAP_28_31r,
   5653             CMIC_LEDUP2_PORT_ORDER_REMAP_32_35r,
   5654             CMIC_LEDUP2_PORT_ORDER_REMAP_36_39r,
   5655             CMIC_LEDUP2_PORT_ORDER_REMAP_40_43r,
   5656             CMIC_LEDUP2_PORT_ORDER_REMAP_44_47r,
   5657             CMIC_LEDUP2_PORT_ORDER_REMAP_48_51r,
   5658             CMIC_LEDUP2_PORT_ORDER_REMAP_52_55r,
   5659             CMIC_LEDUP2_PORT_ORDER_REMAP_56_59r,
   5660             CMIC_LEDUP2_PORT_ORDER_REMAP_60_63r
   5661         },
   5662         {
   5663             CMIC_LEDUP3_PORT_ORDER_REMAP_0_3r,
   5664             CMIC_LEDUP3_PORT_ORDER_REMAP_4_7r,
   5665             CMIC_LEDUP3_PORT_ORDER_REMAP_8_11r,
   5666             CMIC_LEDUP3_PORT_ORDER_REMAP_12_15r,
   5667             CMIC_LEDUP3_PORT_ORDER_REMAP_16_19r,
   5668             CMIC_LEDUP3_PORT_ORDER_REMAP_20_23r,
   5669             CMIC_LEDUP3_PORT_ORDER_REMAP_24_27r,
   5670             CMIC_LEDUP3_PORT_ORDER_REMAP_28_31r,
   5671             CMIC_LEDUP3_PORT_ORDER_REMAP_32_35r,
   5672             CMIC_LEDUP3_PORT_ORDER_REMAP_36_39r,
   5673             CMIC_LEDUP3_PORT_ORDER_REMAP_40_43r,
   5674             CMIC_LEDUP3_PORT_ORDER_REMAP_44_47r,
   5675             CMIC_LEDUP3_PORT_ORDER_REMAP_48_51r,
   5676             CMIC_LEDUP3_PORT_ORDER_REMAP_52_55r,
   5677             CMIC_LEDUP3_PORT_ORDER_REMAP_56_59r,
   5678             CMIC_LEDUP3_PORT_ORDER_REMAP_60_63r
   5679         },
   5680         {
   5681             CMIC_LEDUP4_PORT_ORDER_REMAP_0_3r,
   5682             CMIC_LEDUP4_PORT_ORDER_REMAP_4_7r,
   5683             CMIC_LEDUP4_PORT_ORDER_REMAP_8_11r,
   5684             CMIC_LEDUP4_PORT_ORDER_REMAP_12_15r,
   5685             CMIC_LEDUP4_PORT_ORDER_REMAP_16_19r,
   5686             CMIC_LEDUP4_PORT_ORDER_REMAP_20_23r,
   5687             CMIC_LEDUP4_PORT_ORDER_REMAP_24_27r,
   5688             CMIC_LEDUP4_PORT_ORDER_REMAP_28_31r,
   5689             CMIC_LEDUP4_PORT_ORDER_REMAP_32_35r,
   5690             CMIC_LEDUP4_PORT_ORDER_REMAP_36_39r,
   5691             CMIC_LEDUP4_PORT_ORDER_REMAP_40_43r,
   5692             CMIC_LEDUP4_PORT_ORDER_REMAP_44_47r,
   5693             CMIC_LEDUP4_PORT_ORDER_REMAP_48_51r,
   5694             CMIC_LEDUP4_PORT_ORDER_REMAP_52_55r,
   5695             CMIC_LEDUP4_PORT_ORDER_REMAP_56_59r,
   5696             CMIC_LEDUP4_PORT_ORDER_REMAP_60_63r
   5697         }
   5698     };
   5699     soc_field_t led_port[] = {
   5700          REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f,
   5701          REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f,
   5702          REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f,
   5703          REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f,
   5704          REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f,
   5705          REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f,
   5706          REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f,
   5707          REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f,
   5708          REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f,
   5709          REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f,
   5710          REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f,
   5711          REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f,
   5712          REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f,
   5713          REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f,
   5714          REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f,
   5715          REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f
   5716     };
   5717     soc_reg_t led_clk_div_reg[] = {
   5718         CMIC_LEDUP0_CLK_DIVr, CMIC_LEDUP1_CLK_DIVr,
   5719         CMIC_LEDUP2_CLK_DIVr, CMIC_LEDUP3_CLK_DIVr,
   5720         CMIC_LEDUP4_CLK_DIVr
   5721     };
   5722     int reg_num = COUNTOF(led_reg[0]);
   5723     uint32 rval;
   5724     int i, j, p;
   5725     int freq, cycles;
   5726 
   5727     /* Program the LED clock output frequency based on core clock */
   5728     freq = SOC_INFO(unit).frequency;
   5729 
   5730     /* For LEDCLK_HALF_PERIOD. TH2 uses 2MHz LED clock. */
   5731     /* Formula : cycles = (freq * 10^6) * (250 * 10^-9) = freq/4 */
   5732     /* Round up the value for non-integer clocks */
   5733     cycles = (freq + 3) / 4;
   5734 
   5735     rval = 0;
   5736     soc_reg_field_set(unit, CMIC_LEDUP0_CLK_DIVr, &rval,
   5737                       LEDCLK_HALF_PERIODf, cycles);
   5738     for (i = 0; i < COUNTOF(led_clk_div_reg); i++) {
   5739         soc_pci_write(unit, soc_reg_addr(unit, led_clk_div_reg[i],
   5740                                          REG_PORT_ANY, 0), rval);
   5741     }
   5742 
   5743     /*
   5744      * Configure LED0 remap register settings.
   5745      * Scan chain order: 64, 63, ...., 1
   5746      */
   5747     for (i = 0, rval = 0, p = 0; i < reg_num; i++) {
   5748         for (j = 0; j < 4; j++, p++) {
   5749             soc_reg_field_set(unit, led_reg[0][i], &rval, led_port[p], 63 - p);
   5750         }
   5751         soc_pci_write(unit,
   5752                       soc_reg_addr(unit, led_reg[0][i], REG_PORT_ANY, 0),
   5753                       rval);
   5754     }
   5755 
   5756     /*
   5757      * Configure LED1 remap register settings.
   5758      * Scan chain order: 65, 66, ...., 128
   5759      */
   5760     for (i = 0, rval = 0; i < reg_num; i++) {
   5761         for (j = 0, p = i << 2; j < 4; j++) {
   5762             soc_reg_field_set(unit, led_reg[1][i], &rval, led_port[p + j], p + 3 - j);
   5763         }
   5764         soc_pci_write(unit,
   5765                       soc_reg_addr(unit, led_reg[1][i], REG_PORT_ANY, 0),
   5766                       rval);
   5767     }
   5768 
   5769     /*
   5770      * Configure LED2 remap register settings.
   5771      * Scan chain order: 192, 191, ...., 129
   5772      */
   5773     for (i = 0, rval = 0, p = 0; i < reg_num; i++) {
   5774         for (j = 0; j < 4; j++, p++) {
   5775             soc_reg_field_set(unit, led_reg[2][i], &rval, led_port[p], 63 - p);
   5776         }
   5777         soc_pci_write(unit,
   5778                       soc_reg_addr(unit, led_reg[2][i], REG_PORT_ANY, 0),
   5779                       rval);
   5780     }
   5781 
   5782     /*
   5783      * Configure LED3 remap register settings.
   5784      * Scan chain order: 193, 194, ...., 256
   5785      */
   5786     for (i = 0, rval = 0; i < reg_num; i++) {
   5787         for (j = 0, p = i << 2; j < 4; j++) {
   5788             soc_reg_field_set(unit, led_reg[3][i], &rval, led_port[p + j], p + 3 - j);
   5789         }
   5790         soc_pci_write(unit,
   5791                       soc_reg_addr(unit, led_reg[3][i], REG_PORT_ANY, 0),
   5792                       rval);
   5793     }
   5794 
   5795     /*
   5796      * Configure LED4 remap register settings.
   5797      * Scan chain order: 260, 259, 258, 257
   5798      */
   5799     for (i = 0, rval = 0, p = 0; i < reg_num; i++) {
   5800         for (j = 0; j < 4; j++, p++) {
   5801             soc_reg_field_set(unit, led_reg[4][i], &rval, led_port[p], 0x3f);
   5802         }
   5803         if (i == 0) {
   5804             soc_reg_field_set(unit, led_reg[4][i], &rval, led_port[1], 1);
   5805             soc_reg_field_set(unit, led_reg[4][i], &rval, led_port[3], 0);
   5806         }
   5807         soc_pci_write(unit,
   5808                       soc_reg_addr(unit, led_reg[4][i], REG_PORT_ANY, 0),
   5809                       rval);
   5810     }
   5811 
   5812     /* initialize the LED processors data ram */
   5813     rval = 0;
   5814     for (i = 0; i < 256; i++) {
   5815         WRITE_CMIC_LEDUP0_DATA_RAMr(unit, i, rval);
   5816         WRITE_CMIC_LEDUP1_DATA_RAMr(unit, i, rval);
   5817         soc_pci_write(unit,
   5818                       soc_reg_addr(unit, CMIC_LEDUP2_DATA_RAMr, REG_PORT_ANY, i),
   5819                       rval);
   5820         soc_pci_write(unit,
   5821                       soc_reg_addr(unit, CMIC_LEDUP3_DATA_RAMr, REG_PORT_ANY, i),
   5822                       rval);
   5823         soc_pci_write(unit,
   5824                       soc_reg_addr(unit, CMIC_LEDUP4_DATA_RAMr, REG_PORT_ANY, i),
   5825                       rval);
   5826     }
   5827 
   5828     return SOC_E_NONE;
   5829 }
   5830 
   5831 /* For a given logical port, return the OBM id and the lane number */
   5832 int
   5833 soc_tomahawk2_port_obm_info_get(int unit, soc_port_t port,
   5834                                int *obm_id, int *lane)
   5835 {
   5836     return soc_tomahawk_port_obm_info_get(unit, port, obm_id, lane);
   5837 }
   5838 
   5839 STATIC int
   5840 _soc_tomahawk2_idb_ca_reset(int unit)
   5841 {
   5842     soc_info_t *si = &SOC_INFO(unit);
   5843     _soc_tomahawk2_tdm_t *tdm = SOC_CONTROL(unit)->tdm_info;
   5844     int block_info_idx, pipe, clport, obm, port;
   5845     uint32 rval0, rval1;
   5846     soc_reg_t reg;
   5847     static const soc_reg_t obm_ca_ctrl_regs[] = {
   5848         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
   5849         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
   5850         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
   5851         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr,
   5852         IDB_OBM8_CA_CONTROLr, IDB_OBM9_CA_CONTROLr,
   5853         IDB_OBM10_CA_CONTROLr, IDB_OBM11_CA_CONTROLr,
   5854         IDB_OBM12_CA_CONTROLr, IDB_OBM13_CA_CONTROLr,
   5855         IDB_OBM14_CA_CONTROLr, IDB_OBM15_CA_CONTROLr
   5856     };
   5857     static const int hw_mode_values[SOC_TH_PORT_RATIO_COUNT] = {
   5858         0, 1, 1, 1, 3, 5, 4, 6, 2
   5859     };
   5860 
   5861     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   5862         port = SOC_BLOCK_PORT(unit, block_info_idx);
   5863         pipe = si->port_pipe[port];
   5864         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   5865         obm = clport & 0xF;
   5866 
   5867         /* Set cell assembly mode then toggle reset to send initial credit
   5868          * to EP */
   5869         reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
   5870         rval0 = 0;
   5871         soc_reg_field_set(unit, reg, &rval0, PORT_MODEf,
   5872                           hw_mode_values[tdm->port_ratio[clport]]);
   5873         rval1 = rval0;
   5874         soc_reg_field_set(unit, reg, &rval0, PORT0_RESETf, 1);
   5875         soc_reg_field_set(unit, reg, &rval0, PORT1_RESETf, 1);
   5876         soc_reg_field_set(unit, reg, &rval0, PORT2_RESETf, 1);
   5877         soc_reg_field_set(unit, reg, &rval0, PORT3_RESETf, 1);
   5878         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   5879         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval1));
   5880     }
   5881 
   5882     /* Toggle cpu port cell assembly reset */
   5883     reg = IDB_CA_CPU_CONTROLr;
   5884     rval0 = 0;
   5885     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   5886     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   5887     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   5888 
   5889     /* Toggle loopback port cell assembly reset */
   5890     reg = IDB_CA_LPBK_CONTROLr;
   5891     rval0 = 0;
   5892     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   5893     PBMP_LB_ITER(unit, port) {
   5894         reg = SOC_REG_UNIQUE_ACC(unit, IDB_CA_LPBK_CONTROLr)
   5895             [si->port_pipe[port]];
   5896         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   5897         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   5898     }
   5899 
   5900     return SOC_E_NONE;
   5901 }
   5902 
   5903 /*
   5904  * Function:
   5905  *      _soc_tomahawk2_idb_init
   5906  * Purpose:
   5907  *      IDB initialization, including Cell Assembly reset, Credit init, OBM init
   5908  * Parameters:
   5909  *      unit            - (IN)  Unit number.
   5910  * Returns:
   5911  *      SOC_E_xxx
   5912  * Notes:
   5913  *      The init sequences follow the guideline of TH2_SW_Init.docx
   5914  *          3.8	Cell Assembly Soft Reset
   5915  *          3.9	Enable Credit Propagation
   5916  *          4.1	Oversubscription Buffer Manager
   5917  *      The OBM setting follow the guideline of TH2_mmu_setting_v2.2.xlsx
   5918  */
   5919 int
   5920 _soc_tomahawk2_idb_init(int unit)
   5921 {
   5922 #define _TH2_CELLS_PER_OBM        4608 
   5923     soc_info_t *si;
   5924     soc_reg_t reg;
   5925     soc_mem_t mem;
   5926     soc_field_t field;
   5927     int block_info_idx, pipe, clport, obm, lane, port, lport, phy_port_base;
   5928     int lossless, prio, i, count, num_lanes, pipe_init_usec;
   5929     uint32 rval0, in_progress, pipe_map;
   5930     soc_timeout_t to;
   5931     uint64 rval64;
   5932     uint32 entry[SOC_MAX_MEM_WORDS];
   5933     static const struct obm_setting_s {
   5934         int discard_limit;
   5935         int lossless_discard;
   5936         int port_xoff;
   5937         int port_xon;
   5938         int lossless_xoff;
   5939         int lossless_xon;
   5940         int lossy_low_pri;
   5941         int lossy_discard;
   5942     } obm_settings[2][5] = {
   5943         /* LOSSY Settings*/
   5944         { /* indexed by number of lanes used in the port */
   5945             { /* 0 - invalid */ 0 },
   5946             { /* 1 lane */
   5947                 _TH2_CELLS_PER_OBM/4,           /* discard_limit */
   5948                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   5949                 _TH2_CELLS_PER_OBM,             /* port_xoff */
   5950                 _TH2_CELLS_PER_OBM,             /* port_xon */
   5951                 _TH2_CELLS_PER_OBM,             /* lossless_xoff */
   5952                 _TH2_CELLS_PER_OBM,             /* lossless_xon */
   5953                 768,                            /* lossy_low_pri */
   5954                 1148                            /* lossy_discard */
   5955             },
   5956             { /* 2 lanes */
   5957                 _TH2_CELLS_PER_OBM/2,           /* discard_limit */
   5958                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   5959                 _TH2_CELLS_PER_OBM,             /* port_xoff */
   5960                 _TH2_CELLS_PER_OBM,             /* port_xon */
   5961                 _TH2_CELLS_PER_OBM,             /* lossless_xoff */
   5962                 _TH2_CELLS_PER_OBM,             /* lossless_xon */
   5963                 1920,                           /* lossy_low_pri */
   5964                 2300                            /* lossy_discard */
   5965             },
   5966             { /* 3 - invalid  */ 0 },
   5967             { /* 4 lanes */
   5968                 _TH2_CELLS_PER_OBM,             /* discard_limit */
   5969                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   5970                 _TH2_CELLS_PER_OBM,             /* port_xoff */
   5971                 _TH2_CELLS_PER_OBM,             /* port_xon */
   5972                 _TH2_CELLS_PER_OBM,             /* lossless_xoff */
   5973                 _TH2_CELLS_PER_OBM,             /* lossless_xon */
   5974                 4224,                           /* lossy_low_pri */
   5975                 4604                            /* lossy_discard */
   5976             }
   5977         },
   5978         /* LOSSLESS Settings*/
   5979         { /* indexed by number of lanes used in the port */
   5980             { /* 0 - invalid */ 0 },
   5981             { /* 1 lane */
   5982                 _TH2_CELLS_PER_OBM/4,           /* discard_limit */
   5983                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   5984                 559,                            /* port_xoff */
   5985                 529,                            /* port_xon */
   5986                 129,                            /* lossless_xoff */
   5987                 99,                             /* lossless_xon */
   5988                 270,                            /* lossy_low_pri */
   5989                 654                             /* lossy_discard */
   5990             },
   5991             { /* 2 lanes */
   5992                 _TH2_CELLS_PER_OBM/2,           /* discard_limit */
   5993                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   5994                 1523,                           /* port_xoff */
   5995                 1493,                           /* port_xon */
   5996                 321,                            /* lossless_xoff */
   5997                 291,                            /* lossless_xon */
   5998                 270,                            /* lossy_low_pri */
   5999                 654                             /* lossy_discard */
   6000             },
   6001             { /* 3 - invalid  */ 0 },
   6002             { /* 4 lanes */
   6003                 _TH2_CELLS_PER_OBM,             /* discard_limit */
   6004                 _TH2_CELLS_PER_OBM,             /* lossless_discard */
   6005                 3827,                           /* port_xoff */
   6006                 3797,                           /* port_xon */
   6007                 768,                            /* lossless_xoff */
   6008                 738,                            /* lossless_xon */
   6009                 270,                            /* lossy_low_pri */
   6010                 654                             /* lossy_discard */
   6011             }
   6012         }
   6013     };
   6014     static const soc_reg_t obm_ctrl_regs[] = {
   6015         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
   6016         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
   6017         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
   6018         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr,
   6019         IDB_OBM8_CONTROLr, IDB_OBM9_CONTROLr,
   6020         IDB_OBM10_CONTROLr, IDB_OBM11_CONTROLr,
   6021         IDB_OBM12_CONTROLr, IDB_OBM13_CONTROLr,
   6022         IDB_OBM14_CONTROLr, IDB_OBM15_CONTROLr
   6023     };
   6024     static const soc_reg_t obm_thresh_regs[] = {
   6025         IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr,
   6026         IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr,
   6027         IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr,
   6028         IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr,
   6029         IDB_OBM8_THRESHOLDr, IDB_OBM9_THRESHOLDr,
   6030         IDB_OBM10_THRESHOLDr, IDB_OBM11_THRESHOLDr,
   6031         IDB_OBM12_THRESHOLDr, IDB_OBM13_THRESHOLDr,
   6032         IDB_OBM14_THRESHOLDr, IDB_OBM15_THRESHOLDr
   6033     };
   6034     static const soc_reg_t obm_thresh1_regs[] = {
   6035         IDB_OBM0_THRESHOLD_1r, IDB_OBM1_THRESHOLD_1r,
   6036         IDB_OBM2_THRESHOLD_1r, IDB_OBM3_THRESHOLD_1r,
   6037         IDB_OBM4_THRESHOLD_1r, IDB_OBM5_THRESHOLD_1r,
   6038         IDB_OBM6_THRESHOLD_1r, IDB_OBM7_THRESHOLD_1r,
   6039         IDB_OBM8_THRESHOLD_1r, IDB_OBM9_THRESHOLD_1r,
   6040         IDB_OBM10_THRESHOLD_1r, IDB_OBM11_THRESHOLD_1r,
   6041         IDB_OBM12_THRESHOLD_1r, IDB_OBM13_THRESHOLD_1r,
   6042         IDB_OBM14_THRESHOLD_1r, IDB_OBM15_THRESHOLD_1r
   6043     };
   6044     static const soc_reg_t tpid_regs[] = {
   6045         IDB_OBM0_OUTER_TPIDr, IDB_OBM1_OUTER_TPIDr,
   6046         IDB_OBM2_OUTER_TPIDr, IDB_OBM3_OUTER_TPIDr,
   6047         IDB_OBM4_OUTER_TPIDr, IDB_OBM5_OUTER_TPIDr,
   6048         IDB_OBM6_OUTER_TPIDr, IDB_OBM7_OUTER_TPIDr,
   6049         IDB_OBM8_OUTER_TPIDr, IDB_OBM9_OUTER_TPIDr,
   6050         IDB_OBM10_OUTER_TPIDr, IDB_OBM11_OUTER_TPIDr,
   6051         IDB_OBM12_OUTER_TPIDr, IDB_OBM13_OUTER_TPIDr,
   6052         IDB_OBM14_OUTER_TPIDr, IDB_OBM15_OUTER_TPIDr
   6053     };
   6054     static const soc_reg_t obm_fc_thresh_regs[] = {
   6055         IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr,
   6056         IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr,
   6057         IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr,
   6058         IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr,
   6059         IDB_OBM8_FC_THRESHOLDr, IDB_OBM9_FC_THRESHOLDr,
   6060         IDB_OBM10_FC_THRESHOLDr, IDB_OBM11_FC_THRESHOLDr,
   6061         IDB_OBM12_FC_THRESHOLDr, IDB_OBM13_FC_THRESHOLDr,
   6062         IDB_OBM14_FC_THRESHOLDr, IDB_OBM15_FC_THRESHOLDr
   6063     };
   6064     static const soc_reg_t obm_fc_thresh1_regs[] = {
   6065         IDB_OBM0_FC_THRESHOLD_1r, IDB_OBM1_FC_THRESHOLD_1r,
   6066         IDB_OBM2_FC_THRESHOLD_1r, IDB_OBM3_FC_THRESHOLD_1r,
   6067         IDB_OBM4_FC_THRESHOLD_1r, IDB_OBM5_FC_THRESHOLD_1r,
   6068         IDB_OBM6_FC_THRESHOLD_1r, IDB_OBM7_FC_THRESHOLD_1r,
   6069         IDB_OBM8_FC_THRESHOLD_1r, IDB_OBM9_FC_THRESHOLD_1r,
   6070         IDB_OBM10_FC_THRESHOLD_1r, IDB_OBM11_FC_THRESHOLD_1r,
   6071         IDB_OBM12_FC_THRESHOLD_1r, IDB_OBM13_FC_THRESHOLD_1r,
   6072         IDB_OBM14_FC_THRESHOLD_1r, IDB_OBM15_FC_THRESHOLD_1r
   6073     };
   6074     static const soc_reg_t obm_shared_regs[] = {
   6075         IDB_OBM0_SHARED_CONFIGr, IDB_OBM1_SHARED_CONFIGr,
   6076         IDB_OBM2_SHARED_CONFIGr, IDB_OBM3_SHARED_CONFIGr,
   6077         IDB_OBM4_SHARED_CONFIGr, IDB_OBM5_SHARED_CONFIGr,
   6078         IDB_OBM6_SHARED_CONFIGr, IDB_OBM7_SHARED_CONFIGr,
   6079         IDB_OBM8_SHARED_CONFIGr, IDB_OBM9_SHARED_CONFIGr,
   6080         IDB_OBM10_SHARED_CONFIGr, IDB_OBM11_SHARED_CONFIGr,
   6081         IDB_OBM12_SHARED_CONFIGr, IDB_OBM13_SHARED_CONFIGr,
   6082         IDB_OBM14_SHARED_CONFIGr, IDB_OBM15_SHARED_CONFIGr
   6083     };
   6084     static const soc_reg_t obm_max_usage_regs[] = {
   6085         IDB_OBM0_MAX_USAGE_SELECTr, IDB_OBM1_MAX_USAGE_SELECTr,
   6086         IDB_OBM2_MAX_USAGE_SELECTr, IDB_OBM3_MAX_USAGE_SELECTr,
   6087         IDB_OBM4_MAX_USAGE_SELECTr, IDB_OBM5_MAX_USAGE_SELECTr,
   6088         IDB_OBM6_MAX_USAGE_SELECTr, IDB_OBM7_MAX_USAGE_SELECTr,
   6089         IDB_OBM8_MAX_USAGE_SELECTr, IDB_OBM9_MAX_USAGE_SELECTr,
   6090         IDB_OBM10_MAX_USAGE_SELECTr, IDB_OBM11_MAX_USAGE_SELECTr,
   6091         IDB_OBM12_MAX_USAGE_SELECTr, IDB_OBM13_MAX_USAGE_SELECTr,
   6092         IDB_OBM14_MAX_USAGE_SELECTr, IDB_OBM15_MAX_USAGE_SELECTr
   6093     };
   6094     static const soc_reg_t obm_port_config_regs[] = {
   6095         IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
   6096         IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr,
   6097         IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr,
   6098         IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr,
   6099         IDB_OBM8_PORT_CONFIGr, IDB_OBM9_PORT_CONFIGr,
   6100         IDB_OBM10_PORT_CONFIGr, IDB_OBM11_PORT_CONFIGr,
   6101         IDB_OBM12_PORT_CONFIGr, IDB_OBM13_PORT_CONFIGr,
   6102         IDB_OBM14_PORT_CONFIGr, IDB_OBM15_PORT_CONFIGr
   6103     };
   6104     static const soc_reg_t obm_fc_config_regs[] = {
   6105         IDB_OBM0_FLOW_CONTROL_CONFIGr, IDB_OBM1_FLOW_CONTROL_CONFIGr,
   6106         IDB_OBM2_FLOW_CONTROL_CONFIGr, IDB_OBM3_FLOW_CONTROL_CONFIGr,
   6107         IDB_OBM4_FLOW_CONTROL_CONFIGr, IDB_OBM5_FLOW_CONTROL_CONFIGr,
   6108         IDB_OBM6_FLOW_CONTROL_CONFIGr, IDB_OBM7_FLOW_CONTROL_CONFIGr,
   6109         IDB_OBM8_FLOW_CONTROL_CONFIGr, IDB_OBM9_FLOW_CONTROL_CONFIGr,
   6110         IDB_OBM10_FLOW_CONTROL_CONFIGr, IDB_OBM11_FLOW_CONTROL_CONFIGr,
   6111         IDB_OBM12_FLOW_CONTROL_CONFIGr, IDB_OBM13_FLOW_CONTROL_CONFIGr,
   6112         IDB_OBM14_FLOW_CONTROL_CONFIGr, IDB_OBM15_FLOW_CONTROL_CONFIGr
   6113     };
   6114     static const soc_field_t obm_bypass_fields[] = {
   6115         PORT0_BYPASS_ENABLEf, PORT1_BYPASS_ENABLEf,
   6116         PORT2_BYPASS_ENABLEf, PORT3_BYPASS_ENABLEf
   6117     };
   6118     static const soc_field_t obm_oversub_fields[] = {
   6119         PORT0_OVERSUB_ENABLEf, PORT1_OVERSUB_ENABLEf,
   6120         PORT2_OVERSUB_ENABLEf, PORT3_OVERSUB_ENABLEf
   6121     };
   6122     static const soc_field_t obm_ca_sop_fields[] = {
   6123         PORT0_CA_SOPf, PORT1_CA_SOPf, PORT2_CA_SOPf, PORT3_CA_SOPf
   6124     };
   6125     static const soc_mem_t obm_pri_map_mem[][4] = {
   6126         {IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
   6127          IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m
   6128         },
   6129         {IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
   6130          IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m
   6131         },
   6132         {IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
   6133          IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m
   6134         },
   6135         {IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
   6136          IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m
   6137         },
   6138         {IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
   6139          IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m
   6140         },
   6141         {IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
   6142          IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m
   6143         },
   6144         {IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
   6145          IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m
   6146         },
   6147         {IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
   6148          IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
   6149         },
   6150         {IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m,
   6151          IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m
   6152         },
   6153         {IDB_OBM9_PRI_MAP_PORT0m, IDB_OBM9_PRI_MAP_PORT1m,
   6154          IDB_OBM9_PRI_MAP_PORT2m, IDB_OBM9_PRI_MAP_PORT3m
   6155         },
   6156         {IDB_OBM10_PRI_MAP_PORT0m, IDB_OBM10_PRI_MAP_PORT1m,
   6157          IDB_OBM10_PRI_MAP_PORT2m, IDB_OBM10_PRI_MAP_PORT3m
   6158         },
   6159         {IDB_OBM11_PRI_MAP_PORT0m, IDB_OBM11_PRI_MAP_PORT1m,
   6160          IDB_OBM11_PRI_MAP_PORT2m, IDB_OBM11_PRI_MAP_PORT3m
   6161         },
   6162         {IDB_OBM12_PRI_MAP_PORT0m, IDB_OBM12_PRI_MAP_PORT1m,
   6163          IDB_OBM12_PRI_MAP_PORT2m, IDB_OBM12_PRI_MAP_PORT3m
   6164         },
   6165         {IDB_OBM13_PRI_MAP_PORT0m, IDB_OBM13_PRI_MAP_PORT1m,
   6166          IDB_OBM13_PRI_MAP_PORT2m, IDB_OBM13_PRI_MAP_PORT3m
   6167         },
   6168         {IDB_OBM14_PRI_MAP_PORT0m, IDB_OBM14_PRI_MAP_PORT1m,
   6169          IDB_OBM14_PRI_MAP_PORT2m, IDB_OBM14_PRI_MAP_PORT3m
   6170         },
   6171         {IDB_OBM15_PRI_MAP_PORT0m, IDB_OBM15_PRI_MAP_PORT1m,
   6172          IDB_OBM15_PRI_MAP_PORT2m, IDB_OBM15_PRI_MAP_PORT3m
   6173         },
   6174     };
   6175     static const soc_field_t obm_ob_pri_fields[] = {
   6176         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
   6177         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
   6178         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
   6179         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
   6180         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
   6181         OFFSET15_OB_PRIORITYf
   6182     };
   6183 
   6184     si = &SOC_INFO(unit);
   6185     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
   6186 
   6187     /* Cell Assembly Soft Reset */
   6188     SOC_IF_ERROR_RETURN(_soc_tomahawk2_idb_ca_reset(unit));
   6189 
   6190     /* Prepare pri_map entry value for the loop below */
   6191     sal_memset(entry, 0, sizeof(idb_obm0_pri_map_port0_entry_t));
   6192     mem = SOC_MEM_UNIQUE_ACC(unit, obm_pri_map_mem[0][0])[0];
   6193     count = COUNTOF(obm_ob_pri_fields);
   6194     prio = (lossless ? 2 : 0);
   6195     for (i = 0; i < count; i++) {
   6196         soc_mem_field32_set(unit, mem, entry, obm_ob_pri_fields[i], prio);
   6197     }
   6198 
   6199     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   6200         port = SOC_BLOCK_PORT(unit, block_info_idx);
   6201         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   6202         pipe = si->port_pipe[port];
   6203         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   6204         obm = clport & 0xF;
   6205 
   6206         /*4.1.1	Aggregate Thresholds */
   6207         /* Enable oversub */
   6208         reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
   6209         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));
   6210         for (lane = 0; lane < _TH2_PORTS_PER_PBLK; lane++) {
   6211             if (si->port_p2l_mapping[phy_port_base + lane] == -1) {
   6212                 continue;
   6213             }
   6214             field = obm_bypass_fields[lane];
   6215             soc_reg_field_set(unit, reg, &rval0, field, 1);
   6216             field = obm_oversub_fields[lane];
   6217             soc_reg_field_set(unit, reg, &rval0, field, 1);
   6218             lport = si->port_p2l_mapping[phy_port_base + lane];
   6219             if (si->port_init_speed[lport]< 100000) {
   6220                 field = obm_ca_sop_fields[lane];
   6221                 soc_reg_field_set(unit, reg, &rval0, field, 0);
   6222             }
   6223         }
   6224 
   6225         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6226         if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   6227             continue;
   6228         }
   6229 
   6230         /* Configure shared config */
   6231         reg = SOC_REG_UNIQUE_ACC(unit, obm_shared_regs[obm])[pipe];
   6232         SOC_IF_ERROR_RETURN
   6233             (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   6234         soc_reg64_field32_set(unit, reg, &rval64, DISCARD_THRESHOLDf,
   6235                               _TH2_CELLS_PER_OBM);
   6236         soc_reg64_field32_set(unit, reg, &rval64, SOP_THRESHOLDf,
   6237                               _TH2_CELLS_PER_OBM);
   6238         soc_reg64_field32_set(unit, reg, &rval64, SOP_DISCARD_MODEf, 1);
   6239         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   6240 
   6241         /* IDB OBM Max Usage Counter Configuration */
   6242         rval0 = 0;
   6243         reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[obm])[pipe];
   6244         soc_reg_field_set(unit, reg, &rval0, PRIORITY_SELECTf, 0);
   6245         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6246 
   6247         for (lane = 0; lane < _TH2_PORTS_PER_PBLK; lane++) {
   6248             port = si->port_p2l_mapping[phy_port_base + lane];
   6249             if (port == -1) {
   6250                 continue;
   6251             }
   6252             num_lanes = si->port_num_lanes[port];
   6253 
   6254             /* 4.1.2    Per Port Thresholds */
   6255             /* Configure threshold */
   6256             reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
   6257             SOC_IF_ERROR_RETURN
   6258                 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6259             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
   6260                             _TH2_CELLS_PER_OBM);
   6261             soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf,
   6262                             obm_settings[lossless][num_lanes].lossy_discard);
   6263             soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf,
   6264                             obm_settings[lossless][num_lanes].lossy_low_pri);
   6265             soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0);
   6266             SOC_IF_ERROR_RETURN
   6267                 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6268 
   6269             /* Configure threshold_1 */
   6270             reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh1_regs[obm])[pipe];
   6271             SOC_IF_ERROR_RETURN
   6272                 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6273             soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf,
   6274                             obm_settings[lossless][num_lanes].discard_limit);
   6275             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
   6276                             _TH2_CELLS_PER_OBM);
   6277             SOC_IF_ERROR_RETURN
   6278                 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6279 
   6280             /* Configure pri_map table */
   6281             mem = SOC_MEM_UNIQUE_ACC
   6282                     (unit, obm_pri_map_mem[obm][lane])[pipe];
   6283             SOC_IF_ERROR_RETURN
   6284                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   6285 
   6286             /* Configure OBM Port config */
   6287             rval0 = 0;
   6288             reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[obm])[pipe];
   6289             soc_reg_field_set(unit, reg, &rval0, PORT_PRIf, 2);
   6290             SOC_IF_ERROR_RETURN
   6291                 (soc_reg32_set(unit, reg, REG_PORT_ANY, lane, rval0));
   6292 
   6293             /* Configure Outer TPID */
   6294             rval0 = 0;
   6295             reg = SOC_REG_UNIQUE_ACC(unit, tpid_regs[obm])[pipe];
   6296             soc_reg_field_set(unit, reg, &rval0, ENABLEf, 1);
   6297             soc_reg_field_set(unit, reg, &rval0, TPIDf, 0x8100);
   6298             SOC_IF_ERROR_RETURN
   6299                 (soc_reg32_set(unit, reg, REG_PORT_ANY, lane, rval0));
   6300 
   6301             /* 4.1.3	Flow Control Thresholds */
   6302             /* Configure flow control threshold */
   6303             reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
   6304             SOC_IF_ERROR_RETURN
   6305                 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6306             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf,
   6307                             obm_settings[lossless][num_lanes].lossless_xon);
   6308             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
   6309                             obm_settings[lossless][num_lanes].lossless_xoff);
   6310             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf,
   6311                             obm_settings[lossless][num_lanes].lossless_xon);
   6312             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
   6313                             obm_settings[lossless][num_lanes].lossless_xoff);
   6314             SOC_IF_ERROR_RETURN
   6315                 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6316 
   6317             /* Configure flow control threshold_1 */
   6318             reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh1_regs[obm])[pipe];
   6319             SOC_IF_ERROR_RETURN
   6320                 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6321             soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf,
   6322                             obm_settings[lossless][num_lanes].port_xon);
   6323             soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf,
   6324                             obm_settings[lossless][num_lanes].port_xoff);
   6325             SOC_IF_ERROR_RETURN
   6326                 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6327 
   6328             /* Configure flow control config */
   6329             reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_config_regs[obm])[pipe];
   6330             SOC_IF_ERROR_RETURN
   6331                 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6332             soc_reg64_field32_set(unit, reg, &rval64, PORT_FC_ENf, lossless);
   6333             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_FC_ENf,
   6334                                   lossless);
   6335             soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_FC_ENf, 0);
   6336             soc_reg64_field32_set(unit, reg, &rval64,
   6337                                   LOSSLESS0_PRIORITY_PROFILEf,
   6338                                   (lossless ? 0xffff : 0));
   6339             soc_reg64_field32_set(unit, reg, &rval64,
   6340                                   LOSSLESS1_PRIORITY_PROFILEf, 0);
   6341             SOC_IF_ERROR_RETURN
   6342                 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6343         }
   6344     }
   6345 
   6346     /* Set IDB DPP configuration control register to release credits to IS */
   6347     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   6348 
   6349     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
   6350         if (!(pipe_map & (1 << pipe))) {
   6351             continue;
   6352         }
   6353         reg = SOC_REG_UNIQUE_ACC(unit, IDB_DPP_CTRLr)[pipe];
   6354         SOC_IF_ERROR_RETURN
   6355             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));        
   6356         soc_reg_field_set(unit, reg, &rval0, CREDITSf, 32);
   6357         soc_reg_field_set(unit, reg, &rval0, STARTf, 1);
   6358         soc_reg_field_set(unit, reg, &rval0, DONEf, 0);
   6359         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6360     }
   6361 
   6362     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   6363     if (SAL_BOOT_SIMULATION) {
   6364         pipe_init_usec = 10000000;
   6365     } else {
   6366         pipe_init_usec = 50000;
   6367     }
   6368     soc_timeout_init(&to, pipe_init_usec, 0);
   6369 
   6370     /* Wait for DPP credit initialization done */
   6371     in_progress = pipe_map;
   6372     do {
   6373         for (pipe = 0; pipe < _TH2_PIPES_PER_DEV && in_progress; pipe++) {
   6374             reg = SOC_REG_UNIQUE_ACC(unit, IDB_DPP_CTRLr)[pipe];
   6375             if (in_progress & (1 << pipe)) { /* not done yet */
   6376                 SOC_IF_ERROR_RETURN
   6377                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));
   6378                 if (soc_reg_field_get(unit, reg, rval0, DONEf)) {
   6379                     in_progress ^= (1 << pipe);
   6380                 }
   6381             }
   6382         }
   6383         if (soc_timeout_check(&to)) {
   6384             LOG_WARN(BSL_LS_SOC_COMMON,
   6385                      (BSL_META_U(unit,
   6386                                  "unit %d : IDB_DPP_CTRL timeout\n"), unit));
   6387             break;
   6388         }
   6389     } while (in_progress != 0);
   6390 
   6391     return SOC_E_NONE;
   6392 }
   6393 
   6394 #ifdef BCM_WARM_BOOT_SUPPORT
   6395 
   6396 #define SOC_TDM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
   6397 #define SOC_TDM_WB_DEFAULT_VERSION            SOC_TDM_WB_VERSION_1_0
   6398 
   6399 int soc_th2_tdm_scache_allocate(int unit)
   6400 {
   6401     int rv = SOC_E_NONE;
   6402     uint8 *tdm_scache_ptr;
   6403     soc_scache_handle_t scache_handle;
   6404     uint32 alloc_get = 0;
   6405     uint32 alloc_size = 0;
   6406     int stable_size;
   6407     int default_ver = SOC_TDM_WB_DEFAULT_VERSION;
   6408     int ilen, ovs_size, pkt_shp_size, hpipes;
   6409 
   6410     ilen = sizeof(int);
   6411     ovs_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6412                _TH2_OVS_GROUP_COUNT_PER_HPIPE *
   6413                _TH2_OVS_GROUP_TDM_LENGTH;
   6414     pkt_shp_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6415                    _TH2_PKT_SCH_LENGTH;
   6416     hpipes = _TH2_PIPES_PER_DEV * _TH2_OVS_HPIPE_COUNT_PER_PIPE;
   6417 
   6418     alloc_size = (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   6419                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   6420                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   6421                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   6422                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   6423                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   6424                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   6425                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   6426                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe2 */
   6427                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe2 */
   6428                  (ilen * ovs_size)     + /* Oversub group info on pipe2 */
   6429                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe2     */
   6430                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe3 */
   6431                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe3 */
   6432                  (ilen * ovs_size)     + /* Oversub group info on pipe3 */
   6433                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe3     */
   6434                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   6435                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   6436                  (ilen * _TH2_PBLKS_PER_DEV)     + /* port ratio */
   6437                  (ilen * hpipes);                  /* oversub ratio */
   6438     alloc_get = alloc_size;
   6439 
   6440     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   6441     /* check to see if an scache table has been configured */
   6442     rv = soc_stable_size_get(unit, &stable_size);
   6443     if (SOC_FAILURE(rv) || stable_size <= 0) {
   6444         return rv;
   6445     }
   6446 
   6447     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   6448                                       TRUE, &alloc_get,
   6449                                       &tdm_scache_ptr,
   6450                                       default_ver,
   6451                                       NULL);
   6452 
   6453     if (rv  == SOC_E_CONFIG) {
   6454         /* Probably Level1 */
   6455         return SOC_E_NONE;
   6456     }
   6457     /* NotRequired but just to confirm Get the pointer for the Level 2 cache */
   6458     if (alloc_get != alloc_size) {
   6459         /* Expected size doesn't match retrieved size */
   6460         LOG_ERROR(BSL_LS_SOC_COMMON,
   6461                   (BSL_META_U(unit,
   6462                   "ERROR: scache memory for tdm size mismatch"
   6463                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   6464         return SOC_E_INTERNAL;
   6465     }
   6466 
   6467     if (NULL == tdm_scache_ptr) {
   6468         LOG_ERROR(BSL_LS_SOC_COMMON,
   6469                   (BSL_META_U(unit,
   6470                   "ERROR: scache memory not allocated for tdm"
   6471                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   6472         return SOC_E_MEMORY;
   6473     }
   6474     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6475                 (BSL_META_U(unit,
   6476                 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   6477     return SOC_E_NONE;
   6478 }
   6479 
   6480 /*
   6481  * Function:
   6482  *      soc_th2_tdm_scache_sync
   6483  * Purpose:
   6484  *      Record TDM info that maybe changed during flexport for Level 2 WB
   6485  *
   6486  * Warm Boot Version Map:
   6487  *
   6488  *  BCM_WB_VERSION_1_0
   6489  *    IDB TDM info on pipe0
   6490  *    MMU TDM info on pipe0
   6491  *    Oversub group info on pipe0
   6492  *    pkt shaper info on pipe0
   6493  *    IDB TDM info on pipe1
   6494  *    MMU TDM info on pipe1
   6495  *    Oversub group info on pipe1
   6496  *    pkt shaper info on pipe1
   6497  *    IDB TDM info on pipe2
   6498  *    MMU TDM info on pipe2
   6499  *    Oversub group info on pipe2
   6500  *    pkt shaper info on pipe2
   6501  *    IDB TDM info on pipe3
   6502  *    MMU TDM info on pipe3
   6503  *    Oversub group info on pipe3
   6504  *    pkt shaper info on pipe3
   6505  *    hpipe id of phy-port
   6506  *    pblk id of phy-port
   6507  *    port ratio
   6508  *    oversub ratio
   6509  *
   6510  * Parameters:
   6511  *      unit - StrataSwitch unit number.
   6512  * Returns:
   6513  *      SOC_E_XXX
   6514  */
   6515 int soc_th2_tdm_scache_sync(int unit)
   6516 {
   6517     uint8 *tdm_scache_ptr;
   6518     soc_scache_handle_t scache_handle;
   6519     uint32 alloc_get = 0;
   6520     uint32 alloc_size = 0;
   6521     uint32 var_size = 0;
   6522     uint32 scache_offset=0;
   6523     int rv = 0;
   6524     int ilen, ovs_size, pkt_shp_size, hpipes, phy_port;
   6525     _soc_tomahawk2_tdm_t *tdm = SOC_CONTROL(unit)->tdm_info;
   6526 
   6527     ilen = sizeof(int);
   6528     ovs_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6529                _TH2_OVS_GROUP_COUNT_PER_HPIPE *
   6530                _TH2_OVS_GROUP_TDM_LENGTH;
   6531     pkt_shp_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6532                    _TH2_PKT_SCH_LENGTH;
   6533     hpipes = _TH2_PIPES_PER_DEV * _TH2_OVS_HPIPE_COUNT_PER_PIPE;
   6534 
   6535     alloc_size = (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   6536                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   6537                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   6538                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   6539                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   6540                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   6541                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   6542                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   6543                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe2 */
   6544                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe2 */
   6545                  (ilen * ovs_size)     + /* Oversub group info on pipe2 */
   6546                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe2     */
   6547                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe3 */
   6548                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe3 */
   6549                  (ilen * ovs_size)     + /* Oversub group info on pipe3 */
   6550                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe3     */
   6551                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   6552                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   6553                  (ilen * _TH2_PBLKS_PER_DEV)     + /* port ratio */
   6554                  (ilen * hpipes);                  /* oversub ratio */
   6555     alloc_get = alloc_size;
   6556 
   6557     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   6558     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   6559                                       FALSE, &alloc_get,
   6560                                       &tdm_scache_ptr,
   6561                                       SOC_TDM_WB_DEFAULT_VERSION,
   6562                                       NULL);
   6563     if (rv == SOC_E_NOT_FOUND) {
   6564         /* Probably Level1 */
   6565         return SOC_E_NONE;
   6566     }
   6567 
   6568     if (NULL == tdm_scache_ptr) {
   6569         LOG_ERROR(BSL_LS_SOC_COMMON,
   6570                   (BSL_META_U(unit,
   6571                   "ERROR: scache memory not allocated for tdm"
   6572                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   6573         return SOC_E_MEMORY;
   6574     }
   6575 
   6576     /* IDB TDM info on pipe0 */
   6577     var_size = ilen * _TH2_TDM_LENGTH;
   6578     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6579                tdm->tdm_pipe[0].idb_tdm,
   6580                var_size);
   6581     scache_offset += var_size;
   6582 
   6583     /* MMU TDM info on pipe0 */
   6584     var_size = ilen * _TH2_TDM_LENGTH;
   6585     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6586                tdm->tdm_pipe[0].mmu_tdm,
   6587                var_size);
   6588     scache_offset += var_size;
   6589 
   6590     /* Oversub group info on pipe0 */
   6591     var_size = ilen * ovs_size;
   6592     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6593                tdm->tdm_pipe[0].ovs_tdm,
   6594                var_size);
   6595     scache_offset += var_size;
   6596 
   6597     /* pkt shaper info on pipe0 */
   6598     var_size = ilen * pkt_shp_size;
   6599     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6600                tdm->tdm_pipe[0].pkt_shaper_tdm,
   6601                var_size);
   6602     scache_offset += var_size;
   6603 
   6604     /* IDB TDM info on pipe1 */
   6605     var_size = ilen * _TH2_TDM_LENGTH;
   6606     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6607                tdm->tdm_pipe[1].idb_tdm,
   6608                var_size);
   6609     scache_offset += var_size;
   6610 
   6611     /* MMU TDM info on pipe1 */
   6612     var_size = ilen * _TH2_TDM_LENGTH;
   6613     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6614                tdm->tdm_pipe[1].mmu_tdm,
   6615                var_size);
   6616     scache_offset += var_size;
   6617 
   6618     /* Oversub group info on pipe1 */
   6619     var_size = ilen * ovs_size;
   6620     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6621                tdm->tdm_pipe[1].ovs_tdm,
   6622                var_size);
   6623     scache_offset += var_size;
   6624 
   6625     /* pkt shaper info on pipe1 */
   6626     var_size = ilen * pkt_shp_size;
   6627     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6628                tdm->tdm_pipe[1].pkt_shaper_tdm,
   6629                var_size);
   6630     scache_offset += var_size;
   6631 
   6632     /* IDB TDM info on pipe2 */
   6633     var_size = ilen * _TH2_TDM_LENGTH;
   6634     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6635                tdm->tdm_pipe[2].idb_tdm,
   6636                var_size);
   6637     scache_offset += var_size;
   6638 
   6639     /* MMU TDM info on pipe2 */
   6640     var_size = ilen * _TH2_TDM_LENGTH;
   6641     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6642                tdm->tdm_pipe[2].mmu_tdm,
   6643                var_size);
   6644     scache_offset += var_size;
   6645 
   6646     /* Oversub group info on pipe2 */
   6647     var_size = ilen * ovs_size;
   6648     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6649                tdm->tdm_pipe[2].ovs_tdm,
   6650                var_size);
   6651     scache_offset += var_size;
   6652 
   6653     /* pkt shaper info on pipe2 */
   6654     var_size = ilen * pkt_shp_size;
   6655     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6656                tdm->tdm_pipe[2].pkt_shaper_tdm,
   6657                var_size);
   6658     scache_offset += var_size;
   6659 
   6660     /* IDB TDM info on pipe3 */
   6661     var_size = ilen * _TH2_TDM_LENGTH;
   6662     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6663                tdm->tdm_pipe[3].idb_tdm,
   6664                var_size);
   6665     scache_offset += var_size;
   6666 
   6667     /* MMU TDM info on pipe3 */
   6668     var_size = ilen * _TH2_TDM_LENGTH;
   6669     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6670                tdm->tdm_pipe[3].mmu_tdm,
   6671                var_size);
   6672     scache_offset += var_size;
   6673 
   6674     /* Oversub group info on pipe3 */
   6675     var_size = ilen * ovs_size;
   6676     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6677                tdm->tdm_pipe[3].ovs_tdm,
   6678                var_size);
   6679     scache_offset += var_size;
   6680 
   6681     /* pkt shaper info on pipe3 */
   6682     var_size = ilen * pkt_shp_size;
   6683     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6684                tdm->tdm_pipe[3].pkt_shaper_tdm,
   6685                var_size);
   6686     scache_offset += var_size;
   6687 
   6688     /* hpipe id of phy-port */
   6689     for (phy_port = 0; phy_port < _TH2_PHY_PORTS_PER_DEV; phy_port++) {
   6690         var_size = ilen;
   6691         sal_memcpy(&tdm_scache_ptr[scache_offset],
   6692                    &tdm->pblk_info[phy_port].pblk_hpipe_num,
   6693                    var_size);
   6694         scache_offset += var_size;
   6695     }
   6696 
   6697     /* pblk id of phy-port */
   6698     for (phy_port = 0; phy_port < _TH2_PHY_PORTS_PER_DEV; phy_port++) {
   6699         var_size = ilen;
   6700         sal_memcpy(&tdm_scache_ptr[scache_offset],
   6701                    &tdm->pblk_info[phy_port].pblk_cal_idx,
   6702                    var_size);
   6703         scache_offset += var_size;
   6704     }
   6705 
   6706     /* port ratio */
   6707     var_size = ilen * _TH2_PBLKS_PER_DEV;
   6708     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6709                tdm->port_ratio,
   6710                var_size);
   6711     scache_offset += var_size;
   6712 
   6713     /* oversub ratio */
   6714     var_size = ilen * hpipes;
   6715     sal_memcpy(&tdm_scache_ptr[scache_offset],
   6716                tdm->ovs_ratio_x1000,
   6717                var_size);
   6718     scache_offset += var_size;
   6719 
   6720     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6721                 (BSL_META_U(unit,
   6722                 "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   6723 
   6724     return SOC_E_NONE;
   6725 }
   6726 
   6727 /*
   6728  * Function:
   6729  *      soc_th2_tdm_scache_recovery
   6730  * Purpose:
   6731  *      Recover TDM info that maybe changed during flexport for Level 2 WB
   6732  *
   6733  * Warm Boot Version Map:
   6734  *
   6735  *  BCM_WB_VERSION_1_0
   6736  *    IDB TDM info on pipe0
   6737  *    MMU TDM info on pipe0
   6738  *    Oversub group info on pipe0
   6739  *    pkt shaper info on pipe0
   6740  *    IDB TDM info on pipe1
   6741  *    MMU TDM info on pipe1
   6742  *    Oversub group info on pipe1
   6743  *    pkt shaper info on pipe1
   6744  *    IDB TDM info on pipe2
   6745  *    MMU TDM info on pipe2
   6746  *    Oversub group info on pipe2
   6747  *    pkt shaper info on pipe2
   6748  *    IDB TDM info on pipe3
   6749  *    MMU TDM info on pipe3
   6750  *    Oversub group info on pipe3
   6751  *    pkt shaper info on pipe3
   6752  *    hpipe id of phy-port
   6753  *    pblk id of phy-port
   6754  *    port ratio
   6755  *    oversub ratio
   6756  *
   6757  * Parameters:
   6758  *      unit - StrataSwitch unit number.
   6759  * Returns:
   6760  *      SOC_E_XXX
   6761  */
   6762 int soc_th2_tdm_scache_recovery(int unit)
   6763 {
   6764     uint32 alloc_get = 0;
   6765     uint32 alloc_size = 0;
   6766     int rv = SOC_E_NONE;
   6767     uint8 *tdm_scache_ptr = NULL;
   6768     soc_scache_handle_t scache_handle;
   6769     uint32 scache_offset=0;
   6770     uint32 var_size = 0;
   6771     uint16 recovered_ver = 0;
   6772     int ilen, ovs_size, pkt_shp_size, hpipes, phy_port;
   6773     _soc_tomahawk2_tdm_t *tdm = SOC_CONTROL(unit)->tdm_info;
   6774 
   6775     ilen = sizeof(int);
   6776     ovs_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6777                _TH2_OVS_GROUP_COUNT_PER_HPIPE *
   6778                _TH2_OVS_GROUP_TDM_LENGTH;
   6779     pkt_shp_size = _TH2_OVS_HPIPE_COUNT_PER_PIPE *
   6780                    _TH2_PKT_SCH_LENGTH;
   6781     hpipes = _TH2_PIPES_PER_DEV * _TH2_OVS_HPIPE_COUNT_PER_PIPE;
   6782 
   6783     alloc_size = (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   6784                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   6785                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   6786                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   6787                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   6788                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   6789                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   6790                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   6791                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe2 */
   6792                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe2 */
   6793                  (ilen * ovs_size)     + /* Oversub group info on pipe2 */
   6794                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe2     */
   6795                  (ilen * _TH2_TDM_LENGTH) + /* IDB TDM info on pipe3 */
   6796                  (ilen * _TH2_TDM_LENGTH) + /* MMU TDM info on pipe3 */
   6797                  (ilen * ovs_size)     + /* Oversub group info on pipe3 */
   6798                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe3     */
   6799                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   6800                  (ilen * _TH2_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   6801                  (ilen * _TH2_PBLKS_PER_DEV)     + /* port ratio */
   6802                  (ilen * hpipes);                  /* oversub ratio */
   6803     alloc_get = alloc_size;
   6804 
   6805     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   6806     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   6807                                       FALSE, &alloc_get,
   6808                                       &tdm_scache_ptr,
   6809                                       SOC_TDM_WB_DEFAULT_VERSION,
   6810                                       &recovered_ver);
   6811     if (SOC_FAILURE(rv)) {
   6812         if ((rv == SOC_E_CONFIG) ||
   6813             (rv == SOC_E_NOT_FOUND)) {
   6814             /* warmboot file does not contain this
   6815              * module, or the warmboot state does not exist.
   6816              * in this case return SOC_E_NOT_FOUND
   6817              */
   6818             return SOC_E_NOT_FOUND;
   6819         } else {
   6820             /* Only Level2 - flexport treat this as a error */
   6821             LOG_ERROR(BSL_LS_SOC_COMMON,
   6822                       (BSL_META_U(unit,
   6823                       "Failed to recover scache data - %s\n"),soc_errmsg(rv)));
   6824             return rv;
   6825         }
   6826     }
   6827 
   6828     if (NULL == tdm_scache_ptr) {
   6829         LOG_ERROR(BSL_LS_SOC_COMMON,
   6830                   (BSL_META_U(unit,
   6831                   "ERROR: scache recovery for tdm"
   6832                   "%s()[LINE:%d] DONE \n"),
   6833                   FUNCTION_NAME(),  __LINE__));
   6834         return SOC_E_MEMORY;
   6835     }
   6836 
   6837     /* IDB TDM info on pipe0 */
   6838     var_size = ilen * _TH2_TDM_LENGTH;
   6839     sal_memcpy(tdm->tdm_pipe[0].idb_tdm,
   6840                &tdm_scache_ptr[scache_offset],
   6841                var_size);
   6842     scache_offset += var_size;
   6843 
   6844     /* MMU TDM info on pipe0 */
   6845     var_size = ilen * _TH2_TDM_LENGTH;
   6846     sal_memcpy(tdm->tdm_pipe[0].mmu_tdm,
   6847                &tdm_scache_ptr[scache_offset],
   6848                var_size);
   6849     scache_offset += var_size;
   6850 
   6851     /* Oversub group info on pipe0 */
   6852     var_size = ilen * ovs_size;
   6853     sal_memcpy(tdm->tdm_pipe[0].ovs_tdm,
   6854                &tdm_scache_ptr[scache_offset],
   6855                var_size);
   6856     scache_offset += var_size;
   6857 
   6858     /* pkt shaper info on pipe0 */
   6859     var_size = ilen * pkt_shp_size;
   6860     sal_memcpy(tdm->tdm_pipe[0].pkt_shaper_tdm,
   6861                &tdm_scache_ptr[scache_offset],
   6862                var_size);
   6863     scache_offset += var_size;
   6864 
   6865     /* IDB TDM info on pipe1 */
   6866     var_size = ilen * _TH2_TDM_LENGTH;
   6867     sal_memcpy(tdm->tdm_pipe[1].idb_tdm,
   6868                &tdm_scache_ptr[scache_offset],
   6869                var_size);
   6870     scache_offset += var_size;
   6871 
   6872     /* MMU TDM info on pipe1 */
   6873     var_size = ilen * _TH2_TDM_LENGTH;
   6874     sal_memcpy(tdm->tdm_pipe[1].mmu_tdm,
   6875                &tdm_scache_ptr[scache_offset],
   6876                var_size);
   6877     scache_offset += var_size;
   6878 
   6879     /* Oversub group info on pipe1 */
   6880     var_size = ilen * ovs_size;
   6881     sal_memcpy(tdm->tdm_pipe[1].ovs_tdm,
   6882                &tdm_scache_ptr[scache_offset],
   6883                var_size);
   6884     scache_offset += var_size;
   6885 
   6886     /* pkt shaper info on pipe1 */
   6887     var_size = ilen * pkt_shp_size;
   6888     sal_memcpy(tdm->tdm_pipe[1].pkt_shaper_tdm,
   6889                &tdm_scache_ptr[scache_offset],
   6890                var_size);
   6891     scache_offset += var_size;
   6892 
   6893     /* IDB TDM info on pipe2 */
   6894     var_size = ilen * _TH2_TDM_LENGTH;
   6895     sal_memcpy(tdm->tdm_pipe[2].idb_tdm,
   6896                &tdm_scache_ptr[scache_offset],
   6897                var_size);
   6898     scache_offset += var_size;
   6899 
   6900     /* MMU TDM info on pipe2 */
   6901     var_size = ilen * _TH2_TDM_LENGTH;
   6902     sal_memcpy(tdm->tdm_pipe[2].mmu_tdm,
   6903                &tdm_scache_ptr[scache_offset],
   6904                var_size);
   6905     scache_offset += var_size;
   6906 
   6907     /* Oversub group info on pipe2 */
   6908     var_size = ilen * ovs_size;
   6909     sal_memcpy(tdm->tdm_pipe[2].ovs_tdm,
   6910                &tdm_scache_ptr[scache_offset],
   6911                var_size);
   6912     scache_offset += var_size;
   6913 
   6914     /* pkt shaper info on pipe2 */
   6915     var_size = ilen * pkt_shp_size;
   6916     sal_memcpy(tdm->tdm_pipe[2].pkt_shaper_tdm,
   6917                &tdm_scache_ptr[scache_offset],
   6918                var_size);
   6919     scache_offset += var_size;
   6920 
   6921     /* IDB TDM info on pipe3 */
   6922     var_size = ilen * _TH2_TDM_LENGTH;
   6923     sal_memcpy(tdm->tdm_pipe[3].idb_tdm,
   6924                &tdm_scache_ptr[scache_offset],
   6925                var_size);
   6926     scache_offset += var_size;
   6927 
   6928     /* MMU TDM info on pipe3 */
   6929     var_size = ilen * _TH2_TDM_LENGTH;
   6930     sal_memcpy(tdm->tdm_pipe[3].mmu_tdm,
   6931                &tdm_scache_ptr[scache_offset],
   6932                var_size);
   6933     scache_offset += var_size;
   6934 
   6935     /* Oversub group info on pipe3 */
   6936     var_size = ilen * ovs_size;
   6937     sal_memcpy(tdm->tdm_pipe[3].ovs_tdm,
   6938                &tdm_scache_ptr[scache_offset],
   6939                var_size);
   6940     scache_offset += var_size;
   6941 
   6942     /* pkt shaper info on pipe3 */
   6943     var_size = ilen * pkt_shp_size;
   6944     sal_memcpy(tdm->tdm_pipe[3].pkt_shaper_tdm,
   6945                &tdm_scache_ptr[scache_offset],
   6946                var_size);
   6947     scache_offset += var_size;
   6948 
   6949     /* hpipe id of phy-port */
   6950     for (phy_port = 0; phy_port < _TH2_PHY_PORTS_PER_DEV; phy_port++) {
   6951         var_size = ilen;
   6952         sal_memcpy(&tdm->pblk_info[phy_port].pblk_hpipe_num,
   6953                    &tdm_scache_ptr[scache_offset],
   6954                    var_size);
   6955         scache_offset += var_size;
   6956     }
   6957 
   6958     /* pblk id of phy-port */
   6959     for (phy_port = 0; phy_port < _TH2_PHY_PORTS_PER_DEV; phy_port++) {
   6960         var_size = ilen;
   6961         sal_memcpy(&tdm->pblk_info[phy_port].pblk_cal_idx,
   6962                    &tdm_scache_ptr[scache_offset],
   6963                    var_size);
   6964         scache_offset += var_size;
   6965     }
   6966 
   6967     /* port ratio */
   6968     var_size = ilen * _TH2_PBLKS_PER_DEV;
   6969     sal_memcpy(tdm->port_ratio,
   6970                &tdm_scache_ptr[scache_offset],
   6971                var_size);
   6972     scache_offset += var_size;
   6973 
   6974     /* oversub ratio */
   6975     var_size = ilen * hpipes;
   6976     sal_memcpy(tdm->ovs_ratio_x1000,
   6977                &tdm_scache_ptr[scache_offset],
   6978                var_size);
   6979     scache_offset += var_size;
   6980 
   6981     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6982                 (BSL_META_U(unit,
   6983                 "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   6984 
   6985     return SOC_E_NONE;
   6986 }
   6987 #endif /* BCM_WARM_BOOT_SUPPORT */
   6988 
   6989 int
   6990 _soc_tomahawk2_tdm_init(int unit)
   6991 {
   6992     soc_control_t *soc = SOC_CONTROL(unit);
   6993     soc_info_t *si = &SOC_INFO(unit);
   6994     soc_port_schedule_state_t *port_schedule_state;
   6995     soc_port_map_type_t *in_portmap;
   6996     int port;
   6997     int rv;
   6998     soc_pbmp_t pbmp_mixed_sister_25_50;
   6999 
   7000     if (soc->tdm_info == NULL) {
   7001         soc->tdm_info = sal_alloc(sizeof(_soc_tomahawk2_tdm_t),
   7002                                     "Tomahawk2 TDM info");
   7003         if (soc->tdm_info == NULL) {
   7004             return SOC_E_MEMORY;
   7005         }
   7006         sal_memset(soc->tdm_info, 0, sizeof(_soc_tomahawk2_tdm_t));
   7007     }
   7008 
   7009 #if defined(BCM_WARM_BOOT_SUPPORT)
   7010     if (SOC_WARM_BOOT(unit)) {
   7011         SOC_IF_ERROR_RETURN(
   7012             soc_th2_tdm_scache_recovery(unit));
   7013         return SOC_E_NONE;
   7014     } else {
   7015         SOC_IF_ERROR_RETURN(
   7016             soc_th2_tdm_scache_allocate(unit));
   7017     }
   7018 #endif
   7019 
   7020     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   7021                                     "Tomahawk2 soc_port_schedule_state_t");
   7022     if (port_schedule_state == NULL) {
   7023         return SOC_E_MEMORY;
   7024     }
   7025     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   7026 
   7027     /* Core clock frequency */
   7028     port_schedule_state->frequency = si->frequency;
   7029 
   7030     /* Construct in_port_map */
   7031     in_portmap = &port_schedule_state->in_port_map;
   7032 
   7033     pbmp_mixed_sister_25_50 = soc_property_get_pbmp(
   7034                         unit, spn_PBMP_OVERSUBSCRIBE_MIXED_SISTER_25_50_INIT, 0);
   7035     PBMP_PORT_ITER(unit, port) {
   7036         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   7037             continue;
   7038         }
   7039         in_portmap->log_port_speed[port] = MAX(si->port_speed_max[port],
   7040                                                SPEED_10G);
   7041         in_portmap->port_num_lanes[port] = si->port_num_lanes[port];
   7042         /* in_portmap->physical_pbm used to pass the info about the port bitmap of 25G
   7043                * ports using 50G TDM calendar to TDM code.
   7044                */
   7045         if (SOC_PBMP_MEMBER(pbmp_mixed_sister_25_50, port)) {
   7046             SOC_PBMP_PORT_ADD(in_portmap->physical_pbm, port);
   7047         }
   7048     }
   7049     /* DV API requires LB speed non-zero */
   7050     PBMP_LB_ITER(unit, port) {
   7051         in_portmap->log_port_speed[port] = SPEED_100G;
   7052         in_portmap->port_num_lanes[port] = si->port_num_lanes[port];
   7053     }
   7054 
   7055     sal_memcpy(in_portmap->port_p2l_mapping, si->port_p2l_mapping,
   7056                 sizeof(int)*_TH2_PHY_PORTS_PER_DEV);
   7057     sal_memcpy(in_portmap->port_l2p_mapping, si->port_l2p_mapping,
   7058                 sizeof(int)*_TH2_DEV_PORTS_PER_DEV);
   7059     sal_memcpy(in_portmap->port_p2m_mapping, si->port_p2m_mapping,
   7060                 sizeof(int)*_TH2_PHY_PORTS_PER_DEV);
   7061     sal_memcpy(in_portmap->port_m2p_mapping, si->port_m2p_mapping,
   7062                 sizeof(int)*_TH2_MMU_PORTS_PER_DEV);
   7063     sal_memcpy(in_portmap->port_l2i_mapping, si->port_l2i_mapping,
   7064                 sizeof(int)*_TH2_DEV_PORTS_PER_DEV);
   7065     sal_memcpy(&in_portmap->hg2_pbm, &si->hg.bitmap, sizeof(pbmp_t));
   7066     sal_memcpy(&in_portmap->management_pbm, &si->management_pbm,
   7067                 sizeof(pbmp_t));
   7068     sal_memcpy(&in_portmap->oversub_pbm, &si->oversub_pbm, sizeof(pbmp_t));
   7069     /* DV API requires management ports always be in portmap,
   7070        regardless they exist or not */
   7071     in_portmap->port_p2l_mapping[_TH2_PHY_PORT_MNG0] = _TH2_DEV_PORT_MNG0;
   7072     in_portmap->port_p2l_mapping[_TH2_PHY_PORT_MNG1] = _TH2_DEV_PORT_MNG1;
   7073     in_portmap->port_l2p_mapping[_TH2_DEV_PORT_MNG0] = _TH2_PHY_PORT_MNG0;
   7074     in_portmap->port_l2p_mapping[_TH2_DEV_PORT_MNG1] = _TH2_PHY_PORT_MNG1;
   7075     in_portmap->port_p2m_mapping[_TH2_PHY_PORT_MNG0] = _TH2_MMU_PORT_MNG0;
   7076     in_portmap->port_p2m_mapping[_TH2_PHY_PORT_MNG1] = _TH2_MMU_PORT_MNG1;
   7077     in_portmap->port_m2p_mapping[_TH2_MMU_PORT_MNG0] = _TH2_PHY_PORT_MNG0;
   7078     in_portmap->port_m2p_mapping[_TH2_MMU_PORT_MNG1] = _TH2_PHY_PORT_MNG1;
   7079     in_portmap->port_l2i_mapping[_TH2_DEV_PORT_MNG0] = _TH2_IDB_PORT_CPU_MNG;
   7080     in_portmap->port_l2i_mapping[_TH2_DEV_PORT_MNG1] = _TH2_IDB_PORT_CPU_MNG;
   7081 
   7082     /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */
   7083     port_schedule_state->is_flexport = 0;
   7084     rv = soc_th2_port_schedule_tdm_init(unit, port_schedule_state);
   7085 
   7086     rv = soc_tomahawk2_tdm_init(unit, port_schedule_state);
   7087     if (rv != SOC_E_NONE) {
   7088         LOG_CLI((BSL_META_U(unit,
   7089             "Unsupported config for TDM calendar generation\n")));
   7090         sal_free(port_schedule_state);
   7091         return rv;
   7092     }
   7093 
   7094     /* Update SOC TDM info */
   7095     rv = soc_th2_soc_tdm_update(unit, port_schedule_state);
   7096 
   7097     sal_free(port_schedule_state);
   7098 
   7099     return rv;
   7100 }
   7101 
   7102 int
   7103 _soc_tomahawk2_ing_fsaf_init(int unit)
   7104 {
   7105     int port, pipe, obm, lane;
   7106     int send_en, receive_en, thd, duration;
   7107     uint64 rval64;
   7108     soc_info_t *si = &SOC_INFO(unit);
   7109     soc_reg_t reg;
   7110     static const soc_reg_t idb_obm_fsaf_cfg[] = {
   7111         IDB_OBM0_DBG_Ar,  IDB_OBM1_DBG_Ar,
   7112         IDB_OBM2_DBG_Ar,  IDB_OBM3_DBG_Ar,
   7113         IDB_OBM4_DBG_Ar,  IDB_OBM5_DBG_Ar,
   7114         IDB_OBM6_DBG_Ar,  IDB_OBM7_DBG_Ar,
   7115         IDB_OBM8_DBG_Ar,  IDB_OBM9_DBG_Ar,
   7116         IDB_OBM10_DBG_Ar, IDB_OBM11_DBG_Ar,
   7117         IDB_OBM12_DBG_Ar, IDB_OBM13_DBG_Ar,
   7118         IDB_OBM14_DBG_Ar, IDB_OBM15_DBG_Ar,
   7119     };
   7120     static const soc_reg_t idb_fsaf_cfg = IDB_DBG_Br;
   7121 
   7122     send_en = (si->oversub_mode) ? 1 : 0;
   7123     receive_en = (si->oversub_mode) ? 1 : 0;
   7124     PBMP_ALL_ITER(unit, port) {
   7125         if (SOC_FAILURE(soc_tomahawk2_port_obm_info_get
   7126                 (unit, port, &obm, &lane))) {
   7127             continue;
   7128         }
   7129         thd = ((si->port_speed_max[port] == 10000) ||
   7130                (si->port_speed_max[port] == 11000) ||
   7131                (si->port_speed_max[port] == 20000) ||
   7132                (si->port_speed_max[port] == 21000) ||
   7133                (si->port_speed_max[port] == 40000) ||
   7134                (si->port_speed_max[port] == 42000)) ? 12 : 18;
   7135         pipe = si->port_pipe[port];
   7136         reg = SOC_REG_UNIQUE_ACC(unit, idb_obm_fsaf_cfg[obm])[pipe];
   7137         SOC_IF_ERROR_RETURN
   7138             (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   7139         soc_reg64_field32_set(unit, reg, &rval64, FIELD_Af, receive_en);
   7140         soc_reg64_field32_set(unit, reg, &rval64, FIELD_Bf, send_en);
   7141         soc_reg64_field32_set(unit, reg, &rval64, FIELD_Cf, thd);
   7142         SOC_IF_ERROR_RETURN
   7143             (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   7144     }
   7145 
   7146     duration = si->frequency * 2;
   7147     for (pipe = 0; pipe < si->num_pipe; pipe ++) {
   7148         reg = SOC_REG_UNIQUE_ACC(unit, idb_fsaf_cfg)[pipe];
   7149         SOC_IF_ERROR_RETURN
   7150             (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   7151         soc_reg64_field32_set(unit, reg, &rval64, FIELD_Af, duration);
   7152         SOC_IF_ERROR_RETURN
   7153             (soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   7154     }
   7155 
   7156     return SOC_E_NONE;
   7157 }
   7158 
   7159 int
   7160 soc_tomahawk2_edb_buf_reset(int unit, soc_port_t port, int reset)
   7161 {
   7162     if (SAL_BOOT_XGSSIM || SAL_BOOT_BCMSIM) {
   7163         return SOC_E_NONE;
   7164     }
   7165     return soc_tomahawk_edb_buf_reset(unit, port, reset);
   7166 }
   7167 
   7168 int
   7169 soc_tomahawk2_idb_buf_reset(int unit, soc_port_t port, int reset)
   7170 {
   7171     soc_reg_t reg, reg1;
   7172     int port_block_base, phy_port, lane;
   7173     int pipe, obm, clport, obm_usage_count = ~0, ca_empty = 0;
   7174     uint32 rval;
   7175     uint64 rval1, rval2;
   7176     soc_info_t *si = &SOC_INFO(unit);
   7177     static const soc_reg_t idb_obm_usage_regs[] = {
   7178         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr,
   7179         IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
   7180         IDB_OBM4_USAGEr, IDB_OBM5_USAGEr,
   7181         IDB_OBM6_USAGEr, IDB_OBM7_USAGEr,
   7182         IDB_OBM8_USAGEr, IDB_OBM9_USAGEr,
   7183         IDB_OBM10_USAGEr, IDB_OBM11_USAGEr,
   7184         IDB_OBM12_USAGEr, IDB_OBM13_USAGEr,
   7185         IDB_OBM14_USAGEr, IDB_OBM15_USAGEr
   7186     };
   7187     static const soc_reg_t idb_obm_ca_status_regs[] = {
   7188         IDB_OBM0_CA_HW_STATUSr, IDB_OBM1_CA_HW_STATUSr,
   7189         IDB_OBM2_CA_HW_STATUSr, IDB_OBM3_CA_HW_STATUSr,
   7190         IDB_OBM4_CA_HW_STATUSr, IDB_OBM5_CA_HW_STATUSr,
   7191         IDB_OBM6_CA_HW_STATUSr, IDB_OBM7_CA_HW_STATUSr,
   7192         IDB_OBM8_CA_HW_STATUSr, IDB_OBM9_CA_HW_STATUSr,
   7193         IDB_OBM10_CA_HW_STATUSr, IDB_OBM11_CA_HW_STATUSr,
   7194         IDB_OBM12_CA_HW_STATUSr, IDB_OBM13_CA_HW_STATUSr,
   7195         IDB_OBM14_CA_HW_STATUSr, IDB_OBM15_CA_HW_STATUSr
   7196     };
   7197     static const soc_reg_t obm_ctrl_regs[] = {
   7198         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
   7199         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
   7200         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
   7201         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr,
   7202         IDB_OBM8_CONTROLr, IDB_OBM9_CONTROLr,
   7203         IDB_OBM10_CONTROLr, IDB_OBM11_CONTROLr,
   7204         IDB_OBM12_CONTROLr, IDB_OBM13_CONTROLr,
   7205         IDB_OBM14_CONTROLr, IDB_OBM15_CONTROLr
   7206     };
   7207     static const soc_reg_t obm_ca_ctrl_regs[] = {
   7208         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
   7209         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
   7210         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
   7211         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr,
   7212         IDB_OBM8_CA_CONTROLr, IDB_OBM9_CA_CONTROLr,
   7213         IDB_OBM10_CA_CONTROLr, IDB_OBM11_CA_CONTROLr,
   7214         IDB_OBM12_CA_CONTROLr, IDB_OBM13_CA_CONTROLr,
   7215         IDB_OBM14_CA_CONTROLr, IDB_OBM15_CA_CONTROLr
   7216     };
   7217     static const soc_field_t fifo_empty_port_fields[] = {
   7218         FIFO_EMPTY_PORT0f, FIFO_EMPTY_PORT1f, FIFO_EMPTY_PORT2f,
   7219         FIFO_EMPTY_PORT3f
   7220     };
   7221     static const soc_field_t port_reset_fields[] = {
   7222         PORT0_RESETf, PORT1_RESETf, PORT2_RESETf, PORT3_RESETf
   7223     };
   7224 
   7225     if (SAL_BOOT_XGSSIM || SAL_BOOT_BCMSIM) {
   7226         return SOC_E_NONE;
   7227     }
   7228 
   7229     phy_port = si->port_l2p_mapping[port];
   7230     port_block_base = PORT_BLOCK_BASE_PORT(port);
   7231     lane = phy_port - port_block_base;
   7232     pipe = si->port_pipe[port];
   7233     clport = si->port_serdes[port];
   7234     obm = clport & 0xF;
   7235 
   7236     if (reset && !SAL_BOOT_SIMULATION) {
   7237         soc_timeout_t to;
   7238 
   7239         reg = SOC_REG_UNIQUE_ACC(unit, idb_obm_usage_regs[obm])[pipe];
   7240         reg1 = SOC_REG_UNIQUE_ACC(unit, idb_obm_ca_status_regs[obm])[pipe];
   7241 
   7242         soc_timeout_init(&to, 250000, 0);
   7243         /* Poll until IDB buffer is empty */
   7244         for (;;) {
   7245             if (0 != obm_usage_count) {
   7246                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, lane,
   7247                                                 &rval1));
   7248                 obm_usage_count = soc_reg64_field32_get(unit, reg, rval1,
   7249                                                         TOTAL_COUNTf);
   7250             }
   7251             if (0 == ca_empty) {
   7252                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg1, REG_PORT_ANY, 0,
   7253                                                 &rval2));
   7254                 ca_empty = soc_reg64_field32_get(unit, reg1, rval2,
   7255                                                  fifo_empty_port_fields[lane]);
   7256             }
   7257             if ((0 == obm_usage_count) && (1 == ca_empty)) {
   7258                 break;
   7259             }
   7260             if (soc_timeout_check(&to)) {
   7261                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7262                           (BSL_META_U(unit,
   7263                                       "IDBBufferDrainTimeOut:port %d,%s, timeout"
   7264                                       "(idb_obm_usage: %d) "
   7265                                       "(ca_fifo_empty: %d)\n"),
   7266                            unit, SOC_PORT_NAME(unit, port), obm_usage_count,
   7267                            ca_empty));
   7268                 return SOC_E_INTERNAL;
   7269             }
   7270         }
   7271     }
   7272 
   7273     reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
   7274     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   7275     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
   7276     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   7277 
   7278     reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
   7279     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   7280     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
   7281     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   7282 
   7283     return SOC_E_NONE;
   7284 }
   7285 
   7286 _soc_th2_tcb_hw_cb th2_tcb_cb;
   7287 
   7288 int
   7289 soc_th2_process_mmu_tcb(int unit, int xpe, soc_field_t field)
   7290 {
   7291     int rv = SOC_E_NONE;
   7292     if (th2_tcb_cb != NULL) {
   7293         rv = th2_tcb_cb(unit);
   7294     }
   7295     return rv;
   7296 }
   7297 
   7298 int soc_th2_set_tcb_callback(int unit, _soc_th2_tcb_hw_cb cb)
   7299 {
   7300     th2_tcb_cb = cb;
   7301     return SOC_E_NONE;
   7302 }
   7303 
   7304 /*
   7305  * Function:
   7306  *      soc_th2_port_speed_supported
   7307  * Purpose:
   7308  *      Check if the speed of port is supported
   7309  * Parameters:
   7310  *      unit            - (IN)  Unit number.
   7311  *      port            - (IN)  Logical port number.
   7312  *      speed           - (IN)  Speed (Mbps).
   7313  * Returns:
   7314  *      SOC_E_xxx
   7315  * Notes:
   7316  */
   7317 soc_error_t
   7318 soc_th2_port_speed_supported(int unit, soc_port_t port, int speed)
   7319 {
   7320     int num_lanes, tsc_id, lane_speed;
   7321     uint32 speed_mask, speed_valid;
   7322     soc_info_t *si = &SOC_INFO(unit);
   7323 
   7324     /*
   7325      * If Universal calendar was not selected at init time then
   7326      * disallow speed change to HG2 speeds.
   7327      */
   7328     if (FALSE == si->fabric_port_enable) {
   7329         if (IS_HG2_SPEED(speed)) {
   7330             /*
   7331              * Intentionally returning SOC_E_CONFIG as this is a case
   7332              * of incorrect configuration
   7333              */
   7334             return SOC_E_CONFIG;
   7335         }
   7336     }
   7337 
   7338     /*
   7339      * Management ports only support 1G, 2.5G and 10G. Flexport
   7340      * on management ports is not supported. Management ports
   7341      * are guaranteed 10G bandwidth.
   7342      */
   7343     if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   7344         if ((1000 == speed) || (2500 == speed) || (10000 == speed)) {
   7345             return SOC_E_NONE;
   7346         } else {
   7347             return SOC_E_PARAM;
   7348         }
   7349     }
   7350 
   7351     num_lanes = si->port_num_lanes[port];
   7352 
   7353     if(soc_feature(unit, soc_feature_untethered_otp)) {
   7354         tsc_id = (si->port_l2p_mapping[port] - 1) / _TH2_PORTS_PER_PBLK;
   7355         SOC_IF_ERROR_RETURN
   7356             (soc_tomahawk2_tsc_max_lane_speed_get(unit, tsc_id, &lane_speed));
   7357         if (speed > (num_lanes * lane_speed)) {
   7358             LOG_VERBOSE(BSL_LS_BCM_PORT,
   7359                       (BSL_META_U(unit,
   7360                                   "Invalid speed configuration for port=%d, "
   7361                                   "speed=%d: Max lane speed %d\n"),
   7362                        port, speed, lane_speed));
   7363             return SOC_E_PARAM;
   7364         }
   7365     }
   7366 
   7367     speed_mask = SOC_PA_SPEED(speed);
   7368     SOC_IF_ERROR_RETURN
   7369         (soc_th2_support_speeds(unit, num_lanes, &speed_valid));
   7370     if (!(speed_valid & speed_mask)) {
   7371         LOG_VERBOSE(BSL_LS_BCM_PORT,
   7372                   (BSL_META_U(unit,
   7373                               "Invalid speed configuration for "
   7374                               "port=%d, speed=%d\n"),
   7375                    port, speed));
   7376         return SOC_E_PARAM;
   7377     }
   7378 
   7379     return SOC_E_NONE;
   7380 }
   7381 
   7382 /*
   7383  * All non-parity related interrupts must be handled in this function.
   7384  * All unserviced intr_status bits must either be serviced or disabled.
   7385  *
   7386  * Note:
   7387  * 1. MEM_PAR_ERR_STATf is handled by tomahawk/ser.c, so ignore this
   7388  * 2. blocktype (in) can only be SOC_BLK_MMU_XPE/SC/SED
   7389  */
   7390 int
   7391 soc_th2_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype,
   7392                                  int mmu_base_index,
   7393                                  uint32 rval_intr_status_reg)
   7394 {
   7395     int i;
   7396     uint32 rval = 0;
   7397     soc_reg_t intr_stat_reg, intr_clr_reg;
   7398     static soc_field_t xpe_intr_field_list[] = {
   7399         MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */
   7400         BST_THDI_INT_STATf,
   7401         BST_THDO_INT_STATf,
   7402         DEQ0_NOT_IP_ERR_STATf,
   7403         DEQ1_NOT_IP_ERR_STATf,
   7404         ENQX_TO_CFG_MAX_CELL_INTR_0_STATf,
   7405         ENQX_TO_CFG_MAX_CELL_INTR_1_STATf,
   7406         TCB_FREEZE_INT_STATf,
   7407         INVALIDf
   7408     };
   7409     static soc_field_t sc_intr_field_list[] = {
   7410         MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */
   7411         ES_X_DEADLOCK_DET_INT_STATf,
   7412         ES_Y_DEADLOCK_DET_INT_STATf,
   7413         ES_X_1IN4_ERR_INT_STATf,
   7414         ES_Y_1IN4_ERR_INT_STATf,
   7415         INVALIDf
   7416     };
   7417     static soc_field_t sed_intr_field_list[] = {
   7418         CFAP_A_MEM_FAIL_STATf,
   7419         CFAP_B_MEM_FAIL_STATf,
   7420         MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */
   7421         BST_CFAP_A_INT_STATf,
   7422         BST_CFAP_B_INT_STATf,
   7423         START_BY_START_ERR_STATf,
   7424         INVALIDf
   7425     };
   7426 
   7427     if (blocktype == SOC_BLK_MMU_XPE) {
   7428         intr_stat_reg = MMU_XCFG_XPE_CPU_INT_STATr;
   7429         intr_clr_reg = MMU_XCFG_XPE_CPU_INT_CLEARr;
   7430         for (i = 0; xpe_intr_field_list[i] != INVALIDf; i++) {
   7431             if (!soc_reg_field_get(unit, intr_stat_reg,
   7432                                    rval_intr_status_reg,
   7433                                    xpe_intr_field_list[i])) {
   7434                 continue;
   7435             }
   7436             switch (xpe_intr_field_list[i]) {
   7437             case BST_THDI_INT_STATf:
   7438             case BST_THDO_INT_STATf:
   7439                 /* interrupt processing */
   7440                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7441                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
   7442                                               "from xpe = %0d \n"),
   7443                              unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
   7444                              mmu_base_index));
   7445 
   7446                 /* clear the interrupt */
   7447                 SOC_IF_ERROR_RETURN
   7448                     (soc_tomahawk_xpe_reg32_get(unit, intr_clr_reg,
   7449                                                 mmu_base_index, mmu_base_index,
   7450                                                 0, &rval));
   7451                 rval |= (1 << i);
   7452                 SOC_IF_ERROR_RETURN
   7453                     (soc_tomahawk_xpe_reg32_set(unit, intr_clr_reg,
   7454                                                 mmu_base_index, mmu_base_index,
   7455                                                 0, rval));
   7456                 SOC_IF_ERROR_RETURN
   7457                     (_soc_th_process_mmu_bst(unit, mmu_base_index,
   7458                                              xpe_intr_field_list[i]));
   7459                 break;
   7460             case TCB_FREEZE_INT_STATf:
   7461                 /* interrupt processing */
   7462                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7463                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
   7464                                               "from xpe = %0d \n"),
   7465                              unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
   7466                              mmu_base_index));
   7467 
   7468                 /* clear the interrupt */
   7469                 SOC_IF_ERROR_RETURN
   7470                     (soc_tomahawk_xpe_reg32_get(unit, intr_clr_reg,
   7471                                                 mmu_base_index, mmu_base_index,
   7472                                                 0, &rval));
   7473                 rval |= (1 << i);
   7474                 SOC_IF_ERROR_RETURN
   7475                     (soc_tomahawk_xpe_reg32_set(unit, intr_clr_reg,
   7476                                                 mmu_base_index, mmu_base_index,
   7477                                                 0, rval));
   7478                 SOC_IF_ERROR_RETURN
   7479                     (soc_th2_process_mmu_tcb(unit, mmu_base_index,
   7480                                              xpe_intr_field_list[i]));
   7481                 break;
   7482             default:
   7483                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7484                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
   7485                                             "intr from xpe = %0d \n"),
   7486                            unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
   7487                            mmu_base_index));
   7488                 break;
   7489             }
   7490         }
   7491         return SOC_E_NONE;
   7492     }
   7493 
   7494     if (blocktype == SOC_BLK_MMU_SC) {
   7495         intr_stat_reg = MMU_SCFG_SC_CPU_INT_STATr;
   7496         intr_clr_reg = MMU_SCFG_SC_CPU_INT_CLEARr;
   7497         for (i = 0; sc_intr_field_list[i] != INVALIDf; i++) {
   7498             if (!soc_reg_field_get(unit, intr_stat_reg,
   7499                                    rval_intr_status_reg,
   7500                                    sc_intr_field_list[i])) {
   7501                 continue;
   7502             }
   7503             switch (sc_intr_field_list[i]) {
   7504             default:
   7505                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7506                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
   7507                                             "intr from sc = %0d \n"),
   7508                            unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]),
   7509                            mmu_base_index));
   7510                 break;
   7511             }
   7512         }
   7513         return SOC_E_NONE;
   7514     }
   7515 
   7516     if (blocktype == SOC_BLK_MMU_SED) {
   7517         intr_stat_reg = MMU_SEDCFG_SED_CPU_INT_STATr;
   7518         intr_clr_reg = MMU_SEDCFG_SED_CPU_INT_CLEARr;
   7519         for (i = 0; sed_intr_field_list[i] != INVALIDf; i++) {
   7520             if (!soc_reg_field_get(unit, intr_stat_reg,
   7521                                    rval_intr_status_reg,
   7522                                    sed_intr_field_list[i])) {
   7523                 continue;
   7524             }
   7525             switch (sed_intr_field_list[i]) {
   7526             case BST_CFAP_A_INT_STATf:
   7527             case BST_CFAP_B_INT_STATf:
   7528                 /* interrupt processing */
   7529                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7530                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
   7531                                               "from sed = %0d \n"),
   7532                              unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
   7533                              mmu_base_index));
   7534 
   7535 
   7536                 /* clear the interrupt */
   7537                 SOC_IF_ERROR_RETURN
   7538                     (soc_tomahawk2_sed_reg32_get(unit, intr_clr_reg,
   7539                                                  mmu_base_index, mmu_base_index,
   7540                                                  0, &rval));
   7541                 rval |= (1 << i);
   7542                 SOC_IF_ERROR_RETURN
   7543                     (soc_tomahawk2_sed_reg32_set(unit, intr_clr_reg,
   7544                                                  mmu_base_index, mmu_base_index,
   7545                                                  0, rval));
   7546                 SOC_IF_ERROR_RETURN
   7547                     (_soc_th_process_mmu_bst(unit, mmu_base_index,
   7548                                              sed_intr_field_list[i]));
   7549                 break;
   7550             case CFAP_A_MEM_FAIL_STATf:
   7551             case CFAP_B_MEM_FAIL_STATf:
   7552                 /* interrupt processing */
   7553                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7554                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
   7555                                               "from sed = %0d \n"),
   7556                              unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
   7557                              mmu_base_index));
   7558 
   7559                 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR,
   7560                                    SOC_SWITCH_EVENT_DATA_ERROR_CFAP_MEM_FAIL, -1, -1);
   7561 
   7562                 /* clear the interrupt */
   7563                 SOC_IF_ERROR_RETURN
   7564                     (soc_tomahawk2_sed_reg32_get(unit, intr_clr_reg,
   7565                                                  mmu_base_index, mmu_base_index,
   7566                                                  0, &rval));
   7567                 rval |= (1 << i);
   7568                 SOC_IF_ERROR_RETURN
   7569                     (soc_tomahawk2_sed_reg32_set(unit, intr_clr_reg,
   7570                                                  mmu_base_index, mmu_base_index,
   7571                                                  0, rval));
   7572                 break;
   7573             default:
   7574                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7575                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
   7576                                             "intr from sed = %0d \n"),
   7577                            unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
   7578                            mmu_base_index));
   7579                 break;
   7580             }
   7581         }
   7582         return SOC_E_NONE;
   7583     }
   7584 
   7585     /* cannot be here for any other blocktype */
   7586     return SOC_E_FAIL;
   7587 }
   7588 
   7589 /*
   7590  * Function:
   7591  *      soc_th2_max_lr_bandwidth_validate
   7592  * Purpose:
   7593  *      Check line rate bandwidth for each pipe
   7594  * Parameters:
   7595  *      unit     - (IN) Unit number.
   7596  * Returns:
   7597  *      SOC_E_XXX
   7598  * Note:
   7599  *      This function is called at early stage of initialization for
   7600  *      port configuration check.
   7601  */
   7602 int
   7603 soc_th2_max_lr_bandwidth_validate(int unit)
   7604 {
   7605     soc_info_t *si = &SOC_INFO(unit);
   7606     int port, pipe;
   7607     uint32 max_lr_bw, lr_bw[_TH2_PIPES_PER_DEV] = {0};
   7608     int rv;
   7609 
   7610     PBMP_PORT_ITER(unit, port) {
   7611         if (SOC_PBMP_MEMBER(si->oversub_pbm, port) ||
   7612             SOC_PBMP_MEMBER(si->all.disabled_bitmap, port) ||
   7613             IS_MANAGEMENT_PORT(unit, port)) {
   7614             continue;
   7615         }
   7616         pipe = si->port_pipe[port];
   7617         if (pipe < 0) {
   7618             LOG_ERROR(BSL_LS_SOC_COMMON,
   7619                       (BSL_META_U(unit,
   7620                                   "Failed to get pipe for port %d\n."),
   7621                       port));
   7622             return SOC_E_INTERNAL;
   7623         }
   7624         lr_bw[pipe] += si->port_speed_max[port];
   7625     }
   7626 
   7627     rv = soc_th2_max_lr_bandwidth(unit, &max_lr_bw);
   7628     if (SOC_FAILURE(rv)) {
   7629         LOG_ERROR(BSL_LS_SOC_COMMON,
   7630                   (BSL_META_U(unit,
   7631                             "Failed to get the Max Line Rate Bandwidth.\n")));
   7632         return rv;
   7633     }
   7634     for (pipe = 0; pipe <  NUM_PIPE(unit); pipe++) {
   7635         if (lr_bw[pipe] > max_lr_bw * 1000) {
   7636             LOG_ERROR(BSL_LS_SOC_COMMON,
   7637                       (BSL_META_U(unit,
   7638                                   "Bandwidth (%d Mbps) exceeds the Max Line "
   7639                                   "Rate Bandwidth (%d Mbps) on pipe %d.\n"),
   7640                                   lr_bw[pipe], max_lr_bw*1000, pipe));
   7641             return SOC_E_CONFIG;
   7642         }
   7643     }
   7644 
   7645     return SOC_E_NONE;
   7646 }
   7647 
   7648 /*
   7649  * Function:
   7650  *      soc_th2_speed_class_validate
   7651  * Purpose:
   7652  *      Check speed classes
   7653  * Parameters:
   7654  *      unit     - (IN) Unit number.
   7655  * Returns:
   7656  *      SOC_E_XXX
   7657  * Note:
   7658  *      This function is called at early stage of initialization for
   7659  *      port configuration check.
   7660  */
   7661 int
   7662 soc_th2_speed_class_validate(int unit)
   7663 {
   7664     soc_info_t *si = &SOC_INFO(unit);
   7665     int port, speed;
   7666     uint32 speed_mask, count, speed_class_max_num;
   7667 
   7668     speed_mask = 0;
   7669     speed_class_max_num = si->oversub_mode ?
   7670                     _TH2_TDM_OS_SPEED_CLASS_MAX : _TH2_TDM_LR_SPEED_CLASS_MAX;
   7671     PBMP_PORT_ITER(unit, port) {
   7672         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port) ||
   7673             IS_MANAGEMENT_PORT(unit, port) || IS_CPU_PORT(unit, port) ||
   7674             IS_LB_PORT(unit, port)) {
   7675             continue;
   7676         }
   7677         speed = soc_port_speed_higig2eth(si->port_speed_max[port]);
   7678         speed_mask |= SOC_PA_SPEED(speed);
   7679     }
   7680 
   7681     count = _shr_popcount(speed_mask);
   7682     if (count > speed_class_max_num) {
   7683         LOG_ERROR(BSL_LS_BCM_COMMON,
   7684                   (BSL_META_U(unit,
   7685                               "No port configurations with more than %d port "
   7686                               "speed classes are supported.\n"),
   7687                               speed_class_max_num));
   7688         return SOC_E_CONFIG;
   7689     }
   7690 
   7691     if(SOC_FAILURE(soc_th2_speed_mix_validate(unit, speed_mask))) {
   7692         return SOC_E_CONFIG;
   7693     }
   7694 
   7695     return SOC_E_NONE;
   7696 }
   7697 
   7698 void soc_th2_uft_otp_info_get(int unit, int *num_share_banks_enabled,
   7699     int *share_banks_bitmap_enabled)
   7700 {
   7701     *num_share_banks_enabled = 
   7702         (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank0) ? 0 : 1) 
   7703         + (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank1) ? 0 : 1) 
   7704         + (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank2) ? 0 : 1) 
   7705         + (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank3) ? 0 : 1);
   7706     
   7707     *share_banks_bitmap_enabled = 
   7708         (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank0) ? 0 : 0x1) 
   7709         | (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank1) ? 0 : 0x2) 
   7710         | (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank2) ? 0 : 0x4) 
   7711         | (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureNoUftBank3) ? 0 : 0x8);
   7712 
   7713     return;
   7714 }
   7715 
   7716 int
   7717 soc_th2_set_uft_bank_map(int unit)
   7718 {
   7719     int num_banks, index;
   7720     int num_shared_l2_banks, num_shared_l3_banks, num_shared_fpem_banks;
   7721     int num_share_banks_enabled = 4;
   7722     int share_banks_bitmap_enabled;    
   7723     uint32 bank_counter = 0;
   7724     uint32 unused_bank_bitmap = 0;    
   7725     uint32 l2_bank_bitmap = 0;
   7726     uint32 l3_bank_bitmap = 0;
   7727     uint32 fpem_bank_bitmap = 0;
   7728     uint32 config = 0, map = 0, fpmap = 0;    
   7729     static soc_field_t l2_fields[] = {
   7730         L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
   7731         L2_ENTRY_BANK_5f
   7732     };
   7733     static soc_field_t l3_fields[] = {
   7734         L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f,
   7735         L3_ENTRY_BANK_7f
   7736     };
   7737     static soc_field_t fpem_fields[] = {
   7738         FPEM_ENTRY_BANK_0f, FPEM_ENTRY_BANK_1f, FPEM_ENTRY_BANK_2f,
   7739         FPEM_ENTRY_BANK_3f
   7740     };
   7741 
   7742     SOC_IF_ERROR_RETURN
   7743         (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   7744     num_shared_l2_banks = num_banks - 2; /* minus 2 dedicated L2 banks */
   7745     SOC_IF_ERROR_RETURN
   7746         (soc_tomahawk_hash_bank_count_get(unit, L3_ENTRY_ONLYm, &num_banks));
   7747     num_shared_l3_banks = num_banks - 4; /* minus 4 dedicated L3 banks */
   7748     SOC_IF_ERROR_RETURN
   7749         (soc_tomahawk_hash_bank_count_get(unit, EXACT_MATCH_2m,
   7750                                           &num_shared_fpem_banks));
   7751 
   7752     soc_th2_uft_otp_info_get(unit, &num_share_banks_enabled,
   7753         &share_banks_bitmap_enabled);
   7754 
   7755     if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   7756         int non_alpm = num_shared_fpem_banks + num_shared_l3_banks +
   7757             num_shared_l2_banks;
   7758         if (((non_alpm) && (non_alpm <= (num_share_banks_enabled - 2)))
   7759             /* If any of B4, B5 banks is disabled, ALPM can only use two banks*/
   7760             ||(~share_banks_bitmap_enabled & 0xc)) {
   7761             /* If Shared banks are used between ALPM and non-ALPM memories,
   7762              * then ALPM uses Shared Bank B2, B3 and non-ALPM uses B4, B5 banks
   7763              */
   7764             soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   7765                               ALPM_ENTRY_BANK_CONFIGf, 0x3);
   7766             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   7767                               ALPM_BANK_MODEf, 1);
   7768             SOC_IF_ERROR_RETURN
   7769                 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   7770                                         REG_PORT_ANY, ALPM_BANK_MODEf, 1));
   7771             SOC_IF_ERROR_RETURN
   7772                 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   7773                                         REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0x3));
   7774             soc_th_set_alpm_banks(unit, 2);
   7775         } else {
   7776             soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   7777                               ALPM_ENTRY_BANK_CONFIGf, 0xf);
   7778             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   7779                               ALPM_BANK_MODEf, 0);
   7780             SOC_IF_ERROR_RETURN
   7781                 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   7782                                         REG_PORT_ANY, ALPM_BANK_MODEf, 0));
   7783             SOC_IF_ERROR_RETURN
   7784                 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   7785                                         REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0xf));
   7786             soc_th_set_alpm_banks(unit, 4);
   7787         }
   7788         
   7789         /* get the unused enabled bank bitmap */    
   7790         unused_bank_bitmap = (~((1 << soc_th_get_alpm_banks(unit)) - 1)) 
   7791                                 & share_banks_bitmap_enabled;        
   7792     }    else {
   7793         unused_bank_bitmap = share_banks_bitmap_enabled;     
   7794     }
   7795 
   7796     bank_counter = 0;
   7797     /* get l2_bank_bitmap */
   7798     for (index = 0; index < 4; index++) {
   7799         if (bank_counter == num_shared_l2_banks) {
   7800             break;
   7801         }
   7802         if (unused_bank_bitmap & (1 << index)) {
   7803             l2_bank_bitmap |= 1 << index;
   7804             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   7805                           l2_fields[bank_counter], index);
   7806             bank_counter++;
   7807         }
   7808     }   
   7809     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   7810                       L2_ENTRY_BANK_CONFIGf, l2_bank_bitmap);
   7811     
   7812     unused_bank_bitmap &= (~l2_bank_bitmap);
   7813     /* get l3_bank_bitmap */
   7814     bank_counter = 0;
   7815     for (index = 0; index < 4; index++) {
   7816         if (bank_counter == num_shared_l3_banks) {
   7817             break;
   7818         }
   7819         if (unused_bank_bitmap & (1 << index)) {
   7820             l3_bank_bitmap |= 1 << index;
   7821             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   7822                           l3_fields[bank_counter], index);
   7823             bank_counter++;
   7824         }
   7825     }     
   7826     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   7827                       L3_ENTRY_BANK_CONFIGf, l3_bank_bitmap);
   7828     
   7829     unused_bank_bitmap &= (~l3_bank_bitmap);
   7830     /* get fpem_bank_bitmap */
   7831     bank_counter = 0;
   7832     for (index = 0; index < 4; index++) {
   7833         if (bank_counter == num_shared_fpem_banks) {
   7834             break;
   7835         }
   7836         if (unused_bank_bitmap & (1 << index)) {
   7837             fpem_bank_bitmap |= 1 << index;
   7838             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   7839                               fpem_fields[bank_counter], index);
   7840             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, &fpmap,
   7841                               fpem_fields[bank_counter], index);            
   7842             bank_counter++;
   7843         }
   7844     }    
   7845     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   7846                       FPEM_ENTRY_BANK_CONFIGf, fpem_bank_bitmap);
   7847 
   7848     SOC_IF_ERROR_RETURN
   7849         (soc_reg32_set(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, config));
   7850     SOC_IF_ERROR_RETURN
   7851         (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, map));
   7852     SOC_IF_ERROR_RETURN
   7853         (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map));
   7854     SOC_IF_ERROR_RETURN
   7855         (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, REG_PORT_ANY, 0, fpmap));
   7856 
   7857     return SOC_E_NONE;
   7858 }
   7859 #endif /* BCM_TOMAHAWK2_SUPPORT */