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

port.c (41647B)


      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:        port.c
      8  * Purpose:     Port driver.
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #if defined(BCM_TOMAHAWK3_SUPPORT)
     14 #include <soc/tomahawk.h>
     15 #include <soc/tomahawk3.h>
     16 #include <bcm_int/esw/xgs5.h>
     17 #include <bcm_int/esw/portctrl.h>
     18 #include <bcm_int/esw/tomahawk.h>
     19 #include <bcm_int/esw/trident.h>
     20 #include <bcm_int/esw/tomahawk3.h>
     21 #include <soc/flexport/tomahawk3_flexport.h>
     22 
     23 /*
     24  * Function Vector
     25  */
     26 static bcm_esw_port_drv_t bcm_th3_port_drv = {
     27     /* fn_drv_init                   */ bcmi_th3_port_fn_drv_init,
     28     /* resource_set                  */ bcmi_xgs5_port_resource_set,
     29     /* resource_get                  */ bcmi_xgs5_port_resource_get,
     30     /* resource_multi_set            */ bcmi_xgs5_port_resource_multi_set,
     31     /* resource_speed_set            */ bcmi_xgs5_port_speed_set,
     32     /* resource_traverse             */ bcmi_xgs5_port_resource_traverse,
     33     /* port_redirect_set             */ NULL,
     34     /* port_redirect_get             */ NULL,
     35     /* port_enable_set               */ bcmi_xgs5_port_enable_set,
     36     /* encap_speed_check             */ bcmi_xgs5_port_encap_speed_check,
     37     /* force_lb_set                  */ NULL,
     38     /* force_lb_check                */ NULL,
     39     /* resource_status_update        */ bcmi_xgs5_port_resource_status_update,
     40     /* port_resource_speed_multi_set */ bcmi_xgs5_port_resource_speed_multi_set,
     41     /* device_speed_check            */ bcmi_th3_device_speed_check,
     42 };
     43 
     44 /* Device programming routines */
     45 static bcmi_xgs5_port_func_t bcmi_th3_port_calls = {
     46     /* reconfigure_ports        */ bcmi_tomahawk3_reconfigure_ports,
     47     /* soc_resource_init        */ bcmi_th3_port_soc_resource_init,
     48     /* port_resource_validate   */ bcmi_th3_port_resource_validate,
     49     /* pre_flexport_tdm         */ bcmi_th3_pre_flexport_tdm,
     50     /* post_flexport_tdm        */ NULL, 
     51     /* port_macro_update        */ bcmi_th3_cdport_update,
     52     /* port_enable              */ bcmi_th3_port_enable,
     53     /* port_disable             */ bcmi_th3_port_disable,
     54     /* no_tdm_speed_update      */ bcmi_th3_port_speed_1g_update,
     55     /* speed_ability_get        */ bcmi_th3_speed_ability_get,
     56 };
     57 
     58 static bcmi_xgs5_dev_info_t  *bcmi_th3_dev_info[SOC_MAX_NUM_DEVICES];
     59 
     60 /* HW Definitions */
     61 static bcmi_xgs5_port_drv_t    bcmi_th3_port_drv;
     62 
     63 static 
     64 int (*th3_port_attach_exec[PORT_ATTACH_EXEC__MAX])(int unit, bcm_port_t port) = {
     65     /* MMU config init */
     66     &bcmi_th3_port_attach_mmu,
     67 
     68     /* PORT module (bcm_esw_port_init) */
     69     &bcmi_xgs5_port_attach_dscp,
     70     &bcmi_xgs5_port_attach_software,
     71     &bcmi_xgs5_port_attach_egr_vlan_action,
     72     &bcmi_xgs5_port_cfg_init,
     73     &bcmi_xgs5_port_attach_port_probe,
     74     &bcmi_xgs5_port_attach_frame_length_check,
     75     &bcmi_xgs5_port_attach_rcpu_mtu,
     76     &bcmi_xgs5_port_attach_outer_tpid,
     77     &bcmi_xgs5_port_egr_block_profile_init,
     78     &bcmi_xgs5_port_attach_vlan_protocol,
     79     &bcmi_xgs5_port_attach_eee,
     80     &bcmi_xgs5_port_attach_higig,
     81     &bcmi_xgs5_port_attach_port_info_cfg,
     82     &bcmi_xgs5_port_attach_egr_link_delay,
     83 
     84     /* Other modules related to port */
     85     &bcmi_xgs5_port_attach_stg,
     86     &bcmi_xgs5_port_attach_vlan,
     87     &bcmi_xgs5_port_attach_trunk,
     88     &bcm_th3_cosq_port_attach,
     89     &bcmi_xgs5_port_attach_linkscan,
     90     &bcmi_xgs5_port_attach_stat,
     91     &bcmi_xgs5_port_attach_stack,
     92     &bcmi_xgs5_port_attach_rate,
     93     &bcmi_xgs5_port_attach_field,
     94     &bcmi_xgs5_port_attach_mirror,
     95     &bcmi_xgs5_port_attach_l3,
     96     &bcmi_xgs5_port_attach_ipmc,
     97 #if defined(INCLUDE_L3)
     98     &bcm_th3_ipmc_repl_port_attach,
     99 #else
    100     NULL,
    101 #endif
    102     &bcmi_xgs5_port_attach_mpls,
    103     &bcmi_xgs5_port_attach_mim,
    104 };
    105 
    106 static 
    107 int (*th3_port_detach_exec[PORT_DETACH_EXEC__MAX])(int unit, bcm_port_t port) = {
    108     /* Other modules related to port */
    109 #if defined(INCLUDE_L3)
    110     &bcm_th3_ipmc_repl_port_detach,
    111 #else
    112     NULL,
    113 #endif
    114     &bcmi_xgs5_port_detach_ipmc,
    115     &bcmi_xgs5_port_detach_mpls,
    116     &bcmi_xgs5_port_detach_mim,
    117     &bcmi_xgs5_port_detach_l3,
    118     &bcmi_xgs5_port_detach_mirror,
    119     &bcmi_xgs5_port_detach_field,
    120     &bcmi_xgs5_port_detach_rate,
    121     &bcmi_xgs5_port_detach_stack,
    122     &bcm_th3_cosq_port_detach,
    123     &bcmi_xgs5_port_detach_trunk,
    124     &bcmi_xgs5_port_detach_vlan,
    125     &bcmi_xgs5_port_detach_stg,
    126 
    127     /* PORT module (_bcm_esw_port_deinit) */
    128     &bcmi_th3_port_detach_asf,
    129     &bcmi_xgs5_port_detach_egr_link_delay,
    130     &bcmi_xgs5_port_detach_higig,
    131     &bcmi_xgs5_port_detach_eee,
    132     &bcmi_xgs5_port_detach_vlan_protocol,
    133     &bcmi_xgs5_port_egr_block_profile_init,
    134     &bcmi_xgs5_port_detach_phy,
    135     &bcmi_xgs5_port_detach_dscp,
    136     &bcmi_xgs5_port_cfg_init,
    137     &bcmi_xgs5_port_detach_egr_vlan_action,
    138     &bcmi_xgs5_port_detach_software,
    139 };
    140 
    141 /*
    142  * Function:
    143  *      bcmi_th3_init_condition_set
    144  * Purpose:
    145  *      Set the info of initialized modules in dev_info.
    146  * Parameters:
    147  *      unit - (IN) Unit number.
    148  *      dev_info - (OUT) Device info used during flexport
    149  * Returns:
    150  *      None
    151  * Notes:
    152  *      Must follow the _bcm_modules_init()
    153  */
    154 STATIC void
    155 _bcmi_th3_init_condition_set(int unit, bcmi_xgs5_dev_info_t *dev_info)
    156 {
    157     int init_all;
    158 
    159     init_all = soc_property_get(unit, "init_all_modules",
    160                                 (SAL_BOOT_BCMSIM) || (!SAL_BOOT_SIMULATION));
    161 
    162     if (soc_feature(unit, soc_feature_virtual_switching) ||
    163         soc_feature(unit, soc_feature_gport_service_counters) ||
    164         soc_feature(unit, soc_feature_fast_init) ||
    165         soc_feature(unit, soc_feature_int_common_init)){
    166         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_COMMON);
    167     }
    168 
    169     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PORT);
    170 
    171     if (!(SAL_BOOT_SIMULATION &&
    172           soc_property_get(unit, spn_SKIP_L2_VLAN_INIT, 0))) {
    173         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L2);
    174         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_VLAN);
    175     }
    176 
    177     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_STG);
    178 
    179     if (init_all ||
    180         (soc_property_get(unit, "skip_cosq_init", 0) ? FALSE : TRUE)) {
    181         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_COSQ);
    182     }
    183     if (init_all ||
    184         (soc_property_get(unit, "skip_mirror_init", 0) ? FALSE : TRUE)) {
    185         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MIRROR);
    186     }
    187     if (init_all ||
    188         (soc_property_get(unit, "skip_ipmc_init", 0) ? FALSE : TRUE)) {
    189         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_IPMC);
    190     }
    191     if (init_all) {
    192         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TRUNK);
    193         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MCAST);
    194 
    195         if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) {
    196             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_UDF);
    197         }
    198 
    199 #ifdef BCM_FIELD_SUPPORT
    200         if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECKm)) {
    201             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_RANGE);
    202         }
    203         if (soc_feature(unit, soc_feature_field)) {
    204             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FIELD);
    205             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_AUTH);
    206         }
    207 #endif
    208 
    209 #ifdef INCLUDE_L3
    210         if (soc_feature(unit, soc_feature_failover)) {
    211             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FAILOVER);
    212         }
    213 
    214         if (soc_feature(unit, soc_feature_l3) &&
    215             soc_property_get(unit, spn_L3_ENABLE, 1)) {
    216             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L3);
    217         }
    218         if (soc_feature(unit, soc_feature_ip_mcast)) {
    219             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_IPMC);
    220         }
    221 
    222 #ifdef BCM_MPLS_SUPPORT
    223         if (soc_feature(unit, soc_feature_mpls)) {
    224             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MPLS);
    225         }
    226 #endif
    227         if (soc_feature(unit, soc_feature_mim)) {
    228             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MIM);
    229         }
    230         if (soc_feature(unit, soc_feature_wlan)) {
    231             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_WLAN);
    232         }
    233         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PROXY);
    234 
    235         if (soc_feature(unit, soc_feature_subport) ||
    236             soc_feature(unit, soc_feature_linkphy_coe) ||
    237             soc_feature(unit, soc_feature_subtag_coe) ||
    238             soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    239             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_SUBPORT);
    240         }
    241         if (soc_feature(unit, soc_feature_trill)) {
    242             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TRILL);
    243         }
    244         if (soc_feature(unit, soc_feature_niv)) {
    245             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_NIV);
    246         }
    247         if (soc_feature(unit, soc_feature_l2gre)) {
    248             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L2GRE);
    249         }
    250         if (soc_feature(unit, soc_feature_vxlan)) {
    251             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_VXLAN);
    252         }
    253         if (soc_feature(unit, soc_feature_port_extension)) {
    254             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_EXTENDER);
    255         }
    256         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MULTICAST);
    257 #endif
    258         if (soc_feature(unit, soc_feature_qos_profile)) {
    259             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_QOS);
    260         }
    261         if (soc_feature(unit, soc_feature_oam) ||
    262             soc_feature(unit, soc_feature_fp_based_oam)) {
    263             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_OAM);
    264         }
    265 #ifdef INCLUDE_PTP
    266         if (soc_feature(unit, soc_feature_ptp)) {
    267             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PTP);
    268         }
    269 #endif
    270 #ifdef INCLUDE_BFD
    271         if (soc_feature(unit, soc_feature_bfd)) {
    272             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_BFD);
    273         }
    274 #endif
    275         if (soc_feature(unit, soc_feature_fcoe)) {
    276             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FCOE);
    277         }
    278     }
    279 
    280     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_LINKSCAN);
    281     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_STAT);
    282 #ifdef INCLUDE_KNET
    283     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_KNET);
    284 #endif
    285     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TX);
    286     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_RX);
    287 #ifdef INCLUDE_REGEX
    288     if (soc_feature(unit, soc_feature_regex)) {
    289         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_REGEX);
    290     }
    291 #endif
    292     if (soc_feature(unit, soc_feature_time_support)) {
    293         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TIME);
    294     }
    295     /* Service meter */
    296     if (soc_feature(unit, soc_feature_global_meter)) {
    297         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_GLB_METER);
    298     }
    299 
    300     return;
    301 }
    302 #if 1
    303 /*
    304  * Function:
    305  *      bcmi_th3_port_dev_info_init
    306  * Purpose:
    307  *      Initialize the device info.
    308  * Parameters:
    309  *      unit - (IN) Unit number.
    310  * Returns:
    311  *      BCM_E_xxx
    312  * Notes:
    313  */
    314 int
    315 bcmi_th3_port_dev_info_init(int unit)
    316 {
    317     bcmi_xgs5_dev_info_t *dev_info;
    318     soc_info_t *si = &SOC_INFO(unit);
    319     int alloc_size;
    320     int pipe, phy_port, blk, bindex, rsv_port;
    321     int i, cntmaxsize;
    322 
    323     /* Free bcmi_th3_dev_info[unit] if already allocated */
    324     if (bcmi_th3_dev_info[unit]) {
    325         sal_free(bcmi_th3_dev_info[unit]);
    326         bcmi_th3_dev_info[unit] = NULL;
    327     }
    328 
    329     /* Allocate memory for main SW data structure */
    330     alloc_size = sizeof(bcmi_xgs5_dev_info_t) +
    331                  (sizeof(bcmi_xgs5_phy_port_t) * _TH3_PHY_PORTS_PER_DEV);
    332     dev_info = sal_alloc(alloc_size, "bcmi_th3_dev_info");
    333     if (dev_info == NULL) {
    334         return BCM_E_MEMORY;
    335     }
    336     sal_memset(dev_info, 0, alloc_size);
    337     dev_info->phy_port_info = (bcmi_xgs5_phy_port_t *)&dev_info[1];
    338     bcmi_th3_dev_info[unit] = dev_info;
    339 
    340     /* Clear data structure */
    341 
    342     /* Device information init */
    343     dev_info = bcmi_th3_dev_info[unit];
    344     dev_info->phy_ports_max = _TH3_PHY_PORTS_PER_DEV;
    345     dev_info->mmu_lossless = si->mmu_lossless;
    346     dev_info->asf_prof_default = _SOC_ASF_MEM_PROFILE_SIMILAR;
    347     dev_info->pipe_bound = 1;
    348     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
    349         /* First logical port in pipe   */
    350         dev_info->pipe_log_port_base[pipe] = _TH3_DEV_PORTS_PER_PIPE * pipe;
    351 
    352         /* First physical port in pipe  */
    353         dev_info->pipe_phy_port_base[pipe] = _TH3_GPHY_PORTS_PER_PIPE * pipe +
    354                                              (pipe ? 1 : 0);
    355         /* TH3 has no rserved ports*/
    356         rsv_port = 0;
    357         dev_info->ports_pipe_max[pipe] = _TH3_DEV_PORTS_PER_PIPE - rsv_port;
    358     }
    359     /* 50G is the min speed in TDM calendar program.  However, Tomahawk 3
    360      * allows speeds 10G and 25G
    361      */
    362     dev_info->tdm_speed_min = SPEED_10G;
    363 
    364     /* 10G is the min speed in TDM calculations */
    365     dev_info->tdm_pipe_lr_bw_limit_checker_speed_min = SPEED_10G;
    366 
    367     /* There is no CDPORT_CNTMAXSIZE, but maintain code consistency for these
    368      * fields*/
    369     cntmaxsize = soc_property_get(unit, spn_BCM_STAT_JUMBO, 1518);
    370     if (cntmaxsize > si->max_mtu) {
    371         cntmaxsize = si->max_mtu;
    372     }
    373     dev_info->cntmaxsize_xl = cntmaxsize;
    374     dev_info->cntmaxsize_cl = cntmaxsize;
    375 
    376     dev_info->restriction_mask = /*BCMI_XGS5_FLEXPORT_RESTRICTION_PIPE_BANDWIDTH |
    377                             BCMI_XGS5_FLEXPORT_RESTRICTION_MIX_LR_OVS_DEV | */
    378                             BCMI_XGS5_FLEXPORT_RESTRICTION_SPEED_CLASS |
    379                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_DOUBLE_PLL;
    380                             /*BCMI_XGS5_FLEXPORT_RESTRICTION_PM_MIX_ETH_HIGIG;*/
    381 
    382     dev_info->encap_mask = BCM_PA_ENCAP_IEEE;
    383 
    384     /*
    385      * Restriction 13:No port configurations with more than 4 port speed
    386      *                classes are supported.
    387      *
    388      * Restriction 15:All port configurations with 1-3 port speed classes are
    389      *                supported, except configurations that contain both 20G
    390      *                and 25G port speeds.
    391      */
    392     dev_info->speed_class.speed_class_num = _TH3_TDM_SPEED_CLASS_MAX;
    393 
    394     dev_info->port_ratio_mask = BCMI_XGS5_PORT_RATIO_SINGLE |
    395                                     BCMI_XGS5_PORT_RATIO_DUAL_1_1 |
    396                                     BCMI_XGS5_PORT_RATIO_DUAL_2_1 |
    397                                     BCMI_XGS5_PORT_RATIO_DUAL_1_2 |
    398                                     BCMI_XGS5_PORT_RATIO_TRI_023_2_1_1 |
    399                                     BCMI_XGS5_PORT_RATIO_TRI_023_4_1_1 |
    400                                     BCMI_XGS5_PORT_RATIO_TRI_012_1_1_2 |
    401                                     BCMI_XGS5_PORT_RATIO_TRI_012_1_1_4 |
    402                                     BCMI_XGS5_PORT_RATIO_QUAD;
    403 
    404     /*
    405      * Set physical port info:
    406      *  - Port lane capability
    407      *  - Port is enabled for flexport
    408      *  - pipe
    409      */
    410     for (phy_port = 0; phy_port < _TH3_PHY_PORTS_PER_DEV; phy_port++) {
    411         /* Set information to invalid */
    412         dev_info->phy_port_info[phy_port].pipe = -1;
    413     }
    414 
    415     /* Flexport is not supported for CPU/LB/MNG ports, so skip CPU/LB/MNG */
    416     for (phy_port = 1; phy_port <= _TH3_GPHY_PORTS_PER_DEV; phy_port++) {
    417         /* Check for end of port list */
    418         if (SOC_PORT_BLOCK(unit, phy_port) < 0 &&
    419             SOC_PORT_BINDEX(unit, phy_port) < 0) {
    420             break;
    421         }
    422         /* Set pipe information */
    423         dev_info->phy_port_info[phy_port].pipe =
    424                                     (phy_port - 1) / _TH3_GPHY_PORTS_PER_PIPE;
    425 
    426 
    427         /* Set TSC info */
    428         dev_info->phy_port_info[phy_port].force_lb = 0;
    429         dev_info->phy_port_info[phy_port].max_lane_speed = 53000;
    430 
    431         for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    432             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
    433             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
    434 
    435             if ((blk < 0) || (bindex < 0)) {
    436                 continue;
    437             }
    438             
    439             if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CDPORT) {
    440                 /* Set port lane capabilites */
    441                 dev_info->phy_port_info[phy_port].lanes_valid =
    442                                                 BCMI_XGS5_PORT_LANES_1;
    443                 if (bindex == 0) {
    444                     dev_info->phy_port_info[phy_port].lanes_valid |=
    445                         BCMI_XGS5_PORT_LANES_2 | BCMI_XGS5_PORT_LANES_4 |
    446                         BCMI_XGS5_PORT_LANES_8;
    447                 } else if (bindex == 2 || bindex == 6) {
    448                     dev_info->phy_port_info[phy_port].lanes_valid |=
    449                                                 BCMI_XGS5_PORT_LANES_2;
    450                 } else if (bindex == 4) {
    451                     dev_info->phy_port_info[phy_port].lanes_valid |=
    452                         BCMI_XGS5_PORT_LANES_2 | BCMI_XGS5_PORT_LANES_4;
    453                 }
    454 
    455                 if (SHR_BITGET(si->flexible_pm_bitmap,blk)) {
    456                     dev_info->phy_port_info[phy_port].flex = 1;
    457                 }
    458             }
    459         } /* for port_num_blktype */
    460     }
    461 
    462     /* Init condition */
    463     _bcmi_th3_init_condition_set(unit, dev_info);
    464 
    465     return BCM_E_NONE;
    466 }
    467 #endif
    468 /*
    469  * Function:
    470  *      bcmi_td2p_port_fn_drv_init
    471  * Purpose:
    472  *      Initialize the Port function driver.
    473  * Parameters:
    474  *      unit - (IN) Unit number.
    475  * Returns:
    476  *      BCM_E_xxx
    477  * Notes:
    478  */
    479 int
    480 bcmi_th3_port_fn_drv_init(int unit)
    481 {
    482     int phase_pos, present;
    483 
    484     BCM_IF_ERROR_RETURN
    485         (bcmi_th3_port_dev_info_init(unit));
    486 
    487     /* BCMI Driver init */
    488     sal_memset(&bcmi_th3_port_drv, 0, sizeof(bcmi_th3_port_drv));
    489     bcmi_th3_port_drv.port_calls = &bcmi_th3_port_calls;
    490     bcmi_th3_port_drv.dev_info[unit] = bcmi_th3_dev_info[unit];
    491 
    492 
    493     sal_memcpy(bcmi_th3_port_drv.port_calls->port_attach_exec,
    494                th3_port_attach_exec,
    495                sizeof(bcmi_th3_port_drv.port_calls->port_attach_exec));
    496 
    497     sal_memcpy(bcmi_th3_port_drv.port_calls->port_detach_exec,
    498                th3_port_detach_exec,
    499                sizeof(bcmi_th3_port_drv.port_calls->port_detach_exec));
    500 
    501     /* Initialize Common XGS5 Port module */
    502     BCM_IF_ERROR_RETURN
    503         (bcmi_xgs5_port_fn_drv_init(unit,
    504                                     &bcm_th3_port_drv,
    505                                     &bcmi_th3_port_drv,
    506                                     NULL));
    507 
    508     BCM_IF_ERROR_RETURN(soc_check_flex_phase(unit, th3_flexport_phases,
    509                                              soc_tomahawk3_flex_top_port_down,
    510                                              &present));
    511     /* Detach port enable/disable in DV Flexport */
    512     if (present) {
    513         BCM_IF_ERROR_RETURN
    514             (soc_detach_flex_phase(unit, th3_flexport_phases,
    515                                    soc_tomahawk3_flex_top_port_down,
    516                                    &phase_pos));
    517     }
    518     BCM_IF_ERROR_RETURN(soc_check_flex_phase(unit, th3_flexport_phases,
    519                                              soc_tomahawk3_flex_top_port_up,
    520                                              &present));
    521     if (present) {
    522         BCM_IF_ERROR_RETURN
    523             (soc_detach_flex_phase(unit, th3_flexport_phases,
    524                                    soc_tomahawk3_flex_top_port_up,
    525                                    &phase_pos));
    526     }
    527 
    528     return BCM_E_NONE;
    529 }
    530 /*
    531  * Function:
    532  *      bcmi_th3_port_soc_resource_init
    533  * Purpose:
    534  *      Initialize SOC Port Structure.
    535  *      This includes:
    536  *          Copy Port information from BCM port resource array.
    537  *          Set correct pipe, MMU port, IDB port for new logical port.
    538  * Parameters:
    539  *      unit         - (IN)  Unit number.
    540  *      nport        - (IN)  Number of elements in array resource.
    541  *      resource     - (IN)  BCM Port resource configuration array.
    542  *      soc_resource - (OUT) SOC Port resource array.
    543  * Returns:
    544  *      BCM_E_xxx
    545  * Notes:
    546  */
    547 int
    548 bcmi_th3_port_soc_resource_init(int unit, int nport,
    549                                  bcm_port_resource_t *resource,
    550                                  soc_port_resource_t *soc_resource)
    551 {
    552     int i;
    553     int logic_port, idb_port, mmu_port, pipe;
    554 
    555     /*
    556      * SOC Port Structure initialization
    557      */
    558 
    559     /* Clear data structure */
    560     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
    561 
    562     /* Copy initial information */
    563     for (i = 0; i < nport; i++) {
    564         logic_port = resource[i].port;
    565 #if 0
    566         
    567         if (logic_port == _TH3_DEV_RSV_PORT) {
    568             return BCM_E_PORT;
    569         }
    570 #endif
    571         pipe = logic_port/_TH3_DEV_PORTS_PER_PIPE;
    572         idb_port = (logic_port % _TH3_DEV_PORTS_PER_PIPE) - (pipe == 0 ? 1 : 0);
    573         mmu_port = pipe * _TH3_MMU_PORTS_OFFSET_PER_PIPE + idb_port;
    574 
    575         soc_resource[i].flags = resource[i].flags;
    576         soc_resource[i].logical_port = logic_port;
    577         soc_resource[i].physical_port = resource[i].physical_port;
    578         soc_resource[i].speed = resource[i].speed < SPEED_10G ?
    579                                 SPEED_10G : resource[i].speed;
    580         soc_resource[i].num_lanes = resource[i].lanes;
    581         soc_resource[i].encap = resource[i].encap;
    582         soc_resource[i].pipe = pipe;
    583         soc_resource[i].idb_port = idb_port;
    584         soc_resource[i].mmu_port = mmu_port;
    585         /* TH3 does NOT support port configuration with a mix of line-rate ports
    586          * and oversubscribed ports; all ports are oversub */
    587         soc_resource[i].oversub = 1;
    588 
    589         /* New Speed Config parameters required for FlexPort */
    590         soc_resource[i].fec_type = resource[i].fec_type;
    591         soc_resource[i].phy_lane_config = resource[i].phy_lane_config;
    592         soc_resource[i].link_training = resource[i].link_training;
    593     }
    594 
    595     return BCM_E_NONE;
    596 }
    597 
    598 /*
    599  * Function:
    600  *      bcmi_th3_port_resource_validate
    601  * Purpose:
    602  *      Validate that the given FlexPort operations is valid.
    603  * Parameters:
    604  *      unit                 - (IN)  Unit number.
    605  *      port_schedule_state  - (OUT) Port resource state.
    606  * Returns:
    607  *      BCM_E_xxx
    608  * Notes:
    609  */
    610 int
    611 bcmi_th3_port_resource_validate(int unit,
    612                             soc_port_schedule_state_t *port_schedule_state)
    613 {
    614     return BCM_E_NONE;
    615 }
    616 
    617 /*
    618  * Function:
    619  *      bcmi_th3_pre_flexport_tdm
    620  * Purpose:
    621  *      Pass TDM information pre FlexPort to DV FlexPort API
    622  * Parameters:
    623  *      unit                 - (IN)  Unit number.
    624  *      port_schedule_state  - (OUT) Port resource state.
    625  * Returns:
    626  *      BCM_E_xxx
    627  * Notes:
    628  */
    629 int
    630 bcmi_th3_pre_flexport_tdm(int unit,
    631                             soc_port_schedule_state_t *port_schedule_state)
    632 {
    633     port_schedule_state->is_flexport = 1;
    634 
    635 
    636 
    637     return BCM_E_NONE;
    638 }
    639 
    640 /*
    641  * Function:
    642  *      bcmi_th3_post_flexport_tdm
    643  * Purpose:
    644  *      Update TDM information in SOC with post FlexPort TDM state return from 
    645  *      DV FlexPort API.
    646  * Parameters:
    647  *      unit                 - (IN)  Unit number.
    648  *      port_schedule_state  - (IN) Port resource state.
    649  * Returns:
    650  *      BCM_E_xxx
    651  * Notes:
    652  */
    653 int
    654 bcmi_th3_post_flexport_tdm(int unit,
    655                             soc_port_schedule_state_t *port_schedule_state)
    656 {
    657 
    658 
    659     return BCM_E_NONE;
    660 }
    661 
    662 /*
    663  * Function:
    664  *      bcmi_th3_cdport_update
    665  * Purpose:
    666  *      Update CDPORT.
    667  * Parameters:
    668  *      unit                 - (IN)  Unit number.
    669  *      port_schedule_state  - (IN) Port resource state.
    670  * Returns:
    671  *      BCM_E_xxx
    672  * Notes:
    673  */
    674 int
    675 bcmi_th3_cdport_update(int unit,
    676                             soc_port_schedule_state_t *port_schedule_state)
    677 {
    678     /* This function is intended to update port_mode in CDPORT_MODE_REG.
    679      * On TH3, Portmod(PM8x50) will take care of port_mode update.
    680      * So we just return E_NONE in this function.
    681      */
    682     return BCM_E_NONE;
    683 }
    684 
    685 int
    686 bcmi_th3_port_attach_mmu(int unit, int port)
    687 {
    688     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
    689         IS_MANAGEMENT_PORT(unit, port)) {
    690         return BCM_E_PARAM;
    691     }
    692 # if 0
    693     
    694     /* Assign the base queues and number of queues for the specified port. */
    695     BCM_IF_ERROR_RETURN
    696         (soc_tomahawk3_num_cosq_init_port(unit, port));
    697 
    698     /* Reconfigure THDI, THDO settings */
    699     BCM_IF_ERROR_RETURN
    700         (soc_th3_mmu_config_init_port(unit, port));
    701 #endif
    702     return BCM_E_NONE;
    703 }
    704 
    705 /*
    706  * Function:
    707  *      bcmi_th3_port_detach_asf
    708  * Purpose:
    709  *      Update ASF when port deleted during Flexport operations.
    710  * Parameters:
    711  *      unit                 - (IN)  Unit number.
    712  *      port                 - (IN)  Logical port number.
    713  * Returns:
    714  *      BCM_E_xxx
    715  * Notes:
    716  */
    717 int
    718 bcmi_th3_port_detach_asf(int unit, bcm_port_t port)
    719 {
    720 
    721     if (soc_feature(unit, soc_feature_asf_multimode)) {
    722         BCM_IF_ERROR_RETURN
    723             (soc_th3_port_asf_detach(unit, port));
    724     }
    725 
    726     return BCM_E_NONE;
    727 }
    728 
    729 /*
    730  * Function:
    731  *      bcmi_th3_port_enable
    732  * Purpose:
    733  *      Enable port.
    734  * Parameters:
    735  *      unit                 - (IN)  Unit number.
    736  *      port_schedule_state  - (IN) Port resource state.
    737  * Returns:
    738  *      BCM_E_xxx
    739  * Notes:
    740  *      This function should only be called with PORTMOD enabled
    741  */
    742 int
    743 bcmi_th3_port_enable(int unit,
    744                              soc_port_schedule_state_t *port_schedule_state)
    745 {
    746     int i, nport, rv = 0;
    747     bcm_port_t *port;
    748 
    749     nport = port_schedule_state->nport;
    750 
    751     port = sal_alloc(nport * sizeof(bcm_port_t), "port array");
    752     if (port == NULL) {
    753         return BCM_E_MEMORY;
    754     }
    755     for (i = 0; i < nport; i++) {
    756         port[i] = port_schedule_state->resource[i].logical_port;
    757     }
    758 
    759     if (BCM_SUCCESS(rv)) {
    760         rv = soc_tomahawk3_ep_port_up(unit, port_schedule_state);
    761     }
    762 
    763     if (!SAL_BOOT_BCMSIM) {
    764         if (BCM_SUCCESS(rv)) {
    765             rv = soc_tomahawk3_mmu_port_up(unit, port_schedule_state);
    766         }
    767     }
    768 
    769     if (!SAL_BOOT_BCMSIM) {
    770         if (BCM_SUCCESS(rv)) {
    771             rv = soc_tomahawk3_idb_port_up(unit, port_schedule_state);
    772         }
    773     }
    774    
    775     if (BCM_SUCCESS(rv)) 
    776     {
    777         rv = bcmi_esw_portctrl_mac_up(unit, nport, port);
    778     }
    779     sal_free(port);
    780 
    781     return rv;
    782 }
    783 
    784 /*
    785  * Function:
    786  *      bcmi_th3_port_disable
    787  * Purpose:
    788  *      Disable port.
    789  * Parameters:
    790  *      unit                 - (IN)  Unit number.
    791  *      port_schedule_state  - (IN) Port resource state.
    792  * Returns:
    793  *      BCM_E_xxx
    794  * Notes:
    795  *      This function should only be called with PORTMOD enabled
    796  */
    797 int
    798 bcmi_th3_port_disable(int unit,
    799                                 soc_port_schedule_state_t *port_schedule_state)
    800 {
    801     int i, nport, rv;
    802     bcm_port_t *port;
    803 
    804     nport = port_schedule_state->nport;
    805 
    806     port = sal_alloc(nport * sizeof(bcm_port_t), "port array");
    807     if (port == NULL) {
    808         return BCM_E_MEMORY;
    809     }
    810     for (i = 0; i < nport; i++) {
    811         port[i] = port_schedule_state->resource[i].logical_port;
    812     }
    813 
    814     rv = bcmi_esw_portctrl_mac_rx_down(unit, nport, port);
    815     
    816     if (!SAL_BOOT_BCMSIM) {
    817         if (BCM_SUCCESS(rv)) {
    818             rv = soc_tomahawk3_idb_port_down(unit, port_schedule_state);
    819         }
    820     }
    821 
    822     if (!SAL_BOOT_BCMSIM) {
    823         if (BCM_SUCCESS(rv)) {
    824             rv = soc_tomahawk3_mmu_port_down(unit, port_schedule_state);
    825         }
    826     }
    827 
    828     if (BCM_SUCCESS(rv)) {
    829         rv = soc_tomahawk3_ep_port_down(unit, port_schedule_state);
    830     }
    831     /* Clear EDB_CREDIT_COUNTER */
    832     if (BCM_SUCCESS(rv)) {
    833         rv = soc_tomahawk3_tdm_clear_edb_credit_counter(unit,
    834                                         port_schedule_state);
    835     }
    836     if (BCM_SUCCESS(rv)) 
    837     {
    838         rv = bcmi_esw_portctrl_mac_tx_down(unit, nport, port);
    839     }
    840 
    841     sal_free(port);
    842 
    843     return rv;
    844 }
    845 
    846 /*
    847  * Function:
    848  *      bcmi_th3_port_speed_1g_update
    849  * Purpose:
    850  *      Special operations for 1G speed.
    851  * Parameters:
    852  *      unit                 - (IN) Unit number.
    853  *      port                 - (IN) Logical port number.
    854  *      speed                - (IN) port speed (Mbps).
    855  * Returns:
    856  *      BCM_E_xxx
    857  * Notes:
    858  *      In the PRD, nothing below 10G is officially supported.
    859  *      We enable customers with limited 1G support in Tomahawk3.
    860  *      1G is not a support speed class in TDM calculation, thus treated same as
    861  *      10G in TDM calculation. 1G port does NOT support cut through, flow
    862  *      control.
    863  */
    864 int
    865 bcmi_th3_port_speed_1g_update(int unit, bcm_port_t port, int speed)
    866 {
    867     if (speed != SPEED_1G) {
    868         return BCM_E_NONE;
    869     }
    870 
    871     /* Update port speed info in soc_info */
    872     SOC_INFO(unit).port_init_speed[port] = speed;
    873 
    874     /* Set asf mode to SAF */
    875     if (soc_feature(unit, soc_feature_asf_multimode)) {
    876         BCM_IF_ERROR_RETURN
    877             (soc_th_port_asf_mode_set(unit, port, speed,
    878                                       _SOC_TH_ASF_MODE_SAF));
    879     }
    880 
    881     /* Disable Pause */
    882     BCM_IF_ERROR_RETURN
    883         (bcm_esw_port_pause_set(unit, port, 0, 0));
    884 
    885     /* Disable PFC */
    886     if (soc_feature(unit, soc_feature_priority_flow_control)) {
    887         BCM_IF_ERROR_RETURN
    888             (bcm_esw_port_control_set(unit, port,
    889                                       bcmPortControlPFCReceive, 0));
    890         BCM_IF_ERROR_RETURN
    891             (bcm_esw_port_control_set(unit, port,
    892                                       bcmPortControlPFCTransmit, 0));
    893     }
    894 
    895     return BCM_E_NONE;
    896 }
    897 
    898 /*
    899  * Function:
    900  *      bcmi_th3_speed_ability_get
    901  * Purpose:
    902  *      Retrieve the local port abilities.
    903  * Parameters:
    904  *      unit - Unit.
    905  *      port - Logical port num.
    906  *      mask - (OUT) Mask of BCM_PORT_ABILITY_ values indicating the
    907  *              supported speeds of the port.
    908  * Returns:
    909  *      BCM_E_NONE
    910  *      BCM_E_XXX
    911  */
    912 int
    913 bcmi_th3_speed_ability_get(int unit, bcm_port_t port, bcm_port_abil_t *mask)
    914 {
    915     if (IS_MANAGEMENT_PORT(unit, port)) {
    916         /* TH3 Port Rates for Management ports:
    917          * 100M, 1G, 2.5G, 10G, HG[11G] */
    918         *mask = BCM_PORT_ABILITY_10MB |  BCM_PORT_ABILITY_100MB |
    919                 BCM_PORT_ABILITY_1000MB | BCM_PORT_ABILITY_2500MB |
    920                 BCM_PORT_ABILITY_10GB | BCM_PORT_ABILITY_11GB;
    921     } else {
    922         /* Not supported for PM8x50. */
    923         *mask = 0;
    924         return BCM_E_UNAVAIL;
    925 #if 0
    926         BCM_IF_ERROR_RETURN
    927             (soc_th3_support_speeds(unit,
    928                                     SOC_INFO(unit).port_num_lanes[port],
    929                                     mask));
    930 #endif
    931     }
    932 
    933     return BCM_E_NONE;
    934 }
    935 
    936 /*
    937  * Function:
    938  *      bcmi_th3_tsc_xgxs_reset
    939  * Purpose:
    940  *      Reset TSC.
    941  * Parameters:
    942  *      unit - Unit.
    943  *      pbmp - Bitmap of ports to reset.
    944  * Returns:
    945  *      BCM_E_NONE
    946  *      BCM_E_XXX
    947  */
    948 int
    949 bcmi_th3_tsc_xgxs_reset(int unit, pbmp_t pbmp)
    950 {
    951     int rv = BCM_E_NONE;
    952     soc_info_t *si;
    953     uint64 tsc_map, reset_tsc_map;
    954     int tsc, ports[_TH3_PBLKS_PER_DEV];
    955     bcm_port_t port;
    956     _bcm_port_info_t *port_info = NULL;
    957 
    958     si = &SOC_INFO(unit);
    959     
    960     /* Construct tsc_map covered by the specified pbmp */
    961     COMPILER_64_ZERO(tsc_map);    
    962     PBMP_ITER(pbmp, port) {
    963         tsc = si->port_serdes[port];
    964         if (tsc != -1) {
    965             COMPILER_64_BITSET(tsc_map, tsc);
    966         }
    967     }
    968 
    969     COMPILER_64_ZERO(reset_tsc_map);
    970     PBMP_PORT_ITER(unit, port) {
    971         tsc = si->port_serdes[port];
    972         if (COMPILER_64_BITTEST(tsc_map, tsc)) {
    973             _bcm_port_info_access(unit, port, &port_info);            
    974             if (port_info->flags & _PORT_INFO_PROBE_RESET_SERDES) {
    975                 port_info->flags &= ~_PORT_INFO_PROBE_RESET_SERDES;
    976                 COMPILER_64_BITSET(reset_tsc_map, tsc);
    977                 ports[tsc] = port;
    978             }
    979         }
    980     }
    981     
    982     for (tsc = 0; tsc < _TH3_PBLKS_PER_DEV; tsc++) {
    983         if (COMPILER_64_BITTEST(reset_tsc_map, tsc)) {
    984             rv = soc_tsc_xgxs_reset(unit, ports[tsc], 0);
    985         }
    986     }
    987     
    988     return rv;    
    989 }
    990 
    991 /*
    992  * Function:
    993  *      bcm_th3_port_rate_egress_set
    994  * Purpose:
    995  *      Set egress metering information
    996  * Parameters:
    997  *      unit       - (IN) Unit number
    998  *      port       - (IN) Port number
    999  *      bandwidth  - (IN) Kilobits per second or packets per second
   1000  *                        zero if rate limiting is disabled
   1001  *      burst      - (IN) Maximum burst size in kilobits or packets
   1002  *      mode       - (IN) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE
   1003  * Returns:
   1004  *      BCM_E_XXX
   1005  */
   1006 int
   1007 bcm_th3_port_rate_egress_set(int unit, bcm_port_t port, uint32 bandwidth,
   1008                             uint32 burst, uint32 mode)
   1009 {
   1010     soc_info_t *si;
   1011     int index, pipe;
   1012     soc_mem_t mem;
   1013     uint32 rval, itu_mode_sel;
   1014     mmu_mtro_egrmeteringconfig_entry_t entry;
   1015     uint32 refresh_rate, bucketsize, granularity, flags;
   1016     int refresh_bitsize, bucket_bitsize;
   1017 
   1018     si = &SOC_INFO(unit);
   1019 
   1020     sal_memset(&entry, 0, sizeof(entry));
   1021 
   1022     index = SOC_TH3_MMU_LOCAL_PORT(unit, port);
   1023     pipe = si->port_pipe[port];
   1024 
   1025     mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_EGRMETERINGCONFIGm)[pipe];
   1026 
   1027     /* If metering is disabled on this ingress port we are done. */
   1028     if (!bandwidth || !burst) {
   1029         SOC_IF_ERROR_RETURN
   1030             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
   1031         return BCM_E_NONE;
   1032     }
   1033     if((bandwidth < _BCM_TH3_PORT_RATE_MIN_KILOBITS ||
   1034         bandwidth > _BCM_TH3_PORT_RATE_MAX_KILOBITS) ||
   1035        (burst < _BCM_PORT_BURST_MIN_KILOBITS ||
   1036         burst > _BCM_PORT_BURST_MAX_KILOBITS)){
   1037         return BCM_E_PARAM;
   1038     }
   1039     flags = mode == _BCM_PORT_RATE_PPS_MODE ?
   1040         _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   1041 
   1042     BCM_IF_ERROR_RETURN(READ_MMU_MTRO_CONFIGr(unit, &rval));
   1043     itu_mode_sel = soc_reg_field_get(unit, MMU_MTRO_CONFIGr, rval, ITU_MODE_SELf);
   1044 
   1045     if (itu_mode_sel) {
   1046         flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1047     }
   1048 
   1049     refresh_bitsize = soc_mem_field_length(unit, mem, REFRESHf);
   1050     bucket_bitsize = soc_mem_field_length(unit, mem, THD_SELf);
   1051     BCM_IF_ERROR_RETURN
   1052         (_bcm_th3_rate_to_bucket_encoding(unit, bandwidth, burst, flags,
   1053                                          refresh_bitsize, bucket_bitsize,
   1054                                          &refresh_rate, &bucketsize,
   1055                                          &granularity));
   1056     soc_mem_field32_set(unit, mem, &entry, PACKET_SHAPINGf,
   1057                     mode == _BCM_PORT_RATE_PPS_MODE ? 1 : 0);
   1058 
   1059     soc_mem_field32_set(unit, mem, &entry, METER_GRANf, granularity);
   1060     soc_mem_field32_set(unit, mem, &entry, REFRESHf, refresh_rate);
   1061     soc_mem_field32_set(unit, mem, &entry, THD_SELf, bucketsize);
   1062 
   1063     SOC_IF_ERROR_RETURN
   1064         (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
   1065 
   1066     return BCM_E_NONE;
   1067 }
   1068 
   1069 /*
   1070  * Function:
   1071  *      bcm_th3_port_rate_egress_get
   1072  * Purpose:
   1073  *      Get egress metering information
   1074  * Parameters:
   1075  *      unit       - (IN) Unit number
   1076  *      port       - (IN) Port number
   1077  *      bandwidth  - (OUT) Kilobits per second or packets per second
   1078  *                         zero if rate limiting is disabled
   1079  *      burst      - (OUT) Maximum burst size in kilobits or packets
   1080  *      mode       - (OUT) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE
   1081  * Returns:
   1082  *      BCM_E_XXX
   1083  */
   1084 int
   1085 bcm_th3_port_rate_egress_get(int unit, bcm_port_t port, uint32 *bandwidth,
   1086                             uint32 *burst, uint32 *mode)
   1087 {
   1088     soc_info_t *si;
   1089     int index, pipe;
   1090     soc_mem_t mem;
   1091     uint32 rval, itu_mode_sel;
   1092     mmu_mtro_egrmeteringconfig_entry_t entry;
   1093     uint32 refresh_rate, bucketsize, granularity, flags;
   1094 
   1095     if (bandwidth == NULL || burst == NULL) {
   1096         return BCM_E_PARAM;
   1097     }
   1098 
   1099     si = &SOC_INFO(unit);
   1100     index = SOC_TH3_MMU_LOCAL_PORT(unit, port);
   1101     pipe = si->port_pipe[port];
   1102 
   1103     mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_EGRMETERINGCONFIGm)[pipe];
   1104 
   1105     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry));
   1106 
   1107     refresh_rate = soc_mem_field32_get(unit, mem, &entry, REFRESHf);
   1108     bucketsize = soc_mem_field32_get(unit, mem, &entry, THD_SELf);
   1109     granularity = soc_mem_field32_get(unit, mem, &entry, METER_GRANf);
   1110 
   1111     flags = soc_mem_field32_get(unit, mem, &entry, PACKET_SHAPINGf) ?
   1112         _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   1113 
   1114     BCM_IF_ERROR_RETURN(READ_MMU_MTRO_CONFIGr(unit, &rval));
   1115     itu_mode_sel = soc_reg_field_get(unit, MMU_MTRO_CONFIGr, rval, ITU_MODE_SELf);
   1116 
   1117     if (itu_mode_sel) {
   1118         flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1119     }
   1120 
   1121     BCM_IF_ERROR_RETURN
   1122         (_bcm_th3_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   1123                                          granularity, flags, bandwidth,
   1124                                          burst));
   1125     *mode = flags & _BCM_TD_METER_FLAG_PACKET_MODE ?
   1126         _BCM_PORT_RATE_PPS_MODE : _BCM_PORT_RATE_BYTE_MODE;
   1127 
   1128     return BCM_E_NONE;
   1129 }
   1130 
   1131 /*
   1132  * Function:
   1133  *      bcm_th3_device_speed_check
   1134  * Purpose:
   1135  *      Restriction: Checks supported speeds for TH3
   1136  * Parameters:
   1137  *      unit     - (IN) Unit number
   1138  *      speed    - (IN) speed
   1139  *      lanes    - (IN) lanes (-1 if don't care about lanes)
   1140  * Returns:
   1141  *      BCM_E_XXX
   1142  */
   1143 int
   1144 bcmi_th3_device_speed_check(int unit, int speed, int lanes)
   1145 {
   1146     switch(speed) {
   1147         case 400000:
   1148             if (SOC_INFO(unit).frequency < 1200) {
   1149                 break;
   1150             }
   1151             if (lanes > 0 && lanes != 8) {
   1152                 break;
   1153             }
   1154             return BCM_E_NONE;
   1155         case 200000:
   1156             if (lanes > 0 && lanes != 4) {
   1157                 break;
   1158             }
   1159             return BCM_E_NONE;
   1160         case 100000:
   1161             if (lanes > 0 && lanes != 4 && lanes != 2) {
   1162                 break;
   1163             }
   1164             if (SOC_INFO(unit).frequency < 600) {
   1165                 break;
   1166             }
   1167             return BCM_E_NONE;
   1168         case 50000:
   1169             if (lanes > 0 && lanes != 1 && lanes != 2) {
   1170                 break;
   1171             }
   1172             if (SOC_INFO(unit).frequency < 300) {
   1173                 break;
   1174             }
   1175             return BCM_E_NONE;
   1176         case 40000:
   1177             if (lanes > 0 && lanes != 4 && lanes != 2) {
   1178                 break;
   1179             }
   1180             return BCM_E_NONE;
   1181         case 25000:
   1182             if (lanes > 0 && lanes != 1) {
   1183                 break;
   1184             }
   1185             return BCM_E_NONE;
   1186         case 10000:
   1187             if (lanes > 0 && lanes != 1) {
   1188                 break;
   1189             }
   1190             return BCM_E_NONE;
   1191         default:
   1192             break;
   1193 
   1194     }
   1195     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1196           (BSL_META_U(unit,
   1197                       "Speed Unsupported "
   1198                       "speed=%d\n"
   1199                       "lanes=%d\n"
   1200                       "frequency=%d\n"),
   1201            speed, lanes, SOC_INFO(unit).frequency));
   1202 
   1203     return BCM_E_PARAM;
   1204 }
   1205 
   1206 /*
   1207  * Function:
   1208  *      bcmi_tomahawk3_reconfigure_ports
   1209  * Purpose:
   1210  *      To bring the TSC clock for port macros being flexed up for
   1211  *      the flex operation, and back down if they were brought up
   1212  * Parameters:
   1213  *      unit                   - (IN) Unit number
   1214  *      port_schedule_state    - (IN) Flex info
   1215  * Returns:
   1216  *      BCM_E_XXX
   1217  */
   1218 int
   1219 bcmi_tomahawk3_reconfigure_ports(int unit,
   1220             soc_port_schedule_state_t *port_schedule_state)
   1221 {
   1222     int i;
   1223     int nport;
   1224     int phy_port;
   1225     int pm_id;
   1226     int portmod_pm_id;
   1227     int is_init;
   1228     int rv = BCM_E_NONE;
   1229     char brought_up[SOC_TH3_PM8X50_COUNT];
   1230     soc_port_resource_t *resource;
   1231 
   1232     resource = port_schedule_state->resource;
   1233     nport = port_schedule_state->nport;
   1234 
   1235     sal_memset(brought_up, 0, SOC_TH3_PM8X50_COUNT * sizeof(char));
   1236 
   1237     /* Find ports that are going to come up after flexing and enable
   1238      * the TSC clock so that the DV Flexport code can access
   1239      * the registers */
   1240     for (i = 0; i < nport; i++) {
   1241         phy_port = resource[i].physical_port;
   1242 
   1243         /* Skip Port deletes; we only care about ports coming up because
   1244          * they'll require the port macro to be active */
   1245         if (phy_port == -1) {
   1246             continue;
   1247         }
   1248 
   1249         /* Get the SDK port macro number */
   1250         pm_id = (phy_port - 1) / _TH3_PORTS_PER_PBLK;
   1251 
   1252         /* Skip if we already brought it up */
   1253         if (brought_up[pm_id] == 1) {
   1254             continue;
   1255         }
   1256 
   1257         /* Fetch the portmod pm id since indexing is different than sdk */
   1258         rv = portmod_phy_pm_id_get(unit, phy_port,
   1259                     &portmod_pm_id);
   1260         if (BCM_FAILURE(rv)) {
   1261             goto cleanup;
   1262         }
   1263 
   1264         /* Check if the core is initialized. If it's NOT initialized,
   1265          * we will need to bring up the clocks so that DV Flexport code can
   1266          * access registers
   1267          */
   1268         rv = portmod_pm_is_initialized(unit, portmod_pm_id, &is_init);
   1269         if (BCM_FAILURE(rv)) {
   1270             goto cleanup;
   1271         }
   1272 
   1273         /* If the core is active, skip turning on the PM clocks; they're already on */
   1274         if (PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(is_init)) {
   1275             continue;
   1276         }
   1277 
   1278         /* Enable the PM */
   1279         rv = portmod_pm_enable(unit, portmod_pm_id, 1);
   1280         if (BCM_FAILURE(rv)) {
   1281             goto cleanup;
   1282         }
   1283 
   1284         /* Mark that we brought up the clock on this PM so we can bring it
   1285          * down after DV flexport
   1286          */
   1287         brought_up[pm_id] = 1;
   1288     }
   1289 
   1290 
   1291 
   1292     /******************************
   1293      ** Perform DV Flexport Code **
   1294  */
   1295     rv = soc_tomahawk3_reconfigure_ports(unit,
   1296                         port_schedule_state);
   1297 
   1298 
   1299 cleanup:
   1300     /* Disable all of the port macros that we enabled now that DV flex
   1301      * is done */
   1302     for (i = 0; i < SOC_TH3_PM8X50_COUNT; i++) {
   1303         if (brought_up[i] == 1) {
   1304             phy_port = (i * _TH3_PORTS_PER_PBLK) + 1;
   1305 
   1306             /* These shouldn't return error since they passed in the above code
   1307              * but catch the error anyway so it'll hopefully be easier to find
   1308              * if there is a problem calling these functions */
   1309             BCM_IF_ERROR_RETURN(portmod_phy_pm_id_get(unit, phy_port,
   1310                         &portmod_pm_id));
   1311             /* Disable the PM */
   1312             BCM_IF_ERROR_RETURN(portmod_pm_enable(unit, portmod_pm_id, 0));
   1313         }
   1314     }
   1315 
   1316     return rv;
   1317 }
   1318 
   1319 #endif /* BCM_TOMAHAWK3_SUPPORT */