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

portctrl.c (173783B)


      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:        portctrl.c
      8  * Purpose:     SDK Port Control Layer
      9  *
     10  *              The purpose is to encapsulate port functionality
     11  *              related to the xxPORT block (i.e. XLPORT, CPORT)
     12  *              MAC and PHY.
     13  *
     14  *              Currently, only the PortMod library is being supported.
     15  *              The PortMod library provides support for the MAC, PHY,
     16  *              and xxPORT registers.
     17  */
     18 
     19 #include <shared/bsl.h>
     20 #include <soc/error.h>
     21 #include <soc/esw/portctrl.h>
     22 #include <soc/esw/portctrl_internal.h>
     23 #include <soc/esw/port.h>
     24 #include <bcm_int/esw/port.h>
     25 
     26 #ifdef PORTMOD_SUPPORT
     27 #include <soc/phy/phymod_sim.h>
     28 #include <soc/portmod/portmod.h>
     29 #include <soc/portmod/portmod_common.h>
     30 #include <soc/phy/phymod_port_control.h>
     31 #include <soc/portmod/portmod_chain.h>
     32 #include <soc/portmod/portmod_legacy_phy.h>
     33 
     34 /* Indicates if the Port Control module has been initalized */
     35 static int portctrl_init[SOC_MAX_NUM_DEVICES];
     36 
     37 /*
     38  * Define:
     39  *      PORTCTRL_PORT_TO_PPORT 
     40  * Purpose:
     41  *      Converts a SOC port into port type used in PortMod functions '_pport'
     42  */
     43 #define PORTCTRL_PORT_TO_PPORT(_port, _pport) do {  \
     44         _pport = _port;                             \
     45     } while (0)
     46 
     47 static phymod_bus_t portmod_ext_default_bus = {
     48     "MDIO Bus",
     49     portmod_ext_phy_mdio_c45_reg_read,
     50     portmod_ext_phy_mdio_c45_reg_write,
     51     NULL,
     52     portmod_common_mutex_take,
     53     portmod_common_mutex_give,
     54     NULL,
     55     NULL,
     56     PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL
     57 };
     58 
     59 extern uint32_t phymod_dbg_mask;
     60 extern uint32_t phymod_dbg_addr;
     61 extern uint32_t phymod_dbg_lane;
     62 
     63 /* Used by timestamp adjust */
     64 typedef struct {
     65     int speed;
     66     char *props[2];
     67 } portctrl_ts_adjust_cfg_t;
     68 
     69 static portctrl_ts_adjust_cfg_t ts_adjust_props[] = {
     70 {10, {spn_TIMESTAMP_ADJUST_10MBE_NS, spn_TIMESTAMP_TSTS_ADJUST_10MBE_NS}},
     71 {100, {spn_TIMESTAMP_ADJUST_100MBE_NS, spn_TIMESTAMP_TSTS_ADJUST_100MBE_NS}},
     72 {1000, {spn_TIMESTAMP_ADJUST_1GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_1GBE_NS}},
     73 {2500, {spn_TIMESTAMP_ADJUST_2_5GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_2_5GBE_NS}},
     74 {10000, {spn_TIMESTAMP_ADJUST_10GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_10GBE_NS}},
     75 {25000, {spn_TIMESTAMP_ADJUST_25GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_25GBE_NS}},
     76 {40000, {spn_TIMESTAMP_ADJUST_40GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_40GBE_NS}},
     77 {50000, {spn_TIMESTAMP_ADJUST_50GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_50GBE_NS}},
     78 {100000, {spn_TIMESTAMP_ADJUST_100GBE_NS, spn_TIMESTAMP_TSTS_ADJUST_100GBE_NS}},
     79 {-1, {spn_TIMESTAMP_ADJUST_NS, spn_TIMESTAMP_TSTS_ADJUST_NS}}
     80 };
     81 
     82 /*
     83  * Function:
     84  *      soc_esw_portctrl_init_check
     85  * Purpose:
     86  *      check if portctrl is already initialized.
     87  * Parameters:
     88  *      unit     - (IN) Unit number.
     89  * Returns:
     90  *      SOC_E_NONE  : Initialized
     91  *      SOC_E_INIT  : Not Initialized.
     92  */
     93 int
     94 soc_esw_portctrl_init_check(int unit)
     95 {
     96     if (SOC_PORTCTRL_NOT_INITIALIZED == portctrl_init[unit]) {
     97         return SOC_E_INIT;
     98     }
     99     return SOC_E_NONE;
    100 }
    101 
    102 /*
    103  * Function:
    104  *      soc_esw_portctrl_pm_user_access_alloc
    105  * Purpose:
    106  *      Allocate SW data structure for the port macros (PM).
    107  * Parameters:
    108  *      unit        - (IN) Unit number.
    109  *      num         - (IN) Number of PM port macros in device.
    110  *      user_acc    - (OUT) Returns allocated PMs structures.
    111  * Returns:
    112  *      SOC_E_XXX
    113  */
    114 int
    115 soc_esw_portctrl_pm_user_access_alloc(int unit, int num,
    116                                       portmod_default_user_access_t **user_acc)
    117 {
    118     if (*user_acc == NULL) {
    119         *user_acc = sal_alloc(sizeof(portmod_default_user_access_t) * num,
    120                              "PortMod PM");
    121         if (*user_acc == NULL) {
    122             return SOC_E_MEMORY;
    123         }
    124     }
    125     sal_memset(*user_acc, 0, sizeof(portmod_default_user_access_t) * num);
    126 
    127     return SOC_E_NONE;
    128 }
    129 
    130 /*
    131  * Function:
    132  *      soc_esw_portctrl_dump_txrx_lane_map
    133  * Purpose:
    134  *      Utility function to dump tx, rx lane map
    135  * Parameters:
    136  *      unit        - (IN) Unit number.
    137  * Returns:
    138  *      SOC_E_XXX
    139  */
    140 void
    141 soc_esw_portctrl_dump_txrx_lane_map(int unit, int first_port, int logical_port,
    142               int core_num, uint32 txlane_map_b, uint32 rxlane_map_b,
    143               uint32 txlane_map, uint32 rxlane_map)
    144 {
    145     static int hdr_flag =0;
    146     if (!hdr_flag) {
    147         LOG_ERROR(BSL_LS_SOC_PORT,
    148             (BSL_META_UP(unit, logical_port,
    149             "+-------+-------+-------+-------+------+--------+--------+\n")));
    150         LOG_ERROR(BSL_LS_SOC_PORT,
    151             (BSL_META_UP(unit, logical_port,
    152             "| PPORT | LPORT | TXMAP | RXMAP | CORE | TXSWAP | RXSWAP |\n")));
    153         LOG_ERROR(BSL_LS_SOC_PORT,
    154             (BSL_META_UP(unit, logical_port,
    155             "+-------+-------+-------+-------+------+--------+--------+\n")));
    156         hdr_flag=1;
    157     }
    158     LOG_ERROR(BSL_LS_SOC_PORT,
    159         (BSL_META_UP(unit, logical_port,
    160          "| %04d  | %04d  | %04X  | %04X  | %02d   | %04X   | %04X   |\n"),
    161          first_port, logical_port, txlane_map_b, rxlane_map_b, core_num,
    162          txlane_map, rxlane_map));
    163 
    164     LOG_ERROR(BSL_LS_SOC_PORT,
    165         (BSL_META_UP(unit, logical_port,
    166         "+-------+-------+-------+-------+------+--------+--------+\n")));
    167     return;
    168 }
    169 
    170 /*
    171  * Function:
    172  *      soc_esw_portctrl_ext_phy_config_parameter_get
    173  * Purpose:
    174  *      To extract external phy parameter from config.bcm.
    175  * Parameters:
    176  *      unit             - (IN)  Unit number.
    177  *      port             - (IN)  Logical Port Number 
    178  *      phy_addr         - (OUT) Ext Phy MDIO address. 0xFF mean no ext phy    
    179  *      shift            - (IN)  Phy Port Map Shift from internal map. ( default 0) 
    180  * Returns:
    181  *      BCM_E_XXX
    182  */
    183 STATIC int
    184 soc_esw_portctrl_ext_phy_config_parameter_get (int unit, int port,
    185                    uint32 *phy_addr, uint32 *num_int_cores, uint32 shift[3])
    186 {
    187     char *config_str, *sub_str, *sub_str_end;
    188     int idx;
    189 
    190     /* set default return values. */
    191     *num_int_cores  = 1;
    192     shift[0]        = 0;
    193     shift[1]        = 0;
    194     shift[2]        = 0;
    195 
    196     config_str = soc_property_port_get_str(unit, port, spn_PORT_PHY_ADDR);
    197     if (config_str == NULL) {
    198         *phy_addr = 0xFF; /* NO PHY */
    199         return SOC_E_NONE;        
    200     }
    201 
    202     /*
    203     * port_phy_addr_<port>=<phy addr>:<num_int_cores>:<shift0>:<shift1>:<shift2>
    204     */
    205     sub_str = config_str;
    206 
    207     /* Parse phy address  number */
    208     *phy_addr  = sal_ctoi(sub_str, &sub_str_end);
    209     
    210     if (*sub_str_end == '\0')
    211     {
    212         return SOC_E_NONE ;
    213     }
    214  
    215     /* Skip ':' between physical port number and num_internal_cores */
    216     sub_str = sub_str_end;
    217     if (*sub_str != '\0') {
    218         if (*sub_str != ':') {
    219             LOG_CLI((BSL_META_U(unit, "Port %d: Bad config string \"%s\"\n"),
    220                          port, config_str));
    221                 return SOC_E_FAIL;
    222         }
    223         sub_str++;
    224     } else {
    225         return SOC_E_NONE;
    226     }
    227 
    228     /* parse num of cores. */
    229     *num_int_cores = sal_ctoi(sub_str, &sub_str_end);
    230     if (*num_int_cores > SOC_PM12X10_PM4X10_COUNT) {
    231         LOG_CLI((BSL_META_U(unit, 
    232                 "Port %d: Bad config string bad num of cores \"%s\" %d \n"),
    233                 port, config_str, *num_int_cores));
    234         return SOC_E_FAIL;
    235 
    236     }
    237 
    238     /* check for end of string. */
    239     if( *sub_str_end == '\0' )
    240     {
    241         return SOC_E_NONE ;
    242     }
    243 
    244     for (idx=0; idx < *num_int_cores; idx++) {
    245         /* Skip ':' between physical port number and num_internal_cores */
    246         sub_str = sub_str_end;
    247         if (*sub_str != '\0') {
    248             if (*sub_str != ':') {
    249                 LOG_CLI((BSL_META_U(unit, "Port %d: Bad config string \"%s\"\n"),
    250                          port, config_str));
    251                 return SOC_E_FAIL;
    252             }
    253             sub_str++;
    254         }
    255         shift[idx] = sal_ctoi(sub_str, &sub_str_end);
    256         /* check for end of string. */
    257         if( *sub_str_end == '\0' )
    258         {
    259             return SOC_E_NONE ;
    260         }
    261     } 
    262     return SOC_E_NONE;
    263 }
    264 
    265 typedef struct soc_esw_portctrl_phy_toplogy_s {
    266     uint16_t pport;        /* Physical port number */
    267     uint16_t xphy_index;   /* position of the external phy in the phy chain */
    268     uint16_t xphy_id;      /* Mdio address of the external phy */
    269     int16_t sys_lane;     /* system side lane number connected to the internal pport */
    270     int16_t line_lane;    /* corresponding line side lane number */
    271     uint16_t is_default;
    272 } soc_esw_portctrl_phy_toplogy_t;
    273 
    274 /*
    275  * Function:
    276  *      soc_esw_portctrl_ext_phy_config_topology_get
    277  * Purpose:
    278  *      To extract external phy topology from config.bcm.
    279  * Parameters:
    280  *      unit             - (IN)  Unit number.
    281  *      topology         - (OUT) topology information of the physical port  
    282  * Returns:
    283  *      BCM_E_XXX
    284  */
    285 STATIC int
    286 soc_esw_portctrl_ext_phy_config_topology_get (int unit, soc_esw_portctrl_phy_toplogy_t *topology) 
    287 {
    288 
    289     char *config_str, *sub_str, *sub_str_end;
    290     char pport[8];
    291     
    292     topology->is_default = 0;
    293     sal_itoa(pport, topology->pport, 10, 0, 0);
    294     
    295     config_str = soc_property_suffix_num_str_get(unit, topology->xphy_index, spn_PHY_TOPOLOGY, 
    296                                                  sal_strcat(pport, "_"));
    297     
    298      if (config_str == NULL) {
    299         /* No config found. There is a logical to logical port 
    300            mapping present in the system */
    301         topology->xphy_id = 0xFF;
    302         topology->sys_lane = -1;
    303         topology->line_lane = -1;
    304         topology->is_default = 1;
    305         return SOC_E_NONE;        
    306     }
    307 
    308     /*
    309     * phy_topology_<pport_xphy_index>=<xphy_id>:<sys_lane>:<line_lane>
    310     */
    311     sub_str = config_str;
    312 
    313     /* Parse phy address  number */
    314     topology->xphy_id  = sal_ctoi(sub_str, &sub_str_end);
    315        
    316     /* Skip ':' between phy address and sys lane */
    317     sub_str = sub_str_end;
    318     if (*sub_str != '\0') {
    319         if (*sub_str != ':') {
    320             LOG_CLI((BSL_META_U(unit, "Physical Port %d: Bad config string \"%s\"\n"),
    321                          topology->pport, config_str));       
    322             return SOC_E_FAIL ;
    323         }
    324         sub_str++;
    325     } else {
    326         LOG_CLI((BSL_META_U(unit, "Physical Port %d: Bad config string \"%s\"\n"),
    327                          topology->pport, config_str));       
    328         return SOC_E_FAIL ;
    329     }
    330 
    331     /* parse sys lane */
    332     topology->sys_lane = sal_ctoi(sub_str, &sub_str_end);
    333     sub_str = sub_str_end;
    334     
    335     if (*sub_str != '\0') {
    336         if (*sub_str != ':') {
    337             LOG_CLI((BSL_META_U(unit, "Physical Port %d: Bad config string \"%s\"\n"),
    338                          topology->pport, config_str));       
    339             return SOC_E_FAIL ;
    340         }
    341         sub_str++;
    342     } else {
    343         LOG_CLI((BSL_META_U(unit, "Physical Port %d: Bad config string \"%s\"\n"),
    344                          topology->pport, config_str));       
    345         return SOC_E_FAIL;
    346     }
    347 
    348     /* parse line lane */
    349     topology->line_lane = sal_ctoi(sub_str, &sub_str_end);
    350     sub_str = sub_str_end;
    351 
    352     /* look for end of config string */
    353     if (*sub_str != '\0') {
    354         LOG_CLI((BSL_META_U(unit, "Physical Port %d: Bad config string \"%s\"\n"),
    355                          topology->pport, config_str));       
    356         return SOC_E_FAIL;
    357     }
    358 
    359     return SOC_E_NONE;
    360 }
    361 
    362 int
    363 soc_esw_portctrl_xphy_default_core_access_get(int unit, phymod_core_access_t *core_access)
    364 {
    365     int rv = SOC_E_NONE;
    366     portmod_default_user_access_t*  local_user_access;
    367 
    368     PORTMOD_IF_ERROR_RETURN(phymod_core_access_t_init(core_access));
    369     core_access->access.bus = &portmod_ext_default_bus;
    370     core_access->type = phymodDispatchTypeInvalid; /* Make sure it is invalid. */
    371     local_user_access = sal_alloc(sizeof(portmod_default_user_access_t),
    372                               "xphy_user_acc");
    373     if(local_user_access == NULL){
    374         LOG_CLI((BSL_META_U(unit, "soc_esw_portctrl_xphy_default_core_access_get local_user_access is NULL.\n")));
    375         return SOC_E_FAIL;
    376     }
    377     sal_memset(local_user_access, 0, sizeof(portmod_default_user_access_t));
    378     local_user_access->unit = unit;
    379     core_access->access.user_acc = local_user_access;
    380     return rv;
    381 
    382 }
    383 
    384 static int
    385 soc_esw_portctrl_core_config_update(int unit, int lport, int pport, int lane, uint32_t xphy_addr,  int phy_idx) {
    386 
    387     int rv = SOC_E_NONE;
    388     int fw_ld_method = 0x1, i;
    389     uint32_t rx_polarity, tx_polarity;
    390     uint32_t rx_lane_map, tx_lane_map;
    391     uint32_t psc_repeater_mode = 0;
    392     uint32_t port_phy_clause = 45;
    393 
    394     uint8_t gearbox_enable;
    395     uint8_t pin_compatibility_enable;
    396     uint8_t phy_mode_reverse;
    397     int     force_fw_load, is_legacy_phy;
    398     phymod_firmware_load_method_t fw_load_method;
    399     phymod_core_access_t core_access;
    400     phymod_polarity_t  polarity;
    401     phymod_lane_map_t lane_map;
    402 
    403     rx_polarity = 0;
    404     tx_polarity = 0;
    405     rx_lane_map = 0;
    406     tx_lane_map = 0;
    407 
    408     /* soc read for phy device operation mode */
    409     gearbox_enable = (soc_property_port_get(unit, lport, spn_PHY_GEARBOX_ENABLE, FALSE));
    410     pin_compatibility_enable = soc_property_port_get(unit, lport,
    411                                    spn_PHY_PIN_COMPATIBILITY_ENABLE, FALSE);
    412     psc_repeater_mode = soc_property_port_get(unit, lport, spn_PHY_PCS_REPEATER, 0);
    413     phy_mode_reverse = soc_property_port_get(unit, lport, spn_PORT_PHY_MODE_REVERSE, 0);
    414     port_phy_clause = soc_property_port_get(unit, lport, spn_PORT_PHY_CLAUSE, 45);
    415 
    416     PORTMOD_IF_ERROR_RETURN(portmod_xphy_core_access_get(unit, xphy_addr, &core_access, &is_legacy_phy));
    417     core_access.device_op_mode = 0;
    418     
    419     if(gearbox_enable) {
    420         PHYMOD_INTF_CONFIG_PHY_GEARBOX_ENABLE_SET(&core_access);
    421     }
    422 
    423     if (pin_compatibility_enable) {
    424         PHYMOD_INTF_CONFIG_PHY_PIN_COMPATIBILITY_ENABLE_SET(&core_access);
    425     }
    426 
    427     if (phy_mode_reverse) {
    428         PHYMOD_INTF_CONFIG_PORT_PHY_MODE_REVERSE_SET(&core_access);
    429     }
    430 
    431     if (psc_repeater_mode) {
    432         PHYMOD_INTF_CONFIG_PHY_PSC_REPEATER_MODE_SET(&core_access);
    433     }
    434 
    435     if (45 == port_phy_clause) {
    436         PHYMOD_ACC_F_CLAUSE45_SET(&core_access.access);
    437     }
    438 
    439     /* since core_access got change, save it. device_op_mode is also save to
    440        wb buffer inside portmod_xphy_core_access_set. */
    441 
    442     PORTMOD_IF_ERROR_RETURN(portmod_xphy_core_access_set(unit, xphy_addr, &core_access, is_legacy_phy));
    443 
    444     /*lower nibble to represent Force FW load and upper nibble to represent
    445       load method */
    446     fw_ld_method = 0x11;
    447     fw_ld_method = soc_property_port_get(unit, lport,
    448                                          spn_PHY_FORCE_FIRMWARE_LOAD, fw_ld_method);
    449     switch ((fw_ld_method >> 4) & 0xf) {
    450         case 0:
    451             fw_load_method  = phymodFirmwareLoadMethodNone;
    452         break;
    453         case 1:
    454             fw_load_method  = phymodFirmwareLoadMethodInternal;
    455         break;
    456         case 2:
    457             fw_load_method  = phymodFirmwareLoadMethodProgEEPROM;
    458         break;
    459         default:
    460             fw_load_method  = phymodFirmwareLoadMethodInternal;
    461         break;
    462     }
    463 
    464     PORTMOD_IF_ERROR_RETURN(portmod_xphy_fw_load_method_set(unit, xphy_addr, fw_load_method));
    465     switch (fw_ld_method & 0xf) {
    466         case 0:
    467             /* skip download */
    468             force_fw_load = phymodFirmwareLoadSkip;
    469         break;
    470         case 1:
    471             /* force download */
    472             force_fw_load = phymodFirmwareLoadForce;
    473         break;
    474         case 2:
    475             /* auto download. download firware if two versions are diffirent */
    476             force_fw_load = phymodFirmwareLoadAuto;
    477         break;
    478         default:
    479             force_fw_load = phymodFirmwareLoadSkip;
    480         break;
    481     }
    482     PORTMOD_IF_ERROR_RETURN(portmod_xphy_force_fw_load_set(unit, xphy_addr, force_fw_load));
    483 
    484     PORTMOD_IF_ERROR_RETURN(portmod_xphy_polarity_get(unit, xphy_addr, &polarity));
    485     /* get the plarity settings for the core. look for the legacy config (logical port based) if
    486      * not available then look for a new config mode */
    487      rx_polarity = soc_property_phy_get (unit, pport, phy_idx, 0, 0, 
    488                                         spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF);
    489     if (rx_polarity == 0xFFFFFFFF) { 
    490         rx_polarity = soc_property_port_get(unit, lport, 
    491                             spn_PHY_RX_POLARITY_FLIP, 0);
    492     } else {
    493         rx_polarity = (rx_polarity & 0x1) << lane; ;
    494     }
    495 
    496     tx_polarity = soc_property_phy_get (unit, pport, phy_idx, 0, 0, 
    497                                         spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF);
    498     if (tx_polarity == 0xFFFFFFFF) {
    499         tx_polarity =  soc_property_port_get(unit, lport, 
    500                           spn_PHY_TX_POLARITY_FLIP, 0);
    501     } else {
    502         tx_polarity = (tx_polarity & 0x1) << lane; ;
    503     }
    504 
    505     polarity.rx_polarity |= rx_polarity;
    506     polarity.tx_polarity |= tx_polarity;
    507     PORTMOD_IF_ERROR_RETURN(portmod_xphy_polarity_set(unit, xphy_addr, polarity));
    508 
    509     /* get the lane map information */
    510     rx_lane_map = soc_property_phy_get (unit, pport, phy_idx, 0, 0, 
    511                                         spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0xFFFFFFFF);
    512     if (rx_lane_map == 0xFFFFFFFF) {
    513         rx_lane_map = soc_property_phy_get(unit, pport, phy_idx, 0, 0,
    514                                         spn_PHY_RX_LANE_MAP, 0xFFFFFFFF);
    515     }
    516     if (rx_lane_map == 0xFFFFFFFF) {
    517         rx_lane_map = soc_property_port_get(unit, lport, 
    518                                             spn_PHY_RX_LANE_MAP, 0x3210);
    519     }
    520 
    521     /* get the lane map information */
    522     tx_lane_map = soc_property_phy_get (unit, pport, phy_idx, 0, 0, 
    523                                         spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0xFFFFFFFF);
    524     if (tx_lane_map == 0xFFFFFFFF) {
    525         tx_lane_map = soc_property_phy_get(unit, pport, phy_idx, 0, 0,
    526                                         spn_PHY_TX_LANE_MAP, 0xFFFFFFFF);
    527     }
    528     if (tx_lane_map == 0xFFFFFFFF) {
    529         tx_lane_map = soc_property_port_get(unit, lport, 
    530                                             spn_PHY_TX_LANE_MAP, 0x3210);
    531     }  
    532  
    533     /*FIX harcoding the number of lanes to 4 for now 
    534      * need to figure out the better way to fix this */
    535     lane_map.num_of_lanes = 4;
    536     for (i = 0; i < 4; i++) { 
    537         lane_map.lane_map_rx[i] = ((rx_lane_map >> (i*4)) & 0xf);
    538         lane_map.lane_map_tx[i] = ((tx_lane_map >> (i*4)) & 0xf);
    539     }
    540 
    541     PORTMOD_IF_ERROR_RETURN(portmod_xphy_lane_map_set(unit, xphy_addr, lane_map));
    542 
    543     return rv;
    544 }
    545 
    546 /*
    547  * Function:
    548  *      soc_esw_portctrl_xphy_wb_db_restore(nt unit, soc_pbmp_t phy_ports)
    549  * Purpose:
    550  *      To restore all external phy data bases on warmboot.
    551  * Parameters:
    552  *      unit             - (IN)  Unit number.
    553  *      phy_ports       - (IN)  lane bit map of the phy.
    554  * Returns:
    555  *      BCM_E_XXX
    556  */
    557 int
    558 soc_esw_portctrl_xphy_wb_db_restore(int unit)
    559 {
    560 
    561     xphy_pbmp_t valid_phys;
    562     phymod_core_access_t core_access;
    563     int xphy_idx;
    564     int xphy_addr;
    565 
    566     PORTMOD_IF_ERROR_RETURN(portmod_xphy_all_valid_phys_get(unit, &valid_phys));
    567 
    568     /* iterate all the external phy that need to be restored. */
    569     XPHY_PBMP_ITER(valid_phys, xphy_idx){
    570 
    571         PORTMOD_IF_ERROR_RETURN(portmod_xphy_db_addr_get(unit, xphy_idx, &xphy_addr));
    572         PORTMOD_IF_ERROR_RETURN(soc_esw_portctrl_xphy_default_core_access_get(unit, &core_access));
    573         PORTMOD_IF_ERROR_RETURN(portmod_xphy_wb_db_restore(unit,xphy_idx, xphy_addr,&core_access));
    574     }
    575     return SOC_E_NONE;
    576 }
    577 
    578 
    579 /*
    580  * Function:
    581  *      soc_esw_portctrl_setup_ext_phy_add(int unit, int port, portmod_pbmp_t phy_ports)
    582  * Purpose:
    583  *      Add External PHY info.
    584  * Parameters:
    585  *      unit             - (IN)  Unit number.
    586  *      phy_ports       - (IN)  lane bit map of the phy.
    587  * Returns:
    588  *      BCM_E_XXX
    589  */
    590 int
    591 soc_esw_portctrl_setup_ext_phy_add(int unit, int port, portmod_pbmp_t *phy_ports)
    592 {
    593     int     rv, chain_idx, first_port;
    594     int     pport;
    595     uint8_t is_100G_port;
    596     uint32  ext_phy_addr, xphy_gearbox_mode;
    597     uint32  num_int_cores;
    598     uint32  first_phy_lane[3];
    599     int     phy_chain_length;
    600     uint32 primary_core_num=0;
    601     portmod_dispatch_type_t         type;
    602     soc_esw_portctrl_phy_toplogy_t  topology;
    603     soc_100g_lane_config_t          lane_config;
    604 
    605     phymod_core_access_t            core_access;
    606     phymod_ref_clk_t                ref_clk;
    607     phymod_firmware_load_method_t   fw_load_method;
    608     portmod_xphy_lane_connection_t  xphy_lane_connection;
    609     int xphy_idx = PORTMOD_XPHY_EXISTING_IDX;
    610 
    611     /* add Ext Phy to portmod. */
    612 
    613     /* identify if the pport is part of 100G port and 12x10 PM
    614        if true then get the mapping inf0 3:4:3 or 4:4:2 */
    615     lane_config = SOC_LANE_CONFIG_100G_4_4_2;
    616     pport = 0;
    617     is_100G_port = 0;
    618 
    619     /* assumption is that first pport of the PM12x10 is
    620     specified as a 100G port in portmap_lport=pport:100:map_info */
    621     PORTMOD_PBMP_ITER(*phy_ports, pport) {
    622    
    623         rv = portmod_phy_pm_type_get(unit, pport, &type);
    624         if (rv) return (rv);
    625 
    626         /* 
    627          * Check to see if the port we are using is 100G or greater 
    628          * and is pm12x10 type
    629          */  
    630 #if defined(PORTMOD_PM12X10_XGS_SUPPORT) && defined(PORTMOD_PM12X10_SUPPORT)
    631         if ( (type != portmodDispatchTypePm12x10) && (type != portmodDispatchTypePm12x10_xgs) ) {
    632             continue; 
    633         }
    634 #elif defined(PORTMOD_PM12X10_SUPPORT)
    635         if ( (type != portmodDispatchTypePm12x10) ) { 
    636             continue; 
    637         }
    638 #else 
    639         if ( (type != portmodDispatchTypeCount) ) { 
    640             continue; 
    641         }
    642 #endif
    643 
    644 
    645         if ((port != -1) && (SOC_INFO(unit).port_speed_max[port] >= 100000)) {
    646             /* read the portmap config to get the map info */
    647             lane_config = SOC_INFO(unit).port_100g_lane_config[port];
    648             is_100G_port = 1;
    649         }
    650     }
    651 
    652 
    653     pport = 0;
    654 
    655     /* for each port in the input bit map read get the physical port number and call 
    656      the new config get function to identify the physical topology with the external phy */
    657     first_port = -1;
    658 
    659     PORTMOD_PBMP_ITER(*phy_ports, pport) {
    660 
    661         if (first_port == -1) first_port = pport;
    662 
    663         /* breadth of the phy chain  Assumption here is that all the physical ports in a
    664            logical port will have same phy chain length */
    665         ext_phy_addr = 0xFF;
    666         chain_idx = 0;
    667 
    668         rv = soc_esw_portctrl_ext_phy_config_parameter_get(unit, port,
    669                     &ext_phy_addr, &num_int_cores,  first_phy_lane);
    670         phy_chain_length = soc_property_port_get(unit, port, spn_PHY_CHAIN_LENGTH, 0);
    671         primary_core_num = soc_property_port_get(unit, ext_phy_addr, spn_XPHY_PRIMARY_CORE_NUM, ext_phy_addr);
    672         xphy_gearbox_mode = soc_property_port_get(unit, port, spn_PHY_GEARBOX_ENABLE, 0);
    673 
    674         while((ext_phy_addr != 0xFF) || (phy_chain_length != 0)) {
    675             phy_chain_length = 0;
    676             num_int_cores = 0;
    677 
    678             chain_idx++;
    679 
    680             portmod_xphy_lane_connection_t_init(unit, &xphy_lane_connection);
    681 
    682             
    683             phy_chain_length = soc_property_port_get(unit, port, spn_PHY_CHAIN_LENGTH, 0);
    684 
    685             /* phy chain length and ext_phy_addr configs for a port are mutually exclusive */
    686             if (phy_chain_length && (chain_idx > phy_chain_length)) break;
    687 
    688            /* rv = soc_esw_portctrl_ext_phy_config_parameter_get(unit, xphy_logical_port,
    689                     &ext_phy_addr, &num_int_cores,  first_phy_lane);
    690            */
    691             topology.pport = pport;
    692             topology.xphy_index = chain_idx;
    693             topology.sys_lane = -1;
    694             topology.line_lane = -1;
    695             soc_esw_portctrl_ext_phy_config_topology_get(unit, &topology);
    696 
    697             /* only for the iner most external phys we have an alternate config */
    698             xphy_lane_connection.ss_lane_mask = -1;
    699             xphy_lane_connection.ls_lane_mask = -1;
    700             if (topology.is_default && (chain_idx == 1)) {
    701                 topology.xphy_id = ext_phy_addr;
    702                 xphy_lane_connection.xphy_id = ext_phy_addr;
    703                 /* below logic should be applied only to inner most external phy*/
    704                 if (is_100G_port) {
    705                     xphy_lane_connection.ss_lane_mask = 0x1 << (pport - first_port);
    706                     xphy_lane_connection.ls_lane_mask = 0x1 << (pport - first_port);
    707                     switch (lane_config) {
    708                         case SOC_LANE_CONFIG_100G_4_4_2:
    709                             if ((pport - first_port) == 10 || 
    710                                 (pport - first_port) == 11) {
    711                                 xphy_lane_connection.ss_lane_mask = -1;
    712                                 xphy_lane_connection.ls_lane_mask = -1;
    713                             }
    714                             /* Temp fix for sesto gearbox */
    715                             if ((((pport - first_port) > 3) &&
    716                                ((pport - first_port) < 8))) {
    717                                 xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - first_port)-4);
    718                             } else {
    719                                 xphy_lane_connection.ls_lane_mask = -1;
    720                             }
    721 
    722                         break;
    723                         case SOC_LANE_CONFIG_100G_3_4_3:
    724                             if ((pport - first_port) == 3 || 
    725                                     (pport - first_port) == 11) {
    726                                     xphy_lane_connection.ss_lane_mask = -1;
    727                                     xphy_lane_connection.ls_lane_mask = -1;
    728                             }
    729                             if (((pport - first_port) > 3) &&  
    730                                 ((pport - first_port) < 11)) {
    731                                 xphy_lane_connection.ss_lane_mask = 0x1 << ((pport - first_port) - 1);
    732                                 xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - first_port) - 1);
    733                             }
    734                             /* Temp fix for sesto gearbox */
    735                             if ((((pport - first_port) > 3) &&
    736                                ((pport - first_port) < 8))) {
    737                                 xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - first_port)-4);
    738                             } else {
    739                                 xphy_lane_connection.ls_lane_mask = -1;
    740                             }
    741                             
    742 
    743                         break;
    744                         case SOC_LANE_CONFIG_100G_2_4_4:
    745                             if ((pport - first_port) == 2 || 
    746                                     (pport - first_port) == 3) {
    747                                     xphy_lane_connection.ss_lane_mask = -1;
    748                                     xphy_lane_connection.ls_lane_mask = -1;
    749                             }
    750                             if ((pport - first_port) > 3) {
    751                                 xphy_lane_connection.ss_lane_mask = 0x1 << ((pport - first_port) - 2);
    752                                 xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - first_port) - 2);
    753                             }
    754                             /* Temp fix for sesto gearbox */
    755                             if ((pport - first_port) > 5) {
    756                                 xphy_lane_connection.ls_lane_mask = -1;
    757                             }
    758                             if ((((pport - first_port) > 3) &&
    759                                ((pport - first_port) < 8))) {
    760                                 xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - first_port)-4);
    761                             } else {
    762                                 xphy_lane_connection.ls_lane_mask = -1;
    763                             }
    764 
    765                         break;
    766                         default:
    767                             xphy_lane_connection.ss_lane_mask = 0x1 << (pport - first_port);
    768                             xphy_lane_connection.ls_lane_mask = 0x1 << (pport - first_port);
    769                         break;
    770                     }
    771                     /* if the system is on a Gearbox mode then line side port 
    772                      beyond 3 should be set to -1 on an external phy */
    773                 } else {
    774                     /* for non 100G port like 10G and 40G */
    775                     /*This only support 2x25G to 4x10G gearbox.*/
    776                     if(pport > 0){
    777                        if (xphy_gearbox_mode) {
    778                            xphy_lane_connection.ss_lane_mask = 0x1 << ((pport - 1) % 4);
    779                            xphy_lane_connection.ls_lane_mask = 0x3 << (((pport - 1) % 4) * 2);
    780                        } else {
    781                            xphy_lane_connection.ss_lane_mask = 0x1 << ((pport - 1) % 4);
    782                            xphy_lane_connection.ls_lane_mask = 0x1 << ((pport - 1) % 4);
    783                        }
    784                     }
    785                 }
    786 
    787             } else {
    788                 ext_phy_addr = topology.xphy_id;
    789                 xphy_lane_connection.xphy_id = topology.xphy_id;
    790                 if (topology.sys_lane != -1) {
    791                     xphy_lane_connection.ss_lane_mask = 0x1 << topology.sys_lane;
    792                 } else {
    793                     xphy_lane_connection.ss_lane_mask = -1;
    794                 }
    795                 if (topology.line_lane != -1) { 
    796                     xphy_lane_connection.ls_lane_mask = 0x1 << topology.line_lane;
    797                 } else {
    798                     xphy_lane_connection.ls_lane_mask = -1;    
    799                 }
    800             }
    801 
    802             if((PORTMOD_SUCCESS(rv)) && ((ext_phy_addr != 0xFF) || (phy_chain_length >= chain_idx))) {
    803             
    804                 /* get default xphy  core_access and updated with xphy_addr. */
    805                 soc_esw_portctrl_xphy_default_core_access_get(unit, &core_access);
    806                 core_access.access.addr = ext_phy_addr;
    807 
    808                 PORTMOD_IF_ERROR_RETURN(portmod_xphy_add(unit, ext_phy_addr, &core_access, &xphy_idx));
    809 
    810                 /* if entry is not added, release user_acc from core_access. */
    811                 if (xphy_idx == PORTMOD_XPHY_EXISTING_IDX){
    812                     if (core_access.access.user_acc != NULL){
    813                         sal_free(core_access.access.user_acc);
    814                     }
    815                 } else {
    816                     /* record the user_acc  */
    817                     portmod_chain_xphy_user_access_store(unit, xphy_idx, core_access.access.user_acc);
    818                 }
    819                 /* call external phy lane attach */
    820                 portmod_xphy_lane_attach(unit, pport, topology.xphy_index, &xphy_lane_connection);
    821     
    822                 /* update the value from config */
    823                 ref_clk = phymodRefClk156Mhz;
    824                 fw_load_method = phymodFirmwareLoadMethodExternal;
    825                 /*  xphy_core_info. polarity*/
    826                 PORTMOD_IF_ERROR_RETURN(portmod_xphy_primary_core_num_set(unit, ext_phy_addr, primary_core_num));
    827                 PORTMOD_IF_ERROR_RETURN(portmod_xphy_ref_clk_set(unit, ext_phy_addr, ref_clk));
    828                 PORTMOD_IF_ERROR_RETURN(portmod_xphy_fw_load_method_set(unit, ext_phy_addr, fw_load_method));
    829                 soc_esw_portctrl_core_config_update(unit, port, pport, (pport - first_port),  ext_phy_addr, chain_idx);
    830             }
    831 
    832             /*
    833              * For  only 1 ext phy allowd, if additional phy needed, need to parse the config
    834              * to get external phy addr. 
    835              */    
    836             ext_phy_addr = 0xFF; /* NO Additional PHY */
    837         } /* while each phy at index */
    838     } /* SOC_PBMP_ITER */
    839     return SOC_E_NONE;
    840 }
    841 
    842 
    843 
    844 /*
    845  * Function:
    846  *      soc_esw_portctrl_reset_tsc0_cb
    847  * Purpose:
    848  *      Reset TSC by setting TSC control register.
    849  *      Index 0 means TSC core index0, first TSC ctrl register index,
    850  *      which resides in PGW block.
    851  *      For TD2+ case, the register is PGW_TSC0_CTRL_REG
    852  * Parameters:
    853  *      unit             - (IN)  Unit number.
    854  *      port             - (IN)  Port number.
    855  *      in_reset         - (IN)  reset status
    856  * Returns:
    857  *      BCM_E_XXX
    858  */
    859 int
    860 soc_esw_portctrl_reset_tsc0_cb(int unit, int port, uint32 in_reset)
    861 {
    862 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_SABER2_SUPPORT)
    863     return (!in_reset? soc_tsc_xgxs_reset(unit, port, 0) : SOC_E_NONE);
    864 #else
    865     return SOC_E_NONE;
    866 #endif
    867 }
    868 
    869 /*
    870  * Function:
    871  *      soc_esw_portctrl_reset_tsc1_cb
    872  * Purpose:
    873  *      Reset TSC by setting TSC control register.
    874  *      Index 1 means TSC core index1, 2nd TSC ctrl register index,
    875  *      which resides in PGW block.
    876  *      For TD2+ case, the register is PGW_TSC1_CTRL_REG
    877  * Parameters:
    878  *      unit             - (IN)  Unit number.
    879  *      port             - (IN)  Port number.
    880  *      in_reset         - (IN)  reset status
    881  * Returns:
    882  *      BCM_E_XXX
    883  */
    884 int
    885 soc_esw_portctrl_reset_tsc1_cb(int unit, int port, uint32 in_reset)
    886 {
    887 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_SABER2_SUPPORT)
    888     return (!in_reset? soc_tsc_xgxs_reset(unit, port, 1) : SOC_E_NONE);
    889 #else
    890     return SOC_E_NONE;
    891 #endif
    892 }
    893  
    894 /*
    895  * Function:
    896  *      soc_esw_portctrl_reset_tsc2_cb
    897  * Purpose:
    898  *      Reset TSC by setting TSC control register.
    899  *      Index 2 means TSC core index2, 3rd TSC ctrl register index,
    900  *      which resides in PGW block.
    901  *      For TD2+ case, the register is PGW_TSC2_CTRL_REG
    902  * Parameters:
    903  *      unit             - (IN)  Unit number.
    904  *      port             - (IN)  Port number.
    905  *      in_reset         - (IN)  reset status
    906  * Returns:
    907  *      BCM_E_XXX
    908  */
    909 int
    910 soc_esw_portctrl_reset_tsc2_cb(int unit, int port, uint32 in_reset)
    911 {
    912 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_SABER2_SUPPORT)
    913     return (!in_reset? soc_tsc_xgxs_reset(unit, port, 2) : SOC_E_NONE);
    914 #else
    915     return SOC_E_NONE;
    916 #endif
    917 }
    918  
    919 /*
    920  * Function:
    921  *      soc_esw_portctrl_reset_tsc3_cb
    922  * Purpose:
    923  *      Reset TSC by setting TSC control register.
    924  *      Index 3 means TSC core index3, 4th TSC ctrl register index,
    925  *      which resides in PGW block.
    926  *      For TD2+ case, the register is PGW_TSC3_CTRL_REG
    927  * Parameters:
    928  *      unit             - (IN)  Unit number.
    929  *      port             - (IN)  Port number.
    930  *      in_reset         - (IN)  reset status
    931  * Returns:
    932  *      BCM_E_XXX
    933  */
    934 int
    935 soc_esw_portctrl_reset_tsc3_cb(int unit, int port, uint32 in_reset)
    936 {
    937 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_SABER2_SUPPORT)
    938     return (!in_reset? soc_tsc_xgxs_reset(unit, port, 3) : SOC_E_NONE);
    939 #else
    940     return SOC_E_NONE;
    941 #endif
    942 }
    943 
    944 #ifdef BCM_MONTEREY_SUPPORT
    945 static int
    946 _check_cpri_speed (
    947     int speedi, portmod_encap_t int_mode)
    948 {
    949     int speedo;
    950     if(int_mode == _SHR_PORT_ENCAP_RSVD4) {
    951         switch(speedi) {
    952         case 3072:
    953             speedo = cprimodRsvd4SpdMult4X;
    954             break;
    955         case 6144:
    956             speedo = cprimodRsvd4SpdMult8X;
    957             break;
    958         default:
    959             speedo = -1;
    960             break;
    961         }
    962     } else if(int_mode == _SHR_PORT_ENCAP_CPRI) {
    963         switch(speedi) {
    964         case 1228:
    965             speedo = cprimodSupportedSpd1228p8;
    966             break;
    967         case 2457:
    968             speedo = cprimodSupportedSpd2457p6;
    969             break;
    970         case 3072:
    971             speedo = cprimodSupportedSpd3072p0;
    972             break;
    973         case 4915:
    974             speedo = cprimodSupportedSpd4915p2;
    975             break;
    976         case 6144:
    977             speedo = cprimodSupportedSpd6144p0;
    978             break;
    979         case 9830:
    980             speedo = cprimodSupportedSpd9830p4;
    981             break;
    982         case 10137:
    983             speedo = cprimodSupportedSpd10137p6;
    984             break;
    985         case 12165:
    986             speedo = cprimodSupportedSpd12165p12;
    987             break;
    988         case 24330:
    989             speedo = cprimodSupportedSpd24330p24;
    990             break;
    991         default:
    992             speedo = -1;
    993             break;
    994         }
    995     } else {
    996         speedo = -1;
    997     }
    998     return speedo;
    999 }
   1000 #endif
   1001 
   1002 
   1003 
   1004 /*
   1005  * Function:
   1006  *      soc_esw_portctrl_config_get
   1007  * Purpose:
   1008  *      Get interface and initialization configuration
   1009  *      for given logical port.
   1010  * Parameters:
   1011  *      unit              - (IN) Unit number.
   1012  *      port              - (IN) Logical port number.
   1013  *      interface_config  - (IN/OUT) Port interface configuration.
   1014  *      init_config       - (IN/OUT) Port initialization configuration.
   1015  * Returns:
   1016  *      SOC_E_XXX
   1017  */
   1018 int
   1019 soc_esw_portctrl_config_get(int unit, soc_port_t port, 
   1020                             portmod_port_interface_config_t* interface_config,
   1021                             portmod_port_init_config_t* init_config,
   1022                             phymod_operation_mode_t *phy_op_mode)
   1023 {
   1024     /* soc_port_if_t interface_type; */
   1025     int port_num_lanes, fiber_pref = 0, is_scrambler = 0, i;
   1026     int fs_cl72=0, max_speed, speed;
   1027     /* phymod_tx_t *p_tx; */
   1028     uint32  preemphasis=0xffffffff, driver_current=0xffffffff;
   1029     uint32  port_preemphasis, port_driver_current;
   1030     uint32  lane_preemphasis, lane_driver_current;
   1031     /*int rxaui_mode = 0; */
   1032     int ref_clk_prop = 0, encap_mode;
   1033     int adjust_num = 0;
   1034 #ifdef BCM_MONTEREY_SUPPORT
   1035     int port_speed_cpri = 0;
   1036     int roe_speed_rsvd4, roe_speed_cpri;
   1037 #endif
   1038 
   1039     /* Initialize both interface config and init config */
   1040     PORTMOD_IF_ERROR_RETURN
   1041         (portmod_port_init_config_t_init(unit, init_config));
   1042     PORTMOD_IF_ERROR_RETURN
   1043         (portmod_port_interface_config_t_init(unit, interface_config));
   1044 
   1045     port_num_lanes = SOC_INFO(unit).port_num_lanes[port];
   1046     interface_config->port_num_lanes = port_num_lanes;
   1047 
   1048     *phy_op_mode = soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 
   1049                                          phymodOperationModeRetimer);
   1050 
   1051     init_config->is_hg = (PBMP_MEMBER(SOC_HG2_PBM(unit), port) ||
   1052                           PBMP_MEMBER(PBMP_HG_ALL(unit), port));
   1053     if (init_config->is_hg) {
   1054         PHYMOD_INTF_MODES_HIGIG_SET(interface_config);
   1055     }
   1056 
   1057     fiber_pref = soc_property_port_get(unit, port,
   1058                                        spn_SERDES_FIBER_PREF, fiber_pref);
   1059     if (fiber_pref) {
   1060         PHYMOD_INTF_MODES_FIBER_SET(interface_config);
   1061     }  
   1062 
   1063  
   1064 
   1065     if (IS_C_PORT(unit, port) ||
   1066         (IS_CXX_PORT(unit, port) && IS_CL_PORT(unit, port))) {
   1067         PHYMOD_INTF_MODES_TRIPLE_CORE_SET(interface_config);
   1068 
   1069         switch(SOC_INFO(unit).port_100g_lane_config[port]) {
   1070             case SOC_LANE_CONFIG_100G_4_4_2:
   1071                 PHYMOD_INTF_MODES_TC_442_SET(interface_config);
   1072                 break ;
   1073             case SOC_LANE_CONFIG_100G_2_4_4:
   1074                 PHYMOD_INTF_MODES_TC_244_SET(interface_config);
   1075                 break ;
   1076             case SOC_LANE_CONFIG_100G_3_4_3:
   1077                 PHYMOD_INTF_MODES_TC_343_SET(interface_config);
   1078                 break ;
   1079             default:
   1080                 PHYMOD_INTF_MODES_TC_343_SET(interface_config);
   1081                 break ;
   1082         }
   1083         init_config->port_fallback_lane =
   1084             SOC_INFO(unit).port_fallback_lane[port];
   1085     }
   1086 
   1087 
   1088     /* Should be changed based on the speed later in the flow  */
   1089     if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port))
   1090         interface_config->interface =  SOC_PORT_IF_NULL;
   1091     else 
   1092         interface_config->interface = soc_property_port_get(unit, port,
   1093                                                         spn_SERDES_IF_TYPE,
   1094                                                         SOC_PORT_IF_XFI);
   1095     max_speed = SOC_INFO(unit).port_speed_max[port];
   1096     interface_config->max_speed = max_speed ;
   1097 
   1098     /* Fill in init config */
   1099     init_config->an_cl37 = soc_property_port_get(unit, port,
   1100                                     spn_PHY_AN_C37, 0);
   1101 
   1102     /* default AN mode would be cl73 with no BAM */
   1103     init_config->an_cl73 = soc_property_port_get(unit, port,
   1104                                     spn_PHY_AN_C73, PORTMOD_CL73_WO_BAM);
   1105     init_config->cl37_sgmii_RESTART_CNT = soc_property_port_get(unit, port,
   1106                                             spn_SERDES_CL37_SGMII_RESTART_COUNT,
   1107                                             init_config->cl37_sgmii_RESTART_CNT);
   1108 
   1109     init_config->an_master_lane = soc_property_port_get(unit, port,
   1110                                                         spn_PHY_AUTONEG_MASTER_LANE,
   1111                                                         0);
   1112 
   1113     /* an_cl72 means whether to turn on CL72 when AN is on. Default value
   1114      * should be 1 according to the IEEE spec.
   1115      */
   1116     init_config->an_cl72 = soc_property_port_get(unit, port,
   1117                                                  spn_PHY_AN_C72, 1);
   1118 
   1119    /* Get the timestamp adjust */
   1120     adjust_num = COUNTOF(ts_adjust_props);
   1121     for (i = 0; i < adjust_num; i++) {
   1122          init_config->port_ts_adjust[i].speed = ts_adjust_props[i].speed;
   1123          init_config->port_ts_adjust[i].osts_adjust = soc_property_port_get(unit, port, ts_adjust_props[i].props[0], 0);
   1124          init_config->port_ts_adjust[i].tsts_adjust = soc_property_port_get(unit, port, ts_adjust_props[i].props[1], 0);
   1125     }
   1126 
   1127     init_config->txpi_mode = soc_property_port_get(unit, port, spn_SERDES_TXPI_MODE, 0);
   1128     init_config->txpi_sdm_scheme = soc_property_port_get(unit, port, spn_TXPI_SDM_SCHEME, 0);
   1129 
   1130 #if 0
   1131     if (SOC_IS_TOMAHAWKX(unit)) {
   1132         if(an_cl73) {
   1133             init_config->an_mode =
   1134                ((an_cl73 == 1) ? phymod_AN_MODE_CL73 : phymod_AN_MODE_CL73BAM);
   1135             init_config->an_cl72 = 1;
   1136         } else if (an_cl37) {
   1137             init_config->an_mode =
   1138                ((an_cl37 == 1) ? phymod_AN_MODE_CL37BAM : phymod_AN_MODE_CL37);
   1139             init_config->an_cl72 = 0;
   1140         } else {
   1141             /* in TH/TH2, only management ports are pm4x10, others are pm4x25 */
   1142             if (IS_MANAGEMENT_PORT(unit, port)) {
   1143                 init_config->an_mode = phymod_AN_MODE_CL37;
   1144                 init_config->an_cl72 = 0;
   1145             } else {
   1146                 init_config->an_mode =
   1147                     ((is_hg) ? phymod_AN_MODE_CL73BAM : phymod_AN_MODE_CL73);
   1148                 init_config->an_cl72 = 1;
   1149             }
   1150         }
   1151     }
   1152 #endif
   1153 
   1154     init_config->an_fec = soc_property_port_get(unit, port,
   1155                                                 spn_PHY_AN_FEC,
   1156                                                 init_config->an_fec);
   1157 
   1158     init_config->serdes_fec_enable = soc_property_port_get(unit, port,
   1159                                              spn_SERDES_FEC_ENABLE,
   1160                                              init_config->serdes_fec_enable);
   1161 
   1162     fs_cl72  = soc_property_port_get(unit, port, spn_PORT_INIT_CL72,
   1163                                                 fs_cl72);
   1164     if(fs_cl72) {
   1165         init_config->fs_cl72 = PHYMOD_INTF_F_CL72_REQUESTED_BY_CNFG ;
   1166     }
   1167 
   1168     speed = SOC_INFO(unit).port_init_speed[port] > 0 ?
   1169             SOC_INFO(unit).port_init_speed[port] :
   1170             SOC_INFO(unit).port_speed_max[port];
   1171 
   1172     /* TSCE:for the  Dual lane 10G mode scrambler should be enabled 
   1173      * to get the link up. To interop with legacy devices like TD+
   1174      * that does not require scrambler at dual lane 10g mode
   1175      * spn_SERDES_SCRAMBLER_ENABLE should be explicitly set to "0" from 
   1176      * the config 
   1177      */
   1178     is_scrambler = 0; 
   1179     if (port_num_lanes == 2 && speed == 10000) {
   1180         is_scrambler = 1;
   1181     }
   1182 
   1183     is_scrambler = soc_property_port_get(unit, port,
   1184                                          spn_SERDES_SCRAMBLER_ENABLE, is_scrambler);
   1185     if (is_scrambler) {
   1186         PHYMOD_INTF_MODES_SCR_SET(interface_config);
   1187     }  
   1188         
   1189 
   1190     interface_config->speed =
   1191         soc_property_port_get(unit, port, spn_PORT_INIT_SPEED, speed);
   1192 
   1193     init_config->pll_divider_req      =
   1194         soc_property_port_get(unit, port, spn_XGXS_PHY_PLL_DIVIDER, 0xA);
   1195 
   1196 #if (defined BCM_HELIX5_SUPPORT) || (defined BCM_MAVERICK2_SUPPORT)
   1197     if (SOC_IS_HELIX5(unit) ||
   1198         (SOC_IS_MAVERICK2(unit) && SOC_INFO(unit).bandwidth == 2000000)) {
   1199         init_config->serdes_1000x_at_25g_vco = 1;
   1200         init_config->serdes_10g_at_25g_vco = 1;
   1201     }
   1202 #endif
   1203     init_config->serdes_1000x_at_6250_vco =
   1204         soc_property_port_get(unit, port,
   1205                               spn_SERDES_1000X_AT_6250_VCO,
   1206                               init_config->serdes_1000x_at_6250_vco);
   1207 
   1208     init_config->serdes_1000x_at_12500_vco =
   1209         soc_property_port_get(unit, port,
   1210                       spn_SERDES_1000X_AT_12500_VCO,
   1211                       init_config->serdes_1000x_at_12500_vco);
   1212 
   1213     init_config->serdes_1000x_at_25g_vco =
   1214         soc_property_port_get(unit, port,
   1215                       spn_SERDES_1000X_AT_25G_VCO,
   1216                       init_config->serdes_1000x_at_25g_vco);
   1217 
   1218     init_config->serdes_10g_at_25g_vco =
   1219         soc_property_port_get(unit, port,
   1220                       spn_SERDES_10G_AT_25G_VCO,
   1221                       init_config->serdes_10g_at_25g_vco);
   1222 
   1223     if (init_config->serdes_1000x_at_12500_vco) {
   1224       /*
   1225            * VCO = (PLL_DIV) * (REF_CLK)
   1226            * REF_CLK = 156.25
   1227            * VCO     = 12500
   1228            * PLL_DIV = 80
   1229            */
   1230         init_config->pll_divider_req = 80;
   1231         interface_config->pll_divider_req = 80;
   1232     } else if (init_config->serdes_1000x_at_6250_vco) {
   1233         /*
   1234          * VCO = (PLL_DIV) * (REF_CLK)
   1235          * REF_CLK = 156.25
   1236          * VCO     = 6250
   1237          * PLL_DIV = 40
   1238          */
   1239         init_config->pll_divider_req = 40;
   1240         interface_config->pll_divider_req = 40;
   1241     } else if (init_config->serdes_1000x_at_25g_vco ||
   1242                init_config->serdes_10g_at_25g_vco) {
   1243         /*
   1244          * VCO = (PLL_DIV) * (REF_CLK)
   1245          * REF_CLK = 156.25
   1246          * VCO     = 25G
   1247          * PLL_DIV = 165
   1248          */
   1249         init_config->pll_divider_req = 165;
   1250         interface_config->pll_divider_req = 165;
   1251     }
   1252     init_config->cx4_10g = soc_property_port_get(unit, port,
   1253                                                  spn_10G_IS_CX4, TRUE);
   1254 
   1255     SOC_IF_ERROR_RETURN(portmod_common_default_interface_get(interface_config));
   1256 
   1257 #ifdef BCM_HELIX5_SUPPORT
   1258     /* HX5 supports QSGMII and USXGMII mode in Pm4x10_qtc core. */
   1259     if (SOC_IS_HELIX5(unit)) {
   1260         int phy_port, base_port, port_gmii_mode;
   1261         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   1262         if (SOC_PORT_BLOCK_TYPE(unit, phy_port) == SOC_BLK_GXPORT) {
   1263             base_port = phy_port - (phy_port - 1) % 16;
   1264             port_gmii_mode = soc_property_phys_port_get(unit, base_port,
   1265                                                   spn_PORT_GMII_MODE, 0);
   1266             switch (port_gmii_mode) {
   1267                 case 0:
   1268                     init_config->qtc_mode = portmodQtcModeEthernet;
   1269                     break;
   1270                 case 1:
   1271                     init_config->qtc_mode = portmodQtcModeQsgmii;
   1272                     break;
   1273                 case 2:
   1274                     init_config->qtc_mode = portmodQtcModeUsxgmii;
   1275                     break;
   1276                 default:
   1277                     init_config->qtc_mode = portmodQtcModeInvalid;
   1278                     break;
   1279             }
   1280             if ((init_config->qtc_mode == portmodQtcModeQsgmii) ||
   1281                 (init_config->qtc_mode == portmodQtcModeUsxgmii)) {
   1282                 interface_config->interface = SOC_PORT_IF_SGMII;
   1283             }
   1284         }
   1285     }
   1286 #endif
   1287 
   1288     if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port))
   1289         interface_config->interface =  SOC_PORT_IF_NULL;
   1290 
   1291     /* get internal serdes preemphasis and current property */
   1292     port_preemphasis = 0xffffffff;
   1293     port_driver_current = 0xffffffff;
   1294     port_preemphasis = soc_property_port_get(unit, port,
   1295                                         spn_SERDES_PREEMPHASIS, port_preemphasis);
   1296     port_driver_current = soc_property_port_get(unit, port,
   1297                                            spn_SERDES_DRIVER_CURRENT,
   1298                                            port_driver_current);
   1299     for (i=0; i<port_num_lanes; i++){
   1300         init_config->tx_params_user_flag[i] = 0;
   1301     }
   1302     for (i=0; i<port_num_lanes; i++){
   1303         lane_preemphasis = 0xffffffff;
   1304         lane_preemphasis = soc_property_port_suffix_num_get(unit, port, i, 
   1305                               spn_SERDES_PREEMPHASIS, "lane", lane_preemphasis);
   1306         if (lane_preemphasis != 0xffffffff){
   1307             preemphasis = lane_preemphasis;
   1308         }else if (port_preemphasis != 0xffffffff){
   1309             preemphasis = port_preemphasis;
   1310         }else {
   1311             preemphasis = 0xffffffff;
   1312         }
   1313 
   1314         if(preemphasis != 0xffffffff){
   1315             init_config->tx_params_user_flag[i] |=
   1316                 PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG;
   1317             init_config->tx_params[i].pre  = preemphasis & 0xff;
   1318             init_config->tx_params[i].main = (preemphasis & 0xff00) >> 8;
   1319             init_config->tx_params[i].post = (preemphasis & 0xff0000) >> 16;
   1320         }
   1321     }
   1322     for (i=0; i<port_num_lanes; i++){
   1323         lane_driver_current = 0xffffffff;
   1324         lane_driver_current = soc_property_port_suffix_num_get(unit, port, i,
   1325                                  spn_SERDES_DRIVER_CURRENT, "lane", lane_driver_current);
   1326         if (lane_driver_current != 0xffffffff){
   1327             driver_current = lane_driver_current;
   1328         }else if (port_driver_current != 0xffffffff){
   1329             driver_current = port_driver_current;
   1330         }else {
   1331             driver_current = 0xffffffff;
   1332         }
   1333         
   1334         if(driver_current != 0xffffffff){
   1335             init_config->tx_params_user_flag[i] |= PORTMOD_USER_SET_TX_AMP_BY_CONFIG;
   1336             init_config->tx_params[i].amp  = driver_current;
   1337         }
   1338     }
   1339 
   1340     /* get external phy preemphasis and current property */
   1341     port_preemphasis = 0xffffffff;
   1342     port_driver_current = 0xffffffff;
   1343     port_preemphasis = soc_property_port_get(unit, port,
   1344                                         spn_PHY_PREEMPHASIS, preemphasis);
   1345     port_driver_current = soc_property_port_get(unit, port,
   1346                                            spn_PHY_DRIVER_CURRENT,
   1347                                            driver_current);
   1348     for (i=0; i<port_num_lanes; i++){
   1349         init_config->ext_phy_tx_params_user_flag[i] = 0;
   1350     }
   1351     for (i=0; i<port_num_lanes; i++){
   1352         lane_preemphasis = 0xffffffff;
   1353         lane_preemphasis = soc_property_port_suffix_num_get(unit, port, i,
   1354                               spn_PHY_PREEMPHASIS, "lane", lane_preemphasis);
   1355         if (lane_preemphasis != 0xffffffff){
   1356             preemphasis = lane_preemphasis;
   1357         }else if (port_preemphasis != 0xffffffff){
   1358             preemphasis = port_preemphasis;
   1359         }else {
   1360             preemphasis = 0xffffffff;
   1361         }
   1362 
   1363         if(preemphasis != 0xffffffff){
   1364             init_config->ext_phy_tx_params_user_flag[i] |=
   1365             PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG ;
   1366             init_config->ext_phy_tx_params[i].pre  = preemphasis & 0xff;
   1367             init_config->ext_phy_tx_params[i].main = (preemphasis & 0xff00) >> 8;
   1368             init_config->ext_phy_tx_params[i].post = (preemphasis & 0xff0000) >> 16;
   1369     }
   1370     }
   1371     for (i=0; i<port_num_lanes; i++){
   1372         lane_driver_current = 0xffffffff;
   1373         lane_driver_current = soc_property_port_suffix_num_get(unit, port, i,
   1374                                  spn_PHY_DRIVER_CURRENT, "lane", lane_driver_current);
   1375         if (lane_driver_current != 0xffffffff){
   1376             driver_current = lane_driver_current;
   1377         }else if (port_driver_current != 0xffffffff){
   1378             driver_current = port_driver_current;
   1379         }else {
   1380             driver_current = 0xffffffff;
   1381         }
   1382 
   1383         if(driver_current != 0xffffffff){
   1384             init_config->ext_phy_tx_params_user_flag[i] |= PORTMOD_USER_SET_TX_AMP_BY_CONFIG;
   1385             init_config->ext_phy_tx_params[i].amp  = driver_current;
   1386         }
   1387     }
   1388 
   1389     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   1390         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_port_config_get)) {
   1391          SOC_IF_ERROR_RETURN
   1392             (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_port_config_get(
   1393                 unit, port, (portmod_port_init_config_t *)init_config));
   1394     }
   1395 
   1396     ref_clk_prop = soc_property_port_get(unit, port,
   1397                                 spn_XGXS_LCPLL_XTAL_REFCLK, 156);
   1398 
   1399     if ((ref_clk_prop == 156) ||( ref_clk_prop == 0)) {
   1400         init_config->ref_clk = phymodRefClk156Mhz;     /**< 156.25MHz */
   1401     } else if (ref_clk_prop == 125) {
   1402         init_config->ref_clk = phymodRefClk125Mhz;     /**< 125MHz */
   1403     } else {
   1404         LOG_ERROR(BSL_LS_SOC_PORT,
   1405                 (BSL_META_UP(unit, port,
   1406                           "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop));
   1407     }
   1408     init_config->ref_clk_overwrite = 1;
   1409 
   1410     /* Internal Serdes interface setting if user want to overwrite. */
   1411     interface_config->serdes_interface =
   1412         soc_property_port_get(unit, port, spn_SERDES_IF_TYPE,
   1413                               SOC_PORT_IF_NULL);
   1414 
   1415     if (IS_HG_PORT(unit, port)) {
   1416         if (soc_feature(unit, soc_feature_no_higig_plus)) {
   1417             encap_mode = SOC_ENCAP_HIGIG2;
   1418         } else {
   1419             encap_mode = soc_property_port_get(unit, port,
   1420                          spn_HIGIG2_HDR_MODE, 0) ?
   1421                          SOC_ENCAP_HIGIG2 : SOC_ENCAP_HIGIG;
   1422         }
   1423         interface_config->encap_mode = encap_mode;
   1424     }
   1425 #ifdef BCM_MONTEREY_SUPPORT
   1426     if (IS_CPRI_PORT(unit, port)) {
   1427         port_speed_cpri = _check_cpri_speed(SOC_INFO(unit).port_init_speed[port], _SHR_PORT_ENCAP_CPRI);
   1428         if(port_speed_cpri >= 0) {
   1429             if (IS_RSVD4_PORT(unit, port)) {
   1430                 roe_speed_rsvd4 = _check_cpri_speed(SOC_INFO(unit).port_init_speed[port], _SHR_PORT_ENCAP_RSVD4);
   1431                 roe_speed_cpri = -1;
   1432             } else {
   1433                 roe_speed_cpri = _check_cpri_speed(SOC_INFO(unit).port_init_speed[port], _SHR_PORT_ENCAP_CPRI);
   1434                 roe_speed_rsvd4 = -1;
   1435             }
   1436         } else {
   1437             roe_speed_cpri = soc_property_port_get(unit, port, spn_CPRI_PORT_INIT_SPEED_ID, -1);
   1438             roe_speed_rsvd4 =  soc_property_port_get(unit, port, spn_RSVD4_PORT_INIT_SPEED_ID, -1);
   1439         }
   1440         if ((roe_speed_cpri == -1)&&(roe_speed_rsvd4 == -1)) {
   1441             LOG_WARN(BSL_LS_SOC_PORT,
   1442                 (BSL_META_UP(unit, port,
   1443                 "WARNING: For cpri port speed is not specified moving to 1228.8 M speed\n")));
   1444             roe_speed_cpri = 0;
   1445         }
   1446         if ((roe_speed_cpri != -1)&&(roe_speed_rsvd4 != -1)) {
   1447             LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_UP(unit, port,
   1448                 "ERROR: For cpri port : two speeds are specified : can not have cpri_port_init_speed_id_%d and rsvd4_port_init_speed_id_%d on same port\n"), port, port));
   1449             return SOC_E_PARAM;
   1450         }
   1451         if (roe_speed_cpri != -1) {
   1452             interface_config->encap_mode = _SHR_PORT_ENCAP_CPRI;
   1453             interface_config->speed = roe_speed_cpri;
   1454         } else if (roe_speed_rsvd4 != -1) {
   1455             interface_config->encap_mode = _SHR_PORT_ENCAP_RSVD4;
   1456             interface_config->speed = roe_speed_rsvd4;
   1457         }
   1458         init_config->roe_reserved_bit = soc_property_port_get(unit, port,
   1459                          spn_ROE_RESERVED_BIT, 0);
   1460         init_config->roe_stuffing_bit= soc_property_port_get(unit, port,
   1461                          spn_ROE_STUFFING_BIT, 0);
   1462         interface_config->serdes_scrambler_seed = soc_property_port_get(unit, port,
   1463                          spn_SERDES_SCRAMBLER_SEED, 0x55);
   1464         interface_config->serdes_scrambler_enable = soc_property_port_get(unit, port,
   1465                          spn_SERDES_SCRAMBLER_ENABLE, 0);
   1466     }
   1467 #endif
   1468     init_config->parity_enable = soc_property_port_get(unit, port,
   1469                                                       spn_PARITY_ENABLE, 0);
   1470 
   1471     
   1472     interface_config->port_op_mode =
   1473             soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, TRUE);
   1474 
   1475     return SOC_E_NONE;
   1476 }
   1477 
   1478 
   1479 /*
   1480  * Function:
   1481  *      soc_portctrl_pm_portmod_init
   1482  *
   1483  * Purpose:
   1484  *      Call device specific portmod init function
   1485  *
   1486  * Parameters:
   1487  *      unit     - (IN) Unit number.
   1488  * Returns:
   1489  *      SOC_E_UNAVAIL : if fuction vector is not correctly set
   1490  *      rv            : return rv
   1491  */
   1492 STATIC int
   1493 soc_portctrl_pm_portmod_init(int unit)
   1494 {
   1495     int rv = SOC_E_NONE;
   1496 
   1497     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   1498         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_init)) {
   1499         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_init(unit);
   1500     } else {
   1501         rv = SOC_E_UNAVAIL;
   1502     }
   1503     return rv; 
   1504 }
   1505 
   1506 /*
   1507  * Function:
   1508  *      soc_portctrl_pm_portmod_deinit
   1509  *
   1510  * Purpose:
   1511  *      Call device specific portmod deinit function
   1512  *
   1513  * Parameters:
   1514  *      unit     - (IN) Unit number.
   1515  * Returns:
   1516  *      SOC_E_UNAVAIL : if fuction vector is not correctly set
   1517  *      rv            : return rv
   1518  */
   1519 STATIC int
   1520 soc_portctrl_pm_portmod_deinit(int unit)
   1521 {
   1522     int rv = SOC_E_NONE;
   1523 
   1524     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   1525         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_deinit)) {
   1526         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_deinit(unit);
   1527     } else {
   1528         rv = SOC_E_UNAVAIL;
   1529     }
   1530     return rv; 
   1531 }
   1532 
   1533 /*
   1534  * Function:
   1535  *      soc_portctrl_pm_type_get
   1536  *
   1537  * Purpose:
   1538  *      Call device specific portmod pm_type get function
   1539  *
   1540  * Parameters:
   1541  *      unit     - (IN) Unit number.
   1542  *      phy_port - (IN) Physical port.
   1543  *      pm_type  - (OUT) pm_type
   1544  * Returns:
   1545  *      SOC_E_UNAVAIL : if fuction vector is not correctly set
   1546  *      rv            : return rv
   1547  */
   1548 int
   1549 soc_portctrl_pm_type_get(int unit, soc_port_t phy_port,
   1550                          int* pm_type)
   1551 {
   1552     int rv = SOC_E_NONE;
   1553 
   1554     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   1555         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_type_get)) {
   1556         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_type_get(
   1557                  unit, phy_port, pm_type);
   1558     } else {
   1559         rv = SOC_E_UNAVAIL;
   1560     }
   1561     return rv; 
   1562 }
   1563 
   1564 
   1565 extern soc_portctrl_functions_t soc_td2p_portctrl_func;
   1566 extern soc_portctrl_functions_t soc_th_portctrl_func;
   1567 extern soc_portctrl_functions_t soc_gh_portctrl_func;
   1568 extern soc_portctrl_functions_t soc_ap_portctrl_func;
   1569 extern soc_portctrl_functions_t soc_hr3_portctrl_func;
   1570 extern soc_portctrl_functions_t soc_mn_portctrl_func;
   1571 extern soc_portctrl_functions_t soc_th2_portctrl_func;
   1572 extern soc_portctrl_functions_t soc_th3_portctrl_func;
   1573 extern soc_portctrl_functions_t soc_hx5_portctrl_func;
   1574 
   1575 /*
   1576  * Function:
   1577  *      soc_portctrl_functions_register
   1578  *
   1579  * Purpose:
   1580  *      This will set given function vector to soc_control->soc_portctrl_functions
   1581  *
   1582  * Parameters:
   1583  *      unit     - (IN) Unit number.
   1584  *      func     - (IN) device specific portctrl function vectors
   1585  * Returns:
   1586  *      SOC_E_NONE
   1587  */
   1588 int
   1589 soc_esw_portctrl_functions_register(int unit, soc_driver_t *drv)
   1590 {
   1591     switch (drv->type) {
   1592 #ifdef BCM_MAVERICK2_SUPPORT
   1593     case SOC_CHIP_BCM56770_A0:
   1594     case SOC_CHIP_BCM56771_A0:
   1595         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_mv2_portctrl_func;
   1596         break;
   1597 #endif
   1598 #ifdef BCM_HELIX5_SUPPORT
   1599     case SOC_CHIP_BCM56370_A0:
   1600         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_hx5_portctrl_func;
   1601         break;
   1602 #endif
   1603 #ifdef BCM_TRIDENT3_SUPPORT
   1604     case SOC_CHIP_BCM56870_A0:
   1605     case SOC_CHIP_BCM56873_A0:
   1606         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_td3_portctrl_func;
   1607         break;
   1608 #endif
   1609 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1610     case SOC_CHIP_BCM56860_A0:
   1611         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_td2p_portctrl_func;
   1612         break;
   1613 #endif
   1614 #ifdef BCM_TOMAHAWK_SUPPORT
   1615     case SOC_CHIP_BCM56960_A0:
   1616         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_th_portctrl_func;
   1617         break;
   1618 #endif
   1619 #ifdef BCM_GREYHOUND_SUPPORT
   1620     case SOC_CHIP_BCM53400_A0:
   1621         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_gh_portctrl_func;
   1622         break;
   1623 #endif
   1624 #ifdef BCM_APACHE_SUPPORT
   1625     case SOC_CHIP_BCM56560_A0:
   1626     case SOC_CHIP_BCM56560_B0:
   1627         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_ap_portctrl_func;
   1628         break;
   1629 #endif
   1630 #ifdef BCM_MONTEREY_SUPPORT
   1631     case SOC_CHIP_BCM56670_A0:
   1632     case SOC_CHIP_BCM56670_B0:
   1633         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_mn_portctrl_func;
   1634         break;
   1635 #endif
   1636 #ifdef BCM_TOMAHAWK2_SUPPORT
   1637     case SOC_CHIP_BCM56970_A0:
   1638         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_th2_portctrl_func;
   1639         break;
   1640 #endif
   1641 #ifdef BCM_TOMAHAWK3_SUPPORT
   1642     case SOC_CHIP_BCM56980_A0:
   1643     case SOC_CHIP_BCM56980_B0:
   1644         SOC_PORTCTRL_FUNCTIONS(unit) = &soc_th3_portctrl_func;
   1645         break;
   1646 #endif
   1647     default:
   1648         break;
   1649     }
   1650     return SOC_E_NONE;
   1651 }
   1652 
   1653 /*
   1654  * Function:
   1655  *      soc_portctrl_xport_type_verify
   1656  * Purpose:
   1657  *      Check if the encapsulation is changed from configured selection.
   1658  *      Update the SOC port data structures to match the HW encapsulation selection.
   1659  * Parameters:
   1660  *      unit - XGS unit #.
   1661  * Returns:
   1662  *      SOC_E_XXX
   1663  * Notes:
   1664  *      WARM_BOOT mode only
   1665  */
   1666 STATIC int
   1667 soc_portctrl_xport_type_verify(int unit)
   1668 {
   1669     int        mode;
   1670     soc_port_t port;
   1671 
   1672     PBMP_PORT_ITER(unit, port) {
   1673         SOC_IF_ERROR_RETURN(soc_esw_portctrl_encap_get(unit, port, &mode));
   1674 
   1675         if ((IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port))
   1676              && (mode != SOC_ENCAP_IEEE)) {
   1677             if (mode == SOC_ENCAP_CPRI || mode == SOC_ENCAP_RSVD4) {
   1678                 soc_xport_type_update(unit, port, mode);
   1679             } else {
   1680                soc_xport_type_update(unit, port, TRUE);
   1681             }
   1682         } else if (IS_HG_PORT(unit, port)) { 
   1683            if (mode == SOC_ENCAP_IEEE) {
   1684                soc_xport_type_update(unit, port, FALSE);
   1685            }  else if (mode == SOC_ENCAP_CPRI || mode == SOC_ENCAP_RSVD4) {  
   1686                soc_xport_type_update(unit, port, mode);
   1687            }
   1688         } else if (IS_CPRI_PORT(unit, port) && (mode != SOC_ENCAP_CPRI)) { 
   1689                      
   1690                    if ( mode == SOC_ENCAP_RSVD4) {
   1691                        soc_xport_type_update(unit, port, mode);
   1692                    } else if (mode == SOC_ENCAP_IEEE) {
   1693                        soc_xport_type_update(unit, port, FALSE);
   1694                    } else { 
   1695                        soc_xport_type_update(unit, port,TRUE);
   1696                    }
   1697         } else if (IS_RSVD4_PORT(unit, port) && (mode != SOC_ENCAP_RSVD4)) { 
   1698                    if ( mode == SOC_ENCAP_CPRI) {
   1699                        soc_xport_type_update(unit, port, mode);
   1700                    } else if (mode == SOC_ENCAP_IEEE) {
   1701                        soc_xport_type_update(unit, port, FALSE);
   1702                    } else { 
   1703                        soc_xport_type_update(unit, port,TRUE);
   1704                    }
   1705         }
   1706 
   1707         
   1708         if (mode == SOC_ENCAP_HIGIG2) {
   1709             if (IS_HG_PORT(unit, port)) {
   1710                 SOC_HG2_ENABLED_PORT_ADD(unit, port);
   1711             } else {
   1712                 /* This should not happen */
   1713                 return SOC_E_INTERNAL;
   1714             }
   1715         }
   1716     }
   1717 
   1718     return SOC_E_NONE;
   1719 }
   1720 
   1721 /*
   1722  * Function:
   1723  *      soc_portctrl_phy_lane_config_fill
   1724  * Purpose:
   1725  *      Parses the serdes_lane_config soc property's suffixes to fill in the
   1726  *      integer that's sent to portmod
   1727  * Parameters:
   1728  *      unit - XGS unit #.
   1729  *      port - port of config being parsed
   1730  *      speed_config - pointer to structure containing the int being filled out
   1731  * Returns:
   1732  *      SOC_E_XXX
   1733  * Notes:
   1734  */
   1735 STATIC int
   1736 _soc_portctrl_phy_lane_config_fill(int unit, soc_port_t port, void *speed_config)
   1737 {
   1738 #ifdef PORTMOD_SUPPORT
   1739     int dfe = 1;
   1740     int dfe_lp = 0;
   1741     char *dfe_str;
   1742     char *dfe_types[] = {"off", "on", "lp", NULL};
   1743     int unreliable_los;
   1744     int cl72_auto_polarity_en;
   1745     int cl72_restart_timeout_en;
   1746     int force_nr = 1;
   1747     int force_er = 0;
   1748     char *channel_mode_str;
   1749     char *channel_mode_types[] = {"force_nr", "force_er", NULL};
   1750     int lp_has_prec_en;
   1751     int default_lane_config = 0;
   1752     int i, found_valid;
   1753     int media_type_int = 0;
   1754     char *media_type;
   1755     char *media_types[] = {"backplane", "copper", "optics", NULL};
   1756     portmod_speed_config_t *config = (portmod_speed_config_t *)speed_config;
   1757 
   1758     /* fetch values from config file if user filled them in */
   1759     dfe_str = soc_property_port_suffix_num_get_str(unit, port, 0,
   1760             spn_SERDES_LANE_CONFIG, "dfe");
   1761 
   1762     if (dfe_str != NULL) {
   1763         found_valid = 0;
   1764         for (i = 0; dfe_types[i] != NULL; i++) {
   1765             if (!sal_strncmp(dfe_types[i], dfe_str,
   1766                         sal_strlen(dfe_types[i]))) {
   1767                 switch(i) {
   1768                     case 0:
   1769                         dfe = 0;
   1770                         dfe_lp = 0;
   1771                         found_valid = 1;
   1772                         break;
   1773                     case 1:
   1774                         dfe = 1;
   1775                         dfe_lp = 0;
   1776                         found_valid = 1;
   1777                         break;
   1778                     case 2:
   1779                         dfe = 1;
   1780                         dfe_lp = 1;
   1781                         found_valid = 1;
   1782                         break;
   1783                     default:
   1784                         return SOC_E_INTERNAL;
   1785                 }
   1786             }
   1787         }
   1788 
   1789         if (found_valid == 0) {
   1790             return SOC_E_CONFIG;
   1791         }
   1792     }
   1793 
   1794     media_type = soc_property_port_suffix_num_get_str(unit, port, 0,
   1795             spn_SERDES_LANE_CONFIG, "media_type");
   1796 
   1797     /* get the media type integer from the string */
   1798     if (media_type != NULL) {
   1799         found_valid = 0;
   1800         for (i = 0; media_types[i] != NULL; i++) {
   1801             if (!sal_strncmp(media_types[i], media_type,
   1802                             sal_strlen(media_types[i]))) {
   1803                 media_type_int = i;
   1804                 found_valid = 1;
   1805                 break;
   1806             }
   1807         }
   1808         if (found_valid == 0) {
   1809             return SOC_E_CONFIG;
   1810         }
   1811     }
   1812 
   1813     unreliable_los = soc_property_port_suffix_num_get(unit, port, 0,
   1814             spn_SERDES_LANE_CONFIG, "unreliable_los", 0);
   1815 
   1816     cl72_auto_polarity_en =
   1817             soc_property_port_suffix_num_get(unit, port, 0,
   1818             spn_SERDES_LANE_CONFIG, "cl72_auto_polarity_en",
   1819             0);
   1820 
   1821     cl72_restart_timeout_en =
   1822             soc_property_port_suffix_num_get(unit, port, 0,
   1823             spn_SERDES_LANE_CONFIG, "cl72_restart_timeout_en",
   1824             0);
   1825 
   1826     channel_mode_str = soc_property_port_suffix_num_get_str(unit, port, 0,
   1827             spn_SERDES_LANE_CONFIG, "channel_mode");
   1828 
   1829     if (channel_mode_str != NULL) {
   1830         found_valid = 0;
   1831         for (i = 0; channel_mode_types[i] != NULL; i++) {
   1832             if (!sal_strncmp(channel_mode_types[i], channel_mode_str,
   1833                             sal_strlen(channel_mode_types[i]))) {
   1834                 switch(i) {
   1835                     case 0:
   1836                         force_er = 0;
   1837                         force_nr = 1;
   1838                         found_valid = 1;
   1839                         break;
   1840                     case 1:
   1841                         force_er = 1;
   1842                         force_nr = 0;
   1843                         found_valid = 1;
   1844                         break;
   1845                     default:
   1846                         return SOC_E_INTERNAL;
   1847                 }
   1848                 break;
   1849             }
   1850         }
   1851         if (found_valid == 0) {
   1852             return SOC_E_CONFIG;
   1853         }
   1854     }
   1855 
   1856 
   1857     lp_has_prec_en = soc_property_port_suffix_num_get(unit, port, 0,
   1858             spn_SERDES_LANE_CONFIG, "lp_has_prec_en", 0);
   1859 
   1860     /* first set it to the default values */
   1861     config->lane_config = default_lane_config;
   1862 
   1863     /* Insert the modified values into the phy lane config */
   1864     config->lane_config |= ((dfe & 0x1) << 2);
   1865     config->lane_config |= ((dfe_lp & 0x1) << 3);
   1866     config->lane_config |= ((media_type_int & 0x3) << 5);
   1867     config->lane_config |= ((unreliable_los & 0x1) << 7);
   1868     config->lane_config |= ((cl72_auto_polarity_en & 0x1) << 9);
   1869     config->lane_config |= ((cl72_restart_timeout_en & 0x1) << 10);
   1870     config->lane_config |= ((force_nr & 0x1) << 12);
   1871     config->lane_config |= ((force_er & 0x1) << 11);
   1872     config->lane_config |= ((lp_has_prec_en & 0x1) << 13);
   1873 
   1874     return SOC_E_NONE;
   1875 #else
   1876     return SOC_E_UNAVAIL;
   1877 #endif
   1878 }
   1879 
   1880 /*
   1881  * Function:
   1882  *      soc_esw_portctrl_speed_config_fill
   1883  * Purpose: This function fills in the speed_config structure for portmod.
   1884  *          Starting with PM8x50, the port macro needs this information to
   1885  *          set the speed of a port.
   1886  *
   1887  *          NOTE: If speed, num_lane, fec, link_training, or lane_config are
   1888  *                passed as -1 parameters, then "default" values will be used.
   1889  *
   1890  *                For fec, link_training and lane_config, their values will
   1891  *                try to be read from the config file first.
   1892  *
   1893  *                Otherwise, if those parameters are >= 0, they will be used.
   1894  *
   1895  * Parameters:
   1896  *      unit            - (IN)  Unit number.
   1897  *      port            - (IN)  logical port
   1898  *      speed           - (IN)  Port Speed
   1899  *      num_lane        - (IN)  Number of lanes for port
   1900  *      fec             - (IN)  Forward Error Correction
   1901  *      link_training   - (IN)  link training field
   1902  *      lane_config     - (IN)  lane config field
   1903  *      speed_config    - (OUT) the speed config structure to pass to portmod
   1904  *
   1905  * Returns: SOC_E_X
   1906  */
   1907 int
   1908 soc_esw_portctrl_speed_config_fill(int unit, soc_port_t port,
   1909                 int speed,
   1910                 int num_lane,
   1911                 int fec,
   1912                 int link_training,
   1913                 int lane_config,
   1914                 void *speed_config)
   1915 {
   1916 #ifdef PORTMOD_SUPPORT
   1917     soc_info_t *si = &SOC_INFO(unit);
   1918     portmod_speed_config_t *config = (portmod_speed_config_t *)speed_config;
   1919     
   1920     if (speed >= 0) {
   1921         config->speed = speed;
   1922     } else {
   1923         if (!SOC_PBMP_PORT_VALID(port) || IS_CPU_PORT(unit, port) ||
   1924                 IS_MANAGEMENT_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   1925                 return SOC_E_PARAM;
   1926         }
   1927         config->speed = si->port_speed_max[port];
   1928     }
   1929 
   1930     if (num_lane >= 0) {
   1931         config->num_lane = num_lane;
   1932     } else {
   1933         if (!SOC_PBMP_PORT_VALID(port) || IS_CPU_PORT(unit, port) ||
   1934                 IS_MANAGEMENT_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   1935                 return SOC_E_PARAM;
   1936         }
   1937         config->num_lane = si->port_num_lanes[port];
   1938     }
   1939 
   1940     if (fec >= 0) {
   1941         config->fec = fec;
   1942     } else {
   1943         if (!SOC_PBMP_PORT_VALID(port) || IS_CPU_PORT(unit, port) ||
   1944                 IS_MANAGEMENT_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   1945                 return SOC_E_PARAM;
   1946         }
   1947 
   1948         /* Read in FEC from config file if it was specified */
   1949         fec = soc_property_port_get(unit, port, spn_PORT_FEC, -1);
   1950 
   1951         if (fec >= 0) {
   1952             /* Mapping user config 'port_fec' to soc_port_phy_fec_t */
   1953             switch (fec) {
   1954                 case 0:
   1955                     config->fec = (portmod_fec_t)socPortPhyFecNone;
   1956                     break;
   1957                 case 1:
   1958                     config->fec = (portmod_fec_t)socPortPhyFecBaseR;
   1959                     break;
   1960                 case 2:
   1961                     config->fec = (portmod_fec_t)socPortPhyFecRsFec;
   1962                     break;
   1963                 case 3:
   1964                     config->fec = (portmod_fec_t)socPortPhyFecRs544;
   1965                     break;
   1966                 case 4:
   1967                     config->fec = (portmod_fec_t)socPortPhyFecRs272;
   1968                     break;
   1969                 case 9:
   1970                     config->fec = (portmod_fec_t)socPortPhyFecRs544_2xN;
   1971                     break;
   1972                 case 10:
   1973                     config->fec = (portmod_fec_t)socPortPhyFecRs272_2xN;
   1974                     break;
   1975                 default:
   1976                     return SOC_E_CONFIG;
   1977             }
   1978         } else {
   1979             /* Don't ever let FEC be invalid */
   1980             /* 400G requires RS 544, so default to that */
   1981             if (config->speed == 400000) {
   1982                 config->fec = (portmod_fec_t)socPortPhyFecRs544_2xN;
   1983             /* Default to no FEC if speed is not 400G */
   1984             } else if ((config->speed == 50000) && (config->num_lane == 1)) {
   1985                 config->fec = (portmod_fec_t)socPortPhyFecRs544;
   1986             } else {
   1987                 config->fec = (portmod_fec_t)socPortPhyFecNone;
   1988             }
   1989         }
   1990     }
   1991 
   1992     if (link_training >= 0) {
   1993         config->link_training = link_training;
   1994     } else {
   1995         if (!SOC_PBMP_PORT_VALID(port) || IS_CPU_PORT(unit, port) ||
   1996                 IS_MANAGEMENT_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   1997                 return SOC_E_PARAM;
   1998         }
   1999         config->link_training = 
   2000                 soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0);
   2001     }
   2002 
   2003     if (lane_config >= 0) {
   2004         config->lane_config = lane_config;
   2005     } else if (lane_config == -2) {
   2006         /* User passed in "auto" for lane config, so pass it in to portmod */
   2007         config->lane_config = -1;
   2008     } else {
   2009         /* Use config file values */
   2010         if (!SOC_PBMP_PORT_VALID(port) || IS_CPU_PORT(unit, port) ||
   2011                 IS_MANAGEMENT_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   2012                 return SOC_E_PARAM;
   2013         } else {
   2014             SOC_IF_ERROR_RETURN(
   2015                     _soc_portctrl_phy_lane_config_fill(unit, port, config));
   2016         }
   2017     }
   2018 
   2019     return SOC_E_NONE;
   2020 #else
   2021     return SOC_E_UNAVAIL;
   2022 #endif /* PORTMOD_SUPPORT */
   2023 }
   2024 
   2025 /*
   2026  * Function:
   2027  *      soc_esw_portctrl_pm_update_vco_soc_info
   2028  * Purpose:
   2029  *      The PM8x50 has 3 VCOs and a FEC type to select from that determine
   2030  *      the speed of the ports in use for each individual port macro. These
   2031  *      VCOs are determined by the port's speed, the number of lanes and FEC
   2032  *      used.
   2033  *
   2034  *      Example (Different use of FEC may impact the VCO. 50G IEEE mode uses
   2035  *      PAM-4, but 50G BRCM mode 25G-NRZ):
   2036  *      400G - 8 x 50G => PAM-4
   2037  *      200G - 4 x 50G => PAM-4
   2038  *      100G - 2 x 50G => PAM-4
   2039  *      100G - 4 x 25G => 25G-NRZ
   2040  *      50G  - 1 x 50G => PAM-4
   2041  *      50G  - 2 x 25G => 25G-NRZ
   2042  *      40G  - 4 x 10G => 10G-NRZ
   2043  *      25G  - 1 x 25G => 25G-NRZ
   2044  *      10G  - 1 x 10G => 10G-NRZ
   2045  *
   2046  *      The FEC type can be derived from the config file
   2047  *
   2048  *      This function accepts the parameters below because the parameters
   2049  *      may be coming from SOC_INFO during init or from a
   2050  *      soc_port_schedule_state_t datatype during flexport.
   2051  *
   2052  *      This function modifies the soc_info fields tvco and ovco for the
   2053  *      specified pm_id
   2054  *
   2055  * Parameters:
   2056  *      unit             - (IN)  Unit number.
   2057  *      phy_ports        - (IN)  array of physical ports corresponding to ONE
   2058  *                               PM8x50
   2059  *      num_ports   - (IN)  Number of ports in the array
   2060  *      flags       - (IN)  Flags passed in to Portmod
   2061  * Returns: SOC_E_X
   2062  *
   2063  * NOTE: PORTCTRL does not need to be initialized to use this function.
   2064  *       However, SOC_INFO must have parsed the config file in port_config_init.
   2065  *
   2066  *       This is only called at init!
   2067  */
   2068 int
   2069 soc_esw_portctrl_pm_update_vco_soc_info(int unit,
   2070                                 const int *phy_ports,
   2071                                 int num_ports,
   2072                                 int pm_id,
   2073                                 portmod_dispatch_type_t pm_type,
   2074                                 uint32 flags)
   2075 {
   2076     int port;
   2077     int num_speeds = 0;
   2078     int rv;
   2079     int i, j;
   2080     int *starting_lane_list;
   2081     int *speed_for_pcs_bypass_port = NULL;
   2082     portmod_pm_vco_setting_t vco_setting;
   2083     portmod_speed_config_t speed_config_temp;
   2084     portmod_speed_config_t *speed_config_list = NULL;
   2085 
   2086     soc_info_t * si = &SOC_INFO(unit);
   2087     rv = SOC_E_NONE;
   2088 
   2089     /* This was designed with the PM8x50 in mind. Function needs updating if used for
   2090      * a different PM */
   2091 #ifdef PORTMOD_PM8X50_SUPPORT
   2092     if (pm_type != portmodDispatchTypePm8x50) {
   2093         rv = SOC_E_UNAVAIL;
   2094         LOG_WARN(BSL_LS_SOC_PORT,
   2095                  (BSL_META_U(unit,
   2096                              "%s: found a different PM than PM8x50 %d\n"),
   2097                              __FUNCTION__, rv));
   2098         return rv;
   2099     }
   2100 #endif
   2101 
   2102     /* Find the port speeds in this PM */
   2103     /* allocate space for the speeds we're sending to portmod */
   2104     speed_config_list = sal_alloc(sizeof(portmod_speed_config_t) * num_ports,
   2105                                     "speed_config_list");
   2106     /*
   2107      * Allocate space for flag that indicates if the
   2108      * speed is for PCS bypass port.
   2109      */
   2110     speed_for_pcs_bypass_port = sal_alloc(sizeof(int) * num_ports,
   2111                                           "speed_for_pcs_bypass_port");
   2112     starting_lane_list = sal_alloc(sizeof(int) * num_ports,
   2113                                     "starting_lane_list");
   2114 
   2115     if (speed_config_list == NULL) {
   2116         rv = SOC_E_MEMORY;
   2117         goto vco_cleanup;
   2118     }
   2119     if (speed_for_pcs_bypass_port == NULL) {
   2120         rv = SOC_E_MEMORY;
   2121         goto vco_cleanup;
   2122     }
   2123     if (starting_lane_list == NULL) {
   2124         rv = SOC_E_MEMORY;
   2125         goto vco_cleanup;
   2126     }
   2127 
   2128     sal_memset(speed_config_list, 0,
   2129             sizeof(portmod_speed_config_t) * num_ports);
   2130     sal_memset(speed_for_pcs_bypass_port, 0, sizeof(int) * num_ports);
   2131     sal_memset(starting_lane_list, 0, sizeof(int) * num_ports);
   2132 
   2133     for (i = 0; i < num_ports; i++) {
   2134         port = si->port_p2l_mapping[phy_ports[i]];
   2135 
   2136         /* if port is unmapped */
   2137         if (port == -1) {
   2138             continue;
   2139         }
   2140 
   2141         sal_memset(&speed_config_temp, 0, sizeof(portmod_speed_config_t));
   2142 
   2143         /* If we're doing warmboot, all the values have been loaded into
   2144          * SOC_INFO at this point, so fill the speed_config structure with
   2145          * those values rather than reading from the config file */
   2146         if (SOC_WARM_BOOT(unit)) {
   2147             rv = soc_esw_portctrl_speed_config_fill(unit, port,
   2148                                             si->port_speed_max[port],
   2149                                             si->port_num_lanes[port],
   2150                                             si->port_fec_type[port],
   2151                                             si->port_link_training[port],
   2152                                             si->port_phy_lane_config[port],
   2153                                             &speed_config_temp);
   2154         } else {
   2155             rv = soc_esw_portctrl_speed_config_fill(unit, port,
   2156                                             -1,
   2157                                             -1,
   2158                                             -1,
   2159                                             -1,
   2160                                             -1,
   2161                                             &speed_config_temp);
   2162         }
   2163         if (SOC_FAILURE(rv)) {
   2164             goto vco_cleanup;
   2165         }
   2166 
   2167         /* look through our list of speeds for a free spot. Add the port's speed
   2168          * and starting lane to the list */
   2169         for (j = 0; j < num_ports; j++) {
   2170 
   2171             /* Empty entry if speed is 0 */
   2172             if (speed_config_list[j].speed == 0) {
   2173                 sal_memcpy(&speed_config_list[j], &speed_config_temp,
   2174                                 sizeof(portmod_speed_config_t));
   2175                 starting_lane_list[j] = i;
   2176                 num_speeds++;
   2177 
   2178                 /* Speed added to empty slot. Continue to next port */
   2179                 break;
   2180             }
   2181         }
   2182 
   2183         /* The above for loop will always break out with the port's current
   2184          * settings. It will either break out when it has found a duplicate,
   2185          * or if it has added a new entry to speed_config_list. So set
   2186          * that info into SOC_INFO
   2187          */
   2188         si->port_fec_type[port] = speed_config_list[j].fec;
   2189         si->port_link_training[port] = speed_config_list[j].link_training;
   2190         si->port_phy_lane_config[port] = speed_config_list[j].lane_config;
   2191     }
   2192 
   2193     /* Set the structure being passed to portmod, which will return
   2194      * with the tvco and ovco */
   2195     /* coverity[leaked_storage] */
   2196     rv = portmod_pm_vco_setting_t_init(unit, &vco_setting);
   2197     if (SOC_FAILURE(rv)) {
   2198         goto vco_cleanup;
   2199     }
   2200 
   2201     vco_setting.speed_config_list = speed_config_list;
   2202     vco_setting.speed_for_pcs_bypass_port = speed_for_pcs_bypass_port;
   2203     vco_setting.port_starting_lane_list = starting_lane_list;
   2204     vco_setting.num_speeds = num_speeds;
   2205 
   2206     rv = portmod_pm_vcos_get(unit, pm_type, flags, &vco_setting);
   2207 
   2208     /* Update the VCOs for this port macro */
   2209     si->pm_vco_info[pm_id].tvco = vco_setting.tvco;
   2210     si->pm_vco_info[pm_id].ovco = vco_setting.ovco;
   2211 
   2212 vco_cleanup:
   2213     if (speed_config_list != NULL) {
   2214         sal_free(speed_config_list);
   2215     }
   2216     if (speed_for_pcs_bypass_port != NULL) {
   2217         sal_free(speed_for_pcs_bypass_port);
   2218     }
   2219     if (starting_lane_list != NULL) {
   2220         sal_free(starting_lane_list);
   2221     }
   2222 
   2223     return rv;
   2224 }
   2225 
   2226 /*
   2227  * Function:
   2228  *      _soc_esw_portctrl_pm_flex_fill_speed_config_list
   2229  * Purpose:
   2230  *      This function fills speed_config_list with speeds in the port
   2231  *      macro. Each speed corresponds to a port.
   2232  * Parameters:
   2233  *      unit               - (IN)  Unit number.
   2234  *      lanes_per_pm       - (IN)  Number of lanes in the PM
   2235  *      phy_ports_in       - (IN)  Array of phy ports in PM
   2236  *      port_iter          - (IN)  Index for phy_ports_in
   2237  *      starting_lane_list - (IN/OUT) The list containing starting lane for port
   2238  *      speed_config_list  - (IN/OUT) The speed config list to fill
   2239  *      speeds             - (OUT) count of the speeds. This MUST
   2240  *                              be cleared in the calling function
   2241  *
   2242  * Returns: SOC_E_X
   2243  */
   2244 STATIC int
   2245 _soc_esw_portctrl_pm_flex_fill_speed_config_list(int unit,
   2246                         int lanes_per_pm,
   2247                         soc_port_resource_t **phy_ports_in,
   2248                         int port_iter,
   2249                         int *starting_lane_list,
   2250                         portmod_speed_config_t *speed_config_list,
   2251                         int *speeds)
   2252 {
   2253     int i;
   2254     int count = 0;
   2255     int rv = SOC_E_NONE;
   2256     
   2257     for (i = 0; i < lanes_per_pm; i++) {
   2258         /* Empty entry if speed is 0 */
   2259         if (speed_config_list[i].speed == 0) {
   2260             /* Since lane config can equal -1 to mean auto, we don't
   2261              * want the following function to misinterpret that as an
   2262              * instruction to read the config file value for lane config.
   2263              * So, if lane_config == -1, set it to -2 to tell this function
   2264              * that the value needs to be auto
   2265              */
   2266             if (phy_ports_in[port_iter]->phy_lane_config == -1) {
   2267                 phy_ports_in[port_iter]->phy_lane_config = -2;
   2268             }
   2269             rv = soc_esw_portctrl_speed_config_fill(unit,
   2270                                             phy_ports_in[port_iter]->logical_port,
   2271                                             phy_ports_in[port_iter]->speed,
   2272                                             phy_ports_in[port_iter]->num_lanes,
   2273                                             phy_ports_in[port_iter]->fec_type,
   2274                                             phy_ports_in[port_iter]->link_training,
   2275                                             phy_ports_in[port_iter]->phy_lane_config,
   2276                                             &speed_config_list[i]);
   2277             /* Set the starting lane equal to the port iterator that was passed
   2278              * in mod lanes per pm. This is they physical lane for the pm */
   2279             starting_lane_list[i] = (port_iter - 1) % lanes_per_pm;
   2280 
   2281             if (SOC_FAILURE(rv)) {
   2282                 return rv;
   2283             }
   2284             count++;
   2285             break;
   2286         }
   2287     }
   2288     /* Add count to the total */
   2289     *speeds += count;
   2290     return rv;
   2291 }
   2292 
   2293 
   2294 /*
   2295  * Function:
   2296  *      _soc_esw_portctrl_pm_flex_vco_validation
   2297  * Purpose:
   2298  *      This function validates that a SINGLE port macro's flex configuration
   2299  *      is valid for the flexport scenario requested.
   2300  *
   2301  *      It gathers the port and speed info requested and compares it with the
   2302  *      existing configuration (if there are ports that are persisting through
   2303  *      the flex), and validates that info.
   2304  *
   2305  *      If everything is ok, it stores the port macro VCO information so that
   2306  *      it doesn't have to be recalculated again later.  This VCO information
   2307  *      is then written to SOC_INFO at reconfiguration time.
   2308  *
   2309  * Parameters:
   2310  *      unit                 - (IN) Unit number.
   2311  *      port_schedule_state  - (IN) Contains information for current PM state
   2312  *      phy_port             - (IN) The physical port being flexed, which is
   2313  *                                  used to determine the PM affected
   2314  *      lanes_per_pm         - (IN) The number of lanes in the port macro
   2315  *      phy_ports_in         - (IN) An array of pointers to the soc_port_resource_t
   2316  *                                  of the physical ports being flexed.
   2317  *                                  Non-flexing port indexes will be NULL
   2318  *      phy_deleted_ports    - (IN) an array of ports that will be deleted
   2319  *                                  in the flexport operation. Indexed by phy port
   2320  *
   2321  * Note:
   2322  *      phy_ports_in is essentially a hash where the key is physical ports. If
   2323  *      a port is flexing, the pointer will point to the flex operation. If the
   2324  *      entry is NULL, it means that port is not flexing to a new port.
   2325  *
   2326  * Returns: SOC_E_X
   2327  */
   2328 
   2329 STATIC int
   2330 _soc_esw_portctrl_pm_flex_vco_validation(int unit,
   2331                                 soc_port_schedule_state_t *port_schedule_state,
   2332                                 int phy_port, 
   2333                                 int lanes_per_pm,
   2334                                 soc_port_resource_t **phy_ports_in,
   2335                                 const uint8 *phy_deleted_ports)
   2336 {
   2337 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
   2338     int port_iter;
   2339     int pm_id, portmod_pm_id;
   2340     int count;
   2341     int base_phy_port;
   2342     int rv;
   2343     int logical_port;
   2344     int pll_switch_flag;
   2345     int *starting_lane_list = NULL;
   2346     int *speed_for_pcs_bypass_port = NULL;
   2347     soc_pmvco_info_t pm_vco_info;
   2348     portmod_pm_vco_setting_t pm_vco_setting;
   2349     portmod_pbmp_t flexing_ports;
   2350     portmod_speed_config_t *speed_config_list = NULL;
   2351     soc_port_map_type_t *in_port_map = &(port_schedule_state->in_port_map);
   2352 
   2353     /*
   2354      * Allocate space for flag that indicates if the
   2355      * speed is for PCS bypass port.
   2356      */
   2357     speed_for_pcs_bypass_port = sal_alloc(sizeof(int) * lanes_per_pm,
   2358                                           "speed_for_pcs_bypass_port");
   2359     if (speed_for_pcs_bypass_port == NULL) {
   2360         return SOC_E_MEMORY;
   2361     }
   2362     speed_config_list = sal_alloc(lanes_per_pm * sizeof(portmod_speed_config_t),
   2363                         "speed_config_list array");
   2364     if (speed_config_list == NULL) {
   2365         rv = SOC_E_MEMORY;
   2366         goto cleanup;
   2367     }
   2368     starting_lane_list = sal_alloc(sizeof(int) * lanes_per_pm,
   2369                                     "starting_lane_list");
   2370     if (starting_lane_list == NULL) {
   2371         rv = SOC_E_MEMORY;
   2372         goto cleanup;
   2373     }
   2374 
   2375     /* Iterate through the affected ports in the PM.  Verify
   2376      * that the maximum number of VCOs isn't exceeded
   2377      */
   2378     pm_id = (phy_port - 1) / lanes_per_pm;
   2379     base_phy_port = (pm_id * lanes_per_pm) + 1;
   2380 
   2381     sal_memset(speed_for_pcs_bypass_port, 0, sizeof(int) * lanes_per_pm);
   2382     sal_memset(speed_config_list, 0, lanes_per_pm * sizeof(portmod_speed_config_t));
   2383     sal_memset(starting_lane_list, 0, sizeof(int) * lanes_per_pm);
   2384     sal_memset(&pm_vco_setting, 0, sizeof(pm_vco_setting));
   2385     count = 0;
   2386     PORTMOD_PBMP_CLEAR(flexing_ports);
   2387     pll_switch_flag = PORTMOD_PM_SPEED_VALIDATE_F_TWO_PLL_SWITCH_ALLOWED;
   2388 
   2389     for (port_iter = base_phy_port; port_iter < (base_phy_port + lanes_per_pm);
   2390                                                                 port_iter++) {
   2391 
   2392         if (phy_ports_in[port_iter] == NULL) {
   2393             /* Not creating a new port */
   2394 
   2395             /* Skip if the port is being deleted */
   2396             if (phy_deleted_ports[port_iter] != 0) {
   2397                 continue;
   2398             }
   2399 
   2400             logical_port = in_port_map->port_p2l_mapping[port_iter];
   2401 
   2402             /* Port might not be mapped.  Skip if it isn't mapped */
   2403             if (SOC_PBMP_PORT_VALID(logical_port)) {
   2404 
   2405                 /* Since not all ports on this PM are changing, only allow
   2406                  * one PLL switch
   2407                  */
   2408                 pll_switch_flag = PORTMOD_PM_SPEED_VALIDATE_F_ONE_PLL_SWITCH_ALLOWED;
   2409             }
   2410         } else {
   2411             /* Creating a new port, fill the config list */
   2412             rv = _soc_esw_portctrl_pm_flex_fill_speed_config_list(
   2413                     unit,
   2414                     lanes_per_pm,
   2415                     phy_ports_in,
   2416                     port_iter,
   2417                     starting_lane_list,
   2418                     speed_config_list,
   2419                     &count);
   2420 
   2421             if (SOC_FAILURE(rv)) {
   2422                 goto cleanup;
   2423             }
   2424         }
   2425     }
   2426 
   2427     pm_vco_setting.speed_for_pcs_bypass_port = speed_for_pcs_bypass_port;
   2428     pm_vco_setting.speed_config_list = speed_config_list;
   2429     pm_vco_setting.port_starting_lane_list = starting_lane_list;
   2430     pm_vco_setting.num_speeds = count;
   2431 
   2432     /* Fill in the flexing ports port bitmap with all ports being deleted.
   2433      * If a port is changing, it has to have been deleted
   2434      */
   2435     for (port_iter = 1; port_iter < SOC_MAX_NUM_PORTS; port_iter++) {
   2436         /* Check if the physical port is being deleted */
   2437         if (phy_deleted_ports[port_iter]) {
   2438             /* Only add ports on the PM in question */
   2439             if (((port_iter - 1) / lanes_per_pm) == pm_id) {
   2440                 logical_port = in_port_map->port_p2l_mapping[port_iter];
   2441                 PORTMOD_PBMP_PORT_ADD(flexing_ports, logical_port);
   2442             }
   2443         }
   2444     }
   2445 
   2446 
   2447     /* Portmod's indexing of the port macros differs from SDK's */
   2448     portmod_phy_pm_id_get(unit, phy_port, &portmod_pm_id);
   2449 
   2450     rv = portmod_pm_speed_config_validate(unit, portmod_pm_id, &flexing_ports,
   2451                                 pll_switch_flag, &pm_vco_setting);
   2452 
   2453     if (SOC_FAILURE(rv)) {
   2454         LOG_ERROR(BSL_LS_SOC_PORT,
   2455                     (BSL_META_U(unit,
   2456                                 "  VCO Validation "
   2457                                 "Failed for Port Macro: %d\n"
   2458                                 "Current VCOS: %d %d\n"
   2459                                 "pll_switch_flag: %d\n"),
   2460                      pm_id,
   2461                      SOC_INFO(unit).pm_vco_info[pm_id].tvco,
   2462                      SOC_INFO(unit).pm_vco_info[pm_id].ovco,
   2463                      pll_switch_flag
   2464                      ));
   2465         goto cleanup;
   2466     }
   2467 
   2468 
   2469     /* Save this information so that it doesn't have to be validated later */
   2470     pm_vco_info.tvco = pm_vco_setting.tvco;
   2471     pm_vco_info.ovco = pm_vco_setting.ovco;
   2472     /* Set is_tvco_new and is_ovco_new to 1,
   2473      * indicating the vco in pm_vco_info is updated. */
   2474     pm_vco_info.is_tvco_new = 1;
   2475     pm_vco_info.is_ovco_new = 1;
   2476 
   2477     rv = soc_esw_portctrl_pm_vco_store(unit, pm_id, &pm_vco_info);
   2478 
   2479 cleanup:
   2480     if (speed_for_pcs_bypass_port != NULL) {
   2481         sal_free(speed_for_pcs_bypass_port);
   2482         speed_for_pcs_bypass_port = NULL;
   2483     }
   2484     if (speed_config_list != NULL) {
   2485         sal_free(speed_config_list);
   2486         speed_config_list = NULL;
   2487     }
   2488     if (starting_lane_list != NULL) {
   2489         sal_free(starting_lane_list);
   2490         starting_lane_list = NULL;
   2491     }
   2492 
   2493     return rv;
   2494 #else
   2495     return SOC_E_UNAVAIL;
   2496 #endif /* defined(PORTMOD_SUPPORT && defined(PORTMOD_PM8X50_SUPPORT) */
   2497 }
   2498 
   2499 
   2500 /*
   2501  * Function:
   2502  *      soc_esw_portctrl_pm_vco_store
   2503  * Purpose:
   2504  *      Calls a function vector, if it exists, to store PM VCO info so that
   2505  *      it won't have to be recalculated later
   2506  *
   2507  * Parameters:
   2508  *      unit                 - (IN) Unit number.
   2509  *      index                - (IN) Port Macro index
   2510  *      pm_vco_info          - (IN) VCO info want to store
   2511  *
   2512  * Note:
   2513  *      Does not directly affect SOC_INFO data
   2514  *
   2515  * Returns: SOC_E_X
   2516  */
   2517 int
   2518 soc_esw_portctrl_pm_vco_store(int unit, int index, const void *pm_vco_info)
   2519 {
   2520     int rv;
   2521 
   2522     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   2523         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_store)) {
   2524         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_store(
   2525                  unit, index, pm_vco_info);
   2526     } else {
   2527         rv = SOC_E_UNAVAIL;
   2528     }
   2529 
   2530     return rv;
   2531 }
   2532 
   2533 #endif /* PORTMOD_SUPPORT */
   2534 
   2535 /*
   2536  * Function:
   2537  *      soc_esw_portctrl_pm_vco_reconfigure
   2538  * Purpose:
   2539  *      Called to Reconfigure the VCOs in Port Macros affected during a flex
   2540  *      operation.  This is called AFTER SOC_INFO has been updated with the new
   2541  *      VCO information.
   2542  * Parameters:
   2543  *      unit                 - (IN) Unit number.
   2544  *
   2545  * Note:
   2546  *
   2547  * Returns: SOC_E_X
   2548  */
   2549 int
   2550 soc_esw_portctrl_pm_vco_reconfigure(int unit)
   2551 {
   2552     int rv;
   2553 
   2554     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   2555         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_reconfigure)) {
   2556         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_reconfigure(
   2557                  unit);
   2558     } else {
   2559         rv = SOC_E_UNAVAIL;
   2560     }
   2561 
   2562     return rv;
   2563 }
   2564 
   2565 /*
   2566  * Function:
   2567  *      soc_esw_portctrl_pm_vco_fetch
   2568  * Purpose:
   2569  *      Called to fetch the VCO information saved from a flex operation
   2570  *      calculation for use in setting SOC_INFO
   2571  * Parameters:
   2572  *      unit                 - (IN) Unit number.
   2573  *
   2574  * Note:
   2575  *      Does not directly affect SOC_INFO data
   2576  *
   2577  * Returns: SOC_E_X
   2578  */
   2579 int
   2580 soc_esw_portctrl_pm_vco_fetch(int unit, int index, void *pm_vco_info)
   2581 {
   2582 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
   2583 
   2584     int rv;
   2585 
   2586     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   2587         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_fetch)) {
   2588         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_fetch(
   2589                  unit, index, pm_vco_info);
   2590     } else {
   2591         rv = SOC_E_UNAVAIL;
   2592     }
   2593 
   2594     return rv;
   2595 #else
   2596     return SOC_E_UNAVAIL;
   2597 #endif /* defined(PORTMOD_SUPPORT && defined(PORTMOD_PM8X50_SUPPORT) */
   2598 }
   2599 
   2600 
   2601 /*
   2602  * Function:
   2603  *      soc_esw_portctrl_flex_vco_validation
   2604  * Purpose:
   2605  *      Called to validate the speed and vco configuration for all port macros
   2606  *      in the device.  This function will examine the flexport operation
   2607  *      requested by the user, and will compare it with existing settings
   2608  *      in the device.  It will then make sure that those configurations are
   2609  *      valid.
   2610  *
   2611  * Parameters:
   2612  *      unit                 - (IN) Unit number.
   2613  *      port_schedule_state  - (IN) The flex information
   2614  * Note:
   2615  *
   2616  * Returns: SOC_E_X
   2617  */
   2618 int
   2619 soc_esw_portctrl_flex_vco_validation(int unit,
   2620                     soc_port_schedule_state_t *port_schedule_state)
   2621 {
   2622 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
   2623 
   2624     int i;
   2625     int num_ports;
   2626     int max_num_ports;
   2627     int pm_id;
   2628     int lanes_per_pm;
   2629     portmod_dispatch_type_t pm_type;
   2630     portmod_pm_capability_t pm_cap;
   2631     /* Create a SOC_MAX_NUM_PORTS port array so that we can keep track of physical ports.
   2632      * soc_pbmp_t only goes up to 256 bits, so it's not big enough */
   2633     uint8 phy_deleted_ports[SOC_MAX_NUM_PORTS];
   2634     int rv = SOC_E_NONE;
   2635     soc_info_t *si = &SOC_INFO(unit);
   2636     soc_port_resource_t *resource = port_schedule_state->resource;
   2637     /* array of pointers indexed by physical ports seen in soc_port_resource_t
   2638      * array the user sent
   2639      * NULL = physical port was unseen
   2640      * != NULL = pointer to the soc_port_resource_t
   2641      */
   2642     soc_port_resource_t **phy_ports_in = NULL;
   2643 
   2644     /* Physical Ports for front panel are index offset by 1
   2645      * (start at physical port 1). Physical port 0 is CPU port.
   2646      * So if Physical ports 1 - 256 are usable as front panel ports,
   2647      * we want to be able to access index 256, so allocate 257 slots (0-256) */
   2648     max_num_ports = (SOC_MAX_NUM_PORTS + 1);
   2649 
   2650     phy_ports_in = sal_alloc(max_num_ports * sizeof(soc_port_resource_t *),
   2651                             "Array of soc_port_resource_t *");
   2652     if (phy_ports_in == NULL) {
   2653         return SOC_E_MEMORY;
   2654     }
   2655 
   2656     sal_memset(phy_ports_in, 0, max_num_ports * sizeof(soc_port_resource_t *));
   2657 
   2658     /* Keep track of the deleted ports */
   2659     sal_memset(phy_deleted_ports, 0, sizeof(phy_deleted_ports));
   2660 
   2661     num_ports = port_schedule_state->nport;
   2662 
   2663     /* Mark the incoming physical ports in the phy_ports_in array. Indexes
   2664      * that are NULL means that those ports are NOT flexing.
   2665      */
   2666     for (i = 0; i < num_ports; i++) {
   2667         /* skip ports being deleted */
   2668         if (resource[i].physical_port == -1) {
   2669             /* mark the port as being deleted by marking it in the array
   2670              */
   2671             phy_deleted_ports[si->port_l2p_mapping[resource[i].logical_port]]
   2672                                 = 1;
   2673             continue;
   2674         }
   2675         phy_ports_in[resource[i].physical_port] = &resource[i];
   2676     }
   2677 
   2678     /* Validate for the post flex configuration that each PM doesn't exceed its
   2679      * maximum number of VCOs
   2680      */
   2681     for (i = 1; i < max_num_ports; i++) {
   2682         /* Skip physical ports not seen */
   2683         if (phy_ports_in[i] == NULL) {
   2684             continue;
   2685         }
   2686 #ifdef BCM_TOMAHAWK3_SUPPORT
   2687         /* Tomahawk 3's Management Port Macro requires a spacing between
   2688          * the lanes, so even though the two management ports' physical
   2689          * ports are 257 and 258, the lane needs to be the next one,
   2690          * so logical port 118 being mapped to physical port 258 needs
   2691          * to pass 259 to portmod because portmod only recognizes lane
   2692          * 0 (physical port 257) and lane 2 (physial port 259).
   2693          */
   2694         if (SOC_IS_TOMAHAWK3(unit) && (i == 258)) {
   2695             i = 259;
   2696         }
   2697 #endif
   2698 
   2699         rv = (portmod_phy_pm_type_get(unit, i, &pm_type));
   2700         if (SOC_FAILURE(rv)) {
   2701             goto cleanup;
   2702         }
   2703         switch (pm_type) {
   2704             case portmodDispatchTypePm8x50:
   2705                 rv = (portmod_pm_capability_get(unit, pm_type, &pm_cap));
   2706                 if (SOC_FAILURE(rv)) {
   2707                     goto cleanup;
   2708                 }
   2709 
   2710                 lanes_per_pm = pm_cap.pm_capability.pm8x50_cap.num_lanes;
   2711                 break;
   2712             default:
   2713                 /* Skip Ports that are in PMs that are not PM8x50 */
   2714                 continue;
   2715         }
   2716         /* This will verify that the post flex speeds on the port macro
   2717          * are acceptable
   2718          */
   2719         rv = _soc_esw_portctrl_pm_flex_vco_validation(unit,
   2720                                 port_schedule_state,
   2721                                 i, 
   2722                                 lanes_per_pm,
   2723                                 phy_ports_in,
   2724                                 phy_deleted_ports);
   2725         if (SOC_FAILURE(rv)) {
   2726             goto cleanup;
   2727         }
   2728         /* get the port macro id that this port belongs to */
   2729         pm_id = ((i - 1) / lanes_per_pm);
   2730 
   2731         /* Go to the last port in the port macro. No sense in checking the
   2732          * same port macro over and over again.
   2733          * Example: We just finished PM0, which starts at physical port 1, so
   2734          * go to PM1: ((0 + 1) * 8) = 8. The loop will increment to 9, which
   2735          * is the start of the next PM
   2736          */
   2737         i = ((pm_id + 1) * lanes_per_pm);
   2738     }
   2739 
   2740 
   2741 cleanup:
   2742     if (phy_ports_in != NULL) {
   2743         sal_free(phy_ports_in);
   2744     }
   2745 
   2746     return rv;
   2747 #else
   2748     return SOC_E_UNAVAIL;
   2749 #endif /* defined(PORTMOD_SUPPORT && defined(PORTMOD_PM8X50_SUPPORT) */
   2750 }
   2751 
   2752 
   2753 /*
   2754  * Function:
   2755  *      soc_esw_portctrl_pm_vco_store_clear
   2756  * Purpose:
   2757  *      Clears the calculated VCO information from a flexport operation
   2758  *
   2759  * Parameters:
   2760  *      unit     - (IN) Unit number.
   2761  *      port_schedule_state  - (IN) The flex information
   2762  * Note:
   2763  *      Does not directly affect SOC_INFO data
   2764  *
   2765  * Returns: SOC_E_X
   2766  */
   2767 int
   2768 soc_esw_portctrl_pm_vco_store_clear(int unit)
   2769 {
   2770 #ifdef PORTMOD_SUPPORT
   2771     int rv;
   2772 
   2773     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   2774         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_store_clear)) {
   2775         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_vco_store_clear(
   2776                  unit);
   2777             } else {
   2778         rv = SOC_E_UNAVAIL;
   2779     }
   2780 
   2781     return rv;
   2782 #else
   2783     return SOC_E_NONE;
   2784 #endif
   2785 }
   2786 
   2787 /*
   2788  * Function:
   2789  *      soc_esw_portctrl_pm_ports_delete
   2790  * Purpose:
   2791  *      Remove ports from the corresponding Port Macros.
   2792  * Parameters:
   2793  *      unit           - (IN) Unit number.
   2794  *      nport          - (IN) Number of elements in array resource.
   2795  *      resource       - (IN) Port Resource FlexPort configuration.
   2796  * Returns:
   2797  *      SOC_E_XXX
   2798  * Note:
   2799  *      - Assumes all data is Port Resource arrays has been validated.
   2800  *      - Must be called before SOC_INFO is updated.
   2801  */
   2802 int
   2803 soc_esw_portctrl_pm_ports_delete(int unit,
   2804                                int nport,
   2805                                soc_port_resource_t *resource)
   2806 {
   2807 #ifdef PORTMOD_SUPPORT
   2808     int i;
   2809     soc_port_resource_t *pr;
   2810 
   2811     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2812                 (BSL_META_U(unit,
   2813                             "SOC Port Macro Delete\n")));
   2814 
   2815     /* Check that PortCtrl has been initialized */
   2816     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   2817 
   2818     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2819         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2820                     (BSL_META_U(unit,
   2821                                 "  Port Macro delete "
   2822                                 "logical_port=%d physical_port=%d\n"),
   2823                      pr->logical_port, pr->physical_port));
   2824 
   2825         /* portmod detach */
   2826         SOC_IF_ERROR_RETURN(soc_esw_portctrl_delete(unit, pr->logical_port));
   2827     }
   2828 
   2829     return SOC_E_NONE;
   2830 #else  /* PORTMOD_SUPPORT */
   2831     return SOC_E_UNAVAIL;
   2832 #endif /* PORTMOD_SUPPORT */
   2833 }
   2834 
   2835 
   2836 /*
   2837  * Function:
   2838  *      soc_esw_portctrl_pm_ports_add
   2839  * Purpose:
   2840  *      Add ports and configure the relevant Port Macros for the given
   2841  *      the FlexPort configuration.
   2842  *
   2843  *      This function reconfigures all the blocks inside
   2844  *      the PortMod library, this is xxPORT, MAC, and PHY.
   2845  * Parameters:
   2846  *      unit           - (IN) Unit number.
   2847  *      nport          - (IN) Number of elements in array resource.
   2848  *      resource       - (IN) Port Resource FlexPort configuration.
   2849  * Returns:
   2850  *      SOC_E_XXX
   2851  * Note:
   2852  *      - Assumes all data is Port Resource arrays has been validated.
   2853  *      - Must be called after SOC_INFO has been updated.
   2854  *      - Assumes ports has been already deleted.
   2855  *      - Caller must provide ALL ports (deleted and added), because
   2856  *        for it needs to 'add' NULL driver on cases where ports
   2857  *        become inactive.
   2858  */
   2859 int
   2860 soc_esw_portctrl_pm_ports_add(int unit,
   2861                                int nport,
   2862                                soc_port_resource_t *resource)
   2863 {
   2864 #ifdef PORTMOD_SUPPORT
   2865     int i, lane=0, num_lanes, physical_port;
   2866     soc_port_resource_t *pr;
   2867     soc_info_t *si = &SOC_INFO(unit);
   2868     portmod_pbmp_t phys;
   2869     pbmp_t pbmp;
   2870 #ifdef FW_BCAST_DOWNLOAD
   2871     int bcast_flag, crc_en;
   2872 #endif
   2873 
   2874     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2875                 (BSL_META_U(unit,
   2876                             "SOC Port Macro Add\n")));
   2877 
   2878     /* Check that PortCtrl has been initialized */
   2879     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   2880 
   2881     PORTMOD_PBMP_CLEAR(phys);
   2882     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2883         /*
   2884          * Check if 'delete' port needs to be added (NULL driver).
   2885          */
   2886         if ((pr->physical_port == -1) &&
   2887             !SOC_PBMP_MEMBER(si->all.disabled_bitmap, pr->logical_port)) {
   2888             /* Port is deleted and is not inactive, nothing to add */
   2889             continue;
   2890         }
   2891 
   2892         num_lanes = SOC_INFO(unit).port_num_lanes[pr->logical_port];
   2893         if(num_lanes == 10) num_lanes=12;
   2894         for (lane = 0; lane < num_lanes; lane++) {
   2895             physical_port = SOC_INFO(unit).port_l2p_mapping[pr->logical_port];
   2896 #ifdef BCM_TRIDENT3_SUPPORT
   2897             /*To support the 2nd MGMT port, convert its physical port to the dummy port number 131 on TD3.*/
   2898             if((SOC_IS_TRIDENT3(unit)) && (physical_port == 128) && (SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, pr->logical_port))){
   2899                 physical_port = 131;
   2900             }
   2901 #endif /* BCM_TRIDENT3_SUPPORT */
   2902 #ifdef BCM_TOMAHAWK3_SUPPORT
   2903             /* Tomahawk 3's Management Port Macro requires a spacing between
   2904              * the lanes, so even though the two management ports' physical
   2905              * ports are 257 and 258, the lane needs to be the next one,
   2906              * so logical port 118 being mapped to physical port 258 needs
   2907              * to pass 259 to portmod because portmod only recognizes lane
   2908              * 0 (physical port 257) and lane 2 (physial port 259).
   2909              */
   2910             if (SOC_IS_TOMAHAWK3(unit) && pr->logical_port == 118) {
   2911                 physical_port = 259;
   2912             }
   2913 #endif
   2914             SOC_IF_ERROR_RETURN(
   2915                 portmod_xphy_lane_detach(unit, physical_port + lane, 1));
   2916             SOC_PBMP_PORT_ADD(phys, physical_port + lane);
   2917         }
   2918         SOC_IF_ERROR_RETURN(soc_esw_portctrl_setup_ext_phy_add(unit, pr->logical_port, &phys));
   2919     }
   2920 
   2921     /* Configure port in PortMod */
   2922     SOC_PBMP_CLEAR(pbmp);
   2923     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2924         /*
   2925          * In some cases, ports to be deleted become inactive.
   2926          * In this case, the PortMod NULL driver needs to be installed
   2927          * for the inactive port.
   2928          *
   2929          * The function soc_esw_portctrl_add() sets the right
   2930          * information for the PortMod to install the correct
   2931          * driver.
   2932          */
   2933 
   2934         /*
   2935          * Check if 'delete' port needs to be added (NULL driver).
   2936          */
   2937         if ((pr->physical_port == -1) &&
   2938             !SOC_PBMP_MEMBER(si->all.disabled_bitmap, pr->logical_port)) {
   2939             /* Port is deleted and is not inactive, nothing to add */
   2940             continue;
   2941         }
   2942 
   2943         /* Add port */
   2944         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2945                     (BSL_META_U(unit,
   2946                                 "  Port Macro: Add "
   2947                                 "logical_port=%d physical_port=%d\n"),
   2948                      pr->logical_port, pr->physical_port));
   2949 
   2950         SOC_IF_ERROR_RETURN(soc_esw_portctrl_add(unit, pr->logical_port, PORTMOD_PORT_ADD_F_INIT_CORE_PROBE, NULL));
   2951         SOC_IF_ERROR_RETURN(soc_esw_portctrl_add(unit, pr->logical_port, PORTMOD_PORT_ADD_F_INIT_PASS1, NULL));
   2952         SOC_PBMP_PORT_ADD(pbmp, pr->logical_port);
   2953     }
   2954 
   2955 #ifdef FW_BCAST_DOWNLOAD
   2956     bcast_flag = soc_property_get(unit, spn_LOAD_FIRMWARE, 0);
   2957     if (bcast_flag & 0xff0000) {
   2958         crc_en = (bcast_flag >> 8) & 0xFF;
   2959         SOC_IF_ERROR_RETURN(portmod_common_serdes_fw_bcst(unit, pbmp, crc_en));
   2960     }
   2961 #endif
   2962 
   2963     if (!(SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit))) {
   2964     SOC_IF_ERROR_RETURN(portmod_legacy_ext_phy_init(unit, pbmp));
   2965 
   2966     /* broadcast firmware download to all phymod based phys */
   2967     SOC_IF_ERROR_RETURN(portmod_common_ext_phy_fw_bcst(unit, &pbmp));
   2968     }
   2969 
   2970 
   2971     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2972 
   2973         /*
   2974          * Check if 'delete' port needs to be added (NULL driver).
   2975          */
   2976         if ((pr->physical_port == -1) &&
   2977             !SOC_PBMP_MEMBER(si->all.disabled_bitmap, pr->logical_port)) {
   2978             /* Port is deleted and is not inactive, nothing to add */
   2979             continue;
   2980         }
   2981 
   2982         /* Add port */
   2983         SOC_IF_ERROR_RETURN(soc_esw_portctrl_add(unit, pr->logical_port, PORTMOD_PORT_ADD_F_INIT_PASS2, NULL));
   2984         /* Leave port disabled */
   2985         SOC_IF_ERROR_RETURN(portmod_port_enable_set(unit, pr->logical_port, PORTMOD_PORT_ENABLE_PHY, 0));
   2986     }
   2987 
   2988     return SOC_E_NONE;
   2989 #else  /* PORTMOD_SUPPORT */
   2990     return SOC_E_UNAVAIL;
   2991 #endif /* PORTMOD_SUPPORT */
   2992 }
   2993 
   2994 /*
   2995  * Function:
   2996  *      soc_esw_portctrl_init
   2997  * Purpose:
   2998  *      Initialize the Port Control component and
   2999  *      corresponding library (PortMod library).
   3000  *      1. call soc_portctrl_pm_portmod_init
   3001  *      2. set portctrl_init status to SOC_PORTCTRL_INITIALIZED.
   3002  *
   3003  *      This is to be called by the SOC Port module initialization
   3004  *      function soc_misc_init().
   3005  * Parameters:
   3006  *      unit  - (IN) Unit number.
   3007  * Returns:
   3008  *      SOC_E_XXX
   3009  */
   3010 int
   3011 soc_esw_portctrl_init(int unit)
   3012 {
   3013 #ifdef PORTMOD_SUPPORT
   3014     int rv;
   3015 
   3016     /* Call Device specific PortMod library initialization */
   3017     rv = soc_portctrl_pm_portmod_init(unit);
   3018     /* Successful */
   3019     if (SOC_SUCCESS(rv)) {
   3020         portctrl_init[unit] = SOC_PORTCTRL_INITIALIZED;
   3021 
   3022         if (SOC_WARM_BOOT(unit)) {
   3023             rv = soc_portctrl_xport_type_verify(unit);
   3024         }
   3025     }
   3026     return rv;
   3027 #else  /* PORTMOD_SUPPORT */
   3028     return SOC_E_UNAVAIL;
   3029 #endif /* PORTMOD_SUPPORT */
   3030 }
   3031 
   3032 /*
   3033  * Function:
   3034  *      soc_esw_portctrl_deinit
   3035  * Purpose:
   3036  *      Uninitialize the Port Control component and
   3037  *      corresponding library (PortMod library).
   3038  *      1. call soc_portctrl_pm_portmod_deinit
   3039  *      2. set portctrl_init status to SOC_PORTCTRL_NOT_INITIALIZED.
   3040  *
   3041  *      This function must be called by the BCM Port module
   3042  *      deinit (or detach) function.
   3043  * Parameters:
   3044  *      unit  - (IN) Unit number.
   3045  * Returns:
   3046  *      SOC_E_XXX
   3047  */
   3048 int
   3049 soc_esw_portctrl_deinit(int unit)
   3050 {
   3051 #ifdef PORTMOD_SUPPORT
   3052     int rv;
   3053 
   3054     if (SOC_PORTCTRL_NOT_INITIALIZED == portctrl_init[unit]) {
   3055         return SOC_E_NONE;
   3056     }
   3057 
   3058     /* Call Device specific PortMod library uninitialization */
   3059     rv = soc_portctrl_pm_portmod_deinit(unit);
   3060     portctrl_init[unit] = SOC_PORTCTRL_NOT_INITIALIZED;
   3061 
   3062     return rv;
   3063 #else  /* PORTMOD_SUPPORT */
   3064     return SOC_E_UNAVAIL;
   3065 #endif /* PORTMOD_SUPPORT */
   3066 }
   3067 
   3068 
   3069 /*
   3070  * Function:
   3071  *      soc_esw_portctrl_add
   3072  * Purpose:
   3073  *      Add given logical port to PM (Port Macro).
   3074  * Parameters:
   3075  *      unit      - (IN) Unit number.
   3076  *      port      - (IN) Port number.
   3077  * Returns:
   3078  *      SOC_E_XXX
   3079  * Notes:
   3080  *      Assume port is disabled.
   3081  *      Assume port has been removed from PM.
   3082  *      Assume caller has checked that PortCtrl was initialized.
   3083  *      SOC_INFO SW data structure has been updated.
   3084  */
   3085 int
   3086 soc_esw_portctrl_add(int unit, soc_port_t port, int init_flag, void *port_add_info)
   3087 {
   3088 #ifdef PORTMOD_SUPPORT
   3089     portctrl_pport_t pport;
   3090     portmod_port_add_info_t *add_info = NULL;
   3091     portmod_port_add_info_t *local_add_info = NULL;
   3092     int phy_port;
   3093     int num_lanes;
   3094     int speed;
   3095     int lane, fwload_verify;
   3096     int duplex;
   3097     int ifg;
   3098     soc_ipg_t *si;
   3099     int rv = SOC_E_NONE;
   3100     uint32 mtu_size;
   3101 #ifdef PORTMOD_PM8X50_SUPPORT
   3102     int is_init = 0;
   3103     int pm_id, portmod_pm_id, phy_lane_config;
   3104     portmod_pm_capability_t pm_cap;
   3105     portmod_dispatch_type_t pm_type = portmodDispatchTypeCount;
   3106 #endif
   3107 
   3108     /* Convert port to PortMod port */
   3109     PORTCTRL_PORT_TO_PPORT(port, pport);
   3110 
   3111     if (port_add_info != NULL) {
   3112         add_info = (portmod_port_add_info_t*)port_add_info;
   3113     } else {
   3114         local_add_info = sal_alloc(sizeof(portmod_port_add_info_t),
   3115                          "portmod_port_add_info_t");
   3116         if (local_add_info == NULL) {
   3117         LOG_ERROR(BSL_LS_SOC_PORT,
   3118                   (BSL_META_U(unit, "Mem Alloc Fail: portmod_port_add_info_t")));
   3119         rv = SOC_E_MEMORY;
   3120         return rv;
   3121     }
   3122 
   3123         add_info = local_add_info;
   3124     }
   3125 
   3126     if (((port_add_info!=NULL) &&
   3127         (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE || !init_flag))
   3128         || (port_add_info==NULL)) {
   3129 
   3130         rv = portmod_port_add_info_t_init(unit, add_info);
   3131         if (PORTMOD_FAILURE(rv)) {
   3132             if (local_add_info != NULL) {
   3133                 sal_free(local_add_info);
   3134             }
   3135         return rv;
   3136     }
   3137 
   3138     rv = soc_esw_portctrl_config_get(unit, port,
   3139                                      &(add_info->interface_config),
   3140                                      &(add_info->init_config),
   3141                                      &(add_info->phy_op_mode));
   3142     if (SOC_FAILURE(rv)) {
   3143             if (local_add_info != NULL) {
   3144                 sal_free(local_add_info);
   3145             }
   3146         return rv;
   3147     }
   3148 
   3149     add_info->phy_op_datapath= soc_property_port_get(unit, port,
   3150                                                     spn_PHY_ULL_DATAPATH,
   3151                                                     phymodDatapathNormal);
   3152 
   3153     /*
   3154      * Add port to PM
   3155      */
   3156     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3157     num_lanes = SOC_INFO(unit).port_num_lanes[port];
   3158     if (num_lanes == 10) {
   3159         num_lanes = 12;
   3160     }
   3161 
   3162 #ifdef BCM_TRIDENT3_SUPPORT
   3163         
   3164         if((SOC_IS_TRIDENT3(unit)) && (phy_port == 128)) {
   3165             int pbm_count=0;
   3166             SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, pbm_count);
   3167             if (pbm_count == 2) {
   3168                 phy_port = 131;
   3169             }
   3170         }
   3171 #endif /* BCM_TRIDENT3_SUPPORT */
   3172 
   3173 #ifdef BCM_TOMAHAWK3_SUPPORT
   3174         /* Tomahawk 3's Management Port Macro requires a spacing between
   3175          * the lanes, so even though the two management ports' physical
   3176          * ports are 257 and 258, the lane needs to be the next one,
   3177          * so logical port 118 being mapped to physical port 258 needs
   3178          * to pass 259 to portmod because portmod only recognizes lane
   3179          * 0 (physical port 257) and lane 2 (physial port 259).
   3180          */
   3181         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   3182             phy_port = 259;
   3183         }
   3184 #endif
   3185 
   3186     /*
   3187      * Set lane information
   3188      * Assume lanes are arranged consecutively with respect to
   3189      * the physical port number.
   3190      */
   3191     for (lane = 0 ; lane < num_lanes; lane++) { 
   3192         PORTMOD_PBMP_PORT_ADD(add_info->phys, phy_port + lane);
   3193     }
   3194     }
   3195 
   3196     add_info->flags = 0;
   3197 
   3198     /* By default choose external fw load to speed up */
   3199     /* byte 0 defines fw load method, byte1 defines to verify the load */
   3200     fwload_verify = soc_property_get(unit, spn_LOAD_FIRMWARE, 2);
   3201 
   3202     if ((fwload_verify >> 8) & 0xF) {
   3203         PORTMOD_PORT_ADD_F_BYPASS_FW_CRC_CHECK_CLR(add_info);
   3204     } else {
   3205         PORTMOD_PORT_ADD_F_BYPASS_FW_CRC_CHECK_SET(add_info);
   3206     }
   3207 
   3208     if ((fwload_verify >> 12) & 0xF) {
   3209         PORTMOD_PORT_ADD_F_FIRMWARE_LOAD_VERIFY_SET(add_info);
   3210     }
   3211 
   3212 #ifdef FW_BCAST_DOWNLOAD
   3213     if (((fwload_verify >> 16) & 0xFF)) {
   3214         PORTMOD_PORT_ADD_F_FIRMWARE_DOWNLOAD_BCAST_SET(add_info);
   3215     }
   3216 #endif
   3217 
   3218     if (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE) {
   3219         PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_SET(add_info);
   3220     }
   3221 
   3222     if (init_flag == PORTMOD_PORT_ADD_F_INIT_PASS1) {
   3223         PORTMOD_PORT_ADD_F_INIT_PASS1_SET(add_info);
   3224     }
   3225 
   3226     if (init_flag == PORTMOD_PORT_ADD_F_INIT_PASS2) {
   3227         PORTMOD_PORT_ADD_F_INIT_PASS2_SET(add_info);
   3228     }
   3229 
   3230     if (SAL_BOOT_SIMULATION) {
   3231         PORTMOD_PORT_ADD_F_FIRMWARE_LOAD_VERIFY_CLR(add_info);
   3232     }
   3233 
   3234     if (soc_feature(unit, soc_feature_clmac_16byte_interface_mode)) {
   3235         PORTMOD_PORT_ADD_F_SYS_16B_INTF_MODE_SET(add_info);
   3236     }
   3237 #ifdef BCM_MONTEREY_SUPPORT
   3238     if (SOC_IS_MONTEREY(unit)){ 
   3239         PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_SET (add_info);
   3240     }
   3241 #endif
   3242 #ifdef BCM_TOMAHAWK3_SUPPORT
   3243     if (SOC_IS_TOMAHAWK3(unit)) {
   3244         PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_SET(add_info);
   3245     }
   3246 #endif
   3247 #ifdef PORTMOD_PM8X50_SUPPORT
   3248     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3249 
   3250 #ifdef BCM_TOMAHAWK3_SUPPORT
   3251         /* Tomahawk 3's Management Port Macro requires a spacing between
   3252          * the lanes, so even though the two management ports' physical
   3253          * ports are 257 and 258, the lane needs to be the next one,
   3254          * so logical port 118 being mapped to physical port 258 needs
   3255          * to pass 259 to portmod because portmod only recognizes lane
   3256          * 0 (physical port 257) and lane 2 (physial port 259).
   3257          */
   3258         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   3259             phy_port = 259;
   3260         }
   3261 #endif
   3262 
   3263     rv = portmod_phy_pm_type_get(unit, phy_port, &pm_type);
   3264 
   3265     if (rv != SOC_E_UNAVAIL && rv < 0) {
   3266         if (local_add_info != NULL) {
   3267             sal_free(local_add_info);
   3268         }
   3269         return rv;
   3270     }
   3271 
   3272     /* for PM8x50 core init and adding ports to the PM are separated,
   3273      * so we don't call portmod_port_add for both init and port add.
   3274      * Just initialize the core here (if needed) and return.
   3275      */
   3276     if (pm_type == portmodDispatchTypePm8x50) {
   3277         /* Portmod's indexing of the port macros differs from SDK's */
   3278         portmod_phy_pm_id_get(unit, phy_port, &portmod_pm_id);
   3279 
   3280         /* Check if the core is initialized */
   3281         rv = portmod_pm_is_initialized(unit, portmod_pm_id, &is_init);
   3282         if (rv != SOC_E_UNAVAIL && rv < 0) {
   3283             if (local_add_info != NULL) {
   3284                 sal_free(local_add_info);
   3285             }
   3286             return rv;
   3287         }
   3288 
   3289         /* Get the PM capability so we can figure out the # of lanes
   3290          * per PM */
   3291         rv = portmod_pm_capability_get(unit, pm_type, &pm_cap);
   3292         if (rv != SOC_E_UNAVAIL && rv < 0) {
   3293             if (local_add_info != NULL) {
   3294                 sal_free(local_add_info);
   3295             }
   3296             return rv;
   3297         }
   3298 
   3299         /* PM 0 = phy ports 1-8
   3300          * PM 1 = phy ports 9-16
   3301          * PM 2 = phy ports 17-24
   3302          * etc. */
   3303         pm_id = (phy_port - 1) / pm_cap.pm_capability.pm8x50_cap.num_lanes;
   3304 
   3305         /* Set the TVCO and OVCO of these ports corresponding to
   3306          * the PM they're a member of */
   3307         add_info->tvco = SOC_INFO(unit).pm_vco_info[pm_id].tvco;
   3308         add_info->ovco = SOC_INFO(unit).pm_vco_info[pm_id].ovco;
   3309 
   3310         /* Since lane config can equal -1 to mean auto, we don't
   3311          * want the following function to misinterpret that as an
   3312          * instruction to read the config file value for lane config.
   3313          * So, if lane_config == -1, set it to -2 to tell this function
   3314          * that the value needs to be auto
   3315          */
   3316         phy_lane_config = SOC_INFO(unit).port_phy_lane_config[port];
   3317         if (phy_lane_config == -1) {
   3318             phy_lane_config = -2;
   3319         }
   3320 
   3321         if (SOC_INFO(unit).port_init_speed[port] != 0) {
   3322             speed = SOC_INFO(unit).port_init_speed[port];
   3323         } else {
   3324             speed = SOC_INFO(unit).port_speed_max[port];
   3325         }
   3326 
   3327         /* Set the speed_config information */
   3328         rv = soc_esw_portctrl_speed_config_fill(unit,
   3329                                     port,
   3330                                     speed,
   3331                                     SOC_INFO(unit).port_num_lanes[port],
   3332                                     SOC_INFO(unit).port_fec_type[port],
   3333                                     SOC_INFO(unit).port_link_training[port],
   3334                                     phy_lane_config,
   3335                                     &(add_info->speed_config));
   3336 
   3337 
   3338         /* if the core is not initialized for this port, initialize it here */
   3339         if (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(is_init)) {
   3340             
   3341             /* core init will be called for probe, pass 1, and pass 2
   3342              * as instructed by the portmod team.
   3343              */
   3344             rv = portmod_core_add(unit, portmod_pm_id, add_info);
   3345             if (rv != SOC_E_UNAVAIL && rv < 0) {
   3346                 if (local_add_info != NULL) {
   3347                     sal_free(local_add_info);
   3348                 }
   3349                 return rv;
   3350             }
   3351 
   3352         }
   3353         
   3354         /* Only allow the call to the below portmod_port_add on pass 2
   3355          * because that means the core is init
   3356          */
   3357         if (!((init_flag == PORTMOD_PORT_ADD_F_INIT_PASS2) || (init_flag == 0))) {
   3358             if (local_add_info != NULL) {
   3359                 sal_free(local_add_info);
   3360             }
   3361             return rv;
   3362         }
   3363 
   3364         /* Clear the pass 2 flags because we want to call the port add
   3365          * only once.
   3366          */
   3367         add_info->flags &= ~PORTMOD_PORT_ADD_F_INIT_PASS2;
   3368     }
   3369 #endif
   3370 
   3371     if (soc_feature(unit, soc_feature_clmac_16byte_interface_mode)) {
   3372         PORTMOD_PORT_ADD_F_SYS_16B_INTF_MODE_SET(add_info);
   3373     }
   3374 
   3375 #if (defined BCM_HELIX5_SUPPORT) || (defined BCM_MAVERICK2_SUPPORT)
   3376     if (SOC_IS_HELIX5(unit) || SOC_IS_MAVERICK2(unit)) {
   3377         PORTMOD_PORT_ADD_F_IS_ENHANCED_PM4X25_GEN2_SET(add_info);
   3378     }
   3379 #endif
   3380 
   3381 #if (defined BCM_MAVERICK2_SUPPORT)
   3382     if (SOC_IS_MAVERICK2(unit)) {
   3383         PORTMOD_PORT_ADD_F_DEFAULT_OSR2P5_SET(add_info);
   3384     }
   3385 #endif
   3386     rv = portmod_port_add(unit, pport, add_info);
   3387     if (PORTMOD_FAILURE(rv)) {
   3388         if (local_add_info != NULL) {
   3389             sal_free(local_add_info);
   3390         }
   3391         return rv;
   3392     }
   3393 
   3394     if ((init_flag == PORTMOD_PORT_ADD_F_INIT_PASS2)  || (!init_flag)){
   3395         rv = soc_esw_portctrl_duplex_get(unit, port, &duplex);
   3396         if (PORTMOD_FAILURE(rv)) {
   3397             if (local_add_info != NULL) {
   3398                 sal_free(local_add_info);
   3399             }
   3400             return rv;
   3401         }
   3402 
   3403         si = &SOC_PERSIST(unit)->ipg[port];
   3404         if (IS_HG_PORT(unit, port)) {
   3405             si->fd_hg = ifg = SOC_AVERAGE_IPG_HG;
   3406         } else {
   3407             si->fd_xe = ifg = SOC_AVERAGE_IPG_IEEE;
   3408         }
   3409 
   3410 #ifdef PORTMOD_PM8X50_SUPPORT
   3411         if (pm_type == portmodDispatchTypePm8x50) {
   3412             speed = add_info->speed_config.speed;
   3413         } else
   3414 #endif 
   3415         {
   3416         speed = add_info->interface_config.speed;
   3417         }
   3418 
   3419         if (IS_CPRI_PORT(unit, port)) {
   3420             return SOC_E_NONE;
   3421         }
   3422         rv = soc_esw_portctrl_ifg_set(unit, port, speed, duplex, ifg);
   3423 
   3424         if (PORTMOD_FAILURE(rv)) {
   3425             if (local_add_info != NULL) {
   3426                 sal_free(local_add_info);
   3427             }
   3428             return rv;
   3429         }
   3430 
   3431         mtu_size = SOC_INFO(unit).max_mtu;
   3432         if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)
   3433             || IS_CE_PORT(unit, port)
   3434             || IS_CDE_PORT(unit, port)
   3435             || (IS_C_PORT(unit, port) && IS_E_PORT(unit,port))) {
   3436             /* For VLAN tagged packets */
   3437             mtu_size -= 4;
   3438         }
   3439 
   3440         rv = soc_esw_portctrl_frame_max_set(unit, pport, mtu_size);
   3441         if (PORTMOD_FAILURE(rv)) {
   3442             if (local_add_info != NULL) {
   3443                 sal_free(local_add_info);
   3444             }
   3445             return rv;
   3446         }
   3447 
   3448 #ifdef BCM_TRIDENT3_SUPPORT
   3449         if (SOC_IS_TRIDENT3(unit)) {
   3450             soc_info_t *si = &SOC_INFO(unit);
   3451             if (((add_info->interface_config.speed == 27000) ||
   3452                  (add_info->interface_config.speed == 53000))&&
   3453                  (!(si->oversub_mode))) {
   3454 #if 1
   3455                 LOG_ERROR(BSL_LS_BCM_COMMON,
   3456                           (BSL_META_U(unit,
   3457                                       "27G/53G speeed in Line rate config is not supported.\n")));
   3458                 if (local_add_info != NULL) {
   3459                     sal_free(local_add_info);
   3460                 }
   3461                 return SOC_E_CONFIG;
   3462 #endif
   3463             }
   3464         }
   3465 #endif /* BCM_TRIDENT3_SUPPORT */
   3466 
   3467         rv = soc_esw_portctrl_port_fc_config_init(unit, pport);
   3468         if (PORTMOD_FAILURE(rv)) {
   3469             if (local_add_info != NULL) {
   3470                 sal_free(local_add_info);
   3471             }
   3472             return rv;
   3473         }
   3474     }
   3475 
   3476     if (local_add_info != NULL) {
   3477         sal_free(local_add_info);
   3478     }
   3479 
   3480     return SOC_E_NONE;
   3481 
   3482 #else  /* PORTMOD_SUPPORT */
   3483     return SOC_E_UNAVAIL;
   3484 #endif /* PORTMOD_SUPPORT */
   3485 }
   3486 
   3487 
   3488 /*
   3489  * Function:
   3490  *      soc_esw_portctrl_delete
   3491  * Purpose:
   3492  *      Remove given logical port from PM (Port Macro).
   3493  * Parameters:
   3494  *      unit      - (IN) Unit number.
   3495  *      port      - (IN) Port number.
   3496  * Returns:
   3497  *      SOC_E_XXX
   3498  * Notes:
   3499  *      Assume port is disabled.
   3500  *      Assume caller has checked that PortCtrl was initialized.
   3501  *      SOC_INFO SW data structure has been updated.
   3502  */
   3503 int
   3504 soc_esw_portctrl_delete(int unit, soc_port_t port)
   3505 {
   3506 #ifdef PORTMOD_SUPPORT
   3507     portctrl_pport_t pport;
   3508     int valid;
   3509 
   3510     /* Convert port to PortMod port */
   3511     PORTCTRL_PORT_TO_PPORT(port, pport);
   3512 
   3513     /* Remove port */
   3514     PORTMOD_IF_ERROR_RETURN(portmod_port_is_valid(unit, pport, &valid));
   3515     if (valid) {
   3516         PORTMOD_IF_ERROR_RETURN(portmod_port_remove(unit, pport));
   3517     }
   3518 
   3519     return SOC_E_NONE;
   3520 
   3521 #else  /* PORTMOD_SUPPORT */
   3522     return SOC_E_UNAVAIL;
   3523 #endif /* PORTMOD_SUPPORT */
   3524 }
   3525 
   3526 
   3527 /*
   3528  * Function:
   3529  *      soc_esw_portctrl_pgw_reconfigure
   3530  * Purpose:
   3531  *      This function is called during reconfiguration of PGW during
   3532  *      flexing operation.
   3533  * Parameters:
   3534  *      unit      - (IN) Unit number.
   3535  *      port      - (IN) Logical Port number.
   3536  *      phy_port  - (IN) Physical Port number.
   3537  * Returns:
   3538  *      SOC_E_XXX
   3539  * Notes:
   3540  *      Assumes port is disabled.
   3541  *      Assumes caller has checked that PortCtrl was initialized.
   3542  *      SOC_INFO SW data structure has been updated.
   3543  */
   3544 int
   3545 soc_esw_portctrl_pgw_reconfigure(int unit, soc_port_t port,
   3546                                  int phy_port,
   3547                                  soc_esw_portctrl_pgw_t *pgw_data)
   3548 {
   3549 #ifdef PORTMOD_SUPPORT
   3550     portmod_port_mode_info_t info;
   3551 
   3552     portmod_port_mode_info_t_init(unit, &info);
   3553 
   3554     info.cur_mode = pgw_data->mode;
   3555     info.lanes = pgw_data->lanes;
   3556     info.port_index = pgw_data->port_index;
   3557 
   3558     pgw_data->flags = PORTMOD_PORT_PGW_CONFIGURE;
   3559 
   3560     /* Note this portmod API requires logical port */
   3561     PORTMOD_IF_ERROR_RETURN(portmod_port_pgw_reconfig(unit, port, &info,
   3562                                              phy_port, pgw_data->flags));
   3563 
   3564     return SOC_E_NONE;
   3565 #else  /* PORTMOD_SUPPORT */
   3566     return SOC_E_UNAVAIL;
   3567 #endif /* PORTMOD_SUPPORT */
   3568 }
   3569 
   3570 /*
   3571  * Function:
   3572  *      soc_esw_portctrl_duplex_get
   3573  * Purpose:
   3574  *      Get the port duplex settings
   3575  * Parameters:
   3576  *      unit - StrataSwitch Unit #.
   3577  *      port - StrataSwitch port #.
   3578  *      duplex - (OUT) Duplex setting, one of SOC_PORT_DUPLEX_xxx
   3579  * Returns:
   3580  *      BCM_E_NONE
   3581  *      BCM_E_XXX
   3582  */
   3583 int
   3584 soc_esw_portctrl_duplex_get(int unit, soc_port_t port, int *duplex)
   3585 {
   3586 #ifdef PORTMOD_SUPPORT
   3587     int rv = SOC_E_NONE;
   3588     portctrl_pport_t pport;
   3589     int port_duplex;
   3590     int is_legacy_phy_present;
   3591     int is_macsec_enabled;
   3592 
   3593     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3594 
   3595     PORTCTRL_PORT_TO_PPORT(port, pport);
   3596 
   3597     SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &is_legacy_phy_present));
   3598 
   3599     is_macsec_enabled = soc_property_port_get(unit, pport, spn_MACSEC_ENABLE, 0);
   3600 
   3601     if (is_legacy_phy_present && is_macsec_enabled) {
   3602         rv = portmod_port_legacy_duplex_get(unit, pport, &port_duplex);
   3603     } else {
   3604         rv = portmod_port_duplex_get(unit, pport, &port_duplex);
   3605     }
   3606 
   3607     if (PORTMOD_SUCCESS(rv)) {
   3608         *duplex = port_duplex ? SOC_PORT_DUPLEX_FULL : SOC_PORT_DUPLEX_HALF;
   3609     } else {
   3610         *duplex = SOC_PORT_DUPLEX_FULL;
   3611     }
   3612 
   3613     return rv;
   3614 #else  /* PORTMOD_SUPPORT */
   3615     return SOC_E_UNAVAIL;
   3616 #endif /* PORTMOD_SUPPORT */
   3617 }
   3618 
   3619 /*
   3620  * Function:
   3621  *      soc_esw_portctrl_duplex_set
   3622  * Purpose:
   3623  *      Set the port duplex
   3624  * Parameters:
   3625  *      unit - StrataSwitch Unit #.
   3626  *      port - StrataSwitch port #.
   3627  *      duplex - Duplex setting, one of SOC_PORT_DUPLEX_xxx
   3628  * Returns:
   3629  *      BCM_E_NONE
   3630  *      BCM_E_XXX
   3631  */
   3632 int
   3633 soc_esw_portctrl_duplex_set(int unit, soc_port_t port, int duplex)
   3634 {
   3635 #ifdef PORTMOD_SUPPORT
   3636     int rv = SOC_E_NONE;
   3637     portctrl_pport_t pport;
   3638     int is_legacy_phy_present;
   3639     int is_macsec_enabled;
   3640 
   3641     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3642 
   3643     PORTCTRL_PORT_TO_PPORT(port, pport);
   3644 
   3645     SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &is_legacy_phy_present));
   3646 
   3647     is_macsec_enabled = soc_property_port_get(unit, pport, spn_MACSEC_ENABLE, 0);
   3648 
   3649     if (is_legacy_phy_present && is_macsec_enabled) {
   3650         rv = portmod_port_legacy_duplex_set(unit, pport, duplex);
   3651     } else {
   3652         rv = portmod_port_duplex_set(unit, pport, duplex);
   3653     }
   3654 
   3655     return rv;
   3656 #else  /* PORTMOD_SUPPORT */
   3657     return SOC_E_UNAVAIL;
   3658 #endif /* PORTMOD_SUPPORT */
   3659 }
   3660 
   3661 
   3662 /*
   3663  * Function:
   3664  *      soc_esw_portctrl_port_fc_config_init
   3665  * Purpose:
   3666  *      Configure default flow control configuration
   3667  *      in the port macro. Depending on the each chip's
   3668  *      support level, we will either have to program
   3669  *      PARALLEL_FC_EN to 1 or 0. Depending on this config
   3670  *      either the serial interface (mmu flow control) or
   3671  *      the parallel interface (for obm flow control) is used.
   3672  *      For devices where the flow control is to be used from
   3673  *      both the interfaces, we need to enable merge mode (and
   3674  *      not configure parallel_fc_en).
   3675  *
   3676  * Parameters:
   3677  *      unit - StrataSwitch Unit #.
   3678  *      port - StrataSwitch port #.
   3679  * Returns:
   3680  *      BCM_E_NONE
   3681  *      BCM_E_XXX
   3682  */
   3683 int
   3684 soc_esw_portctrl_port_fc_config_init(int unit, soc_port_t port)
   3685 {
   3686 #ifdef PORTMOD_SUPPORT
   3687     int rv = SOC_E_NONE;
   3688     portctrl_pport_t pport;
   3689 
   3690     /*
   3691      * Note that MMU uses serial interface (legacy) and OBM uses parallel
   3692      * interface for pause control. If pause from only OBM is required, then
   3693      * we should enable parallel_fc mode. Disabling parallel fc mode enables
   3694      * the legacy serial interface. When pause from both the interfaces are
   3695      * desired, then merge_mode_en should be enabled.
   3696      *
   3697      * For Apache, FC signals from MMU and OBM must be honored for
   3698      * proper flow control handling.
   3699  */
   3700     if (soc_feature(unit, soc_feature_pm_fc_merge_mode) && !IS_QSGMII_PORT(unit, port)) {
   3701         SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3702 
   3703         PORTCTRL_PORT_TO_PPORT(port, pport);
   3704 
   3705         rv = portmod_port_flow_control_set(unit, pport,
   3706                                            1 /* merge_mode  */,
   3707                                            0 /* parallel_fc */);
   3708     }
   3709 
   3710     return rv;
   3711 #else  /* PORTMOD_SUPPORT */
   3712     return SOC_E_UNAVAIL;
   3713 #endif /* PORTMOD_SUPPORT */
   3714 }
   3715 
   3716 
   3717 int
   3718 soc_esw_portctrl_frame_max_set(int unit, soc_port_t port, int size)
   3719 {
   3720 #ifdef PORTMOD_SUPPORT
   3721     int rv = SOC_E_NONE;
   3722     portctrl_pport_t pport;
   3723     int max_size = SOC_INFO(unit).max_mtu;
   3724     soc_reg_t reg;
   3725     egr_mtu_entry_t mtu;
   3726     uint32 rval;
   3727     uint32 mtu_size;
   3728 
   3729     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3730 
   3731     PORTCTRL_PORT_TO_PPORT(port, pport);
   3732 
   3733     if (size < 0) {
   3734         return SOC_E_PARAM;
   3735     }
   3736 
   3737     if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)
   3738         || IS_CE_PORT(unit, port)
   3739         || IS_CDE_PORT(unit, port)
   3740         || (IS_C_PORT(unit, port) && IS_E_PORT(unit,port))) {
   3741         /* For VLAN tagged packets */
   3742         size += 4;
   3743     }
   3744 
   3745     if (size > max_size) {
   3746         return SOC_E_PARAM;
   3747     }
   3748 
   3749     rv = portmod_port_max_packet_size_set(unit, pport, size);
   3750 
   3751     if (PORTMOD_SUCCESS(rv)) {
   3752         soc_mem_t mem = EGR_MTUm;
   3753         if (SOC_MEM_IS_VALID(unit, mem)) {
   3754             if (soc_feature(unit, soc_feature_egr_all_profile)) {
   3755                 int field_cnt = 0;
   3756                 soc_field_t fields[2];
   3757                 uint32 values[2];
   3758 
   3759                 fields[field_cnt] = MTU_SIZEf;
   3760                 values[field_cnt++] = size;
   3761                 fields[field_cnt] = MTU_ENABLEf;
   3762                 values[field_cnt++] = 1;
   3763                 rv = bcm_esw_port_egr_lport_fields_set(unit, port, mem,
   3764                                                        field_cnt, fields, values);
   3765             } else {
   3766                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, &mtu);
   3767             if (SOC_SUCCESS(rv)) {
   3768                 mtu_size = size;
   3769                     soc_mem_field32_set(unit, mem, &mtu, MTU_SIZEf, mtu_size);
   3770                 if (soc_mem_field_valid(unit, EGR_MTUm, MTU_ENABLEf)) {
   3771                     soc_mem_field32_set(unit, EGR_MTUm, &mtu, MTU_ENABLEf, 1);
   3772                 }
   3773                     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, port, &mtu);
   3774                 }
   3775             }
   3776         } else {
   3777             reg = SOC_REG_IS_VALID(unit, EGR_MTUr) ? EGR_MTUr : EGR_MTU_SIZEr;
   3778 
   3779             rv = soc_reg32_get(unit, reg, port, 0, &rval);
   3780             if (SOC_SUCCESS(rv)) {
   3781                 soc_reg_field_set(unit, reg, &rval, MTU_SIZEf, size);
   3782                 if (soc_reg_field_valid(unit, reg, MTU_ENABLEf)) {
   3783                     soc_reg_field_set(unit, reg, &rval, MTU_ENABLEf, 1);
   3784                 }
   3785                 rv = soc_reg32_set(unit, reg, port, 0, rval);
   3786             }
   3787         }
   3788     }
   3789 
   3790     return rv;
   3791 
   3792 #else  /* PORTMOD_SUPPORT */
   3793     return SOC_E_UNAVAIL;
   3794 #endif /* PORTMOD_SUPPORT */
   3795 }
   3796 
   3797 
   3798 int
   3799 soc_esw_portctrl_frame_max_get(int unit, soc_port_t port, int *size)
   3800 {
   3801 #ifdef PORTMOD_SUPPORT
   3802     int rv = SOC_E_NONE;
   3803     portctrl_pport_t pport;
   3804 
   3805     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3806 
   3807     PORTCTRL_PORT_TO_PPORT(port, pport);
   3808 
   3809     rv = portmod_port_max_packet_size_get(unit, pport, size);
   3810 
   3811     if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)
   3812         || IS_CE_PORT(unit, port)
   3813         || IS_CDE_PORT(unit, port)
   3814         || (IS_C_PORT(unit, port) && IS_E_PORT(unit,port))) {
   3815         /* For VLAN tagged packets */
   3816         *size -= 4;
   3817     }
   3818 
   3819     return rv;
   3820 #else  /* PORTMOD_SUPPORT */
   3821     return SOC_E_UNAVAIL;
   3822 #endif /* PORTMOD_SUPPORT */
   3823 }
   3824 
   3825 int
   3826 soc_esw_portctrl_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx)
   3827 {
   3828 #ifdef PORTMOD_SUPPORT
   3829     int rv;
   3830     portctrl_pport_t pport;
   3831     portmod_pause_control_t control;
   3832 
   3833     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3834 
   3835     PORTCTRL_PORT_TO_PPORT(port, pport);
   3836 
   3837     portmod_pause_control_t_init(unit, &control);
   3838 
   3839     rv = portmod_port_pause_control_get(unit, pport, &control);
   3840     if (PORTMOD_SUCCESS(rv)) {
   3841         control.tx_enable = pause_tx ? TRUE : FALSE;
   3842         control.rx_enable = pause_rx ? TRUE : FALSE;
   3843         rv = portmod_port_pause_control_set(unit, pport, &control);
   3844     }
   3845     return rv;
   3846 #else  /* PORTMOD_SUPPORT */
   3847     return SOC_E_UNAVAIL;
   3848 #endif /* PORTMOD_SUPPORT */
   3849 }
   3850 
   3851 int
   3852 soc_esw_portctrl_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx)
   3853 {
   3854 #ifdef PORTMOD_SUPPORT
   3855     int rv;
   3856     portctrl_pport_t pport;
   3857     portmod_pause_control_t control;
   3858 
   3859     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3860 
   3861     PORTCTRL_PORT_TO_PPORT(port, pport);
   3862 
   3863     portmod_pause_control_t_init(unit, &control);
   3864 
   3865     rv = portmod_port_pause_control_get(unit, pport, &control);
   3866     if (PORTMOD_SUCCESS(rv)) {
   3867         *pause_tx = control.tx_enable ? TRUE : FALSE;
   3868         *pause_rx = control.rx_enable ? TRUE : FALSE;
   3869     }
   3870     return rv;
   3871 #else  /* PORTMOD_SUPPORT */
   3872     return SOC_E_UNAVAIL;
   3873 #endif /* PORTMOD_SUPPORT */
   3874 }
   3875 
   3876 /*
   3877  * Function:
   3878  *      soc_esw_portctrl_ifg_set
   3879  * Purpose:
   3880  *      Set Inter Frame Gap
   3881  * Parameters:
   3882  *      unit    - StrataSwitch unit number.
   3883  *      port    - Port.
   3884  *      speed   - Speed
   3885  *      duplex  - Duplex Setting
   3886  *      ifg     - InterFrame Gap
   3887  * Returns:
   3888  *      BCM_E_NONE
   3889  *      BCM_E_INTERNAL - internal error.
   3890  */
   3891 int
   3892 soc_esw_portctrl_ifg_set(int unit, soc_port_t port, int speed,
   3893                          soc_port_duplex_t duplex, int ifg)
   3894 {
   3895 #ifdef PORTMOD_SUPPORT
   3896     int rv = SOC_E_NONE;
   3897     portctrl_pport_t pport;
   3898     soc_ipg_t *si;
   3899     int real_ifg = 0;
   3900     int         cur_speed;
   3901     int         cur_duplex;
   3902     portmod_port_ability_t ability;
   3903     uint32      pa_flag;
   3904 #ifdef PORTMOD_PM8X50_SUPPORT
   3905     portmod_dispatch_type_t pm_type = portmodDispatchTypeCount;
   3906     int phy_port;
   3907 #endif
   3908 
   3909     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3910 
   3911     PORTCTRL_PORT_TO_PPORT(port, pport);
   3912 
   3913 #ifdef PORTMOD_PM8X50_SUPPORT
   3914     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3915     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   3916          SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_type_get) {
   3917         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_type_get(
   3918                                         unit, phy_port, ((int *)&pm_type));
   3919     }
   3920 
   3921     /* PM8x50 doesn't support ability local get */
   3922     if (pm_type != portmodDispatchTypePm8x50)
   3923 #endif
   3924     {
   3925     pa_flag = SOC_PA_SPEED(speed); 
   3926     sal_memset(&ability, 0, sizeof(portmod_port_ability_t));
   3927 
   3928     rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &ability);
   3929     SOC_IF_ERROR_RETURN(rv);
   3930 
   3931     if (!(pa_flag & ability.speed_full_duplex)) {
   3932         return SOC_E_PARAM;
   3933     }
   3934     }
   3935 
   3936     SOC_IF_ERROR_RETURN(portmod_port_duplex_get(unit, pport, &cur_duplex));
   3937     SOC_IF_ERROR_RETURN(portmod_port_speed_get(unit, pport, &cur_speed));
   3938 
   3939     /* XLMAC_MODE supports only 4 speeds with 4 being max as LINK_10G_PLUS */ 
   3940     if ((speed > 10000) && (cur_speed == 10000)) { 
   3941         cur_speed = speed; 
   3942     } 
   3943 
   3944     if (cur_speed == speed &&
   3945         cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) {
   3946             rv = portmod_port_tx_average_ipg_set (unit, pport, ifg);
   3947             SOC_IF_ERROR_RETURN(rv);
   3948     }
   3949 
   3950     if (PORTMOD_SUCCESS(rv)) {
   3951         SOC_IF_ERROR_RETURN(portmod_port_tx_average_ipg_get(unit, pport, &real_ifg));
   3952         si = &SOC_PERSIST(unit)->ipg[port];
   3953         if (IS_HG_PORT(unit, port)) {
   3954             si->fd_hg = real_ifg ;
   3955         } else {
   3956             si->fd_xe = real_ifg ;
   3957         }
   3958     }
   3959 
   3960     return rv;
   3961 #else /* PORTMOD_SUPPORT */
   3962     return SOC_E_UNAVAIL;
   3963 #endif /* PORTMOD_SUPPORT */
   3964 }
   3965 
   3966 /*
   3967  * Function:
   3968  *      soc_esw_portctrl_ifg_get
   3969  * Purpose:
   3970  *      Get Inter Frame Gap
   3971  * Parameters:
   3972  *      unit    - StrataSwitch unit number.
   3973  *      port    - Port.
   3974  *      speed   - Speed
   3975  *      duplex  - Duplex Setting
   3976  *      ifg     - InterFrame Gap
   3977  * Returns:
   3978  *      BCM_E_NONE
   3979  *      BCM_E_INTERNAL - internal error.
   3980  */
   3981 int
   3982 soc_esw_portctrl_ifg_get(int unit, soc_port_t port, int speed,
   3983                          soc_port_duplex_t duplex, int *ifg)
   3984 {
   3985 #ifdef PORTMOD_SUPPORT
   3986     int rv = SOC_E_NONE;
   3987     soc_ipg_t  *si;
   3988     uint32      pa_flag;
   3989     portctrl_pport_t pport;
   3990     portmod_port_ability_t ability;
   3991 
   3992     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit));
   3993 
   3994     PORTCTRL_PORT_TO_PPORT(port, pport);
   3995 
   3996     if (!SOC_IS_TOMAHAWK3(unit)) {
   3997     pa_flag = SOC_PA_SPEED(speed);
   3998     sal_memset(&ability, 0, sizeof(portmod_port_ability_t));
   3999 
   4000     rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &ability);
   4001     SOC_IF_ERROR_RETURN(rv);
   4002 
   4003     if (!(pa_flag & ability.speed_full_duplex)) {
   4004         return SOC_E_PARAM;
   4005     }
   4006     }
   4007     si = &SOC_PERSIST(unit)->ipg[port];
   4008     if (IS_HG_PORT(unit, port)) {
   4009         *ifg = si->fd_hg;
   4010     } else {
   4011         *ifg = si->fd_xe;
   4012     }
   4013 
   4014     return rv;
   4015 #else /* PORTMOD_SUPPORT */
   4016     return SOC_E_UNAVAIL;
   4017 #endif /* PORTMOD_SUPPORT */
   4018 }
   4019 
   4020 /*
   4021  * Function:
   4022  *      soc_portctrl_led_chain_config
   4023  * Purpose:
   4024  *      Set the port mode
   4025  * Parameters:
   4026  *      unit - SOC Unit #
   4027  *      port - Port #
   4028  *      value - Intra-Port delay for each subports in PORT block
   4029  * Returns:
   4030  *      SOC_E_XXX
   4031  */
   4032 int
   4033 soc_portctrl_led_chain_config(int unit, int port, int value)
   4034 {
   4035 #ifdef PORTMOD_SUPPORT
   4036     return portmod_port_led_chain_config(unit, port, value);
   4037 
   4038 #else  /* PORTMOD_SUPPORT */
   4039     return SOC_E_UNAVAIL;
   4040 #endif /* PORTMOD_SUPPORT */
   4041 }
   4042 
   4043 /*
   4044  * Function:
   4045  *      soc_portctrl_phy_name_get
   4046  * Purpose:
   4047  *      Get the phy name of the given port
   4048  * Parameters:
   4049  *      unit - SOC Unit #.
   4050  *      port - Port #.
   4051  *      phy_name - PHY name string. Note: The max length of PHY name is 32.
   4052  * Returns:
   4053  *      SOC_E_XXX
   4054  */
   4055 int
   4056 soc_portctrl_phy_name_get(int unit, int port, char *phy_name)
   4057 {
   4058 #ifdef PORTMOD_SUPPORT
   4059     phymod_core_access_t core_acc;
   4060     phymod_core_info_t core_info;
   4061     int nof_cores = 0;
   4062     char    *pname = NULL, namelen;
   4063     portmod_port_diag_info_t diag_info;
   4064     int phy = 0, core_num = 0, pcount = 0;
   4065     int range_start = 0;
   4066     int rv;
   4067 
   4068     if (NULL == phy_name) {
   4069         return SOC_E_PARAM;
   4070     }
   4071     sal_memset(&diag_info, 0, sizeof(portmod_port_diag_info_t));
   4072     sal_memset(phy_name, 0, sizeof(char)*SOC_PM_PHY_NAME_MAX_LEN);
   4073 
   4074     portmod_port_core_access_get(unit, port, -1, 1, &core_acc, &nof_cores, NULL);
   4075     if (nof_cores == 0) {
   4076         LOG_VERBOSE(BSL_LS_SOC_PORT,
   4077                  (BSL_META_UP(unit, port,
   4078                               "ERROR: getting port%d information.\n"),
   4079                   port));
   4080         sal_snprintf(phy_name, SOC_PM_PHY_NAME_MAX_LEN, "%s", "<nophy>");
   4081         return SOC_E_NONE;
   4082     }
   4083 
   4084     /*
   4085      * COVERITY
   4086      *
   4087      * It doesn't check return value.
   4088      */
   4089     /* coverity[check_return] */
   4090     phymod_core_info_get(&core_acc, &core_info);
   4091     rv = portmod_port_diag_info_get(unit, port, &diag_info);
   4092     if (SOC_FAILURE(rv)) {
   4093         return rv;
   4094     }
   4095     rv = portmod_port_core_num_get(unit, port, &core_num);
   4096     if (SOC_FAILURE(rv)) {
   4097         return rv;
   4098     }
   4099 
   4100     PORTMOD_PBMP_ITER(diag_info.phys, phy){
   4101         range_start = phy;
   4102         break;
   4103     }
   4104 
   4105     PORTMOD_PBMP_COUNT(diag_info.phys, pcount);
   4106     pname = phymod_core_version_t_mapping[core_info.core_version].key;
   4107     namelen = strlen(pname);
   4108 
   4109     sal_snprintf(phy_name, SOC_PM_PHY_NAME_MAX_LEN, "%s", pname);
   4110     sal_snprintf(phy_name+namelen, SOC_PM_PHY_NAME_MAX_LEN-namelen, "/%02d/", core_num);
   4111 
   4112     pname = phy_name+strlen(phy_name);
   4113     if (pcount == 4)
   4114        sal_snprintf(pname, SOC_PM_PHY_NAME_MAX_LEN-namelen-4, "%d", pcount);
   4115     else if (pcount == 2)
   4116        sal_snprintf(pname, SOC_PM_PHY_NAME_MAX_LEN-namelen-4, "%d-%d", (range_start-1)%4, ((range_start-1)%4)+1);
   4117     else
   4118        sal_snprintf(pname, SOC_PM_PHY_NAME_MAX_LEN-namelen-4, "%d", (range_start-1)%4);
   4119 
   4120     return SOC_E_NONE;
   4121 #else  /* PORTMOD_SUPPORT */
   4122     return SOC_E_UNAVAIL;
   4123 #endif /* PORTMOD_SUPPORT */
   4124 }
   4125 
   4126 /*
   4127  * Function:
   4128  *      soc_portctrl_port_mode_set
   4129  * Purpose:
   4130  *      Set the port mode
   4131  * Parameters:
   4132  *      unit - SOC Unit #
   4133  *      port - Port #
   4134  *      mode - port mode
   4135  * Returns:
   4136  *      SOC_E_XXX
   4137  */
   4138 int
   4139 soc_portctrl_port_mode_set(int unit, int port, int mode)
   4140 {
   4141 #ifdef PORTMOD_SUPPORT
   4142     portmod_port_mode_info_t port_mode_info;
   4143 
   4144     portmod_port_mode_info_t_init(unit, &port_mode_info);
   4145 
   4146     port_mode_info.cur_mode = mode;
   4147 
   4148     return portmod_port_mode_set(unit, port, &port_mode_info);
   4149 
   4150 #else  /* PORTMOD_SUPPORT */
   4151     return SOC_E_UNAVAIL;
   4152 #endif /* PORTMOD_SUPPORT */
   4153 }
   4154 
   4155 /*
   4156  * Function:
   4157  *      soc_portctrl_port_mode_get
   4158  * Purpose:
   4159  *      Get the port mode
   4160  * Parameters:
   4161  *      unit - SOC Unit #
   4162  *      port - Port #
   4163  *      mode - port mode
   4164  *      lanes - lanes of the port
   4165  * Returns:
   4166  *      SOC_E_XXX
   4167  */
   4168 int
   4169 soc_portctrl_port_mode_get(int unit, int port, int *mode, int *lanes)
   4170 {
   4171 #ifdef PORTMOD_SUPPORT
   4172     int rv;
   4173     portmod_port_mode_info_t port_mode_info;
   4174 
   4175     portmod_port_mode_info_t_init(unit, &port_mode_info);
   4176 
   4177     rv = portmod_port_mode_get(unit, port, &port_mode_info);
   4178 
   4179     if (SOC_SUCCESS(rv)) {
   4180         *mode = port_mode_info.cur_mode;
   4181         *lanes = port_mode_info.lanes;
   4182     }
   4183 
   4184     return rv;
   4185 
   4186 #else  /* PORTMOD_SUPPORT */
   4187     return SOC_E_UNAVAIL;
   4188 #endif /* PORTMOD_SUPPORT */
   4189 }
   4190 
   4191 /*
   4192  * Function:
   4193  *      soc_portctrl_phy_control_set
   4194  * Purpose:
   4195  *      Set PHY specific configuration
   4196  * Parameters:
   4197  *      unit - SOC Unit #.
   4198  *      port - Port number.
   4199  *      phyn - Phy number
   4200  *      phy_lane - Lane number
   4201  *      sys  - Control set to be applied 
   4202  *             on system side(1)or line side(0).
   4203  *      phy_ctrl - PHY control type to change
   4204  *      value    - New setting for the PHY control
   4205  * Returns:
   4206  *      SOC_E_XXX
   4207  */
   4208 int
   4209 soc_portctrl_phy_control_set(int unit, soc_port_t port, int phyn,
   4210                              int phy_lane, int sys_side,
   4211                              soc_phy_control_t phy_ctrl, uint32 value)
   4212 {
   4213 #ifdef PORTMOD_SUPPORT
   4214     phymod_phy_access_t pm_acc;
   4215     phymod_phy_access_t pm_acc12[3];
   4216     uint32_t saved_lane_mask[3];    
   4217     int i=0;
   4218     int num_pm_acc;
   4219     portmod_access_get_params_t params;
   4220     int is_legacy_ext_phy_present = 0;
   4221     int per_lane_ctrl = 1;
   4222     int ref_clk;
   4223     int pport;
   4224     portmod_dispatch_type_t pm_type;
   4225     uint32_t port_dynamic_state = 0;
   4226 
   4227     portmod_access_get_params_t_init(unit, &params);
   4228 
   4229     /*  
   4230         phyn ==  0  ( outermost )
   4231         phyn ==  1  ( internal )
   4232         phyn ==  >1 ( ext phy )
   4233 
   4234         portmod internal        
   4235         phyn == -1 (outermost )
   4236         phyn == 0 ( internal )  
   4237         phyn == >=1 external phy#
   4238     */
   4239 
   4240     if( phyn >= 1) {
   4241         params.phyn = phyn-1;
   4242     } else { 
   4243         params.phyn = -1;
   4244     }
   4245 
   4246     params.lane = phy_lane;
   4247     params.sys_side = (sys_side == 1) ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE;
   4248     params.apply_lane_mask = 1;
   4249 
   4250     if (IS_C_PORT(unit, port) ||
   4251         (IS_CXX_PORT(unit, port) && IS_CL_PORT(unit, port))) {
   4252         SOC_IF_ERROR_RETURN
   4253             (portmod_port_phy_lane_access_get(unit, port, &params,
   4254                                               3, &pm_acc12[0], &num_pm_acc, NULL));
   4255         /* if the phys  are identical, consolidate lane mask and run  once. */
   4256         if ( num_pm_acc == 3 ){
   4257             for(i=0; i < num_pm_acc; i++) {
   4258                 saved_lane_mask[i] = pm_acc12[i].access.lane_mask;
   4259                 pm_acc12[i].access.lane_mask = 0; /* need this to do compare. */
   4260             }
   4261 
   4262             if( !sal_memcmp( &pm_acc12[0],&pm_acc12[1], sizeof(phymod_phy_access_t)) &&
   4263                 !sal_memcmp( &pm_acc12[0],&pm_acc12[2], sizeof(phymod_phy_access_t))){
   4264                 pm_acc12[0].access.lane_mask = ( saved_lane_mask[0]| saved_lane_mask[1]| saved_lane_mask[2]);
   4265                 phymod_access_t_init(&pm_acc12[1].access);
   4266                 phymod_access_t_init(&pm_acc12[2].access);
   4267                 /* cli_out("Consolidating entries.\n");*/
   4268                 num_pm_acc = 1;
   4269             } else {
   4270                 /* restore lane mask */
   4271                 for(i=0; i < num_pm_acc; i++) {
   4272                     pm_acc12[i].access.lane_mask = saved_lane_mask[i];
   4273                 }
   4274             }
   4275         }
   4276 
   4277     } else {
   4278         SOC_IF_ERROR_RETURN
   4279             (portmod_port_phy_lane_access_get(unit, port, &params,
   4280                                               1, &pm_acc, &num_pm_acc, NULL));
   4281     }
   4282 
   4283     if (num_pm_acc == 0) {
   4284         return SOC_E_FAIL;
   4285     }
   4286 
   4287     SOC_IF_ERROR_RETURN
   4288         (portmod_port_ref_clk_get(unit, port, &ref_clk));
   4289 
   4290     switch (phy_ctrl) {
   4291         /* Not per lane control */
   4292         case SOC_PHY_CONTROL_LANE_SWAP:
   4293             per_lane_ctrl = 0;
   4294             break;
   4295         default:
   4296             break;
   4297     }
   4298 
   4299     /* only check if phy is legacy when phyn is not 0 (in portmod internal phy is always not legacy) */
   4300     if(params.phyn != 0) {
   4301       SOC_IF_ERROR_RETURN(
   4302         portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_ext_phy_present));
   4303     }
   4304 
   4305     if(!is_legacy_ext_phy_present) {
   4306         if (IS_C_PORT(unit, port) ||
   4307             (IS_CXX_PORT(unit, port) && IS_CL_PORT(unit, port))) {
   4308             if (phy_ctrl == SOC_PHY_CONTROL_CL72) {
   4309                 SOC_IF_ERROR_RETURN
   4310                     (portmod_port_pm_type_get(unit, port, &pport, &pm_type));
   4311 #if defined(PORTMOD_PM12X10_SUPPORT)
   4312                 if (pm_type == portmodDispatchTypePm12x10) {
   4313                     SOC_IF_ERROR_RETURN (
   4314                         portmod_port_cl72_set(unit, port, value));
   4315                     return SOC_E_NONE;
   4316                 }
   4317 #endif
   4318             }
   4319             SOC_IF_ERROR_RETURN(
   4320                 soc_port_control_set_wrapper(unit, ref_clk, per_lane_ctrl,
   4321                                              &pm_acc12[0], num_pm_acc, phy_ctrl, value));
   4322         } else {
   4323             if (phy_ctrl != SOC_PHY_CONTROL_AUTONEG_MODE) {
   4324             SOC_IF_ERROR_RETURN(
   4325                 soc_port_control_set_wrapper(unit, ref_clk, per_lane_ctrl,
   4326                                              &pm_acc, 1, phy_ctrl, value));
   4327         }
   4328         }
   4329     } else {
   4330         SOC_IF_ERROR_RETURN(
   4331             portmod_port_ext_phy_control_set(unit, port, phyn, phy_lane, sys_side, 
   4332                                              phy_ctrl, value));
   4333     }
   4334 
   4335     /* update the state in portmod */
   4336     switch(phy_ctrl) {
   4337         case SOC_PHY_CONTROL_AUTONEG_MODE:
   4338              PORTMOD_PORT_AUTONEG_MODE_UPDATED_SET(port_dynamic_state);
   4339              port_dynamic_state |= value << 16;
   4340              portmod_port_update_dynamic_state(unit, port, port_dynamic_state);
   4341         break;
   4342         case SOC_PHY_CONTROL_TX_FIR_PRE:
   4343         case SOC_PHY_CONTROL_TX_FIR_MAIN:
   4344         case SOC_PHY_CONTROL_TX_FIR_POST:
   4345         case SOC_PHY_CONTROL_TX_FIR_POST2:
   4346         case SOC_PHY_CONTROL_TX_FIR_POST3:
   4347         case SOC_PHY_CONTROL_PREEMPHASIS:
   4348         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4349             PORTMOD_PORT_DEFAULT_TX_PARAMS_UPDATED_SET(port_dynamic_state);
   4350             portmod_port_update_dynamic_state(unit, port, port_dynamic_state);
   4351         break;
   4352         default:
   4353             break;
   4354     }
   4355     
   4356     return SOC_E_NONE;
   4357 
   4358 #else  /* PORTMOD_SUPPORT */
   4359     return SOC_E_UNAVAIL;
   4360 #endif /* PORTMOD_SUPPORT */
   4361 }
   4362 
   4363 /*
   4364  * Function:
   4365  *      soc_portctrl_phy_control_get
   4366  * Purpose:
   4367  *      Get PHY specific configuration
   4368  * Parameters:
   4369  *      unit - SOC Unit #.
   4370  *      port - Port number.
   4371  *      phyn - Phy number
   4372  *      phy_lane - Lane number
   4373  *      sys  - Control get to be applied
   4374  *             on system side(1)or line side(0).
   4375  *      phy_ctrl - PHY control type to read
   4376  *      value    - Current setting for the PHY control
   4377  * Returns:
   4378  *      SOC_E_XXX
   4379  */
   4380 int
   4381 soc_portctrl_phy_control_get(int unit, soc_port_t port, int phyn,
   4382                              int phy_lane, int sys_side,
   4383                              soc_phy_control_t phy_ctrl, uint32 *value)
   4384 {
   4385 #ifdef PORTMOD_SUPPORT
   4386     phymod_phy_access_t pm_acc, pm12_acc[3];
   4387     uint32_t saved_lane_mask[3];    
   4388     int i=0;
   4389     int num_pm_acc;
   4390     portmod_access_get_params_t params;
   4391     int is_legacy_ext_phy = 0;
   4392     int per_lane_ctrl = 1;
   4393     int ref_clk;
   4394 
   4395     portmod_access_get_params_t_init(unit, &params);
   4396 
   4397     /*
   4398         phyn == -1  ( outermost phy GPORT 0 get converted to -1)
   4399         phyn ==  1  ( internal )
   4400         phyn ==  >1 ( ext phy )
   4401 
   4402         portmod internal
   4403         phyn == -1 (outermost )
   4404         phyn == 0 ( internal )
   4405         phyn == >=1 external phy#
   4406     */
   4407     if( phyn >= 1) {
   4408         params.phyn = phyn-1;
   4409     } else  { 
   4410         params.phyn = -1;
   4411     } 
   4412  
   4413     params.lane = phy_lane;
   4414     params.apply_lane_mask = 1;
   4415     params.sys_side = (sys_side == 1) ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE;
   4416 
   4417     if (IS_C_PORT(unit, port) ||
   4418         (IS_CXX_PORT(unit, port) && IS_CL_PORT(unit, port))) {
   4419         SOC_IF_ERROR_RETURN
   4420             (portmod_port_phy_lane_access_get(unit, port, &params,
   4421                                           3, &pm12_acc[0], &num_pm_acc, NULL));
   4422         
   4423         /* if the phys  are identical, consolidate lane mask and run  once. */
   4424         if ( num_pm_acc == 3 ){
   4425             for(i=0; i < num_pm_acc; i++) {
   4426                 saved_lane_mask[i] = pm12_acc[i].access.lane_mask;
   4427                 pm12_acc[i].access.lane_mask = 0; /* need this to do compare. */
   4428             }
   4429             if( !sal_memcmp( &pm12_acc[0],&pm12_acc[1], sizeof(phymod_phy_access_t)) &&
   4430                 !sal_memcmp( &pm12_acc[0],&pm12_acc[2], sizeof(phymod_phy_access_t))){
   4431                 pm12_acc[0].access.lane_mask = ( saved_lane_mask[0]| saved_lane_mask[1]| saved_lane_mask[2]);
   4432                 phymod_access_t_init(&pm12_acc[1].access); 
   4433                 phymod_access_t_init(&pm12_acc[2].access); 
   4434                 /* cli_out("Consolidating entries.\n");*/
   4435                 num_pm_acc = 1;
   4436             } else {
   4437                 /* restore lane mask */
   4438                 for(i=0; i < num_pm_acc; i++) {
   4439                     pm12_acc[i].access.lane_mask = saved_lane_mask[i];
   4440                 }
   4441             }
   4442         }
   4443     } else {
   4444         SOC_IF_ERROR_RETURN
   4445             (portmod_port_phy_lane_access_get(unit, port, &params,
   4446                                           1,  &pm_acc, &num_pm_acc, NULL));
   4447     }
   4448     if (IS_CPRI_PORT(unit, port)) {
   4449         if(phy_ctrl==SOC_PHY_CONTROL_EEE) {
   4450             return SOC_E_UNAVAIL;
   4451         }
   4452     }
   4453     if (num_pm_acc == 0) {
   4454         return SOC_E_FAIL;
   4455     }
   4456 
   4457     SOC_IF_ERROR_RETURN
   4458         (portmod_port_ref_clk_get(unit, port, &ref_clk));
   4459 
   4460     switch (phy_ctrl) {
   4461         /* Not per lane control */
   4462         case SOC_PHY_CONTROL_LANE_SWAP:
   4463             per_lane_ctrl = 0;
   4464             break;
   4465         case SOC_PHY_CONTROL_FEC_CORRECTED_CODEWORD_COUNT:
   4466             per_lane_ctrl = 0;
   4467             break;
   4468         case SOC_PHY_CONTROL_FEC_UNCORRECTED_CODEWORD_COUNT:
   4469             per_lane_ctrl = 0;
   4470             break;
   4471         default:
   4472             break;
   4473     }
   4474 
   4475     /* only check if phy is legacy when phyn is not 0 (in portmod internal phy is always not legacy) */
   4476     if(params.phyn != 0) {
   4477         SOC_IF_ERROR_RETURN(
   4478             portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_ext_phy));
   4479     }
   4480 
   4481     if (!is_legacy_ext_phy) {
   4482         if (IS_C_PORT(unit, port) ||
   4483             (IS_CXX_PORT(unit, port) && IS_CL_PORT(unit, port))) {
   4484             SOC_IF_ERROR_RETURN(
   4485                 soc_port_control_get_wrapper(unit, ref_clk, per_lane_ctrl,
   4486                                              &pm12_acc[0], num_pm_acc, phy_ctrl, value));
   4487         } else {
   4488             SOC_IF_ERROR_RETURN(
   4489                 soc_port_control_get_wrapper(unit, ref_clk, per_lane_ctrl,
   4490                                              &pm_acc, 1, phy_ctrl, value));
   4491         }
   4492     } else {
   4493         /* Legacy ext PHYs do not support CL91, below we return SOC_E_UNAVAIL */
   4494         if (phy_ctrl == SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION_CL91) {
   4495             return SOC_E_UNAVAIL;
   4496         }
   4497 
   4498         SOC_IF_ERROR_RETURN(
   4499             portmod_port_ext_phy_control_get(unit, port, phyn, phy_lane, sys_side, 
   4500                                              phy_ctrl, value));
   4501     }
   4502 
   4503     return SOC_E_NONE;
   4504 
   4505 #else  /* PORTMOD_SUPPORT */
   4506     return SOC_E_UNAVAIL;
   4507 #endif /* PORTMOD_SUPPORT */
   4508 }
   4509 
   4510 /*
   4511  * Function:
   4512  *      soc_portctrl_phy_timesync_config_set
   4513  * Purpose:
   4514  *      Set timesync config
   4515  * Parameters:
   4516  *      unit - SOC Unit #.
   4517  *      port - Port number.
   4518  *      phyn - Phy number
   4519  * Returns:
   4520  *      SOC_E_XXX
   4521  */
   4522 int
   4523 soc_portctrl_phy_timesync_config_set(int unit, soc_port_t port,
   4524                                      soc_port_phy_timesync_config_t *conf)
   4525 {
   4526 #ifdef PORTMOD_SUPPORT
   4527     int         rv;
   4528 
   4529     INT_MCU_LOCK(unit);
   4530     rv = portmod_port_timesync_config_set(unit, port, conf);
   4531     INT_MCU_UNLOCK(unit);
   4532 
   4533     if (SOC_FAILURE(rv)) {
   4534         LOG_WARN(BSL_LS_SOC_PORT,
   4535                  (BSL_META_U(unit,
   4536                              "_soc_portctrl_phy_timesync_config_set failed %d\n"), rv));
   4537     }
   4538     return rv;
   4539 #else  /* PORTMOD_SUPPORT */
   4540     return SOC_E_UNAVAIL;
   4541 #endif /* PORTMOD_SUPPORT */
   4542 }
   4543 
   4544 /*
   4545  * Function:
   4546  *      soc_portctrl_phy_timesync_config_set
   4547  * Purpose:
   4548  *      Set timesync config
   4549  * Parameters:
   4550  *      unit - SOC Unit #.
   4551  *      port - Port number.
   4552  *      phyn - Phy number
   4553  * Returns:
   4554  *      SOC_E_XXX
   4555  */
   4556 int
   4557 soc_portctrl_phy_timesync_config_get(int unit, soc_port_t port,
   4558                                      soc_port_phy_timesync_config_t *conf)
   4559 {
   4560 #ifdef PORTMOD_SUPPORT
   4561     int         rv;
   4562 
   4563     INT_MCU_LOCK(unit);
   4564     rv = portmod_port_timesync_config_get(unit, port, conf);
   4565     INT_MCU_UNLOCK(unit);
   4566 
   4567     if (SOC_FAILURE(rv)) {
   4568         LOG_WARN(BSL_LS_SOC_PORT,
   4569                  (BSL_META_U(unit,
   4570                              "_soc_portctrl_phy_timesync_config_get failed %d\n"), rv));
   4571     }
   4572     return rv;
   4573 #else  /* PORTMOD_SUPPORT */
   4574     return SOC_E_UNAVAIL;
   4575 #endif /* PORTMOD_SUPPORT */
   4576 }
   4577 
   4578 /*
   4579  * Function:
   4580  *      soc_portctrl_control_phy_timesync_config_set
   4581  * Purpose:
   4582  *      Set timesync config
   4583  * Parameters:
   4584  *      unit - SOC Unit #.
   4585  *      port - Port number.
   4586  *      phyn - Phy number
   4587  * Returns:
   4588  *      SOC_E_XXX
   4589  */
   4590 int
   4591 soc_portctrl_control_phy_timesync_set(int unit, soc_port_t port,
   4592                                       soc_port_control_phy_timesync_t type,
   4593                                       uint64 value)
   4594 {
   4595 #ifdef PORTMOD_SUPPORT
   4596     int         rv;
   4597 
   4598     INT_MCU_LOCK(unit);
   4599     rv = portmod_port_control_phy_timesync_set(unit, port, type, value);
   4600     INT_MCU_UNLOCK(unit);
   4601 
   4602     if (SOC_FAILURE(rv)) {
   4603         LOG_WARN(BSL_LS_SOC_PORT,
   4604                  (BSL_META_U(unit,
   4605                              "_soc_portctrl_control_phy_timesync_set failed %d\n"), rv));
   4606     }
   4607     return rv;
   4608 #else  /* PORTMOD_SUPPORT */
   4609     return SOC_E_UNAVAIL;
   4610 #endif /* PORTMOD_SUPPORT */
   4611 }
   4612 
   4613 /*
   4614  * Function:
   4615  *      soc_portctrl_control_phy_timesync_config_get
   4616  * Purpose:
   4617  *      Set timesync config
   4618  * Parameters:
   4619  *      unit - SOC Unit #.
   4620  *      port - Port number.
   4621  *      phyn - Phy number
   4622  * Returns:
   4623  *      SOC_E_XXX
   4624  */
   4625 int
   4626 soc_portctrl_control_phy_timesync_get(int unit, soc_port_t port,
   4627                                       soc_port_control_phy_timesync_t type,
   4628                                       uint64 *value)
   4629 {
   4630 #ifdef PORTMOD_SUPPORT
   4631     int         rv;
   4632 
   4633     INT_MCU_LOCK(unit);
   4634     rv = portmod_port_control_phy_timesync_get(unit, port, type, value);
   4635     INT_MCU_UNLOCK(unit);
   4636 
   4637     if (SOC_FAILURE(rv)) {
   4638         LOG_WARN(BSL_LS_SOC_PORT,
   4639                  (BSL_META_U(unit,
   4640                              "_soc_portctrl_phy_timesync_set failed %d\n"), rv));
   4641     }
   4642     return rv;
   4643 #else  /* PORTMOD_SUPPORT */
   4644     return SOC_E_UNAVAIL;
   4645 #endif /* PORTMOD_SUPPORT */
   4646 }
   4647 
   4648 /*
   4649  * Function:
   4650  *      soc_esw_portctrl_encap_get
   4651  * Purpose:
   4652  *      Get the port encapsulation mode.
   4653  * Parameters:
   4654  *      unit   - (IN) Unit number.
   4655  *      port   - (IN) Port number.
   4656  *      mode   - (OUT) One of _SHR_PORT_ENCAP_xxx.
   4657  * Returns:
   4658  *      SOC_E_XXX
   4659  */
   4660 int
   4661 soc_esw_portctrl_encap_get(int unit, soc_port_t port, int *mode)
   4662 {
   4663 #ifdef PORTMOD_SUPPORT
   4664     int rv = SOC_E_NONE;
   4665     int flags = 0;
   4666     portctrl_pport_t pport;
   4667     portmod_encap_t encap;
   4668 
   4669     PORTCTRL_PORT_TO_PPORT(port, pport);
   4670 
   4671     SOC_CONTROL_LOCK(unit);
   4672     rv = portmod_port_encap_get(unit, pport, &flags, &encap);
   4673     SOC_CONTROL_UNLOCK(unit);
   4674 
   4675     if (PORTMOD_SUCCESS(rv)) {
   4676         *mode = encap;
   4677     }
   4678 
   4679     return rv;
   4680 
   4681 #else  /* PORTMOD_SUPPORT */
   4682     return SOC_E_UNAVAIL;
   4683 #endif /* PORTMOD_SUPPORT */
   4684 }
   4685 
   4686 /*
   4687  * Function:
   4688  *      soc_esw_portctrl_port_to_phyaddr
   4689  * Purpose:
   4690  *      This function gets phy address associated with the port
   4691  * Parameters:
   4692  *      unit   - (IN) Unit number.
   4693  *      port   - (IN) Port number.
   4694  * Returns:
   4695  *      Phy address value
   4696  */
   4697 int
   4698 soc_esw_portctrl_port_to_phyaddr(int unit, soc_port_t port, uint8* phy_addr)
   4699 {
   4700 #ifdef PORTMOD_SUPPORT
   4701     int addr;
   4702     portctrl_pport_t pport;
   4703     int rv = SOC_E_NONE;
   4704 
   4705     PORTCTRL_PORT_TO_PPORT(port, pport);
   4706 
   4707     SOC_CONTROL_LOCK(unit);
   4708     addr = portmod_port_to_phyaddr(unit, pport);
   4709     SOC_CONTROL_UNLOCK(unit);
   4710 
   4711     /* Portmod API returns phy address on successful execution, and
   4712      * negative value in case of error.
   4713      * So we program phy_addr, rv accordingly
   4714      */
   4715     /* coverity[negative_returns] */
   4716     if (addr >= 0) {
   4717         *phy_addr = addr; 
   4718     } else {
   4719         rv = addr;
   4720     }
   4721 
   4722     return rv;
   4723 
   4724 #else  /* PORTMOD_SUPPORT */
   4725     return SOC_E_UNAVAIL;
   4726 #endif /* PORTMOD_SUPPORT */
   4727 }
   4728 
   4729 /*
   4730  * Function:
   4731  *      soc_esw_portctrl_speed_get
   4732  * Purpose:
   4733  *      Get the port speed.
   4734  * Parameters:
   4735  *      unit   - (IN) Unit number.
   4736  *      port   - (IN) Port number.
   4737  *      speed  - (OUT) Port speed.
   4738  * Returns:
   4739  *      SOC_E_XXX
   4740  */
   4741 int
   4742 soc_esw_portctrl_speed_get(int unit, soc_port_t port, int *speed)
   4743 {
   4744 #ifdef PORTMOD_SUPPORT
   4745     int rv = SOC_E_NONE;
   4746     portctrl_pport_t pport;
   4747     portmod_port_interface_config_t portmod_if_config;
   4748 
   4749     PORTCTRL_PORT_TO_PPORT(port, pport);
   4750 
   4751     /*
   4752      * Temporary solution until PortMod null driver is in place
   4753      */
   4754     if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port)) {
   4755         *speed = SOC_INFO(unit).port_speed_max[port];
   4756         return SOC_E_NONE;
   4757     }
   4758 
   4759     SOC_CONTROL_LOCK(unit);
   4760     rv = portmod_port_interface_config_get(unit, pport, &portmod_if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   4761     SOC_CONTROL_UNLOCK(unit);
   4762 
   4763     if (PORTMOD_SUCCESS(rv)) {
   4764         *speed = portmod_if_config.speed;
   4765 
   4766         if (IS_HG_PORT(unit, port) && *speed < 5000) {
   4767             *speed = 0;
   4768         }
   4769     }
   4770 
   4771     return rv;
   4772 
   4773 #else  /* PORTMOD_SUPPORT */
   4774     return SOC_E_UNAVAIL;
   4775 #endif /* PORTMOD_SUPPORT */
   4776 }
   4777 
   4778 /*
   4779  * Function:
   4780  *     _soc_esw_portctrl_speed_slots_get
   4781  * Purpose:
   4782  *     Get number of slots required for given port speed
   4783  * Returns:
   4784  *      SOC_E_XXX
   4785  */
   4786 STATIC int
   4787 _soc_esw_portctrl_speed_slots_get(int unit, int speed)
   4788 {
   4789     int slot_num = 0;
   4790 
   4791     switch(speed) {
   4792     case 10:
   4793     case 100:
   4794     case 1000:
   4795     case 2500:
   4796         slot_num = 1;
   4797         break;
   4798     case 5000:
   4799     case 10000:
   4800     case 11000:
   4801         slot_num = 4;
   4802         break;
   4803     case 13000:
   4804     case 16000:
   4805         if(SOC_IS_TITAN2PLUS(unit)){
   4806             slot_num = 8;
   4807         } else {
   4808             LOG_ERROR(BSL_LS_SOC_PORT,
   4809                       ("Unsupported port speed %d\n", speed));
   4810         }
   4811         break;
   4812     case 20000:
   4813     case 21000:
   4814         slot_num = 8;
   4815         break;
   4816     case 25000:
   4817     case 25450:
   4818     case 27000:
   4819         slot_num = 10;
   4820         break;
   4821     case 40000:
   4822     case 42000:
   4823         slot_num = 16;
   4824         break;
   4825     case 50000:
   4826     case 53000:
   4827         slot_num = 20;
   4828         break;
   4829     case 100000:
   4830     case 106000:
   4831         slot_num = 40;
   4832         break;
   4833     case 120000:
   4834     case 127000:
   4835         slot_num = 48;
   4836         break;
   4837     default:
   4838         LOG_ERROR(BSL_LS_SOC_PORT,
   4839                   ("Unsupported port speed %d\n", speed));
   4840         break;
   4841     }
   4842 
   4843     return (slot_num);
   4844 }
   4845 
   4846 /*
   4847  * Function:
   4848  *      soc_port_is_same_speed_class
   4849  * Purpose:
   4850  *      Check if pre,post speeds are same speed class
   4851  *      to know TDM reconfiguration is required or not.
   4852  *      Speed Class is defined as below
   4853  *      -------------------------
   4854  *      | Group    | Speeds     |
   4855  *      |=======================|
   4856  *      | 0        | 1G, 2.5G   |
   4857  *      | 1        | 10G, 11G   |
   4858  *      | 2        | 20G, 21G   |
   4859  *      | 3        | 25G, 27G   |
   4860  *      | 4        | 40G, 42G   |
   4861  *      | 5        | 100G, 106G |
   4862  *      | 6        | 120G, 127G |
   4863  *      -------------------------
   4864  *      If speed group is different, then need to reconfigure TDM
   4865  */
   4866 int
   4867 soc_esw_portctrl_is_same_speed_class(int unit, int pre_speed, int post_speed)
   4868 {
   4869     int rv;
   4870     int pre_slot, post_slot;
   4871 
   4872     pre_slot = _soc_esw_portctrl_speed_slots_get(unit, pre_speed);
   4873     post_slot = _soc_esw_portctrl_speed_slots_get(unit, post_speed);
   4874 
   4875     if (pre_slot == post_slot) {
   4876         rv = TRUE;
   4877     } else {
   4878         rv = FALSE;
   4879     }
   4880 
   4881     return rv;
   4882 }
   4883 
   4884 /*
   4885  * Function:
   4886  *      soc_esw_portctrl_port_ability_update
   4887  * Purpose:
   4888  *      Update supported abilities of a port
   4889  * Parameters:
   4890  *      unit - StrataSwitch unit #
   4891  *      port - StrataSwitch port #
   4892  *      ability - (OUT) Returns updated soc_port_ability_t structure information.
   4893  *
   4894  * Returns:
   4895  *      SOC_E_XXX
   4896  */
   4897 soc_error_t
   4898 soc_esw_portctrl_port_ability_update(int unit, soc_port_t port, soc_port_ability_t *ability)
   4899 {
   4900     int rv = SOC_E_NONE;
   4901 #ifdef PORTMOD_SUPPORT
   4902     if ((SOC_PORTCTRL_FUNCTIONS(unit)) &&
   4903         (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_port_ability_update)) {
   4904         rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_port_ability_update(unit, port, ability);
   4905     } else {
   4906         rv = SOC_E_NONE;
   4907     }
   4908     return rv;
   4909 #else
   4910     return rv;
   4911 #endif
   4912 }
   4913 
   4914 /*
   4915  * Function:
   4916  *      soc_esw_portctrl_pll_div_get
   4917  * Purpose:
   4918  *      Get VCO frequency(PLL div) for port.
   4919  *      PLL DIV value can be converted to VCO frequency by following equation.
   4920  *      VCO = (PLL_DIV) * (REF_CLK)
   4921  *
   4922  *      Here is the complete table for TSCE(TD2+)
   4923  *    ----------------------------------------------------------
   4924  *    | encap type | speed | lanes | VCO     | PLL_DIV | REF_CLK
   4925  *    | IEEE       | 1     | 1     | 10312.5 | 66      | 156.25
   4926  *    | IEEE       | 1     | 1     | 6250    | 40      | 156.25
   4927  *    | IEEE       | 2.5   | 1     | 6250    | 40      | 156.25
   4928  *    | IEEE       | 10    | 1     | 10312.5 | 66      | 156.25
   4929  *    | HIGIG2     | 10    | 1     | 10312.5 | 66      | 156.25
   4930  *    | HIGIG2     | 11    | 1     | 10937.5 | 70      | 156.25
   4931  *    | IEEE       | 20    | 2     | 10312.5 | 66      | 156.25
   4932  *    | HIGIG2     | 20    | 2     | 10312.5 | 66      | 156.25
   4933  *    | HIGIG2     | 21    | 2     | 10937.5 | 70      | 156.25
   4934  *    | IEEE       | 10    | 4     | 6250    | 40      | 156.25
   4935  *    | HIGIG2     | 10    | 4     | 6250    | 40      | 156.25
   4936  *    | HIGIG2     | 11    | 4     | 6562.5  | 42      | 156.25
   4937  *    | IEEE       | 40    | 4     | 10312.5 | 66      | 156.25
   4938  *    | HIGIG2     | 40    | 4     | 10312.5 | 66      | 156.25
   4939  *    | HIGIG2     | 42    | 4     | 10937.5 | 70      | 156.25
   4940  *    | IEEE       | 100   | 10    | 10312.5 | 66      | 156.25
   4941  *    | HIGIG2     | 100   | 10    | 10312.5 | 66      | 156.25
   4942  *    | HIGIG2     | 106   | 10    | 10937.5 | 70      | 156.25
   4943  *    | IEEE       | 120   | 12    | 10312.5 | 66      | 156.25
   4944  *    | HIGIG2     | 127   | 12    | 10937.5 | 70      | 156.25
   4945  *    ----------------------------------------------------------
   4946  *
   4947  * Parameters:
   4948  *      unit       - (IN) Unit number
   4949  *      logic_port - (IN) logical port number
   4950  *      phy_port   - (IN) Physical port number
   4951  *      speed      - (IN) Speed
   4952  *      num_lane   - (IN) Number of lanes
   4953  *      encap      - (IN) Encap mode
   4954  *      pll_div    - (OUT) pll div
   4955  * Returns:
   4956  * Note:
   4957  */
   4958 /*In flex port, there are some logic ports are generated. And the new ports is not initialized in Add SOC_INFO(unit).port_p2l_mapping. 
   4959   That is to say we can`t retrieve the logical port via physical port.
   4960  */
   4961 int
   4962 soc_esw_portctrl_pll_div_get(int unit, soc_port_t logic_port, soc_port_t phy_port,
   4963                              int speed, int num_lane, int encap,
   4964                              uint32 *pll_div)
   4965 {
   4966 #ifdef PORTMOD_SUPPORT
   4967     int rv;
   4968     portmod_port_resources_t pr;
   4969     int serdes_1000x_at_25g_vco = 0;
   4970     int serdes_10g_at_25g_vco = 0;
   4971     int serdes_1000x_at_6250_vco = 0;
   4972     int serdes_1000x_at_12500_vco = 0;
   4973 
   4974 #if (defined BCM_HELIX5_SUPPORT) || (defined BCM_MAVERICK2_SUPPORT)
   4975     if (SOC_IS_HELIX5(unit) ||
   4976         (SOC_IS_MAVERICK2(unit) && SOC_INFO(unit).bandwidth == 2000000)) {
   4977         serdes_1000x_at_25g_vco = 1;
   4978         serdes_10g_at_25g_vco = 1;
   4979     }
   4980 #endif
   4981     pr.flag = 0;
   4982     /*In flex port, customer can configure the following properties to select pll DIV for the new generated ports.
   4983       So we need to parse these properties here directly.
   4984      */
   4985     serdes_1000x_at_6250_vco =
   4986         soc_property_port_get(unit, logic_port,
   4987                               spn_SERDES_1000X_AT_6250_VCO, serdes_1000x_at_6250_vco);
   4988     if (serdes_1000x_at_6250_vco) {
   4989         PORTMOD_SERDES_1000X_AT_6250_SET(pr.flag);
   4990     }
   4991 
   4992     serdes_1000x_at_12500_vco =
   4993         soc_property_port_get(unit, logic_port,
   4994                       spn_SERDES_1000X_AT_12500_VCO, serdes_1000x_at_12500_vco);
   4995     if (serdes_1000x_at_12500_vco) {
   4996         PORTMOD_SERDES_1000X_AT_12500_SET(pr.flag);
   4997     }
   4998 
   4999     serdes_1000x_at_25g_vco =
   5000         soc_property_port_get(unit, logic_port,
   5001                       spn_SERDES_1000X_AT_25G_VCO, serdes_1000x_at_25g_vco);
   5002     if (serdes_1000x_at_25g_vco) {
   5003         PORTMOD_SERDES_1000X_AT_25G_SET(pr.flag);
   5004     }
   5005 
   5006     serdes_10g_at_25g_vco =
   5007         soc_property_port_get(unit, logic_port,
   5008                       spn_SERDES_10G_AT_25G_VCO, serdes_10g_at_25g_vco);
   5009     if (serdes_10g_at_25g_vco) {
   5010         PORTMOD_SERDES_10G_AT_25G_SET(pr.flag);
   5011     }
   5012 
   5013     pr.speed = speed;
   5014     pr.num_lane = num_lane;
   5015     pr.encap_mode = encap;
   5016 
   5017     SOC_CONTROL_LOCK(unit);
   5018     rv = portmod_pm_port_pll_div_get(unit, logic_port, phy_port, &pr, pll_div);
   5019     SOC_CONTROL_UNLOCK(unit);
   5020     if (PORTMOD_FAILURE(rv)) {
   5021         LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   5022                   "Failed to get pll_div\n")));
   5023         return rv;
   5024     }
   5025 
   5026     return SOC_E_NONE;
   5027 #else  /* PORTMOD_SUPPORT */
   5028     return SOC_E_UNAVAIL;
   5029 #endif /* PORTMOD_SUPPORT */
   5030 }
   5031 
   5032 /*
   5033  * Function:
   5034  *      soc_esw_portmod_port_vcos_get  
   5035  * Purpose:
   5036  *      Verify if the given port combination is supported on a port macro
   5037  * Parameters:
   5038  *      unit - StrataSwitch unit #
   5039  *      phy_port - array of ports in given port macro #
   5040  *      lanes - lanes for each port in given port macro #
   5041  *      speed - speed of each port in port macro #
   5042  *      encap - encap of each  port in port macro #
   5043  *      size - no of ports in port macro #
   5044  *
   5045  * Returns:
   5046  *      SOC_E_XXX
   5047  */
   5048 #ifdef PORTMOD_SUPPORT
   5049 int 
   5050 soc_esw_portmod_port_vcos_get(int unit, soc_port_t phy_port,
   5051                               portmod_dispatch_type_t pm_type, int* lanes,
   5052                               int* speed, int* encap, int size)   
   5053 {
   5054 
   5055      #ifdef PORTMOD_CPM4X25_SUPPORT
   5056      portmod_vcos_speed_config_t speed_config_list[4];
   5057      portmod_dual_vcos_t dual_vco;
   5058      int ethernet = 0 ;
   5059      int cpri = 0 ; 
   5060      int i = 0 ;
   5061      int rv = 0; 
   5062      
   5063      if ((pm_type != portmodDispatchTypePm4x25) && (pm_type != portmodDispatchTypeCpm4x25)) {
   5064           LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   5065                       "soc_esw_portmod_port_vcos_get not supported for pm_type %d\n"), pm_type));
   5066      }
   5067      for (i = 0 ; i < size ; i++) { 
   5068           speed_config_list[i].speed = speed[i]; 
   5069           speed_config_list[i].num_lanes = lanes[i];
   5070           speed_config_list[i].eth_of_mixed_mode = 0;
   5071           speed_config_list[i].higig_mode = 0;
   5072           speed_config_list[i].ieee_mode = 0;
   5073           if (encap[i] ==  SOC_ENCAP_IEEE) {  
   5074               speed_config_list[i].ieee_mode = 1;
   5075               speed_config_list[i].port_type = portmodCpmPrtEthMode;
   5076               ethernet = 1; 
   5077           } else if (encap[i] ==  SOC_ENCAP_CPRI) {
   5078               speed_config_list[i].port_type = portmodCpmPrtCpriMode;
   5079               cpri = 1 ; 
   5080           } else if (encap[i] ==  SOC_ENCAP_RSVD4) {
   5081               speed_config_list[i].port_type = portmodCpmPrtRsvd4Mode;
   5082               cpri = 1 ; 
   5083           } else if ((encap[i] == SOC_ENCAP_HIGIG) || (encap[i] == SOC_ENCAP_HIGIG2)) {
   5084              speed_config_list[i].higig_mode = 1;
   5085              speed_config_list[i].port_type = portmodCpmPrtEthMode;
   5086              ethernet = 1; 
   5087           }
   5088 
   5089      }
   5090     if (ethernet && cpri) { 
   5091         for (i = 0 ; i < size ; i++) { 
   5092              if ((encap[i] ==  SOC_ENCAP_IEEE) || (encap[i] == SOC_ENCAP_HIGIG) || (encap[i] == SOC_ENCAP_HIGIG2) ) { 
   5093                  speed_config_list[i].eth_of_mixed_mode = 1;
   5094                  speed_config_list[i].port_type = portmodCpmPrtEthOfMixedMode;
   5095              } else if (speed_config_list[i].port_type == portmodCpmPrtCpriMode) {
   5096                  speed_config_list[i].port_type = portmodCpmPrtCpriOfMixedMode;
   5097              } else if (speed_config_list[i].port_type == portmodCpmPrtRsvd4Mode) {
   5098                  speed_config_list[i].port_type = portmodCpmPrtRsvd4OfMixedMode;
   5099              }
   5100         }
   5101     }
   5102     portmod_dual_vcos_t_init(unit , &dual_vco);
   5103     rv = portmod_pm_supported_vcos_get(unit, phy_port, pm_type, speed_config_list, size, &dual_vco);
   5104     if (PORTMOD_FAILURE(rv)) {
   5105             LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   5106                       "Failed to get dual_vcos\n")));
   5107             return rv;
   5108     }
   5109     return SOC_E_NONE;
   5110 #else  /* PORTMOD_CPM4X25_SUPPORT */
   5111     return SOC_E_UNAVAIL;
   5112 #endif /* PORTMOD_CPM4X25_SUPPORT */
   5113 }
   5114 #endif /* PORTMOD_SUPPORT */
   5115 
   5116 int
   5117 soc_esw_portctrl_phy_tx_set(int unit, soc_port_t port,
   5118                            int phyn, int phy_lane,
   5119                            int sys_side, soc_port_phy_tx_t *tx)
   5120 {
   5121 #ifdef PORTMOD_SUPPORT
   5122     int rv = SOC_E_NONE;
   5123     phymod_tx_t phy_tx;
   5124     int nof_phys;
   5125     portmod_access_get_params_t params;
   5126     phymod_phy_access_t phy_access;
   5127 
   5128     sal_memset(&phy_tx, 0, sizeof(phymod_tx_t));
   5129     portmod_access_get_params_t_init(unit, &params);
   5130     phymod_phy_access_t_init(&phy_access);
   5131 
   5132     params.lane = phy_lane;
   5133     SOC_IF_ERROR_RETURN
   5134         (portmod_port_phy_lane_access_get(unit, port, &params, 1, &phy_access, &nof_phys, NULL));
   5135 
   5136     /* convert from soc structure to phymod structure */
   5137     phy_tx.pre = tx->pre;
   5138     phy_tx.main = tx->main;
   5139     phy_tx.post = tx->post;
   5140     phy_tx.post2 = tx->post2;
   5141     phy_tx.post3 = tx->post3;
   5142     phy_tx.pre2  = tx->pre2;
   5143 
   5144     /* Enums for tap mode and signalling mode differ between SDK and portmod */
   5145     switch(tx->tx_tap_mode) {
   5146         case socPortPhyTxTapMode3Tap:
   5147             phy_tx.tap_mode = phymodTxTapMode3Tap;
   5148             break;
   5149         case socPortPhyTxTapMode6Tap:
   5150             phy_tx.tap_mode = phymodTxTapMode6Tap;
   5151             break;
   5152         default:
   5153             return SOC_E_PARAM;
   5154     }
   5155     switch(tx->signalling_mode) {
   5156         case socPortPhySignallingModeNRZ:
   5157             phy_tx.sig_method = phymodSignallingMethodNRZ;
   5158             break;
   5159         case socPortPhySignallingModePAM4:
   5160             phy_tx.sig_method = phymodSignallingMethodPAM4;
   5161             break;
   5162         default:
   5163             return SOC_E_INTERNAL;
   5164     }
   5165 
   5166     SOC_IF_ERROR_RETURN
   5167         (soc_portctrl_phy_tx_set(unit, &phy_access, &phy_tx));
   5168 
   5169     return rv;
   5170 #else
   5171     return SOC_E_UNAVAIL;
   5172 #endif
   5173 }
   5174 
   5175 int
   5176 soc_esw_portctrl_phy_tx_get(int unit, soc_port_t port,
   5177                             int phyn, int phy_lane,
   5178                             int sys_side, soc_port_phy_tx_t *tx)
   5179 {
   5180 #ifdef PORTMOD_SUPPORT
   5181     int rv = SOC_E_NONE;
   5182     phymod_tx_t phy_tx;
   5183     int nof_phys;
   5184     portmod_access_get_params_t params;
   5185     phymod_phy_access_t phy_access;
   5186 
   5187     portmod_access_get_params_t_init(unit, &params);
   5188     phymod_phy_access_t_init(&phy_access);
   5189 
   5190     params.lane = phy_lane;
   5191     SOC_IF_ERROR_RETURN
   5192         (portmod_port_phy_lane_access_get(unit, port, &params, 1, &phy_access, &nof_phys, NULL));
   5193 
   5194     SOC_IF_ERROR_RETURN
   5195         (soc_portctrl_phy_tx_get(unit, &phy_access, &phy_tx));
   5196 
   5197     /* convert from phymod structure to soc structure */
   5198     if (SOC_SUCCESS(rv)) {
   5199         tx->pre2 = phy_tx.pre2;
   5200         tx->pre  = phy_tx.pre;
   5201         tx->main = phy_tx.main;
   5202         tx->post = phy_tx.post;
   5203         tx->post2 = phy_tx.post2;
   5204         tx->post3 = phy_tx.post3;
   5205 
   5206         /* Enums for tap mode and signalling mode differ between
   5207          * SDK and portmod */
   5208         switch(phy_tx.tap_mode) {
   5209             case phymodTxTapMode3Tap:
   5210                 tx->tx_tap_mode = socPortPhyTxTapMode3Tap;
   5211                 break;
   5212             case phymodTxTapMode6Tap:
   5213                 tx->tx_tap_mode = socPortPhyTxTapMode6Tap;
   5214                 break;
   5215             default:
   5216                 return SOC_E_INTERNAL;
   5217         }
   5218         switch(phy_tx.sig_method) {
   5219             case phymodSignallingMethodNRZ:
   5220                 tx->signalling_mode = socPortPhySignallingModeNRZ;
   5221                 break;
   5222             case phymodSignallingMethodPAM4:
   5223                 tx->signalling_mode = socPortPhySignallingModePAM4;
   5224                 break;
   5225             default:
   5226                 return SOC_E_INTERNAL;
   5227         }
   5228     }
   5229     return rv;
   5230 #else
   5231     return SOC_E_UNAVAIL;
   5232 #endif
   5233 }