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

pm8x50.c (365250B)


      1 /*
      2  *
      3  * 
      4  *
      5  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      6  * 
      7  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      8  */
      9 
     10 #include <soc/types.h>
     11 #include <soc/error.h>
     12 #include <soc/drv.h>
     13 #include <soc/wb_engine.h>
     14 #include <soc/portmod/portmod_internal.h>
     15 #include <soc/portmod/portmod.h>
     16 #include <soc/portmod/portmod_dispatch.h>
     17 #include <soc/portmod/portmod_chain.h>
     18 #include <soc/portmod/portmod_common.h>
     19 #include <soc/portmod/portmod_defs.h>
     20 #include <soc/mcm/memregs.h>
     21 #include <soc/portmod/portmod_legacy_phy.h>
     22 
     23 #ifdef _ERR_MSG_MODULE_NAME
     24 #error "_ERR_MSG_MODULE_NAME redefined"
     25 #endif
     26 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT
     27 
     28 #ifdef PORTMOD_PM8X50_SUPPORT
     29 
     30 #include <soc/portmod/cdmac.h>
     31 #include <soc/portmod/pm8x50.h>
     32 #include <soc/portmod/pm8x50_shared.h>
     33 #include <soc/portmod/pm8x50_private.h>
     34 #include <soc/portmod/pm8x50_internal.h>
     35 
     36 #define PM_8x50_INFO(pm_info) ((pm_info)->pm_data.pm8x50_db)
     37 
     38 /* Warmboot variable defines - start */
     39 
     40 #define PM8x50_WB_BUFFER_VERSION        (4)
     41 #define PORTMOD_THREAD_INTERVAL_1s 1000000
     42 #define TIMEOUT_COUNT_400G_AN     10
     43 
     44 #define PM8x50_IS_CORE_INITIALIZED_SET(unit, pm_info, is_core_initialized) \
     45     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                     \
     46                           pm_info->wb_vars_ids[isCoreInitialized],         \
     47                           &is_core_initialized)
     48 #define PM8x50_IS_CORE_INITIALIZED_GET(unit, pm_info, is_core_initialized) \
     49     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                     \
     50                           pm_info->wb_vars_ids[isCoreInitialized],         \
     51                           is_core_initialized)
     52 
     53 #define PM8x50_IS_ACTIVE_SET(unit, pm_info, is_active)   \
     54     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
     55                           pm_info->wb_vars_ids[isActive],\
     56                          &is_active)
     57 #define PM8x50_IS_ACTIVE_GET(unit, pm_info, is_active)    \
     58     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
     59                           pm_info->wb_vars_ids[isActive],\
     60                           is_active)
     61 
     62 #define PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, ovco_pll_active_lane_bitmap)\
     63     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                            \
     64                           pm_info->wb_vars_ids[ovcopllActiveLaneBitmap],             \
     65                           &ovco_pll_active_lane_bitmap)
     66 #define PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, ovco_pll_active_lane_bitmap)\
     67     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                            \
     68                           pm_info->wb_vars_ids[ovcopllActiveLaneBitmap],             \
     69                           ovco_pll_active_lane_bitmap)
     70 
     71 #define PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, tvco_pll_active_lane_bitmap)\
     72     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                            \
     73                           pm_info->wb_vars_ids[tvcopllActiveLaneBitmap],             \
     74                           &tvco_pll_active_lane_bitmap)
     75 #define PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, tvco_pll_active_lane_bitmap)\
     76     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                            \
     77                           pm_info->wb_vars_ids[tvcopllActiveLaneBitmap],             \
     78                           tvco_pll_active_lane_bitmap)
     79 
     80 #define PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, ovco_pll_adv_lane_bitmap)\
     81     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
     82                           pm_info->wb_vars_ids[ovcopllAdvLaneBitmap],          \
     83                           &ovco_pll_adv_lane_bitmap)
     84 #define PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, ovco_pll_adv_lane_bitmap)\
     85     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
     86                           pm_info->wb_vars_ids[ovcopllAdvLaneBitmap],          \
     87                           ovco_pll_adv_lane_bitmap)
     88 
     89 #define PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, tvco_pll_adv_lane_bitmap)\
     90     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
     91                           pm_info->wb_vars_ids[tvcopllAdvLaneBitmap],          \
     92                           &tvco_pll_adv_lane_bitmap)
     93 #define PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, tvco_pll_adv_lane_bitmap)\
     94     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
     95                           pm_info->wb_vars_ids[tvcopllAdvLaneBitmap],          \
     96                           tvco_pll_adv_lane_bitmap)
     97 
     98 #define PM8x50_LANE2PORT_SET(unit, pm_info, lane, port)                  \
     99     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                   \
    100                           pm_info->wb_vars_ids[lane2portMap], &port, lane)
    101 #define PM8x50_LANE2PORT_GET(unit, pm_info, lane, port)                 \
    102     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                  \
    103                           pm_info->wb_vars_ids[lane2portMap], port, lane)
    104 
    105 #define PM8x50_MAX_SPEED_SET(unit, pm_info, max_speed, port_index)              \
    106     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                          \
    107                           pm_info->wb_vars_ids[maxSpeed], &max_speed, port_index)
    108 #define PM8x50_MAX_SPEED_GET(unit, pm_info, max_speed, port_index)             \
    109     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                         \
    110                           pm_info->wb_vars_ids[maxSpeed], max_speed, port_index)
    111 
    112 #define PM8x50_AN_MODE_SET(unit, pm_info, an_mode, port_index)              \
    113     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    114                           pm_info->wb_vars_ids[anMode], &an_mode, port_index)
    115 #define PM8x50_AN_MODE_GET(unit, pm_info, an_mode, port_index)             \
    116     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    117                           pm_info->wb_vars_ids[anMode], an_mode, port_index)
    118 
    119 #define PM8x50_LANE2FEC_SET(unit, pm_info, lane, fec)                   \
    120     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                  \
    121                           pm_info->wb_vars_ids[lane2fecMap], &fec, lane)
    122 #define PM8x50_LANE2FEC_GET(unit, pm_info, lane, fec)                   \
    123     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                  \
    124                           pm_info->wb_vars_ids[lane2fecMap], fec, lane)
    125 
    126 #define PM8x50_PORT_IS_PCS_BYPASSED_SET(unit, pm_info, is_bypassed, port_index)             \
    127     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                                      \
    128                           pm_info->wb_vars_ids[portIsPcsBypassed], &is_bypassed, port_index)
    129 #define PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, is_bypassed, port_index)             \
    130     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                                      \
    131                           pm_info->wb_vars_ids[portIsPcsBypassed], is_bypassed, port_index)
    132 
    133 #define PM8x50_TS_ENABLE_PORT_COUNT_SET(unit, pm_info, ts_enable_port_count)   \
    134     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    135                           pm_info->wb_vars_ids[tsEnablePortCount],\
    136                          &ts_enable_port_count)
    137 #define PM8x50_TS_ENABLE_PORT_COUNT_GET(unit, pm_info, ts_enable_port_count)    \
    138     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    139                           pm_info->wb_vars_ids[tsEnablePortCount],\
    140                           ts_enable_port_count)
    141 
    142 #define PM8x50_TIMESYNC_ENABLE_SET(unit, pm_info, timesync_enable, port_index) \
    143     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    144                           pm_info->wb_vars_ids[timesyncEnable], &timesync_enable, port_index)
    145 #define PM8x50_TIMESYNC_ENABLE_GET(unit, pm_info, timesync_enable, port_index) \
    146     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    147                           pm_info->wb_vars_ids[timesyncEnable], timesync_enable, port_index)
    148 
    149 #define PM8x50_RLM_ENABLE_SET(unit, pm_info, rlmEnabled, port_index)                   \
    150     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    151                           pm_info->wb_vars_ids[rlmEnable], &rlmEnabled, port_index)
    152 #define PM8x50_RLM_ENABLE_GET(unit, pm_info, rlmEnabled, port_index)             \
    153     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    154                           pm_info->wb_vars_ids[rlmEnable], rlmEnabled, port_index)
    155 
    156 #define PM8x50_INITIATOR_SET(unit, pm_info, is_initiator, port_index)                   \
    157     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    158                           pm_info->wb_vars_ids[initiator], &is_initiator, port_index)
    159 #define PM8x50_INITIATOR_GET(unit, pm_info, is_initiator, port_index)             \
    160     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    161                           pm_info->wb_vars_ids[initiator], is_initiator, port_index)
    162 
    163 #define PM8x50_PCS_RECONFIG_SET(unit, pm_info, pcs_reconfig, port_index)                   \
    164     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    165                           pm_info->wb_vars_ids[pcsReconfigured], &pcs_reconfig, port_index)
    166 #define PM8x50_PCS_RECONFIG_GET(unit, pm_info, pcs_reconfig, port_index)             \
    167     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    168                           pm_info->wb_vars_ids[pcsReconfigured], pcs_reconfig, port_index)
    169 
    170 #define PM8x50_ACTIVE_LANE_MAP_SET(unit, pm_info, active_lane_map, port_index)                   \
    171     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    172                           pm_info->wb_vars_ids[activeLaneBitMap], &active_lane_map, port_index)
    173 #define PM8x50_ACTIVE_LANE_MAP_GET(unit, pm_info, active_lane_map, port_index)             \
    174     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    175                           pm_info->wb_vars_ids[activeLaneBitMap], active_lane_map, port_index)
    176 
    177 #define PM8x50_RLM_STATE_SET(unit, pm_info, rlm_state, port_index)                   \
    178     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    179                           pm_info->wb_vars_ids[rlmState], &rlm_state, port_index)
    180 #define PM8x50_RLM_STATE_GET(unit, pm_info, rlm_state, port_index)             \
    181     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    182                           pm_info->wb_vars_ids[rlmState], rlm_state, port_index)
    183 
    184 #define PM8x50_ORIGINAL_FEC_SET(unit, pm_info, orig_fec, port_index)                   \
    185     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    186                           pm_info->wb_vars_ids[originalFec], &orig_fec, port_index)
    187 #define PM8x50_ORIGINAL_FEC_GET(unit, pm_info, orig_fec, port_index)             \
    188     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    189                           pm_info->wb_vars_ids[originalFec], orig_fec, port_index)
    190 
    191 #define PM8x50_ORIG_TX_LANE_MAP_SET(unit, pm_info, tx_lane_map)\
    192     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    193                           pm_info->wb_vars_ids[originalTxLaneSwap],          \
    194                           &tx_lane_map)
    195 #define PM8x50_ORIG_TX_LANE_MAP_GET(unit, pm_info, tx_lane_map)\
    196     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    197                           pm_info->wb_vars_ids[originalTxLaneSwap],          \
    198                           tx_lane_map)
    199 
    200 #define PM8x50_ORIG_RX_LANE_MAP_SET(unit, pm_info, rx_lane_map)\
    201     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    202                           pm_info->wb_vars_ids[originalRxLaneSwap],          \
    203                           &rx_lane_map)
    204 #define PM8x50_ORIG_RX_LANE_MAP_GET(unit, pm_info, rx_lane_map)\
    205     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                      \
    206                           pm_info->wb_vars_ids[originalRxLaneSwap],          \
    207                           rx_lane_map)
    208 
    209 #define PM8x50_400G_AN_ENABLE_SET(unit, pm_info, is_400g_an, port_index) \
    210     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    211                           pm_info->wb_vars_ids[is400gAn], &is_400g_an, port_index)
    212 #define PM8x50_400G_AN_ENABLE_GET(unit, pm_info, is_400g_an, port_index) \
    213     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    214                           pm_info->wb_vars_ids[is400gAn], is_400g_an, port_index)
    215 
    216 #define PM8x50_400G_AN_STATE_SET(unit, pm_info, an_state_400g)   \
    217     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    218                           pm_info->wb_vars_ids[anState400g],\
    219                          &an_state_400g)
    220 #define PM8x50_400G_AN_STATE_GET(unit, pm_info, an_state_400g)    \
    221     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    222                           pm_info->wb_vars_ids[anState400g],\
    223                           an_state_400g)
    224 
    225 #define PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, an_wait_link_count)   \
    226     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    227                           pm_info->wb_vars_ids[anWaitlinkCount],\
    228                          &an_wait_link_count)
    229 #define PM8x50_400G_AN_WAIT_LINK_COUNT_GET(unit, pm_info, an_wait_link_count)    \
    230     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD,   \
    231                           pm_info->wb_vars_ids[anWaitlinkCount],\
    232                           an_wait_link_count)
    233 
    234 #define PM8x50_BER_WAR_ENABLE_SET(unit, pm_info, is_ber_war_enable, port_index) \
    235     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    236                           pm_info->wb_vars_ids[isBerWarEnable], &is_ber_war_enable, port_index)
    237 
    238 #define PM8x50_BER_WAR_STATE_SET(unit, pm_info, ber_war_state, port_index) \
    239     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    240                           pm_info->wb_vars_ids[berWarState], &ber_war_state, port_index)
    241 
    242 #define PM8x50_BER_WAR_WAIT_COUNT_SET(unit, pm_info, ber_war_wait_count, port_index) \
    243     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    244                           pm_info->wb_vars_ids[berWarWaitCount], &ber_war_wait_count, port_index)
    245 
    246 #define PM8x50_IS_CORE_FLEXE_CONFIGURED_SET(unit, pm_info, is_core_flexe_configured) \
    247     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD,                     \
    248                           pm_info->wb_vars_ids[coreisFlexeConfigured],         \
    249                           &is_core_flexe_configured)
    250 
    251 #define PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, an_400g_remote_pause, port_index) \
    252     SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    253                           pm_info->wb_vars_ids[an400gRemotePause], &an_400g_remote_pause, port_index)
    254 #define PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, an_400g_remote_pause, port_index) \
    255     SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD,                       \
    256                           pm_info->wb_vars_ids[an400gRemotePause], an_400g_remote_pause, port_index)
    257 
    258 typedef enum pm8x50_wb_vars{
    259     isCoreInitialized,
    260     isActive,
    261     isBypassed, /* Removed */
    262     ovcopllActiveLaneBitmap,
    263     tvcopllActiveLaneBitmap,
    264     ovcopllAdvLaneBitmap,
    265     tvcopllAdvLaneBitmap,
    266     lane2portMap,
    267     maxSpeed,
    268     anMode,
    269     anFec,  /* Removed */
    270     fsCl72, /* Removed */
    271     lane2fecMap,
    272     tsEnablePortCount,
    273     timesyncEnable,
    274     rlmEnable,        /* for RLM */
    275     initiator,        /* for RLM */
    276     pcsReconfigured,  /* for RLM */
    277     activeLaneBitMap, /* for RLM */
    278     rlmState,           /* for RLM */
    279     originalFec,        /* for RLM */
    280     originalTxLaneSwap, /* for RLM */
    281     originalRxLaneSwap, /* for RLM */
    282     is400gAn,           /* 400g An enabled */
    283     anState400g,        /* 400G an state */
    284     anWaitlinkCount,    /* 400G wait for link up count */
    285     portIsPcsBypassed,
    286     isBerWarEnable,     /* Currently not supported */
    287     berWarState,        /* Currently not supported */
    288     berWarWaitCount,    /* Currently not supported */
    289     coreisFlexeConfigured,   /* Currently not supported */
    290     an400gRemotePause,  /* 400G AN Remote PAUSE value */
    291 }pm8x50_wb_vars_t;
    292 
    293 typedef enum pm8x50_port_soft_reset_mode{
    294     PM8X50_PORT_SOFT_RESET_MODE_IN_OUT = 0,
    295     PM8X50_PORT_SOFT_RESET_MODE_IN     = 1,
    296     PM8X50_PORT_SOFT_RESET_MODE_OUT    = 2
    297 }pm8x50_port_soft_reset_mode_t;
    298 
    299 /* Warmboot variable defines - end */
    300 
    301 /* This macro set devad to reg_addr if it is PMD phy address. */
    302 #define PM8X50_PHY_REG_SET(reg_addr) \
    303     do { \
    304         uint32 phy_reg_addr; \
    305         phy_reg_addr = reg_addr & 0xffff; \
    306         if ((0x90 <= phy_reg_addr && phy_reg_addr <= 0x9f) || \
    307             (0xd000 <= phy_reg_addr && phy_reg_addr <= 0xd4ff) || \
    308             (0xffd0 <= phy_reg_addr && phy_reg_addr <= 0xffdf)) { \
    309             reg_addr |= 1 << 16; \
    310         } \
    311     } while (0)
    312 
    313 #define PM8X50_MAX_NUM_PLLS (2)
    314 
    315 #define PM8X50_TVCO_PLL_INDEX_GET(pm_info) PM_8x50_INFO(pm_info)->int_core_access.access.tvco_pll_index
    316 
    317 #define PM8x50_VCO_ALL (PM8x50_VCO_ILKN_20P625G | PM8x50_VCO_ETH_20P625G | PM8x50_VCO_ILKN_25G | PM8x50_VCO_ETH_25G | PM8x50_VCO_ETH_25P781G | PM8x50_VCO_ILKN_25P781G | PM8x50_VCO_ETH_26P562G | PM8x50_VCO_ILKN_26P562G | PM8x50_VCO_ILKN_27P343G | PM8x50_VCO_ILKN_28P125G)
    318 
    319 #define PM8x50_VCO_BMP_EMPTY(bmp) \
    320         ( (bmp & PM8x50_VCO_ALL) == 0 )
    321 
    322 #define PM8x50_VCO_BMP_20P625G_ETH_ONLY(bmp) \
    323         ( (bmp == PM8x50_VCO_ETH_20P625G) || (bmp == (PM8x50_VCO_ETH_20P625G | PM8x50_VCO_ILKN_20P625G)) )
    324 
    325 #define PM8x50_VCO_BMP_25G_ETH_ONLY(bmp) \
    326         ((bmp == PM8x50_VCO_ETH_25G) || (bmp == (PM8x50_VCO_ETH_25G | PM8x50_VCO_ILKN_25G)))
    327 
    328 /* VCO is dedicated for bypassed ports */
    329 #define PORTMOD_VCO_PCS_BYPASS_DEDICATED(vco) \
    330     ((vco == portmodVCO28P125G) || (vco == portmodVCO27P343G) || (vco == portmodVCO25G))
    331 
    332 /* Highest NRZ per lane speed is 28.125G, supported in ILKN mode */
    333 #define NRZ_MAX_PER_LANE_SPEED 28125
    334 
    335 #define PM8x50_FS_ABILITY_TABLE_SIZE 29
    336 #define PM8x50_AN_ABILITY_TABLE_SIZE 34
    337 #define PM8x50_MAX_AN_ABILITY 20
    338 
    339 #define FLEXPORT_SW_WAR_ENABLE  0x1000
    340 
    341 /* following defines are used for 400G AN SW WAR */
    342 #define AN_X4_SW_CTRL_STS_REG 0xc1e6
    343 #define AN_X4_SW_CTRL_STS_AN_COMPLETE_MASK 0x8000
    344 #define AN_X4_CL73_CFG_REG 0xc1c0
    345 #define AN_X4_CL73_CFG_AN_DISABLE_MASK 0xfaff
    346 #define MAIN0_SETUP_REG 0x9000
    347 #define MAIN0_SETUP_PORT_MODE_CLEAR 0xff8f
    348 #define MAIN0_SETUP_PORT_MODE_OCTAL 0x50
    349 #define SPEED_CTRL_REG  0xc050
    350 #define SPEED_CTRL_SPEED_ID_CLEAR 0xffc0
    351 #define SPEED_ID_400G    0xa
    352 
    353 #define AN_X4_LP_BASE1r_REG 0xc1d3
    354 #define AN_LP_BASE1r_PAGE_PAUSE_MASK   0x3
    355 #define AN_LP_BASE1r_PAGE_PAUSE_OFFSET 0xA
    356 
    357 STATIC portmod_ucode_buf_t pm8x50_ucode_buf[SOC_MAX_NUM_DEVICES] = {{NULL, 0}};
    358 STATIC portmod_ucode_buf_t pm8x50_ucode_buf_2nd[SOC_MAX_NUM_DEVICES] = {{NULL, 0}};
    359 
    360 typedef enum pm8x50_port_400g_an_state_e {
    361     PM8X50_PORT_AN_CHECK_PAGE_COMPLETE,
    362     PM8X50_PORT_AN_CHECK_PCS_LINKUP,
    363     PM8X50_PORT_AN_CREDIT_RESET,
    364     PM8X50_PORT_AN_DISABLE,
    365     PM8X50_PORT_AN_RESTART,
    366     PM8X50_PORT_AN_COMPLETE,
    367     PM8X50_PORT_AN_STATE_COUNT
    368 } pm8x50_port_400g_an_state_t;
    369 
    370 /*
    371  * 200G and 400G BER monitoring workaround state
    372  */
    373 typedef enum pm8x50_port_ber_war_state_e {
    374     PM8X50_PORT_BER_WAR_STATE_COUNT = 4
    375 } pm8x50_port_ber_war_state_t;
    376 
    377 /*
    378  * Entries of the force speed ability table; each entry specifies a
    379  * unique FS port speed ability and its associated VCO rate
    380  */
    381 typedef struct pm8x50_fs_ability_table_entry_s {
    382     uint32 speed; /* port speed in Mbps */
    383     uint32 num_lanes; /* number of lanes */
    384     portmod_fec_t fec_type; /* FEC type */
    385     portmod_vco_type_t vco; /* associated VCO rate of the ability */
    386 } pm8x50_fs_ability_table_entry_t;
    387 
    388 /*
    389  * Entries of the autoneg ability table; each entry specifies a unique
    390  * AN speed ability and its associated VCO rate
    391  */
    392 typedef struct pm8x50_an_ability_table_entry_s {
    393     uint32 speed; /* port speed in Mbps */
    394     uint32 num_lanes; /* number of lanes */
    395     portmod_fec_t fec_type; /* FEC type */
    396     portmod_port_phy_control_autoneg_mode_t an_mode; /* autoneg mode such as cl73, bam or msa */
    397     portmod_vco_type_t vco; /* associated VCO rate of the ability */
    398 } pm8x50_an_ability_table_entry_t;
    399 
    400 typedef enum cdmac_port_mode_e{
    401     CDMAC_4_LANES_SEPARATE  = 0,
    402     CDMAC_3_TRI_0_1_2_2     = 1,
    403     CDMAC_3_TRI_0_0_2_3     = 2,
    404     CDMAC_2_LANES_DUAL      = 3,
    405     CDMAC_4_LANES_TOGETHER  = 4
    406 } cdmac_port_mode_t;
    407 
    408 #define CDMAC_NUM_LANES 4
    409 /*
    410  * Defines:
    411  *     portmod_port_rlm_fsm_t *
    412  * Purpose:
    413  *     Valid values Reduced Lane Mode state
    414  */
    415 typedef enum portmod_port_rlm_fsm_e {
    416     PORTMOD_PORT_RLM_SEND_PACKET_DATA,  /*entry state for RLM */
    417     PORTMOD_PORT_RLM_STOP_MAC,          /* STALL TX */
    418     PORTMOD_PORT_RLM_SEND_LI,           /* SEND link interrupt protocol */
    419     PORTMOD_PORT_RLM_SEND_PRBS,         /* SEND prbs data  */
    420     PORTMOD_PORT_RLM_SEND_IDLE,         /* send idle */
    421     PORTMOD_PORT_RLM_DONE,              /* RLM transition done */
    422     PORTMOD_PORT_RLM_ERROR,             /* RLM error state */
    423     PORTMOD_PORT_RLM_FSM_COUNT
    424 } portmod_port_rlm_fsm_t;
    425 
    426 /*
    427  * Defines:
    428  *     portmod_port_rlm_state_t *
    429  * Purpose:
    430  *     pm8x50 RLM data structure
    431  */
    432 typedef struct portmod_port_rlm_state_s {
    433        portmod_port_rlm_fsm_t rlm_state;
    434  } portmod_port_rlm_state_t;
    435 
    436 
    437 /* a comprehensive list of pm8x50 forced speed abilities and their VCO rates */
    438 const pm8x50_fs_ability_table_entry_t pm8x50_fs_ability_table[PM8x50_FS_ABILITY_TABLE_SIZE] =
    439 {
    440     /* port_speed, num_lanes, fec_type, vco */
    441     {10000,  1, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO20P625G},
    442     {10000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     portmodVCO20P625G},
    443     {12000,  1, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25G    },
    444     {20000,  1, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO20P625G},
    445     {20000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     portmodVCO20P625G},
    446     {40000,  4, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO20P625G},
    447     {40000,  4, PORTMOD_PORT_PHY_FEC_BASE_R,     portmodVCO20P625G},
    448     {40000,  2, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO20P625G},
    449     {25000,  1, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25P781G},
    450     {25000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     portmodVCO25P781G},
    451     {25000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     portmodVCO25P781G},
    452     {50000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     portmodVCO25P781G},
    453     {50000,  2, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25P781G},
    454     {50000,  2, PORTMOD_PORT_PHY_FEC_RS_FEC,     portmodVCO25P781G},
    455     {100000, 2, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25P781G},
    456     {100000, 2, PORTMOD_PORT_PHY_FEC_RS_FEC,     portmodVCO25P781G},
    457     {100000, 4, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25P781G},
    458     {100000, 4, PORTMOD_PORT_PHY_FEC_RS_FEC,     portmodVCO25P781G},
    459     {200000, 4, PORTMOD_PORT_PHY_FEC_NONE,       portmodVCO25P781G},
    460     {50000,  1, PORTMOD_PORT_PHY_FEC_RS_544,     portmodVCO26P562G},
    461     {50000,  1, PORTMOD_PORT_PHY_FEC_RS_272,     portmodVCO26P562G},
    462     {50000,  2, PORTMOD_PORT_PHY_FEC_RS_544,     portmodVCO26P562G},
    463     {100000, 2, PORTMOD_PORT_PHY_FEC_RS_544,     portmodVCO26P562G},
    464     {100000, 2, PORTMOD_PORT_PHY_FEC_RS_272,     portmodVCO26P562G},
    465     {100000, 4, PORTMOD_PORT_PHY_FEC_RS_544,     portmodVCO26P562G},
    466     {200000, 4, PORTMOD_PORT_PHY_FEC_RS_272,     portmodVCO26P562G},
    467     {200000, 4, PORTMOD_PORT_PHY_FEC_RS_544,     portmodVCO26P562G},
    468     {200000, 4, PORTMOD_PORT_PHY_FEC_RS_544_2XN, portmodVCO26P562G},
    469     {400000, 8, PORTMOD_PORT_PHY_FEC_RS_544_2XN, portmodVCO26P562G}
    470 };
    471 
    472 /* a comprehensive list of pm8x50 autoneg abilities and their VCO rates */
    473 const pm8x50_an_ability_table_entry_t pm8x50_an_ability_table[PM8x50_AN_ABILITY_TABLE_SIZE] =
    474 {
    475     /* port_speed, num_lanes, fec_type, autoneg_mode, vco */
    476     {10000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO20P625G},
    477     {10000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO20P625G},
    478     {20000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO20P625G},
    479     {20000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO20P625G},
    480     {40000,  2, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO20P625G},
    481     {40000,  4, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO20P625G},
    482     {40000,  4, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO20P625G},
    483     {25000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO25P781G},
    484     {25000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO25P781G},
    485     {25000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO25P781G},
    486     {25000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO25P781G},
    487     {25000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO25P781G},
    488     {25000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO25P781G},
    489     {25000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    490     {25000,  1, PORTMOD_PORT_PHY_FEC_BASE_R,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    491     {25000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    492     {50000,  1, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    493     {50000,  1, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    494     {50000,  2, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO25P781G},
    495     {50000,  2, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO25P781G},
    496     {50000,  2, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    497     {50000,  2, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    498     {100000, 2, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    499     {100000, 2, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    500     {100000, 4, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    501     {100000, 4, PORTMOD_PORT_PHY_FEC_RS_FEC,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO25P781G},
    502     {200000, 4, PORTMOD_PORT_PHY_FEC_NONE,       PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO25P781G},
    503     {50000,  1, PORTMOD_PORT_PHY_FEC_RS_544,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO26P562G},
    504     {50000,  2, PORTMOD_PORT_PHY_FEC_RS_544,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO26P562G},
    505     {100000, 2, PORTMOD_PORT_PHY_FEC_RS_544,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO26P562G},
    506     {100000, 4, PORTMOD_PORT_PHY_FEC_RS_544,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO26P562G},
    507     {200000, 4, PORTMOD_PORT_PHY_FEC_RS_544_2XN, PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73    , portmodVCO26P562G},
    508     {200000, 4, PORTMOD_PORT_PHY_FEC_RS_544,     PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM, portmodVCO26P562G},
    509     {400000, 8, PORTMOD_PORT_PHY_FEC_RS_544_2XN, PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA, portmodVCO26P562G}
    510 };
    511 
    512 static phymod_dispatch_type_t pm8x50_serdes_list[] =
    513 {
    514     phymodDispatchTypeTscbh,
    515     phymodDispatchTypeInvalid
    516 };
    517 
    518 /*
    519  * given the port speed, number of lanes, and FEC type, return the VCO specified in
    520  * pm8x50_fs_ability_table in the associated entry; VCO should be portmodVCOInvalid
    521  * if the ability is invalid
    522  */
    523 STATIC
    524 int _pm8x50_fs_ability_table_vco_get(uint32 speed, uint32 num_lanes, portmod_fec_t fec_type,
    525                                      portmod_vco_type_t* vco)
    526 {
    527     int i;
    528 
    529     *vco = portmodVCOInvalid;
    530     for (i = 0; i < PM8x50_FS_ABILITY_TABLE_SIZE; i++) {
    531         if (pm8x50_fs_ability_table[i].speed == speed &&
    532             pm8x50_fs_ability_table[i].num_lanes == num_lanes &&
    533             pm8x50_fs_ability_table[i].fec_type == fec_type)
    534         {
    535             *vco = pm8x50_fs_ability_table[i].vco;
    536             break;
    537         }
    538     }
    539 
    540     return SOC_E_NONE;
    541 }
    542 
    543 /*
    544  * given the port speed, number of lanes, FEC type, and autoneg mode, return the VCO specified in
    545  * pm8x50_an_ability_table; VCO should be portmodVCOInvalid if the ability is invalid.
    546  * this function is temporarily masked out because there is no caller. advert_ability_get() will
    547  * need to call this function to verify the VCO requirement
    548  */
    549 STATIC
    550 int _pm8x50_an_ability_table_vco_get(uint32 speed, uint32 num_lanes, portmod_fec_t fec_type,
    551                                      portmod_port_phy_control_autoneg_mode_t an_mode,
    552                                      portmod_vco_type_t* vco)
    553 {
    554     int i;
    555 
    556     *vco = portmodVCOInvalid;
    557     for (i = 0; i < PM8x50_AN_ABILITY_TABLE_SIZE; i++) {
    558         if (pm8x50_an_ability_table[i].speed == speed &&
    559             pm8x50_an_ability_table[i].num_lanes == num_lanes &&
    560             pm8x50_an_ability_table[i].fec_type == fec_type &&
    561             pm8x50_an_ability_table[i].an_mode == an_mode)
    562         {
    563             *vco = pm8x50_an_ability_table[i].vco;
    564             break;
    565         }
    566     }
    567 
    568     return SOC_E_NONE;
    569 }
    570 
    571 /* read an entry of pm8x50_fs_ability_table[] */
    572 STATIC
    573 int _pm8x50_fs_ability_table_read_entry(int index, pm8x50_fs_ability_table_entry_t *table_entry)
    574 {
    575     SOC_INIT_FUNC_DEFS;
    576 
    577     if (index < 0 || index >= PM8x50_FS_ABILITY_TABLE_SIZE) {
    578         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("index to read in pm8x50_fs_ability_table is out of boundary"));
    579     }
    580 
    581     *table_entry = pm8x50_fs_ability_table[index];
    582 
    583 exit:
    584     SOC_FUNC_RETURN;
    585 }
    586 
    587 /* read an entry of pm8x50_an_ability_table[] */
    588 STATIC
    589 int _pm8x50_an_ability_table_read_entry(int index, pm8x50_an_ability_table_entry_t *table_entry)
    590 {
    591     SOC_INIT_FUNC_DEFS;
    592 
    593     if (index < 0 || index >= PM8x50_AN_ABILITY_TABLE_SIZE) {
    594         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("index to read in pm8x50_an_ability_table is out of boundary"));
    595     }
    596 
    597     *table_entry = pm8x50_an_ability_table[index];
    598 
    599 exit:
    600     SOC_FUNC_RETURN;
    601 }
    602 
    603 STATIC
    604 int _pm8x50_port_index_get(int unit, int port, pm_info_t pm_info,
    605                            int *first_index, uint32 *bitmap)
    606 {
    607    int i, rv = 0, tmp_port = 0;
    608 
    609    SOC_INIT_FUNC_DEFS;
    610 
    611    *first_index = -1;
    612    *bitmap = 0;
    613 
    614    for( i = 0 ; i < MAX_PORTS_PER_PM8X50; i++){
    615        rv = PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port);
    616        _SOC_IF_ERR_EXIT(rv);
    617 
    618        if(tmp_port == port){
    619            *first_index = (*first_index == -1 ? i : *first_index);
    620            SHR_BITSET(bitmap, i);
    621        }
    622    }
    623 
    624    if(*first_index == -1) {
    625        _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL,
    626               (_SOC_MSG("port was not found in internal DB %d"), port));
    627    }
    628 
    629 exit:
    630     SOC_FUNC_RETURN;
    631 }
    632 
    633 STATIC int
    634 _pm8x50_phy_access_get(
    635     int unit,
    636     int port,
    637     pm_info_t pm_info,
    638     int *phy_acc)
    639 {
    640     uint32 is_bypassed = 0;
    641     int port_index;
    642     uint32 bitmap[1];
    643 
    644     SOC_INIT_FUNC_DEFS;
    645 
    646     *phy_acc = 0;
    647     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, bitmap));
    648     _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index));
    649     if (is_bypassed) {
    650         *phy_acc = (PM_8x50_INFO(pm_info)->first_phy + port_index) | SOC_REG_ADDR_PHY_ACC_MASK;
    651     } else {
    652         *phy_acc = port;
    653     }
    654 
    655 exit:
    656     SOC_FUNC_RETURN;
    657 }
    658 
    659 STATIC
    660 int _pm8x50_port_interrupt_all_enable_set(int unit, int port, int enable)
    661 {
    662     int i = 0;
    663     portmod_intr_type_t intrs[] = {
    664                                     portmodIntrTypeMacErr,
    665                                     portmodIntrTypeTscCore0Err,
    666                                     portmodIntrTypeTscCore1Err,
    667                                     portmodIntrTypeTxPktUnderflow,
    668                                     portmodIntrTypeTxPktOverflow,
    669                                     portmodIntrTypeTxCdcSingleBitErr,
    670                                     portmodIntrTypeTxCdcDoubleBitErr,
    671                                     portmodIntrTypeMibMemSingleBitErr,
    672                                     portmodIntrTypeMibMemDoubleBitErr,
    673                                     portmodIntrTypeMibMemMultipleBitErr
    674                                   };
    675     SOC_INIT_FUNC_DEFS;
    676 
    677     for (i = 0; i < sizeof(intrs)/sizeof(intrs[0]); i++) {
    678         _SOC_IF_ERR_EXIT(
    679         portmod_port_interrupt_enable_set(unit, port, intrs[i], enable));
    680     }
    681 
    682 exit:
    683     SOC_FUNC_RETURN;
    684 }
    685 
    686 STATIC
    687 int _pm8x50_pm_port_mode_update(int unit,
    688                                 int port,
    689                                 pm_info_t pm_info,
    690                                 int first_phy_index,
    691                                 int num_lanes)
    692 {
    693     uint32 reg_val, mac_port_mode, mac_new_port_mode = 0, is_400g_port = 0;
    694     int phy_acc, first_lane_local = 0, mac_stage_id = 0;
    695 
    696     SOC_INIT_FUNC_DEFS;
    697 
    698     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
    699 
    700     mac_stage_id = first_phy_index / CDMAC_NUM_LANES;
    701     first_lane_local = first_phy_index % CDMAC_NUM_LANES;
    702 
    703     _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, &reg_val));
    704     is_400g_port = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, SINGLE_PORT_MODE_SPEED_400Gf);
    705 
    706     if (mac_stage_id) {
    707         /* MAC1 need to update port mode */
    708         mac_port_mode = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, MAC1_PORT_MODEf);
    709     } else {
    710         /* MAC0 need to update port mode */
    711         mac_port_mode = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, MAC0_PORT_MODEf);
    712     }
    713 
    714     if (num_lanes == 8) {
    715         /* 400G single port mode */
    716         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, SINGLE_PORT_MODE_SPEED_400Gf, 1);
    717         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    718         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    719     } else if (num_lanes == 4) {
    720         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, SINGLE_PORT_MODE_SPEED_400Gf, 0);
    721         if (mac_stage_id) {
    722             /* MAC1 is single-port mode */
    723             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    724         } else {
    725             /* MAC0 is single-port mode */
    726             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    727         }
    728     } else if (num_lanes == 2) {
    729         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, SINGLE_PORT_MODE_SPEED_400Gf, 0);
    730         switch (mac_port_mode) {
    731             case CDMAC_4_LANES_SEPARATE:
    732                 if (first_lane_local == 0) {
    733                     mac_new_port_mode = CDMAC_3_TRI_0_0_2_3;
    734                 } else{
    735                     mac_new_port_mode = CDMAC_3_TRI_0_1_2_2;
    736                 }
    737                 break;
    738             case CDMAC_3_TRI_0_1_2_2:
    739                 if (first_lane_local == 0) {
    740                     mac_new_port_mode = CDMAC_2_LANES_DUAL;
    741                 } else {
    742                     mac_new_port_mode = CDMAC_3_TRI_0_1_2_2;
    743                 }
    744                 break;
    745             case CDMAC_3_TRI_0_0_2_3:
    746                 if (first_lane_local == 0) {
    747                     mac_new_port_mode = CDMAC_3_TRI_0_0_2_3;
    748                 } else {
    749                     mac_new_port_mode = CDMAC_2_LANES_DUAL;
    750                 }
    751                 break;
    752             case CDMAC_2_LANES_DUAL:
    753                 mac_new_port_mode = CDMAC_2_LANES_DUAL;
    754                 break;
    755             case CDMAC_4_LANES_TOGETHER:
    756                 mac_new_port_mode = CDMAC_2_LANES_DUAL;
    757                 break;
    758             default:
    759                 break;
    760         }
    761         if (mac_stage_id) {
    762             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, mac_new_port_mode);
    763         } else {
    764             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, mac_new_port_mode);
    765         }
    766     } else if (num_lanes == 1) {
    767         soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, SINGLE_PORT_MODE_SPEED_400Gf, 0);
    768         switch (mac_port_mode) {
    769             case CDMAC_4_LANES_SEPARATE:
    770                 mac_new_port_mode = CDMAC_4_LANES_SEPARATE;
    771                 break;
    772             case CDMAC_3_TRI_0_1_2_2:
    773                 if ((first_lane_local == 0) || (first_lane_local == 1)) {
    774                     mac_new_port_mode = CDMAC_3_TRI_0_1_2_2;
    775                 } else if ((first_lane_local == 2) || (first_lane_local == 3)) {
    776                     mac_new_port_mode = CDMAC_4_LANES_SEPARATE;
    777                 }
    778                 break;
    779             case CDMAC_3_TRI_0_0_2_3:
    780                 if ((first_lane_local == 0) || (first_lane_local == 1)) {
    781                     mac_new_port_mode = CDMAC_4_LANES_SEPARATE;
    782                 } else if ((first_lane_local == 2) || (first_lane_local == 3)) {
    783                     mac_new_port_mode = CDMAC_3_TRI_0_0_2_3;
    784                 }
    785                 break;
    786             case CDMAC_2_LANES_DUAL:
    787                 if ((first_lane_local == 0) || (first_lane_local == 1)) {
    788                     mac_new_port_mode = CDMAC_3_TRI_0_1_2_2;
    789                 } else if ((first_lane_local == 2) || (first_lane_local == 3)){
    790                     mac_new_port_mode = CDMAC_3_TRI_0_0_2_3;
    791                 }
    792                 break;
    793             case CDMAC_4_LANES_TOGETHER:
    794                 mac_new_port_mode = CDMAC_4_LANES_SEPARATE;
    795                 break;
    796             default:
    797                 break;
    798         }
    799         if (mac_stage_id) {
    800             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, mac_new_port_mode);
    801         } else {
    802             soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, mac_new_port_mode);
    803             /* if current port is 400G mode, need to write cdmac1 as well */
    804             if (is_400g_port) {
    805                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, mac_new_port_mode);
    806             }
    807         }
    808     }
    809     _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val));
    810 
    811 exit:
    812     SOC_FUNC_RETURN;
    813 
    814 }
    815 
    816 
    817 STATIC
    818 int _pm8x50_400g_an_workaround(int unit, int port, pm_info_t pm_info, int* is_done)
    819 {
    820     portmod_access_get_params_t params;
    821     phymod_phy_access_t phy_access;
    822     uint32_t serdes_reg_val, wait_link_count, base_reg_val, remote_pause;
    823     int nof_phys;
    824     pm8x50_port_400g_an_state_t an_state;
    825     phymod_autoneg_control_t an_control;
    826     char* state_string = "\n";
    827     int port_index;
    828     uint32 bitmap;
    829 
    830     SOC_INIT_FUNC_DEFS;
    831 
    832     *is_done = 0;
    833 
    834     /* first get the an state and wait link count */
    835     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_GET(unit, pm_info, &an_state));
    836     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_WAIT_LINK_COUNT_GET(unit, pm_info, &wait_link_count));
    837 
    838     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
    839     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
    840                                 &params, 1, &phy_access, &nof_phys, NULL));
    841 
    842     /* based on the AN state */
    843     switch (an_state) {
    844         case PM8X50_PORT_AN_CHECK_PAGE_COMPLETE:
    845         {
    846             state_string = "AN_CHECK_PAGE_COMPLETE\n";
    847             /* first read SW autoneg status register 0xc1e6 */
    848             /* clear the status first*/
    849             _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_SW_CTRL_STS_REG, &serdes_reg_val));
    850             sal_usleep(100);
    851             _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_SW_CTRL_STS_REG, &serdes_reg_val));
    852 
    853             if (serdes_reg_val & AN_X4_SW_CTRL_STS_AN_COMPLETE_MASK) {
    854                 int phy_acc;
    855                 uint32 reg_val;
    856 
    857                 /* get port index */
    858                 _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
    859                 _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_LP_BASE1r_REG, &base_reg_val));
    860                 /* store remote pause value */
    861                 remote_pause = (base_reg_val >> AN_LP_BASE1r_PAGE_PAUSE_OFFSET) & AN_LP_BASE1r_PAGE_PAUSE_MASK;
    862                 _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, port_index));
    863 
    864                 /* need to move one to the next stage */
    865                 /* disable AN_Cl73 and AN_CL73BAM */
    866                 _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_CL73_CFG_REG, &serdes_reg_val));
    867                 serdes_reg_val &= AN_X4_CL73_CFG_AN_DISABLE_MASK;
    868                 _SOC_IF_ERR_EXIT(phymod_phy_reg_write(&phy_access, AN_X4_CL73_CFG_REG, serdes_reg_val));
    869 
    870                 /* next disable rx/tx and set discard */
    871                 _SOC_IF_ERR_EXIT(cdmac_rx_enable_set(unit, port, 0));
    872                 _SOC_IF_ERR_EXIT(cdmac_discard_set(unit, port, 1));
    873                 _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, 1));
    874                 _SOC_IF_ERR_EXIT(cdmac_tx_enable_set(unit, port, 0));
    875 
    876                 /* next update the cdport mode register */
    877                 _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
    878                 _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, &reg_val));
    879                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, SINGLE_PORT_MODE_SPEED_400Gf, 1);
    880                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    881                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, CDMAC_4_LANES_TOGETHER);
    882                 _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val));
    883 
    884                 /* next update serdes side port mode to be octal */
    885                 _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, MAIN0_SETUP_REG, &serdes_reg_val));
    886                 serdes_reg_val = (serdes_reg_val & MAIN0_SETUP_PORT_MODE_CLEAR) | MAIN0_SETUP_PORT_MODE_OCTAL;
    887                 _SOC_IF_ERR_EXIT(phymod_phy_reg_write(&phy_access, MAIN0_SETUP_REG, serdes_reg_val));
    888 
    889                 /* next assert pcs reset */
    890                 _SOC_IF_ERR_EXIT(phymod_phy_pcs_enable_set(&phy_access, 0));
    891                 /* change the speed id  to use 0xa*/
    892                 _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, SPEED_CTRL_REG, &serdes_reg_val));
    893                 serdes_reg_val = (serdes_reg_val & SPEED_CTRL_SPEED_ID_CLEAR) | SPEED_ID_400G;
    894                 _SOC_IF_ERR_EXIT(phymod_phy_reg_write(&phy_access, SPEED_CTRL_REG, serdes_reg_val));
    895                 /* release pcs reset */
    896                 _SOC_IF_ERR_EXIT(phymod_phy_pcs_enable_set(&phy_access, 1));
    897                 an_state = PM8X50_PORT_AN_CHECK_PCS_LINKUP;
    898             }
    899             break;
    900        }
    901        case PM8X50_PORT_AN_CHECK_PCS_LINKUP:
    902        {
    903             int link, phy_acc, remote_fault;
    904             uint32 rval;
    905 
    906             state_string = "AN_CHECK_PCS_LINKUP\n";
    907             /* first check link status */
    908             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *)&link));
    909             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *)&link));
    910 
    911             /* next check remote fualt */
    912             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
    913             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
    914 
    915             if (link && (!remote_fault)) {
    916                 /*re-enable tx/rx and disable DISCARD */
    917                 _SOC_IF_ERR_EXIT(cdmac_discard_set(unit, port, 0));
    918 
    919                 /* next re-enable CDMAC TX/RX */
    920                 _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
    921                 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, phy_acc, &rval));
    922                 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, TRUE);
    923                 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, TRUE);
    924                 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SW_LINK_STATUSf, TRUE);
    925                 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, phy_acc, rval));
    926                 wait_link_count = 0;
    927                 an_state = PM8X50_PORT_AN_CREDIT_RESET;
    928                 _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, 0));
    929             } else {
    930                 wait_link_count++;
    931                 /* next check if AN needs to restarted */
    932                 if (wait_link_count > TIMEOUT_COUNT_400G_AN) {
    933                     an_state = PM8X50_PORT_AN_DISABLE;
    934                     wait_link_count = 0;
    935                 }
    936             }
    937 
    938             break;
    939        }
    940        case PM8X50_PORT_AN_DISABLE:
    941        {
    942             state_string = "AN_DISABLE \n";
    943             /* first needs to disable */
    944             an_control.enable = 0;
    945             an_control.an_mode = phymod_AN_MODE_CL73_MSA;
    946             an_control.num_lane_adv = 8;
    947             _SOC_IF_ERR_EXIT(phymod_phy_autoneg_set(&phy_access, &an_control));
    948             an_state = PM8X50_PORT_AN_RESTART;
    949             break;
    950        }
    951        case PM8X50_PORT_AN_RESTART:
    952        {
    953             state_string = "AN_RESTART \n";
    954             _SOC_IF_ERR_EXIT(_pm8x50_pm_port_mode_update(unit, port, pm_info, 0, 1));
    955 
    956             /* needs to enable autoneg */
    957             an_control.enable = 1;
    958             an_control.an_mode = phymod_AN_MODE_CL73_MSA;
    959             an_control.num_lane_adv = 8;
    960             _SOC_IF_ERR_EXIT(phymod_phy_autoneg_set(&phy_access, &an_control));
    961             an_state = PM8X50_PORT_AN_CHECK_PAGE_COMPLETE;
    962             break;
    963        }
    964 
    965        case PM8X50_PORT_AN_CREDIT_RESET:
    966        {
    967             int link, remote_fault;
    968             state_string = "AN_CREDIT_RESET \n";
    969 
    970             /* first check if link is up, if not, need to re-start AN */
    971             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *)&link));
    972             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *)&link));
    973 
    974             /* next check remote fualt */
    975             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
    976             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
    977 
    978             if (link && (!remote_fault)) {
    979                 /* first assert MAC soft reset */
    980                  _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, 1));
    981                 /* Callback egress buffer reset function */
    982                 if (PM_8x50_INFO(pm_info)->portmod_egress_buffer_reset) {
    983                      _SOC_IF_ERR_EXIT(PM_8x50_INFO(pm_info)->portmod_egress_buffer_reset(unit, port));
    984                 } else {
    985                     _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
    986                               (_SOC_MSG("The callback function is not defined \n")));
    987                 }
    988 
    989                 /* de-assert CDMAC soft reset */
    990                 _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, 0));
    991 
    992                 an_state = PM8X50_PORT_AN_COMPLETE;
    993             } else {
    994                 /*if no link or remote fault, re-start AN */
    995                 an_state = PM8X50_PORT_AN_DISABLE;
    996                 wait_link_count = 0;
    997             }
    998             break;
    999        }
   1000        case PM8X50_PORT_AN_COMPLETE:
   1001        {
   1002             int link, remote_fault;
   1003             state_string = "AN_COMPLETE \n";
   1004 
   1005             /* first check link status */
   1006             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *)&link));
   1007             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access, (uint32_t *) &link));
   1008 
   1009             /* next check remote fault */
   1010             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
   1011             _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, &remote_fault));
   1012 
   1013             /* only if link up and no remote fault, declare AN complete */
   1014             if (link && (!remote_fault)) {
   1015                 state_string = "AN_COMPLETE \n";
   1016                 *is_done = 1;
   1017             } else {
   1018                 an_state = PM8X50_PORT_AN_DISABLE;
   1019                 wait_link_count = 0;
   1020                 *is_done = 0;
   1021             }
   1022             break;
   1023        }
   1024         default:
   1025             *is_done = 1;
   1026             break;
   1027     }
   1028 
   1029     LOG_VERBOSE(BSL_LS_SOC_PHY,
   1030                 (BSL_META_U(unit,
   1031                             "port %d 400G AN state is %-23s \n"),
   1032                  port, state_string));
   1033 
   1034     /* next store the an state */
   1035     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_SET(unit, pm_info, an_state));
   1036     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, wait_link_count)); 
   1037 
   1038 exit:
   1039     SOC_FUNC_RETURN;
   1040 }
   1041 
   1042 STATIC
   1043 void _pm8x50_signalling_method_get(int is_bypassed,
   1044                                    const portmod_speed_config_t *speed_config,
   1045                                    phymod_phy_signalling_method_t *signalling_method)
   1046 {
   1047     int lane_rate;
   1048 
   1049     if (!is_bypassed) {
   1050         lane_rate = speed_config->speed / speed_config->num_lane;
   1051     } else {
   1052         lane_rate = speed_config->speed;
   1053     }
   1054 
   1055     *signalling_method = (lane_rate > NRZ_MAX_PER_LANE_SPEED ? phymodSignallingMethodPAM4 : phymodSignallingMethodNRZ);
   1056 }
   1057 
   1058 /* Convert the given VCO value to bitmap
   1059  *
   1060  * Inputs:
   1061  *     unit:              unit number;
   1062  *     vco:               vco value;
   1063  *     is_pcs_bypass:     is port in PCS bypass mode;
   1064  *     required_vco_bmp:  vco bitmap;
   1065  *
   1066  * Output:
   1067  *     non_bypassed_ports:   Non-bypass ports bitmap
   1068  */
   1069 
   1070 STATIC
   1071 int _pm8x50_required_vco_bitmap_get(
   1072     int unit,
   1073     portmod_vco_type_t vco,
   1074     int is_pcs_bypass,
   1075     pm8x50_vcos_bmp_t *required_vco_bmp)
   1076 {
   1077     SOC_INIT_FUNC_DEFS;
   1078 
   1079     *required_vco_bmp = 0;
   1080     if (vco == portmodVCO20P625G && is_pcs_bypass) {
   1081         PM8x50_VCO_ILKN_20P625G_SET(*required_vco_bmp);
   1082     } else if (vco == portmodVCO20P625G && !is_pcs_bypass) {
   1083         PM8x50_VCO_ETH_20P625G_SET(*required_vco_bmp);
   1084     } else if (vco == portmodVCO25G && is_pcs_bypass) {
   1085         PM8x50_VCO_ILKN_25G_SET(*required_vco_bmp);
   1086     } else if (vco == portmodVCO25P781G && !is_pcs_bypass) {
   1087         PM8x50_VCO_ETH_25P781G_SET(*required_vco_bmp);
   1088     } else if (vco == portmodVCO25P781G && is_pcs_bypass) {
   1089         PM8x50_VCO_ILKN_25P781G_SET(*required_vco_bmp);
   1090     } else if (vco == portmodVCO26P562G && !is_pcs_bypass) {
   1091         PM8x50_VCO_ETH_26P562G_SET(*required_vco_bmp);
   1092     } else if (vco == portmodVCO26P562G && is_pcs_bypass) {
   1093         PM8x50_VCO_ILKN_26P562G_SET(*required_vco_bmp);
   1094     } else if (vco == portmodVCO27P343G && is_pcs_bypass) {
   1095         PM8x50_VCO_ILKN_27P343G_SET(*required_vco_bmp);
   1096     } else if (vco == portmodVCO28P125G && is_pcs_bypass) {
   1097         PM8x50_VCO_ILKN_28P125G_SET(*required_vco_bmp);
   1098     } else if (vco == portmodVCO25G && !is_pcs_bypass) {
   1099         PM8x50_VCO_ETH_25G_SET(*required_vco_bmp);
   1100     } else {
   1101         _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("Unsupport VCO value! \n")));
   1102     }
   1103 exit:
   1104     SOC_FUNC_RETURN;
   1105 }
   1106 
   1107 /* Iterate over VCO values from VCO bitmap:
   1108  *  - return the VCO value of highest rate.
   1109  *  - clear returned VCO rate.
   1110  *
   1111  * Inputs:
   1112  *     unit:           unit number;
   1113  *     required_vcos:  VCO bitmap;
   1114  *     vco:            VCO rate;
   1115  *     is_pcs_bypass:  is in PCS bypass mode
   1116  * Output:
   1117  *     non_bypassed_ports:   Non-bypass ports bitmap
   1118  */
   1119 STATIC
   1120 int _pm8x50_required_vco_value_iter(
   1121         int unit,
   1122         pm8x50_vcos_bmp_t *required_vcos,
   1123         portmod_vco_type_t *vco,
   1124         int *is_pcs_bypass)
   1125 {
   1126     SOC_INIT_FUNC_DEFS;
   1127 
   1128     if (PM8x50_VCO_ILKN_28P125G_GET(*required_vcos)) {
   1129         *vco = portmodVCO28P125G;
   1130         *is_pcs_bypass = 1;
   1131         PM8x50_VCO_ILKN_28P125G_CLR(*required_vcos);
   1132     } else if (PM8x50_VCO_ILKN_27P343G_GET(*required_vcos)) {
   1133         *vco = portmodVCO27P343G;
   1134         *is_pcs_bypass = 1;
   1135         PM8x50_VCO_ILKN_27P343G_CLR(*required_vcos);
   1136     } else if (PM8x50_VCO_ETH_26P562G_GET(*required_vcos)) {
   1137         *vco = portmodVCO26P562G;
   1138         *is_pcs_bypass = 0;
   1139         PM8x50_VCO_ETH_26P562G_CLR(*required_vcos);
   1140     } else if (PM8x50_VCO_ILKN_26P562G_GET(*required_vcos)) {
   1141         *vco = portmodVCO26P562G;
   1142         *is_pcs_bypass = 1;
   1143         PM8x50_VCO_ILKN_26P562G_CLR(*required_vcos);
   1144     } else if (PM8x50_VCO_ETH_25P781G_GET(*required_vcos)) {
   1145         *vco = portmodVCO25P781G;
   1146         *is_pcs_bypass = 0;
   1147         PM8x50_VCO_ETH_25P781G_CLR(*required_vcos);
   1148     } else if (PM8x50_VCO_ILKN_25P781G_GET(*required_vcos)) {
   1149         *vco = portmodVCO25P781G;
   1150         *is_pcs_bypass = 1;
   1151         PM8x50_VCO_ILKN_25P781G_CLR(*required_vcos);
   1152     } else if (PM8x50_VCO_ILKN_25G_GET(*required_vcos)) {
   1153         *vco = portmodVCO25G;
   1154         *is_pcs_bypass = 1;
   1155         PM8x50_VCO_ILKN_25G_CLR(*required_vcos);
   1156     } else if (PM8x50_VCO_ETH_20P625G_GET(*required_vcos)) {
   1157         *vco = portmodVCO20P625G;
   1158         *is_pcs_bypass = 0;
   1159         PM8x50_VCO_ETH_20P625G_CLR(*required_vcos);
   1160     } else if (PM8x50_VCO_ILKN_20P625G_GET(*required_vcos)) {
   1161         *vco = portmodVCO20P625G;
   1162         *is_pcs_bypass = 1;
   1163         PM8x50_VCO_ILKN_20P625G_CLR(*required_vcos);
   1164     } else if (PM8x50_VCO_ETH_25G_GET(*required_vcos)) {
   1165         /*
   1166          * Ethernet 25G need to be served after Ethernet 20.625G.
   1167          * Because TVCO can never run at 25G, while 20.625G could be
   1168          * TVCO if requested by user.
   1169          */
   1170         *vco = portmodVCO25G;
   1171         *is_pcs_bypass = 0;
   1172         PM8x50_VCO_ETH_25G_CLR(*required_vcos);
   1173     } else {
   1174         _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("Unsupport VCO value! \n")));
   1175     }
   1176 
   1177 exit:
   1178     SOC_FUNC_RETURN;
   1179 }
   1180 
   1181 
   1182 
   1183 /*
   1184  * Get PM active Ethernet port lanes bitmap.
   1185  *
   1186  *    This API doesn't consider the ports whose speeds
   1187  *    are not configured.
   1188  *
   1189  * Inputs:
   1190  *     unit:          unit number;
   1191  *     pm_info:       pm_info data structure;
   1192  *
   1193  * Output:
   1194  *     eth_active_lanes:   active ethernet lane bitmap
   1195  */
   1196 
   1197 STATIC
   1198 int _pm8x50_pm_active_eth_lanes_get(int unit,
   1199                            pm_info_t pm_info,
   1200                            uint8_t * eth_active_lanes)
   1201 {
   1202     int tmp_port, i, is_pcs_bypassed = 0;
   1203     uint8_t ovco_pll_active_lane_bitmap, tvco_pll_active_lane_bitmap;
   1204     uint8_t ovco_pll_adv_lane_bitmap, tvco_pll_adv_lane_bitmap;
   1205     uint8_t all_active_lane_bitmap;
   1206 
   1207     SOC_INIT_FUNC_DEFS;
   1208 
   1209     _SOC_IF_ERR_EXIT(
   1210         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bitmap));
   1211     _SOC_IF_ERR_EXIT(
   1212         PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_active_lane_bitmap));
   1213     _SOC_IF_ERR_EXIT(
   1214         PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bitmap));
   1215     _SOC_IF_ERR_EXIT(
   1216         PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_adv_lane_bitmap));
   1217 
   1218     all_active_lane_bitmap = (ovco_pll_active_lane_bitmap | tvco_pll_active_lane_bitmap |
   1219                               ovco_pll_adv_lane_bitmap | tvco_pll_adv_lane_bitmap);
   1220 
   1221     *eth_active_lanes = 0;
   1222     for(i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   1223         /* Exclude the ports whose speeds are not configured */
   1224         if (all_active_lane_bitmap & (1 << i)) {
   1225             _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port));
   1226             if (tmp_port >= 0) {
   1227                 _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_pcs_bypassed, i));
   1228                 if (!is_pcs_bypassed) {
   1229                     *eth_active_lanes |= (1 << i);
   1230                 }
   1231             }
   1232         }
   1233     }
   1234 exit:
   1235     SOC_FUNC_RETURN;
   1236 }
   1237 
   1238 
   1239 /*
   1240  * Check if the VCO rate served as TVCO rate can drive Ethernet ports.
   1241  *
   1242  * This function will return 1 if the input VCO can drvie
   1243  * Ethernet ports as TVCO rate. Otherwise, return 0.
   1244  *
   1245  * Inputs:
   1246  *   unit    -  Unit number.
   1247  *   flags   -  Flags to decide Ethernet driving TVCO rate. (PM8X50_TVCO_SUPPORT_20P625G)
   1248  *   vco     -  VCO rate to check.
   1249  */
   1250 STATIC
   1251 int _pm8x50_ethernet_tvco_check(int unit,
   1252                                 uint32 flags,
   1253                                 portmod_vco_type_t vco)
   1254 {
   1255     if (PM8X50_TVCO_SUPPORT_20P625G_GET(flags)) {
   1256         return ((vco == portmodVCO25P781G) ||
   1257                 (vco == portmodVCO26P562G) ||
   1258                 (vco == portmodVCO20P625G));
   1259     } else {
   1260         return ((vco == portmodVCO25P781G) || (vco == portmodVCO26P562G));
   1261     }
   1262 
   1263 }
   1264 
   1265 /*Get whether the inerface type is supported by PM */
   1266 int pm8x50_pm_interface_type_is_supported(int unit,
   1267                                           soc_port_if_t interface,
   1268                                           int* is_supported)
   1269 {
   1270 
   1271     switch(interface){
   1272     case SOC_PORT_IF_ILKN:
   1273         *is_supported = FALSE;
   1274         break;
   1275     default:
   1276         *is_supported = TRUE;
   1277     }
   1278 
   1279     return (SOC_E_NONE);
   1280 }
   1281 
   1282 STATIC int
   1283 pm8x50_default_fw_loader(const phymod_core_access_t* core, uint32_t length, const uint8_t* data)
   1284 {
   1285     int rv, bcast_en = 0;
   1286     portmod_default_user_access_t *user_data;
   1287     int unit = ((portmod_default_user_access_t*)core->access.user_acc)->unit;
   1288     portmod_ucode_buf_order_t load_order;
   1289     SOC_INIT_FUNC_DEFS;
   1290 
   1291     user_data = (portmod_default_user_access_t*)core->access.user_acc;
   1292 
   1293     if (PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_GET(user_data)) {
   1294         load_order = portmod_ucode_buf_order_reversed;
   1295     } else {
   1296         load_order = portmod_ucode_buf_order_straight;
   1297     }
   1298 
   1299     rv = portmod_firmware_set(unit,
   1300                               user_data->blk_id,
   1301                               data,
   1302                               length,
   1303                               load_order,
   1304                               bcast_en,
   1305                               &(pm8x50_ucode_buf[unit]),
   1306                               &(pm8x50_ucode_buf_2nd[unit]),
   1307                               CDPORT_TSC_UCMEM_DATAm,
   1308                               CDPORT_TSC_MEM_CTRLr);
   1309     _SOC_IF_ERR_EXIT(rv);
   1310 
   1311 exit:
   1312     SOC_FUNC_RETURN;
   1313 }
   1314 
   1315 
   1316 STATIC
   1317 int
   1318 pm8x50_default_bus_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr,
   1319                          uint32_t val)
   1320 {
   1321     /* will force the core_addr to zero since it's  NOT being used */
   1322     return portmod_common_phy_sbus_reg_write(CDPORT_TSC_UCMEM_DATAm, user_acc,
   1323                                              0x0, reg_addr, val);
   1324 }
   1325 
   1326 STATIC
   1327 int
   1328 pm8x50_default_mem_write(void* user_acc,
   1329                          phymod_mem_type_t mem_type,
   1330                          uint32_t mem_index,
   1331                          const uint32_t* val)
   1332 {
   1333     int rv = SOC_E_NONE;
   1334     soc_mem_t tsc_mem_data;
   1335     const uint32_t *array_ptr;
   1336     portmod_default_user_access_t *user_data = user_acc;
   1337 
   1338     if(user_data == NULL){
   1339         return SOC_E_PARAM;
   1340     }
   1341 
   1342     /* sanity check on the mem_type */
   1343     if (mem_type >= phymodMemCount) {
   1344         return SOC_E_PARAM;
   1345     }
   1346 
   1347     /*next check if simulation */
   1348     if (SAL_BOOT_QUICKTURN) {
   1349         return SOC_E_NONE;
   1350     }
   1351 
   1352     /* next need to map to the correct memory */
   1353     switch (mem_type) {
   1354     case phymodMemSpeedIdTable:
   1355         tsc_mem_data = SPEED_ID_TABLEm;
   1356         break;
   1357     case phymodMemAMTable:
   1358         tsc_mem_data = AM_TABLEm;
   1359         break;
   1360     case phymodMemUMTable:
   1361         tsc_mem_data = UM_TABLEm;
   1362         break;
   1363     case phymodMemTxLkup1588Mpp0:
   1364         tsc_mem_data = TX_LKUP_1588_MEM_MPP0m;
   1365         break;
   1366     case phymodMemTxLkup1588Mpp1:
   1367         tsc_mem_data = TX_LKUP_1588_MEM_MPP1m;
   1368         break;
   1369     case phymodMemTxLkup1588400G:
   1370         tsc_mem_data = TX_LKUP_1588_MEM_400Gm;
   1371         break;
   1372     case phymodMemRxLkup1588Mpp0:
   1373         tsc_mem_data = RX_LKUP_1588_MEM_MPP0m;
   1374         break;
   1375     case phymodMemRxLkup1588Mpp1:
   1376         tsc_mem_data = RX_LKUP_1588_MEM_MPP1m;
   1377         break;
   1378     case phymodMemRxLkup1588400G:
   1379         tsc_mem_data = RX_LKUP_1588_MEM_400Gm;
   1380         break;
   1381     case phymodMemSpeedPriorityMapTable:
   1382         tsc_mem_data = SPEED_PRIORITY_MAP_TBLm;
   1383         break;
   1384     default:
   1385         return SOC_E_PARAM;
   1386     }
   1387     array_ptr = val;
   1388 
   1389     rv = soc_mem_write(user_data->unit, tsc_mem_data, user_data->blk_id, mem_index, (void *) &array_ptr[0]);
   1390 
   1391     return rv;
   1392 }
   1393 
   1394 
   1395 STATIC
   1396 int
   1397 pm8x50_default_bus_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr,
   1398                         uint32_t *val)
   1399 {
   1400     int rv = SOC_E_NONE;
   1401 
   1402     /* will force the core_addr to zero since it's NOT being used */
   1403     rv = portmod_common_phy_sbus_reg_read(CDPORT_TSC_UCMEM_DATAm, user_acc,
   1404                                             0x0, reg_addr, val);
   1405     /* needs to down shift read by 16 bit due to pm8x50 HW change */
   1406     *val = (*val >> 16) & 0xffff;
   1407     return (rv);
   1408 }
   1409 
   1410 STATIC
   1411 int
   1412 pm8x50_default_mem_read(void* user_acc,
   1413                         phymod_mem_type_t mem_type,
   1414                         uint32_t mem_index,
   1415                         uint32_t* val)
   1416 {
   1417     int rv = SOC_E_NONE;
   1418     soc_mem_t tsc_mem_data;
   1419     portmod_default_user_access_t *user_data = user_acc;
   1420 
   1421     if(user_data == NULL){
   1422         return SOC_E_PARAM;
   1423     }
   1424     /* sanity check on the mem_type */
   1425     if (mem_type >= phymodMemCount) {
   1426         return SOC_E_PARAM;
   1427     }
   1428 
   1429     /*next check if simulation */
   1430     if (SAL_BOOT_QUICKTURN) {
   1431         return SOC_E_NONE;
   1432     }
   1433 
   1434     /* next need to map to the correct memory */
   1435     switch (mem_type) {
   1436     case phymodMemSpeedIdTable:
   1437         tsc_mem_data = SPEED_ID_TABLEm;
   1438         break;
   1439     case phymodMemAMTable:
   1440         tsc_mem_data = AM_TABLEm;
   1441         break;
   1442     case phymodMemUMTable:
   1443         tsc_mem_data = UM_TABLEm;
   1444         break;
   1445     case phymodMemTxLkup1588Mpp0:
   1446         tsc_mem_data = TX_LKUP_1588_MEM_MPP0m;
   1447         break;
   1448     case phymodMemTxLkup1588Mpp1:
   1449         tsc_mem_data = TX_LKUP_1588_MEM_MPP1m;
   1450         break;
   1451     case phymodMemTxLkup1588400G:
   1452         tsc_mem_data = TX_LKUP_1588_MEM_400Gm;
   1453         break;
   1454     case phymodMemRxLkup1588Mpp0:
   1455         tsc_mem_data = RX_LKUP_1588_MEM_MPP0m;
   1456         break;
   1457     case phymodMemRxLkup1588Mpp1:
   1458         tsc_mem_data = RX_LKUP_1588_MEM_MPP1m;
   1459         break;
   1460     case phymodMemRxLkup1588400G:
   1461         tsc_mem_data = RX_LKUP_1588_MEM_400Gm;
   1462         break;
   1463     case phymodMemSpeedPriorityMapTable:
   1464         tsc_mem_data = SPEED_PRIORITY_MAP_TBLm;
   1465         break;
   1466     default:
   1467         return SOC_E_PARAM;
   1468     }
   1469 
   1470     rv = soc_mem_read(user_data->unit, tsc_mem_data, user_data->blk_id, mem_index, val);
   1471 
   1472     return rv;
   1473 }
   1474 
   1475 
   1476 /*
   1477  * Function:
   1478  *      portmod_pm8x50_wb_upgrade_func
   1479  * Purpose:
   1480  *      This function will take care of the warmboot variable manipulation
   1481  *      in case of upgrade case, when variable definition got change or
   1482  *      unspoorted varaible from previous version.
   1483  * Parameters:
   1484  *      unit              -(IN) Device unit number .
   1485  *      arg               -(IN) Generic pointer for a specific module to be used
   1486  *      recovered_version -(IN) Warmboot version of the existing data.
   1487  *      new_version       -(IN) Warmboot version of new data.
   1488  * Returns:
   1489  *      Status
   1490  */
   1491 
   1492 int portmod_pm8x50_wb_upgrade_func(int unit, void *arg, int recovered_version,
   1493                                    int new_version)
   1494 {
   1495     pm_info_t pm_info;
   1496     int port_is_pcs_bypased;
   1497     int i, ts_enable_port_count;
   1498     uint32 fec_null, timesync_enable;
   1499     int remote_pause;
   1500 
   1501     SOC_INIT_FUNC_DEFS;
   1502 
   1503     pm_info = arg;
   1504 
   1505     if ((recovered_version <= 1) &&
   1506         (new_version >= 2)) {
   1507         ts_enable_port_count = 0;
   1508         fec_null = 0;
   1509         timesync_enable = 0;
   1510         _SOC_IF_ERR_EXIT(
   1511             PM8x50_TS_ENABLE_PORT_COUNT_SET(unit, pm_info, ts_enable_port_count));
   1512 
   1513         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   1514             _SOC_IF_ERR_EXIT(
   1515                 PM8x50_LANE2FEC_SET(unit, pm_info, i, fec_null));
   1516             _SOC_IF_ERR_EXIT(
   1517                 PM8x50_TIMESYNC_ENABLE_SET(unit, pm_info, timesync_enable, i));
   1518         }
   1519     }
   1520     if ((recovered_version <= 2) &&
   1521         (new_version >= 3)) {
   1522         port_is_pcs_bypased = 0;
   1523 
   1524         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   1525             _SOC_IF_ERR_EXIT(
   1526                 PM8x50_PORT_IS_PCS_BYPASSED_SET(unit, pm_info, port_is_pcs_bypased, i));
   1527         }
   1528     }
   1529     if ((recovered_version <= 3) &&
   1530         (new_version >= 4)) {
   1531         remote_pause = 0;
   1532         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   1533             _SOC_IF_ERR_EXIT(
   1534                 PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, i));
   1535         }
   1536     }
   1537 
   1538 exit:
   1539     SOC_FUNC_RETURN;
   1540 }
   1541 
   1542 /*
   1543  * Initialize the buffer to support warmboot
   1544  * The state of warmboot is store in the variables like
   1545  * isInitialized, isActive, portIsPcsBypassed, ports.. etc.,
   1546  * All of these variables need to be added to warmboot
   1547  * any variables added to save the state of warmboot should be
   1548  * included here.
   1549  */
   1550 STATIC
   1551 int pm8x50_wb_buffer_init(int unit, int wb_buffer_index, pm_info_t pm_info)
   1552 {
   1553     /* Declare the common variables needed for warmboot */
   1554     WB_ENGINE_INIT_TABLES_DEFS;
   1555     int wb_var_id, rv;
   1556     int buffer_id = wb_buffer_index; /*required by SOC_WB_ENGINE_ADD_ Macros*/
   1557     SOC_INIT_FUNC_DEFS;
   1558 
   1559     COMPILER_REFERENCE(buffer_is_dynamic);
   1560 
   1561     SOC_WB_ENGINE_ADD_BUFF(SOC_WB_ENGINE_PORTMOD, wb_buffer_index, "pm8x50",
   1562                            portmod_pm8x50_wb_upgrade_func, pm_info,
   1563                            PM8x50_WB_BUFFER_VERSION, 1,
   1564                            SOC_WB_ENGINE_PRE_RELEASE);
   1565     _SOC_IF_ERR_EXIT(rv);
   1566 
   1567     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1568     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id,
   1569                          "is_core_initialized", wb_buffer_index, sizeof(int),
   1570                           NULL, MAX_PORTS_PER_PM8X50, VERSION(1));
   1571     _SOC_IF_ERR_EXIT(rv);
   1572     pm_info->wb_vars_ids[isCoreInitialized] = wb_var_id;
   1573 
   1574     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1575     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_active",
   1576                           wb_buffer_index, sizeof(uint32), NULL, VERSION(1));
   1577     _SOC_IF_ERR_EXIT(rv);
   1578     pm_info->wb_vars_ids[isActive] = wb_var_id;
   1579 
   1580     /* "isBypassed" has been not supported from version 3 */
   1581     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1582     SOC_WB_ENGINE_REMOVED_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_bypassed", wb_buffer_index, sizeof(uint32),
   1583                               NULL, 1, VERSION(1), VERSION(3));
   1584     _SOC_IF_ERR_EXIT(rv);
   1585     pm_info->wb_vars_ids[isBypassed] = wb_var_id;
   1586 
   1587     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1588     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ovco_pll_active_lane_bitmap",
   1589                           wb_buffer_index, sizeof(uint8), NULL, VERSION(1));
   1590     _SOC_IF_ERR_EXIT(rv);
   1591     pm_info->wb_vars_ids[ovcopllActiveLaneBitmap] = wb_var_id;
   1592 
   1593     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1594     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "tvco_pll_active_lane_bitmap",
   1595                           wb_buffer_index, sizeof(uint8), NULL, VERSION(1));
   1596     _SOC_IF_ERR_EXIT(rv);
   1597     pm_info->wb_vars_ids[tvcopllActiveLaneBitmap] = wb_var_id;
   1598 
   1599     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1600     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ovco_pll_adv_lane_bitmap",
   1601                           wb_buffer_index, sizeof(uint8), NULL, VERSION(1));
   1602     _SOC_IF_ERR_EXIT(rv);
   1603     pm_info->wb_vars_ids[ovcopllAdvLaneBitmap] = wb_var_id;
   1604 
   1605     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1606     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "tvco_pll_adv_lane_bitmap",
   1607                           wb_buffer_index, sizeof(uint8), NULL, VERSION(1));
   1608     _SOC_IF_ERR_EXIT(rv);
   1609     pm_info->wb_vars_ids[tvcopllAdvLaneBitmap] = wb_var_id;
   1610 
   1611     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1612     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "lane2portMap",
   1613                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(1));
   1614     _SOC_IF_ERR_EXIT(rv);
   1615     pm_info->wb_vars_ids[lane2portMap] = wb_var_id;
   1616 
   1617     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1618     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "max_speed",
   1619                           wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(1));
   1620     _SOC_IF_ERR_EXIT(rv);
   1621     pm_info->wb_vars_ids[maxSpeed] = wb_var_id;
   1622 
   1623     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1624     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_mode",
   1625                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(1));
   1626     _SOC_IF_ERR_EXIT(rv);
   1627     pm_info->wb_vars_ids[anMode] = wb_var_id;
   1628 
   1629     /* Deleting below 2 WB structures since they are not needed. */
   1630     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1631     SOC_WB_ENGINE_REMOVED_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_fec", wb_buffer_index, sizeof(uint32),
   1632                               NULL, MAX_PORTS_PER_PM8X50, VERSION(1), VERSION(2));
   1633     _SOC_IF_ERR_EXIT(rv);
   1634     pm_info->wb_vars_ids[anFec] = wb_var_id;
   1635 
   1636     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1637     SOC_WB_ENGINE_REMOVED_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "fs_cl72", wb_buffer_index, sizeof(uint32),
   1638                               NULL, MAX_PORTS_PER_PM8X50, VERSION(1), VERSION(2));
   1639     _SOC_IF_ERR_EXIT(rv);
   1640     pm_info->wb_vars_ids[fsCl72] = wb_var_id;
   1641     
   1642     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1643     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "lane2fecMap",
   1644                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1645     _SOC_IF_ERR_EXIT(rv);
   1646     pm_info->wb_vars_ids[lane2fecMap] = wb_var_id;
   1647 
   1648     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1649 
   1650     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ts_enable_port_count",
   1651                           wb_buffer_index, sizeof(int), NULL, VERSION(2));
   1652     _SOC_IF_ERR_EXIT(rv);
   1653     pm_info->wb_vars_ids[tsEnablePortCount] = wb_var_id;
   1654 
   1655     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1656     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "timesync_enable",
   1657                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1658     _SOC_IF_ERR_EXIT(rv);
   1659     pm_info->wb_vars_ids[timesyncEnable] = wb_var_id;
   1660 
   1661     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1662     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "rlm_enabled",
   1663                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1664     _SOC_IF_ERR_EXIT(rv);
   1665     pm_info->wb_vars_ids[rlmEnable] = wb_var_id;
   1666 
   1667     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1668     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_initiator",
   1669                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1670     _SOC_IF_ERR_EXIT(rv);
   1671     pm_info->wb_vars_ids[initiator] = wb_var_id;
   1672 
   1673     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1674     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "pcs_reconfigured",
   1675                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1676     _SOC_IF_ERR_EXIT(rv);
   1677     pm_info->wb_vars_ids[pcsReconfigured] = wb_var_id;
   1678 
   1679     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1680     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "active_lame_map",
   1681                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1682     _SOC_IF_ERR_EXIT(rv);
   1683     pm_info->wb_vars_ids[activeLaneBitMap] = wb_var_id;
   1684 
   1685     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1686     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "rlm_state",
   1687                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1688     _SOC_IF_ERR_EXIT(rv);
   1689     pm_info->wb_vars_ids[rlmState] = wb_var_id;
   1690 
   1691     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1692     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "fec_type",
   1693                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1694     _SOC_IF_ERR_EXIT(rv);
   1695     pm_info->wb_vars_ids[originalFec] = wb_var_id;
   1696 
   1697     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1698     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "tx_lane_swap",
   1699                           wb_buffer_index, sizeof(int), NULL, VERSION(2));
   1700     _SOC_IF_ERR_EXIT(rv);
   1701     pm_info->wb_vars_ids[originalTxLaneSwap] = wb_var_id;
   1702 
   1703     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1704     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "rx_lane_swap",
   1705                           wb_buffer_index, sizeof(int), NULL, VERSION(2));
   1706     _SOC_IF_ERR_EXIT(rv);
   1707     pm_info->wb_vars_ids[originalRxLaneSwap] = wb_var_id;
   1708 
   1709     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1710     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "400g_an_enable",
   1711                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(2));
   1712     _SOC_IF_ERR_EXIT(rv);
   1713     pm_info->wb_vars_ids[is400gAn] = wb_var_id;
   1714 
   1715     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1716     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_state_400g",
   1717                           wb_buffer_index, sizeof(int), NULL, VERSION(2));
   1718     _SOC_IF_ERR_EXIT(rv);
   1719     pm_info->wb_vars_ids[anState400g] = wb_var_id;
   1720 
   1721     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1722     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_wait_link_count",
   1723                           wb_buffer_index, sizeof(int), NULL, VERSION(2));
   1724     _SOC_IF_ERR_EXIT(rv);
   1725     pm_info->wb_vars_ids[anWaitlinkCount] = wb_var_id;
   1726 
   1727     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1728     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "port_is_pcs_bypassed",
   1729                           wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(3));
   1730     _SOC_IF_ERR_EXIT(rv);
   1731     pm_info->wb_vars_ids[portIsPcsBypassed] = wb_var_id;
   1732 
   1733     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1734     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_ber_war_enable",
   1735                            wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
   1736     _SOC_IF_ERR_EXIT(rv);
   1737     pm_info->wb_vars_ids[isBerWarEnable] = wb_var_id;
   1738 
   1739     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1740     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ber_war_state",
   1741                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
   1742     _SOC_IF_ERR_EXIT(rv);
   1743     pm_info->wb_vars_ids[berWarState] = wb_var_id;
   1744 
   1745     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1746     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ber_war_wait_count",
   1747                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
   1748     _SOC_IF_ERR_EXIT(rv);
   1749     pm_info->wb_vars_ids[berWarWaitCount] = wb_var_id;
   1750 
   1751     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id,
   1752                          "is_core_flexe_configured", wb_buffer_index, sizeof(int),
   1753                           NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
   1754     _SOC_IF_ERR_EXIT(rv);
   1755     pm_info->wb_vars_ids[coreisFlexeConfigured] = wb_var_id;
   1756 
   1757     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
   1758     SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_400g_remote_pause",
   1759                           wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
   1760     _SOC_IF_ERR_EXIT(rv);
   1761     pm_info->wb_vars_ids[an400gRemotePause] = wb_var_id;
   1762 
   1763     _SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD,
   1764                                                wb_buffer_index, FALSE));
   1765 
   1766 exit:
   1767     SOC_FUNC_RETURN;
   1768 }
   1769 
   1770 phymod_bus_t pm8x50_default_bus = {
   1771     "PM8x50 Bus",
   1772     pm8x50_default_bus_read,
   1773     pm8x50_default_bus_write,
   1774     NULL,
   1775     portmod_common_mutex_take,
   1776     portmod_common_mutex_give,
   1777     pm8x50_default_mem_read,
   1778     pm8x50_default_mem_write,
   1779     PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL
   1780 };
   1781 
   1782 STATIC
   1783 int _pm8x50_pll_to_vco_get(phymod_ref_clk_t ref_clock, uint32_t pll, portmod_vco_type_t* vco)
   1784 {
   1785     int rv = SOC_E_NONE;
   1786 
   1787     if (ref_clock == phymodRefClk156Mhz) {
   1788         switch (pll) {
   1789             case phymod_TSCBH_PLL_DIV132:
   1790                 *vco = portmodVCO20P625G;
   1791                 break;
   1792             case phymod_TSCBH_PLL_DIV165:
   1793                 *vco = portmodVCO25P781G;
   1794                 break;
   1795             case phymod_TSCBH_PLL_DIV170:
   1796                 *vco = portmodVCO26P562G;
   1797                 break;
   1798             case phymod_TSCBH_PLL_DIV160:
   1799                 *vco = portmodVCO25G;
   1800                 break;
   1801             case phymod_TSCBH_PLL_DIV175:
   1802                 *vco = portmodVCO27P343G;
   1803                 break;
   1804             case phymod_TSCBH_PLL_DIV180:
   1805                 *vco = portmodVCO28P125G;
   1806                 break;
   1807             default:
   1808                 rv = SOC_E_PARAM;
   1809         }
   1810     } else if (ref_clock == phymodRefClk312Mhz) {
   1811         switch (pll) {
   1812             case phymod_TSCBH_PLL_DIV66:
   1813                 *vco = portmodVCO20P625G;
   1814                 break;
   1815             case phymod_TSCBH_PLL_DIV82P5:
   1816                 *vco = portmodVCO25P781G;
   1817                 break;
   1818             case phymod_TSCBH_PLL_DIV85:
   1819                 *vco = portmodVCO26P562G;
   1820                 break;
   1821             case phymod_TSCBH_PLL_DIV80:
   1822                 *vco = portmodVCO25G;
   1823                 break;
   1824             case phymod_TSCBH_PLL_DIV87P5:
   1825                 *vco = portmodVCO27P343G;
   1826                 break;
   1827             case phymod_TSCBH_PLL_DIV90:
   1828                 *vco = portmodVCO28P125G;
   1829                 break;
   1830             default:
   1831                 rv = SOC_E_PARAM;
   1832         }
   1833     } else {
   1834         rv = SOC_E_PARAM;
   1835     }
   1836 
   1837     return rv;
   1838 }
   1839 
   1840 /* Translate phymod_fec type to portmod_fec_type */
   1841 STATIC
   1842 int _pm8x50_port_phy_to_port_fec(phymod_fec_type_t phymod_fec, portmod_fec_t* portmod_fec)
   1843 {
   1844     int rv = SOC_E_NONE;
   1845     if (phymod_fec == phymod_fec_None) {
   1846         *portmod_fec = PORTMOD_PORT_PHY_FEC_NONE;
   1847     } else if (phymod_fec == phymod_fec_CL74) {
   1848         *portmod_fec = PORTMOD_PORT_PHY_FEC_BASE_R;
   1849     } else if (phymod_fec == phymod_fec_CL91) {
   1850         *portmod_fec = PORTMOD_PORT_PHY_FEC_RS_FEC;
   1851     } else if (phymod_fec == phymod_fec_RS544) {
   1852         *portmod_fec = PORTMOD_PORT_PHY_FEC_RS_544;
   1853     } else if (phymod_fec == phymod_fec_RS272) {
   1854         *portmod_fec = PORTMOD_PORT_PHY_FEC_RS_272;
   1855     } else if (phymod_fec == phymod_fec_RS544_2XN) {
   1856         *portmod_fec = PORTMOD_PORT_PHY_FEC_RS_544_2XN;
   1857     } else if (phymod_fec == phymod_fec_RS272_2XN) {
   1858         *portmod_fec  = PORTMOD_PORT_PHY_FEC_RS_272_2XN;
   1859     } else {
   1860         rv = SOC_E_PARAM;
   1861     }
   1862     return rv;
   1863 }
   1864 
   1865 
   1866 
   1867 /* this function is to  manage the RLM state machine during PORT
   1868 transition into RLM mode 
   1869 */
   1870 
   1871 int pm8x50_port_rlm_state_update(int unit, int port, pm_info_t pm_info, int *is_done)
   1872 {
   1873     portmod_access_get_params_t params;
   1874     phymod_phy_access_t phy_access, phy_copy;
   1875     uint32  rval, is_initiator, pcs_is_reconfigured, active_lane_map, active_lane_num;
   1876     phymod_fec_type_t FecType;
   1877     uint32 txLaneSwap, rxLaneSwap, bitmap, prbs_active_lane_num = 0, prbs_active_lane_map = 0x0, num_lane = 0;
   1878     portmod_port_rlm_state_t local_port_rlm_state;
   1879     int nof_phys,  port_index = -1, mac_link = 0;
   1880     uint32 prbs_flag = 0x0, i;
   1881     phymod_prbs_t prbs_config;
   1882     phymod_prbs_status_t prbs_status;
   1883     char* state_string = " \n";
   1884 
   1885 
   1886     SOC_INIT_FUNC_DEFS;
   1887 
   1888     *is_done = 0;
   1889 
   1890     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   1891     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   1892                                 &params, 1, &phy_access, &nof_phys, NULL));
   1893 
   1894     sal_memcpy(&phy_copy, &phy_access, sizeof(phy_copy));
   1895 
   1896     /* need to know if 4 lane or 8 lane port and also start lane of this port */
   1897     PORTMOD_BIT_COUNT(phy_access.access.lane_mask, num_lane);
   1898     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   1899 
   1900     /* first get all the RLM warmboot variable */
   1901     _SOC_IF_ERR_EXIT
   1902         (PM8x50_INITIATOR_GET(unit, pm_info, &is_initiator, port_index));
   1903 
   1904     _SOC_IF_ERR_EXIT
   1905         (PM8x50_PCS_RECONFIG_GET(unit, pm_info, &pcs_is_reconfigured, port_index));
   1906 
   1907     _SOC_IF_ERR_EXIT
   1908         (PM8x50_ACTIVE_LANE_MAP_GET(unit, pm_info, &active_lane_map, port_index));
   1909 
   1910     _SOC_IF_ERR_EXIT
   1911         (PM8x50_RLM_STATE_GET(unit, pm_info, &local_port_rlm_state.rlm_state, port_index));
   1912 
   1913     _SOC_IF_ERR_EXIT
   1914         (PM8x50_ORIGINAL_FEC_GET(unit, pm_info, &FecType, port_index));
   1915 
   1916     _SOC_IF_ERR_EXIT
   1917         (PM8x50_ORIG_TX_LANE_MAP_GET(unit, pm_info, &txLaneSwap));
   1918 
   1919     _SOC_IF_ERR_EXIT
   1920         (PM8x50_ORIG_RX_LANE_MAP_GET(unit, pm_info, &rxLaneSwap));
   1921 
   1922     /* get the active lane number */
   1923     active_lane_num = 0;
   1924     for (i = 0; i < num_lane; i++) {
   1925         if (active_lane_map &  1 << (port_index + i)) {
   1926             active_lane_num++;
   1927         }
   1928     }
   1929 
   1930     /* first thing is to check MAC link status */
   1931     if (port_index == 4) {
   1932         _SOC_IF_ERR_EXIT(
   1933             READ_CDPORT_XGXS0_LN4_STATUS_REGr(unit, port, &rval));
   1934         mac_link = soc_reg_field_get(unit, CDPORT_XGXS0_LN4_STATUS_REGr, rval, LINK_STATUSf);
   1935 
   1936     } else {
   1937         _SOC_IF_ERR_EXIT(
   1938             READ_CDPORT_XGXS0_LN0_STATUS_REGr(unit, port, &rval));
   1939         mac_link = soc_reg_field_get(unit, CDPORT_XGXS0_LN0_STATUS_REGr, rval, LINK_STATUSf);
   1940     }
   1941 
   1942     /* if mac link status ever go low, directly go to error state */
   1943      if (!mac_link)  {
   1944         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_ERROR;
   1945     } else    {
   1946         /* RLM state machine update */
   1947         switch (local_port_rlm_state.rlm_state) {
   1948         case PORTMOD_PORT_RLM_SEND_PACKET_DATA:
   1949             state_string ="SEND_PACKET_DATA";
   1950             /* first disable tx stall */
   1951              _SOC_IF_ERR_EXIT
   1952                 (cdmac_tx_stall_enable_set(unit, port, 0));
   1953 
   1954             /* first check initiator  set or not */
   1955             if (is_initiator) {
   1956                 /* update the state */
   1957                 local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_STOP_MAC;
   1958             } else { /* follower */
   1959                 /* first if link interruption status */
   1960                 uint32  li_status = 0;
   1961                 _SOC_IF_ERR_EXIT
   1962                     (cdmac_link_interruption_live_status_get(unit, port, &li_status));
   1963                 if (li_status) {
   1964                     /* update the state */
   1965                     local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_STOP_MAC;
   1966                 }
   1967             }
   1968             break;
   1969         case PORTMOD_PORT_RLM_STOP_MAC:
   1970             state_string ="STOP_MAC";
   1971             /* clear the pcs reconfigured */
   1972             pcs_is_reconfigured = FALSE;
   1973             /* enable tx stall */
   1974              _SOC_IF_ERR_EXIT
   1975                 (cdmac_tx_stall_enable_set(unit, port, 1));
   1976             /* update the state to SEND_LI*/
   1977             local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_LI;
   1978             break;
   1979         case PORTMOD_PORT_RLM_SEND_LI:
   1980         {
   1981             uint32 li_enable = 0, prbs_enabled = 0, li_status;
   1982             int pcs_link = 0;
   1983 
   1984             state_string ="SEND_LI";
   1985 
   1986             /* first check if LI is enabled or not */
   1987             _SOC_IF_ERR_EXIT
   1988                 (cdmac_link_interrupt_ordered_set_enable_get(unit, port, &li_enable));
   1989             if (!li_enable) {
   1990                 _SOC_IF_ERR_EXIT
   1991                     (cdmac_link_interrupt_ordered_set_enable(unit, port, 1));
   1992             }
   1993             /*next check if initiator */
   1994             if (is_initiator) {
   1995                 /* if initiator, then check pcs reconfigured status */
   1996                 if (pcs_is_reconfigured) {
   1997                     /*next need to check prbs status */
   1998                     _SOC_IF_ERR_EXIT
   1999                         (phymod_phy_prbs_enable_get(&phy_access, 0, &prbs_enabled));
   2000                     if (prbs_enabled) {
   2001                         /* disable prbs for both tx/rx */
   2002                         _SOC_IF_ERR_EXIT
   2003                             (phymod_phy_prbs_enable_set(&phy_access, 0, 0));
   2004                         /* disable the tx/disable and lane dp reset override */
   2005                         _SOC_IF_ERR_EXIT
   2006                             (phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDLaneReset, 0,  0));
   2007                         _SOC_IF_ERR_EXIT
   2008                             (phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDTxDisable, 0,  0));
   2009                     }
   2010                     /* next poll the pcs link status and LI status */
   2011                     _SOC_IF_ERR_EXIT
   2012                         (cdmac_link_interruption_live_status_get(unit, port, &li_status));
   2013                    /* read twice the pcs link status */
   2014                     _SOC_IF_ERR_EXIT
   2015                         (pm8x50_port_link_get(unit, port, pm_info, 0,  &pcs_link));
   2016                     _SOC_IF_ERR_EXIT
   2017                         (pm8x50_port_link_get(unit, port, pm_info, 0,  &pcs_link));
   2018                     if (li_status && pcs_link) {
   2019                         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_IDLE;
   2020                     }
   2021                 } else { /* pcs is not reconfigured */
   2022                     /* need to check LI status */
   2023                     _SOC_IF_ERR_EXIT
   2024                         (cdmac_link_interruption_live_status_get(unit, port, &li_status));
   2025                     if (li_status) {
   2026                         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_PRBS;
   2027                     }
   2028                 }
   2029             } else { /*non initiator */
   2030                 if (pcs_is_reconfigured) {
   2031                     /*next need to check prbs status */
   2032                     _SOC_IF_ERR_EXIT
   2033                         (phymod_phy_prbs_enable_get(&phy_access, 0, &prbs_enabled));
   2034                     if (prbs_enabled) {
   2035                         /* disable prbs for both tx/rx */
   2036                         _SOC_IF_ERR_EXIT
   2037                             (phymod_phy_prbs_enable_set(&phy_access, 0, 0));
   2038                         /* disable the tx/disable and lane dp reset override */
   2039                         _SOC_IF_ERR_EXIT
   2040                             (phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDLaneReset, 0,  0));
   2041                         _SOC_IF_ERR_EXIT
   2042                             (phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDTxDisable, 0,  0));
   2043                     }
   2044                     /* next poll the pcs link status and LI status */
   2045                     _SOC_IF_ERR_EXIT
   2046                         (cdmac_link_interruption_live_status_get(unit, port, &li_status));
   2047                    /* read twice the pcs link status */
   2048                     _SOC_IF_ERR_EXIT
   2049                         (pm8x50_port_link_get(unit, port, pm_info, 0,  &pcs_link));
   2050                     _SOC_IF_ERR_EXIT
   2051                         (pm8x50_port_link_get(unit, port, pm_info, 0,  &pcs_link));
   2052                     if (li_status && pcs_link) {
   2053                         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_IDLE;
   2054                     }
   2055                 } else { /* pcs is not reconfigured yet */
   2056                     uint32 prbs_active_lane_num = 0, prbs_active_lane_map = 0x0, pmd_lock = 0;
   2057                     prbs_flag = 0x0;
   2058 
   2059                     /* first set RX prbs only  and check if rx prbs is enabled or not*/
   2060                     PHYMOD_PRBS_DIRECTION_RX_SET(prbs_flag);
   2061                     _SOC_IF_ERR_EXIT
   2062                         (phymod_phy_prbs_enable_get(&phy_access, prbs_flag, &prbs_enabled));
   2063                     if (!prbs_enabled) {
   2064                         prbs_config.poly = phymodPrbsPoly13;
   2065                         prbs_config.invert = 0;
   2066                         _SOC_IF_ERR_EXIT
   2067                             (phymod_phy_prbs_config_set(&phy_access, prbs_flag, &prbs_config));
   2068                         _SOC_IF_ERR_EXIT
   2069                             (phymod_phy_prbs_enable_set(&phy_access, prbs_flag, 1));
   2070                     }
   2071 
   2072                     /*before check the prbs status, make sure signal detection are valid on all lanes*/
   2073                     _SOC_IF_ERR_EXIT
   2074                         (phymod_phy_rx_pmd_locked_get(&phy_access, &pmd_lock));
   2075                     sal_usleep(100);
   2076                     _SOC_IF_ERR_EXIT
   2077                         (phymod_phy_rx_pmd_locked_get(&phy_access, &pmd_lock));
   2078 
   2079                     /* next check per lane prbs status only if PMD is locked */
   2080                     if ((pmd_lock) && (!is_initiator)) {
   2081                         /* next check per lane prbs status */
   2082                         for (i = 0; i < num_lane; i ++) {
   2083                             phy_copy.access.lane_mask = 1 << (i + port_index);
   2084                             /*first read clear the status */
   2085                             _SOC_IF_ERR_EXIT
   2086                                 (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2087 
   2088                             sal_usleep(100);
   2089 
   2090                             _SOC_IF_ERR_EXIT
   2091                                 (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2092                             /* next check the lock status */
   2093                             if (prbs_status.prbs_lock) {
   2094                                 prbs_active_lane_num++;
   2095                                 prbs_active_lane_map |= 1 << (i + port_index);
   2096                             }
   2097                         }
   2098                         /* next check active lane PRBS status */
   2099                         if ( ((num_lane == 4) && (prbs_active_lane_num == 3)) ||
   2100                              ((num_lane == 4) && (prbs_active_lane_num == 4)) ||
   2101                              ((num_lane == 8) && (prbs_active_lane_num == 8)) ||
   2102                              ((num_lane == 8) && (prbs_active_lane_num == 6)) ||
   2103                              ((num_lane == 8) && (prbs_active_lane_num == 7)) ) {
   2104 
   2105                             if (active_lane_map == prbs_active_lane_map) {
   2106                                 local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_PRBS;
   2107                             } else {
   2108                                 active_lane_map = prbs_active_lane_map;
   2109                             }
   2110                         }
   2111                     }
   2112                 } /* end of pcs not configured for follower */
   2113             }
   2114             break;
   2115         } /* end of this  LI case */
   2116         case PORTMOD_PORT_RLM_SEND_PRBS:
   2117         {
   2118             uint32 first_active_lane_num = 0, prbs_enabled  = 0, need_reconfig_pcs = 0;
   2119             int follower_prbs_resend = 0;
   2120             prbs_flag = 0;
   2121 
   2122             state_string ="SEND_PRBS";
   2123 
   2124             /*first for follower check the prbs lane active map */
   2125             if ((!is_initiator) && (!pcs_is_reconfigured)) {
   2126                 /* next check per lane prbs status */
   2127                 for (i = 0; i < num_lane; i ++) {
   2128                     phy_copy.access.lane_mask = 1 << (i + port_index);
   2129                     /*first read clear the status */
   2130                     _SOC_IF_ERR_EXIT
   2131                         (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2132 
   2133                     sal_usleep(100);
   2134                     /* next read the status */
   2135                     _SOC_IF_ERR_EXIT
   2136                         (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2137                     /*first read clear the status */
   2138                     /* next check the lock status */
   2139                     if (prbs_status.prbs_lock) {
   2140                         prbs_active_lane_num++;
   2141                         prbs_active_lane_map |= 1 << (i + port_index);
   2142                     }
   2143                 }
   2144 
   2145                 if ((prbs_active_lane_map != active_lane_map) && (prbs_active_lane_map != 0x0)) {
   2146                     active_lane_map = prbs_active_lane_map;
   2147                     follower_prbs_resend = 1;
   2148                 }
   2149             }
   2150 
   2151             /* first set TX prbs only  and check if tx prbs is enabled or not*/
   2152             /* only if the pcs is not reconfigured */
   2153             if (!pcs_is_reconfigured) {
   2154                 for (i = 0; i < num_lane; i++) {
   2155                     if (active_lane_map &  1 << (port_index + i)) {
   2156                         first_active_lane_num = port_index + i;
   2157                         break;
   2158                     }
   2159                 }
   2160                 PHYMOD_PRBS_DIRECTION_TX_SET(prbs_flag);
   2161                 phy_copy.access.lane_mask = 1 << first_active_lane_num;
   2162                 _SOC_IF_ERR_EXIT
   2163                     (phymod_phy_prbs_enable_get(&phy_copy, prbs_flag, &prbs_enabled));
   2164                 /* enable tx prbs if not enabled */
   2165                 prbs_config.invert = 0;
   2166 
   2167                 if ((!prbs_enabled) || follower_prbs_resend)  {
   2168                     for (i = 0; i < num_lane; i++) {
   2169                         phy_copy.access.lane_mask = 1 << (port_index + i);
   2170                         if (active_lane_map &  1 << (port_index + i)) {
   2171                             /* if active lane, use prbspoly13 */
   2172                             prbs_config.poly = phymodPrbsPoly13;
   2173                         } else {
   2174                             /* if inactive lane, use prbspoly31 */
   2175                             prbs_config.poly = phymodPrbsPoly31;
   2176                         }
   2177                         /* enable prbs on a per lane basis */
   2178                         _SOC_IF_ERR_EXIT
   2179                             (phymod_phy_prbs_config_set(&phy_copy, prbs_flag, &prbs_config));
   2180                         _SOC_IF_ERR_EXIT
   2181                             (phymod_phy_prbs_enable_set(&phy_copy, prbs_flag, 1));
   2182                         /* set tx_disable and pmd lane reset override enable */
   2183                         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_copy, phymodPMDTxDisable, 1, 0));
   2184                         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_copy, phymodPMDLaneReset, 1, 1));
   2185                     }
   2186                     /* next check if initiator  */
   2187                     if (is_initiator) {
   2188                         prbs_flag = 0;
   2189                         prbs_config.invert = 0;
   2190                         prbs_config.poly = phymodPrbsPoly13;
   2191                         PHYMOD_PRBS_DIRECTION_RX_SET(prbs_flag);
   2192                         _SOC_IF_ERR_EXIT
   2193                             (phymod_phy_prbs_config_set(&phy_access, prbs_flag, &prbs_config));
   2194                         _SOC_IF_ERR_EXIT
   2195                             (phymod_phy_prbs_enable_set(&phy_access, prbs_flag, 1));
   2196                     }
   2197                 }
   2198             }
   2199 
   2200             /* next check prbs rx status if initiator */
   2201             if ((is_initiator) && (!pcs_is_reconfigured)) {
   2202                 prbs_active_lane_num = 0;
   2203                 prbs_active_lane_map = 0x0;
   2204                 for (i = 0; i < num_lane; i++) {
   2205                     phy_copy.access.lane_mask = 1 << (port_index + i);
   2206                     /*first read clear the status */
   2207                     _SOC_IF_ERR_EXIT
   2208                         (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2209                     sal_usleep(500);
   2210                     /* first read clear the status */
   2211                     _SOC_IF_ERR_EXIT
   2212                         (phymod_phy_prbs_status_get(&phy_copy, 0, &prbs_status));
   2213                     /* next check the lock status */
   2214                     if (prbs_status.prbs_lock) {
   2215                         prbs_active_lane_num++;
   2216                         prbs_active_lane_map |= 1 << (i + port_index);
   2217                     }
   2218                 }
   2219             }
   2220 
   2221             /* next check the prbs active lane map if initiator*/
   2222             if ((is_initiator) && (prbs_active_lane_map == active_lane_map) && (!pcs_is_reconfigured)) {
   2223                 need_reconfig_pcs = 1;
   2224             } else if ((!is_initiator) && (!pcs_is_reconfigured) && (!follower_prbs_resend)) {
   2225                 need_reconfig_pcs = 1;
   2226             }
   2227 
   2228             /* check pcs needs to be re-configured if it's no re-congiured already */
   2229             if (need_reconfig_pcs) {
   2230                 phymod_fec_type_t fec_type;
   2231                 /* need to reconfigure the pcs */
   2232                 /* first disable pcs of the port */
   2233                 phy_copy.access.lane_mask = 1 << port_index;
   2234                 _SOC_IF_ERR_EXIT
   2235                     (phymod_phy_pcs_enable_set(&phy_access, 0));
   2236                 /*set the rx lock and sig detection override */
   2237                 _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDRxLock, 1, 1));
   2238                 _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDSignalDetect, 1, 1));
   2239 
   2240                 /* need to adjust the pcs lane swap */
   2241                 _SOC_IF_ERR_EXIT
   2242                     (phymod_phy_pcs_lane_swap_adjust(&phy_access, active_lane_map, txLaneSwap, rxLaneSwap));
   2243 
   2244                 /*then disablethe rx lock and sig detection override */
   2245                 _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDRxLock, 0, 0));
   2246                 _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDSignalDetect, 0, 0));
   2247 
   2248                 /* then load the speed id based on the active lane num */
   2249                 if ((active_lane_num == 4) || (active_lane_num == 8)) {
   2250                     fec_type = FecType;
   2251                 } else {
   2252                     /* for all the reduced lane speed, only 544_2xn is valid */
   2253                     fec_type = phymod_fec_RS544_2XN;
   2254                 }
   2255                 _SOC_IF_ERR_EXIT
   2256                     (phymod_phy_load_speed_id_entry(&phy_access, 50000 * active_lane_num, active_lane_num, fec_type));
   2257 
   2258                 /* next re-enable pcs */
   2259                 phy_copy.access.lane_mask = 1 << port_index;
   2260                 _SOC_IF_ERR_EXIT
   2261                     (phymod_phy_pcs_enable_set(&phy_access, 1));
   2262                 /* set the warm boot variable */
   2263                 pcs_is_reconfigured = TRUE;
   2264             }
   2265 
   2266             if (is_initiator && need_reconfig_pcs) {
   2267                 local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_LI;
   2268             } else if (!is_initiator) {
   2269                 /* for follower, need to check LI status */
   2270                 uint32 li_status = 0;
   2271                 _SOC_IF_ERR_EXIT
   2272                     (cdmac_link_interruption_live_status_get(unit, port, &li_status));
   2273                 if (li_status) {
   2274                     local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_LI;
   2275                 }
   2276             }
   2277             break;
   2278         }
   2279         case PORTMOD_PORT_RLM_SEND_IDLE:
   2280         {
   2281             uint32 li_enable, li_status, reg_val;
   2282             int local_fault_status, remote_fault_status;
   2283 
   2284             state_string ="SEND_ILDE";
   2285 
   2286             /* first check if LI is enabled or not */
   2287             _SOC_IF_ERR_EXIT
   2288                 (cdmac_link_interrupt_ordered_set_enable_get(unit, port, &li_enable));
   2289             /* disable LI if LI is enabled */
   2290             if (li_enable) {
   2291                 _SOC_IF_ERR_EXIT
   2292                     (cdmac_link_interrupt_ordered_set_enable(unit, port, 0));
   2293             }
   2294             /* next check idles are valid */
   2295             _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &reg_val));
   2296             li_status = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, reg_val, LINK_INTERRUPTION_LIVE_STATUSf);
   2297             local_fault_status = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, reg_val, LOCAL_FAULT_STATUSf);
   2298             remote_fault_status = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, reg_val, REMOTE_FAULT_STATUSf);
   2299             /* idle is valid only if none of the above three status are 0 */
   2300             if( (!li_status && !local_fault_status && !remote_fault_status) ||
   2301                  (!is_initiator) ) {
   2302                 local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_DONE;
   2303                 /* clear tx stall */
   2304                 _SOC_IF_ERR_EXIT
   2305                    (cdmac_tx_stall_enable_set(unit, port, 0));
   2306             }
   2307             break;
   2308         }
   2309         case PORTMOD_PORT_RLM_ERROR:
   2310             state_string ="ERROR";
   2311             *is_done = 1;
   2312             break;
   2313         case PORTMOD_PORT_RLM_DONE:
   2314             state_string ="DONE";
   2315             *is_done = 1;
   2316             /* do nothing */
   2317             break;
   2318         default:
   2319             *is_done = 1;
   2320             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   2321                                (_SOC_MSG("RLM state not supported \n")));
   2322             break;
   2323         }
   2324     }
   2325 
   2326     /* finally restore all the Warm boot variables */
   2327     _SOC_IF_ERR_EXIT
   2328         (PM8x50_INITIATOR_SET(unit, pm_info, is_initiator, port_index));
   2329 
   2330     _SOC_IF_ERR_EXIT
   2331         (PM8x50_PCS_RECONFIG_SET(unit, pm_info, pcs_is_reconfigured, port_index));
   2332 
   2333     _SOC_IF_ERR_EXIT
   2334         (PM8x50_ACTIVE_LANE_MAP_SET(unit, pm_info, active_lane_map, port_index));
   2335 
   2336     _SOC_IF_ERR_EXIT
   2337         (PM8x50_RLM_STATE_SET(unit, pm_info, local_port_rlm_state.rlm_state, port_index));
   2338 
   2339     LOG_VERBOSE(BSL_LS_SOC_PHY,
   2340                 (BSL_META_U(unit,
   2341                             "port %d RLM state is %-23s \n"),
   2342                  port, state_string));
   2343 
   2344 exit:
   2345     SOC_FUNC_RETURN;
   2346 }
   2347 
   2348 
   2349 static int pm8x50_periodic_callback(int unit, int port)
   2350 {
   2351     pm_info_t pm_info;
   2352     int port_index, rlm_enabled, rlm_state, is_400g_an, an_400g_state;
   2353     uint32 bitmap;
   2354     int rlm_done = 1, an_done = 1;
   2355 
   2356     SOC_INIT_FUNC_DEFS;
   2357 
   2358 
   2359     _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, port, &pm_info));
   2360 
   2361     /* LOG_ERROR(BSL_LS_SOC_PORT,
   2362                   (BSL_META_U(unit, "Callback was called port=%d\n"), port)); */
   2363 
   2364     /* get port index */
   2365     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   2366 
   2367     /* first get all the RLM warmboot variable */
   2368     _SOC_IF_ERR_EXIT
   2369         (PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, port_index));
   2370 
   2371     _SOC_IF_ERR_EXIT
   2372         (PM8x50_RLM_STATE_GET(unit, pm_info, &rlm_state, port_index));
   2373 
   2374     /* read the 400G an enabled */
   2375     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   2376 
   2377    /* check if RLM state machine needs to be updated */
   2378    if (rlm_enabled == 1) {
   2379         /*next check only state is not done or error */
   2380         if ((rlm_state != PORTMOD_PORT_RLM_DONE) && (rlm_state != PORTMOD_PORT_RLM_ERROR)) {
   2381             _SOC_IF_ERR_EXIT(pm8x50_port_rlm_state_update(unit, port, pm_info, &rlm_done));
   2382         }
   2383     }
   2384 
   2385     /* check if 400G an state machine needs to be updated */
   2386     if (is_400g_an) {
   2387         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_GET(unit, pm_info, &an_400g_state));
   2388         if (an_400g_state < PM8X50_PORT_AN_COMPLETE) {
   2389             _SOC_IF_ERR_EXIT(_pm8x50_400g_an_workaround(unit, port, pm_info, &an_done));
   2390         }
   2391     }
   2392 
   2393     /* if both signal unregister - go for it */
   2394     if (rlm_done && an_done) {
   2395         _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_unregister(unit, port));
   2396     }
   2397 
   2398 
   2399 exit:
   2400     SOC_FUNC_RETURN;
   2401 }
   2402 
   2403 
   2404 /*Add new pm.*/
   2405 int pm8x50_pm_init(int unit,
   2406                    const portmod_pm_create_info_internal_t* pm_add_info,
   2407                    int wb_buffer_index,
   2408                    pm_info_t pm_info)
   2409 {
   2410     const portmod_pm8x50_create_info_t *info =
   2411                 &pm_add_info->pm_specific_info.pm8x50;
   2412     pm8x50_t pm8x50_data = NULL;
   2413     int i, rv;
   2414     int pm_is_active, ts_enable_port_count, is_initiator, pcs_reconfigured, active_lane_map;
   2415     int is_core_initialized, fec, invalid_port, rlm_state, fecType, txLaneMap, rxLaneMap, rlm_enabled;
   2416     int an_state, is_400g_an, an_wait_link_count, is_ber_war_enable = 0, ber_war_state = 0, ber_war_wait_count = 0;
   2417     int core_is_flexe_configured, remote_pause;
   2418     uint8 ovco_pll_adv_lane_bitmap, tvco_pll_adv_lane_bitmap;
   2419     uint8 ovco_pll_active_lane_bitmap, tvco_pll_active_lane_bitmap;
   2420     int probe= 0;
   2421     uint32_t pll_div;
   2422     phymod_phy_access_t phy_access;
   2423     portmod_vco_type_t vco;
   2424     int phy;
   2425     SOC_INIT_FUNC_DEFS;
   2426 
   2427     pm_info->type = pm_add_info->type;
   2428     pm_info->unit = unit;
   2429     pm_info->wb_buffer_id = wb_buffer_index;
   2430 
   2431     /* PM8x50 specific info */
   2432     pm8x50_data = sal_alloc(sizeof(struct pm8x50_s), "specific_db");
   2433     SOC_NULL_CHECK(pm8x50_data);
   2434     pm_info->pm_data.pm8x50_db = pm8x50_data;
   2435 
   2436     PORTMOD_PBMP_ASSIGN(pm8x50_data->phys, pm_add_info->phys);
   2437     pm8x50_data->int_core_access.type = phymodDispatchTypeCount;
   2438     PORTMOD_PBMP_ITER(pm_add_info->phys, phy) {
   2439         PM_8x50_INFO(pm_info)->first_phy = phy;
   2440         break;
   2441     }
   2442     pm8x50_data->warmboot_skip_db_restore = TRUE;
   2443     pm8x50_data->rescal = info->rescal;
   2444     pm8x50_data->portmod_mac_soft_reset = info->portmod_mac_soft_reset;
   2445     pm8x50_data->portmod_egress_buffer_reset = info->portmod_egress_buffer_reset;
   2446 
   2447     /* init intertnal SerDes core access */
   2448     phymod_core_access_t_init(&pm8x50_data->int_core_access);
   2449 
   2450     sal_memcpy(&pm8x50_data->polarity, &info->polarity,
   2451                sizeof(phymod_polarity_t));
   2452     sal_memcpy(&(pm8x50_data->int_core_access.access), &info->access.access,
   2453                 sizeof(phymod_access_t));
   2454 
   2455     sal_memcpy(&pm8x50_data->lane_map, &info->lane_map,
   2456                 sizeof(pm8x50_data->lane_map));
   2457     pm8x50_data->ref_clk = info->ref_clk;
   2458     pm8x50_data->fw_load_method = info->fw_load_method;
   2459     pm8x50_data->external_fw_loader = info->external_fw_loader;
   2460     pm8x50_data->tvco = info->tvco;
   2461     pm8x50_data->ovco = info->ovco;
   2462     pm8x50_data->core_num  = info->core_num;
   2463     pm8x50_data->afe_pll = info->afe_pll;
   2464     pm8x50_data->is_master_pm = info->is_master_pm;
   2465     pm8x50_data->allow_20p625g_tvco = info->allow_20p625g_tvco;
   2466 
   2467     if (info->access.access.bus == NULL) {
   2468         /* if null - use default */
   2469         pm8x50_data->int_core_access.access.bus = &pm8x50_default_bus;
   2470     } else {
   2471         /* check null for mem_read/mem_write */
   2472         if (pm8x50_data->int_core_access.access.bus->mem_read == NULL) {
   2473             pm8x50_data->int_core_access.access.bus->mem_read =pm8x50_default_bus.mem_read;
   2474         }
   2475         if (pm8x50_data->int_core_access.access.bus->mem_write == NULL) {
   2476             pm8x50_data->int_core_access.access.bus->mem_write =pm8x50_default_bus.mem_write;
   2477         }
   2478     }
   2479 
   2480     if (pm8x50_data->external_fw_loader == NULL) {
   2481         /* if null - use default */
   2482         pm8x50_data->external_fw_loader = pm8x50_default_fw_loader;
   2483     }
   2484 
   2485     /*init wb buffer*/
   2486     _SOC_IF_ERR_EXIT(pm8x50_wb_buffer_init(unit, wb_buffer_index,  pm_info));
   2487 
   2488 
   2489     if (pm8x50_data->int_core_access.access.pmd_info_ptr == NULL) {
   2490         pm8x50_data->int_core_access.access.pmd_info_ptr = sal_alloc(PMD_INFO_DATA_STRUCTURE_SIZE,
   2491                              "PortMod PM PMD info");
   2492         if (pm8x50_data->int_core_access.access.pmd_info_ptr == NULL) {
   2493             return SOC_E_MEMORY;
   2494         }
   2495         sal_memset(pm8x50_data->int_core_access.access.pmd_info_ptr, 0, PMD_INFO_DATA_STRUCTURE_SIZE);
   2496     }
   2497 
   2498 
   2499     if (SOC_WARM_BOOT(unit)) {
   2500         int rlm_enabled, rlm_state, i, port_local;
   2501         /* For warmboot, probe Serdes driver type for active PMs. */
   2502         is_core_initialized = 0;
   2503         rlm_enabled = 0;
   2504         rlm_state = PORTMOD_PORT_RLM_FSM_COUNT;
   2505         rv = PM8x50_IS_CORE_INITIALIZED_GET(unit, pm_info, &is_core_initialized);
   2506         _SOC_IF_ERR_EXIT(rv);
   2507         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_GET(unit, pm_info, &an_state));
   2508 
   2509         /* next check if RLM portmod thread needs to be re-registered */
   2510         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2511             /* first get the logical port id */
   2512             _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info,i, &port_local));
   2513             _SOC_IF_ERR_EXIT(PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, i));
   2514             _SOC_IF_ERR_EXIT(PM8x50_RLM_STATE_GET(unit, pm_info, &rlm_state, i));
   2515             _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, i));
   2516             _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, &remote_pause, i));
   2517             /* need to re-register the call back */
   2518             if ( (port_local >= 0) && (((rlm_enabled) && (rlm_state >= PORTMOD_PORT_RLM_SEND_PACKET_DATA) &&
   2519                (rlm_state < PORTMOD_PORT_RLM_DONE)) ||
   2520                ((is_400g_an) && (an_state < PM8X50_PORT_AN_COMPLETE))) ) {
   2521                     _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_register(unit, port_local, pm8x50_periodic_callback, PORTMOD_THREAD_INTERVAL_1s));
   2522             }
   2523         }
   2524 
   2525         if (is_core_initialized) {
   2526             _SOC_IF_ERR_EXIT(portmod_common_serdes_probe(pm8x50_serdes_list, &pm8x50_data->int_core_access, &probe));
   2527             if (!probe) {
   2528                 LOG_ERROR(BSL_LS_SOC_PORT,
   2529                       (BSL_META_U(unit, "ERROR: serdes probe failed type=%d\n"), pm8x50_data->int_core_access.type));
   2530             }
   2531 
   2532             /* Get VCO rates from HW */
   2533             sal_memcpy(&phy_access, &(pm8x50_data->int_core_access),
   2534                        sizeof(phymod_phy_access_t));
   2535 
   2536             /* 1. Get TVCO rate */
   2537             phy_access.access.pll_idx = phy_access.access.tvco_pll_index;
   2538             _SOC_IF_ERR_EXIT(phymod_phy_pll_multiplier_get(&phy_access, &pll_div));
   2539             _SOC_IF_ERR_EXIT(_pm8x50_pll_to_vco_get(info->ref_clk, pll_div, &vco));
   2540             pm8x50_data->tvco = vco;
   2541             /* 2. Get OVCO rate:
   2542              *    a. If OVCO is not free, get OVCO rate from HW.
   2543              *    b. If OVCO is free, OVCO is powerdown.
   2544              */
   2545             _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bitmap));
   2546             _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bitmap));
   2547             if (ovco_pll_active_lane_bitmap | ovco_pll_adv_lane_bitmap) {
   2548                 phy_access.access.pll_idx = (phy_access.access.tvco_pll_index == 1)? 0: 1;
   2549                 _SOC_IF_ERR_EXIT(phymod_phy_pll_multiplier_get(&phy_access, &pll_div));
   2550                 _SOC_IF_ERR_EXIT(_pm8x50_pll_to_vco_get(info->ref_clk, pll_div, &vco));
   2551                 pm8x50_data->ovco = vco;
   2552             } else {
   2553                 pm8x50_data->ovco = portmodVCOInvalid;
   2554             }
   2555         }
   2556     } else {
   2557         /* For coldboot, initialized warmboot variables for the PM. */
   2558         is_core_initialized = 0;
   2559         rv = PM8x50_IS_CORE_INITIALIZED_SET(unit, pm_info,
   2560                                             is_core_initialized);
   2561         _SOC_IF_ERR_EXIT(rv);
   2562 
   2563         pm_is_active = 0;
   2564         rv = PM8x50_IS_ACTIVE_SET(unit, pm_info, pm_is_active);
   2565         _SOC_IF_ERR_EXIT(rv);
   2566 
   2567         ovco_pll_adv_lane_bitmap = 0;
   2568         rv = PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, ovco_pll_adv_lane_bitmap);
   2569         _SOC_IF_ERR_EXIT(rv);
   2570 
   2571         tvco_pll_adv_lane_bitmap = 0;
   2572         rv = PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, tvco_pll_adv_lane_bitmap);
   2573         _SOC_IF_ERR_EXIT(rv);
   2574 
   2575         ovco_pll_active_lane_bitmap = 0;
   2576         rv = PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, ovco_pll_active_lane_bitmap);
   2577         _SOC_IF_ERR_EXIT(rv);
   2578 
   2579         tvco_pll_active_lane_bitmap = 0;
   2580         rv = PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, tvco_pll_active_lane_bitmap);
   2581         _SOC_IF_ERR_EXIT(rv);
   2582 
   2583         fec = 0;
   2584         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2585             _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec));
   2586         }
   2587 
   2588         invalid_port = -1;
   2589         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2590             _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_SET(unit, pm_info, i, invalid_port));
   2591         }
   2592 
   2593         ts_enable_port_count = 0;
   2594         rv = PM8x50_TS_ENABLE_PORT_COUNT_SET(unit, pm_info, ts_enable_port_count);
   2595         _SOC_IF_ERR_EXIT(rv);
   2596 
   2597         rlm_enabled = 0;
   2598         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2599             _SOC_IF_ERR_EXIT(PM8x50_RLM_ENABLE_SET(unit, pm_info, rlm_enabled, i));
   2600         }
   2601 
   2602         is_initiator = 0;
   2603         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2604             _SOC_IF_ERR_EXIT(PM8x50_INITIATOR_SET(unit, pm_info, is_initiator, i));
   2605         }
   2606 
   2607         pcs_reconfigured = 0;
   2608         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2609             _SOC_IF_ERR_EXIT(PM8x50_PCS_RECONFIG_SET(unit, pm_info, pcs_reconfigured, i));
   2610         }
   2611 
   2612         active_lane_map = 0;
   2613         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2614             _SOC_IF_ERR_EXIT(PM8x50_ACTIVE_LANE_MAP_SET(unit, pm_info, active_lane_map, i));
   2615         }
   2616 
   2617         rlm_state = PORTMOD_PORT_RLM_FSM_COUNT;
   2618         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2619             _SOC_IF_ERR_EXIT(PM8x50_RLM_STATE_SET(unit, pm_info, rlm_state, i));
   2620         }
   2621 
   2622         fecType = 0;
   2623         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2624             _SOC_IF_ERR_EXIT(PM8x50_ORIGINAL_FEC_SET(unit, pm_info, fecType, i));
   2625         }
   2626 
   2627         txLaneMap = 0x76543210;
   2628         rv = PM8x50_ORIG_TX_LANE_MAP_SET(unit, pm_info, txLaneMap);
   2629         _SOC_IF_ERR_EXIT(rv);
   2630 
   2631         rxLaneMap = 0x76543210;
   2632         rv = PM8x50_ORIG_RX_LANE_MAP_SET(unit, pm_info, rxLaneMap);
   2633         _SOC_IF_ERR_EXIT(rv);
   2634 
   2635         is_400g_an = 0;
   2636         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2637             _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_SET(unit, pm_info, is_400g_an, i));
   2638         }
   2639 
   2640         an_state = PM8X50_PORT_AN_STATE_COUNT;
   2641         rv = PM8x50_400G_AN_STATE_SET(unit, pm_info, an_state);
   2642         _SOC_IF_ERR_EXIT(rv);
   2643 
   2644         an_wait_link_count = 0;
   2645         rv = PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, an_wait_link_count);
   2646         _SOC_IF_ERR_EXIT(rv);
   2647 
   2648         is_ber_war_enable = 0;
   2649         ber_war_state = PM8X50_PORT_BER_WAR_STATE_COUNT;
   2650         ber_war_wait_count = 0;
   2651         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2652             _SOC_IF_ERR_EXIT(PM8x50_BER_WAR_ENABLE_SET(unit, pm_info, is_ber_war_enable, i));
   2653 
   2654             rv = PM8x50_BER_WAR_STATE_SET(unit, pm_info, ber_war_state, i);
   2655             _SOC_IF_ERR_EXIT(rv);
   2656 
   2657             rv = PM8x50_BER_WAR_WAIT_COUNT_SET(unit, pm_info, ber_war_wait_count, i);
   2658             _SOC_IF_ERR_EXIT(rv);
   2659         }
   2660 
   2661         core_is_flexe_configured = 0;
   2662         rv = PM8x50_IS_CORE_FLEXE_CONFIGURED_SET(unit, pm_info, core_is_flexe_configured);
   2663         _SOC_IF_ERR_EXIT(rv);
   2664 
   2665         remote_pause = 0;
   2666         for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   2667             _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, i));
   2668         }
   2669     }
   2670 
   2671 exit:
   2672     if (SOC_FUNC_ERROR) {
   2673         pm8x50_pm_destroy(unit, pm_info);
   2674     }
   2675     SOC_FUNC_RETURN;
   2676 }
   2677 
   2678 /*Release PM resources*/
   2679 int pm8x50_pm_destroy(int unit, pm_info_t pm_info)
   2680 {
   2681     SOC_INIT_FUNC_DEFS;
   2682 
   2683     if (pm_info->pm_data.pm8x50_db != NULL) {
   2684         if (PM_8x50_INFO(pm_info)->int_core_access.access.pmd_info_ptr != NULL) {
   2685             sal_free(PM_8x50_INFO(pm_info)->int_core_access.access.pmd_info_ptr);
   2686             PM_8x50_INFO(pm_info)->int_core_access.access.pmd_info_ptr = NULL;
   2687         }
   2688         sal_free(pm_info->pm_data.pm8x50_db);
   2689         pm_info->pm_data.pm8x50_db = NULL;
   2690     }
   2691 
   2692     SOC_FUNC_RETURN;
   2693 }
   2694 
   2695 /* This function will check the speed config is valid or not, and return required vco for valid input */
   2696 /* The supported speed config in this function is based on PM8x50 Portmod Spec */
   2697 STATIC
   2698 int _pm8x50_port_speed_config_to_vco_get(const portmod_speed_config_t* speed_config,
   2699                                          int speed_for_pcs_bypass_port,
   2700                                          portmod_vco_type_t* vco)
   2701 {
   2702     SOC_INIT_FUNC_DEFS;
   2703 
   2704     if (!speed_for_pcs_bypass_port) {
   2705         _SOC_IF_ERR_EXIT(
   2706                 _pm8x50_fs_ability_table_vco_get(speed_config->speed,
   2707                                                  speed_config->num_lane,
   2708                                                  speed_config->fec,
   2709                                                  vco));
   2710     } else {
   2711         _SOC_IF_ERR_EXIT(
   2712                 pm8x50_shared_pcs_bypassed_vco_get(speed_config->speed, vco));
   2713     }
   2714     /*
   2715      * when *vco == portmodVCOInvalid, it means the entered combination of
   2716      * port speed, number of lanes, and FEC type is not supported.
   2717      */
   2718     if (*vco == portmodVCOInvalid) {
   2719         return SOC_E_CONFIG;
   2720     }
   2721 
   2722 exit:
   2723     SOC_FUNC_RETURN;
   2724 }
   2725 
   2726 /* This function can be called before port is attached.
   2727  * So we need to use physical port number to access the register.
   2728  */
   2729 STATIC
   2730 int _pm8x50_pm_version_get(int unit, pm_info_t pm_info, pm_version_t *version)
   2731 {
   2732     uint32 reg_val, tech_process;
   2733     int phy_acc;
   2734 
   2735     SOC_INIT_FUNC_DEFS;
   2736 
   2737     version->type            = PM_TYPE_PM8X50;
   2738     version->gen             = PM_GEN_INVALID;
   2739     version->tech_process    = PM_TECH_INVALID;
   2740     version->revision_number = PM_REVISION_NUM_INVALID;
   2741     version->revision_letter = PM_REVISION_LETTER_INVALID;
   2742 
   2743     phy_acc = PM_8x50_INFO(pm_info)->first_phy | SOC_REG_ADDR_PHY_ACC_MASK;
   2744 
   2745     _SOC_IF_ERR_EXIT(READ_CDPORT_PM_VERSION_IDr(unit, phy_acc, &reg_val));
   2746 
   2747     tech_process  = soc_reg_field_get(unit, CDPORT_PM_VERSION_IDr, reg_val, TECH_PROCESSf);
   2748     if (tech_process == 1) {
   2749         version->tech_process  = PM_TECH_16NM;
   2750     }
   2751 
   2752 exit:
   2753     SOC_FUNC_RETURN;
   2754 }
   2755 
   2756 STATIC
   2757 int _pm8x50_lanebitmap_set(int starting_lane, int num_lane, uint8 *bitmap)
   2758 {
   2759     int i;
   2760 
   2761     for (i = 0; i < num_lane; i++) {
   2762         *bitmap |= 1 << (starting_lane + i);
   2763     }
   2764 
   2765     return SOC_E_NONE;
   2766 }
   2767 
   2768 /* This function is to validate the FEC settings on each PM.
   2769  * For each MPP, we can not support both RS544 and RS272.
   2770  * On 16nm, we can also not support both RS528 and RS272 on the same MPP.
   2771  */
   2772 STATIC
   2773 int _pm8x50_fec_validate(int unit,
   2774                          uint32 flags,
   2775                          uint8 rs528_bitmap,
   2776                          uint8 rs544_bitmap,
   2777                          uint8 rs272_bitmap,
   2778                          uint8 *affected_lane_bitmap)
   2779 {
   2780     uint8 rs_fec_mpp0, rs_fec_mpp1, rs272_mpp0, rs272_mpp1;
   2781     SOC_INIT_FUNC_DEFS;
   2782 
   2783     /* rs_fec_mpp0, rs_fec_mpp1 contains lane bitmap for
   2784      * the RS FECs which can not co-exist with RS272.
   2785      * For 16nm, rsfec contains bitmap for both RS544 and RS528.
   2786      * For 7nm, rsfec contains bitmap for RS544 only.
   2787      */
   2788     if (PM8X50_PM_VERSION_F_REV0_16NM_GET(flags)) {
   2789         rs_fec_mpp0 = (rs528_bitmap | rs544_bitmap) & 0xf;
   2790         rs_fec_mpp1 = (rs528_bitmap | rs544_bitmap) & 0xf0;
   2791     } else {
   2792         rs_fec_mpp0 = rs544_bitmap & 0xf;
   2793         rs_fec_mpp1 = rs544_bitmap & 0xf0;
   2794     }
   2795     rs272_mpp0 = rs272_bitmap & 0xf;
   2796     rs272_mpp1 = rs272_bitmap & 0xf0;
   2797     *affected_lane_bitmap = 0;
   2798 
   2799     if (rs_fec_mpp0 && rs272_mpp0) {
   2800         *affected_lane_bitmap = rs_fec_mpp0 | rs272_mpp0;
   2801         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   2802                           (_SOC_MSG("Can not accommodate FEC settings on MPP0.")));
   2803 
   2804     } else if (rs_fec_mpp1 && rs272_mpp1) {
   2805         *affected_lane_bitmap = rs_fec_mpp1 | rs272_mpp1;
   2806         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   2807                           (_SOC_MSG("Can not accommodate FEC settings on MPP1.")));
   2808     }
   2809 
   2810 exit:
   2811     SOC_FUNC_RETURN;
   2812 }
   2813 
   2814 /*Get the suggested VCO values based on the speed config list*/
   2815 int pm8x50_pm_vcos_get(int unit,
   2816                        portmod_dispatch_type_t pm_type,
   2817                        uint32 flags,
   2818                        portmod_pm_vco_setting_t* vco_select)
   2819 {
   2820     pm8x50_vcos_bmp_t vcos = 0, vco_bmp = 0;
   2821     portmod_vco_type_t current_tvco, current_ovco;
   2822     uint8_t rs528_bm = 0, rs544_bm = 0, rs272_bm = 0, affected_bm = 0;
   2823     portmod_vco_type_t vco;
   2824     int i, rv = 0;
   2825     int is_pcs_bypass;
   2826     uint32 fec_flags = 0, vcos_flags = 0;
   2827 
   2828     SOC_INIT_FUNC_DEFS;
   2829 
   2830     if(vco_select == NULL){
   2831         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   2832                           (_SOC_MSG("vco_select NULL paramaeter")));
   2833     }
   2834 
   2835     for (i = 0; i < vco_select->num_speeds; i++) {
   2836         vco = portmodVCOInvalid;
   2837         rv = _pm8x50_port_speed_config_to_vco_get(&(vco_select->speed_config_list[i]),
   2838                                                   vco_select->speed_for_pcs_bypass_port[i], &vco);
   2839         if (rv == SOC_E_CONFIG) {
   2840             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   2841                       (_SOC_MSG("Speed config is not supported")));
   2842         }
   2843         is_pcs_bypass = vco_select->speed_for_pcs_bypass_port[i];
   2844         _SOC_IF_ERR_EXIT(_pm8x50_required_vco_bitmap_get(unit, vco, is_pcs_bypass, &vco_bmp));
   2845         vcos |= vco_bmp;
   2846 
   2847         if ((vco_select->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_272) ||
   2848             (vco_select->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_272_2XN)) {
   2849             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_select->port_starting_lane_list[i],
   2850                                                     vco_select->speed_config_list[i].num_lane,
   2851                                                     &rs272_bm));
   2852         } else if ((vco_select->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_544) ||
   2853                    (vco_select->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   2854             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_select->port_starting_lane_list[i],
   2855                                                     vco_select->speed_config_list[i].num_lane,
   2856                                                     &rs544_bm));
   2857         } else if (vco_select->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   2858             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_select->port_starting_lane_list[i],
   2859                                                     vco_select->speed_config_list[i].num_lane,
   2860                                                     &rs528_bm));
   2861         }
   2862     }
   2863 
   2864     /* Validate FEC settings for RS528, RS544 and RS272 */
   2865     if (PORTMOD_PM8X50_REV0_16NM_GET(flags)) {
   2866         PM8X50_PM_VERSION_F_REV0_16NM_SET(fec_flags);
   2867     }
   2868     _SOC_IF_ERR_EXIT(_pm8x50_fec_validate(unit,
   2869                                           fec_flags,
   2870                                           rs528_bm,
   2871                                           rs544_bm,
   2872                                           rs272_bm,
   2873                                           &affected_bm));
   2874 
   2875     current_tvco = portmodVCOInvalid;
   2876     current_ovco = portmodVCOInvalid;
   2877 
   2878     if (PORTMOD_ALLOW_20P625G_TVCO_GET(flags)) {
   2879         PM8X50_TVCO_SUPPORT_20P625G_SET(vcos_flags);
   2880     }
   2881 
   2882     /* Try to allocate required VCOs */
   2883     _SOC_IF_ERR_EXIT(
   2884             pm8x50_vcos_request_allocate(unit, vcos_flags, vcos, &current_tvco, &current_ovco));
   2885 
   2886     /* Set Output */
   2887     vco_select->tvco = current_tvco;
   2888     vco_select->ovco = current_ovco;
   2889     vco_select->is_tvco_new = (current_tvco == portmodVCOInvalid) ? 0 : 1;
   2890     vco_select->is_ovco_new = (current_ovco == portmodVCOInvalid) ? 0 : 1;
   2891 
   2892 exit:
   2893     SOC_FUNC_RETURN;
   2894 }
   2895 
   2896 STATIC
   2897 int _pm8x50_port_tsc_reset_set(int unit, pm_info_t pm_info, int phy_acc, int tvco_pll_index, int in_reset)
   2898 {
   2899     uint32 reg_val;
   2900     SOC_INIT_FUNC_DEFS;
   2901 
   2902     _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_CTRL_REGr(unit, phy_acc, &reg_val));
   2903     soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_CLK_SELf, tvco_pll_index);
   2904 
   2905     /*
   2906      * in_reset == 1:
   2907      *       1. Power down TSC.
   2908      *       2. Put TSC into RST for slave cores.
   2909      * in_reset == 0:
   2910      *       1. Power up TSC.
   2911      *       2. Toggle TSC RST bit.
   2912      */
   2913     if (in_reset) {
   2914         int is_core_initialized = 0;
   2915         soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_PWRDWNf, 1);
   2916         if (!(PM_8x50_INFO(pm_info)->is_master_pm)) {
   2917             /* Put TSC into reset for slave PMs */
   2918             soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_RSTBf, 0);
   2919         }
   2920         _SOC_IF_ERR_EXIT(WRITE_CDPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val));
   2921 
   2922         /* clear the warm boot variable */
   2923         _SOC_IF_ERR_EXIT(PM8x50_IS_CORE_INITIALIZED_SET(unit, pm_info, is_core_initialized));
   2924     } else {
   2925         soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_PWRDWNf, 1);
   2926         soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_RSTBf, 0);
   2927         _SOC_IF_ERR_EXIT(WRITE_CDPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val));
   2928 
   2929         soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_PWRDWNf, 0);
   2930         soc_reg_field_set(unit, CDPORT_XGXS0_CTRL_REGr, &reg_val, TSC_RSTBf, 1);
   2931         _SOC_IF_ERR_EXIT(WRITE_CDPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val));
   2932     }
   2933 
   2934 
   2935     /* Based on the feedback from SJ pmd support team, ~10-15usecs would be sufficient
   2936      * for the PLL/AFE to settle down out of IDDQ reset.
   2937      */
   2938     sal_usleep(10);
   2939 
   2940 exit:
   2941     SOC_FUNC_RETURN;
   2942 }
   2943 
   2944 /*Enable port macro.*/
   2945 /* This function contains 3 parts:
   2946  * 1. Bring Serdes out of hard reset.
   2947  * 2. Bring 2 CDMACs out of hard reset.
   2948  */
   2949 int pm8x50_pm_enable(int unit,
   2950                      int pm_id,
   2951                      pm_info_t pm_info,
   2952                      int enable)
   2953 {
   2954     uint32 reg_val;
   2955     int phy_acc;
   2956     int is_reset;
   2957     int tvco_pll_index;
   2958     SOC_INIT_FUNC_DEFS;
   2959 
   2960     /* Get the first physical port of the pm core */
   2961     phy_acc = PM_8x50_INFO(pm_info)->first_phy | SOC_REG_ADDR_PHY_ACC_MASK;
   2962 
   2963     _SOC_IF_ERR_EXIT(READ_CDPORT_MAC_CONTROLr(unit, phy_acc, &reg_val));
   2964     is_reset = soc_reg_field_get(unit, CDPORT_MAC_CONTROLr, reg_val, CDMAC0_RESETf);
   2965 
   2966     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   2967 
   2968     if(enable && is_reset) {
   2969         /* Bring Serdes OOR */
   2970         _SOC_IF_ERR_EXIT(_pm8x50_port_tsc_reset_set(unit, pm_info, phy_acc, tvco_pll_index, 0));
   2971 
   2972         /* Bring MAC OOR */
   2973         _SOC_IF_ERR_EXIT(READ_CDPORT_MAC_CONTROLr(unit, phy_acc, &reg_val));
   2974         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &reg_val, CDMAC0_RESETf, 0);
   2975         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &reg_val, CDMAC1_RESETf, 0);
   2976         _SOC_IF_ERR_EXIT(WRITE_CDPORT_MAC_CONTROLr(unit, phy_acc, reg_val));
   2977     } else if ((!enable) && (!is_reset)){ /* disable */
   2978         /* put MAC in reset */
   2979         _SOC_IF_ERR_EXIT(READ_CDPORT_MAC_CONTROLr(unit, phy_acc, &reg_val));
   2980         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &reg_val, CDMAC0_RESETf, 1);
   2981         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &reg_val, CDMAC1_RESETf, 1);
   2982         _SOC_IF_ERR_EXIT(WRITE_CDPORT_MAC_CONTROLr(unit, phy_acc, reg_val));
   2983 
   2984         /* If current PM is not master PM, put Serdes into reset*/
   2985         _SOC_IF_ERR_EXIT(_pm8x50_port_tsc_reset_set(unit, pm_info, phy_acc, tvco_pll_index, 1));
   2986     }
   2987 
   2988 exit:
   2989     SOC_FUNC_RETURN;
   2990 }
   2991 
   2992 STATIC
   2993 int _pm8x50_pm_core_probe(int unit, pm_info_t pm_info, const portmod_port_add_info_t* add_info)
   2994 {
   2995     int probe =0;
   2996     SOC_INIT_FUNC_DEFS;
   2997 
   2998     _SOC_IF_ERR_EXIT(portmod_common_serdes_probe(pm8x50_serdes_list, &PM_8x50_INFO(pm_info)->int_core_access, &probe));
   2999 
   3000 exit:
   3001     SOC_FUNC_RETURN;
   3002 }
   3003 
   3004 /* This function will return required pll based on the ref_clk and vco */
   3005 /* For now, assume PM8x50 only support:
   3006    VCO: 20.625G, 25.78125G,26.5625G;
   3007    Ref_CLK: 156.25M, 312.5M
   3008   For any other input, this function will return E_PARAM
   3009 */
   3010 STATIC
   3011 int _pm8x50_vco_to_pll_get(phymod_ref_clk_t ref_clock, portmod_vco_type_t vco, uint32_t* pll)
   3012 {
   3013     int rv = SOC_E_NONE;
   3014     SOC_INIT_FUNC_DEFS;
   3015 
   3016     switch (vco) {
   3017         case portmodVCO20P625G:
   3018             if (ref_clock == phymodRefClk156Mhz) {
   3019                 *pll = phymod_TSCBH_PLL_DIV132;
   3020             } else if (ref_clock == phymodRefClk312Mhz) {
   3021                 *pll = phymod_TSCBH_PLL_DIV66;
   3022             } else {
   3023                 rv = SOC_E_PARAM;
   3024             }
   3025             break;
   3026         case portmodVCO25P781G:
   3027             if (ref_clock == phymodRefClk156Mhz) {
   3028                 *pll = phymod_TSCBH_PLL_DIV165;
   3029             } else if (ref_clock == phymodRefClk312Mhz) {
   3030                 *pll = phymod_TSCBH_PLL_DIV82P5;
   3031             } else {
   3032                 rv = SOC_E_PARAM;
   3033             }
   3034             break;
   3035         case portmodVCO26P562G:
   3036             if (ref_clock == phymodRefClk156Mhz) {
   3037                 *pll = phymod_TSCBH_PLL_DIV170;
   3038             } else if (ref_clock == phymodRefClk312Mhz) {
   3039                 *pll = phymod_TSCBH_PLL_DIV85;
   3040             } else {
   3041                 rv = SOC_E_PARAM;
   3042             }
   3043             break;
   3044         case portmodVCO25G:
   3045             if (ref_clock == phymodRefClk156Mhz) {
   3046                 *pll = phymod_TSCBH_PLL_DIV160;
   3047             } else if (ref_clock == phymodRefClk312Mhz) {
   3048                 *pll = phymod_TSCBH_PLL_DIV80;
   3049             } else {
   3050                 rv = SOC_E_PARAM;
   3051             }
   3052             break;
   3053         case portmodVCO27P343G:
   3054             if (ref_clock == phymodRefClk156Mhz) {
   3055                 *pll = phymod_TSCBH_PLL_DIV175;
   3056             } else if (ref_clock == phymodRefClk312Mhz) {
   3057                 *pll = phymod_TSCBH_PLL_DIV87P5;
   3058             } else {
   3059                 rv = SOC_E_PARAM;
   3060             }
   3061             break;
   3062         case portmodVCO28P125G:
   3063             if (ref_clock == phymodRefClk156Mhz) {
   3064                 *pll = phymod_TSCBH_PLL_DIV180;
   3065             } else if (ref_clock == phymodRefClk312Mhz) {
   3066                 *pll = phymod_TSCBH_PLL_DIV90;
   3067             } else {
   3068                 rv = SOC_E_PARAM;
   3069             }
   3070             break;
   3071        case portmodVCOInvalid:
   3072             *pll = phymod_TSCBH_PLL_DIVNONE;
   3073             break;
   3074        default:
   3075             rv = SOC_E_PARAM;
   3076             break;
   3077     }
   3078     _SOC_IF_ERR_EXIT(rv);
   3079 
   3080  exit:
   3081      SOC_FUNC_RETURN;
   3082 }
   3083 
   3084 STATIC
   3085 int _pm8x50_pm_serdes_core_init(int unit, pm_info_t pm_info, const portmod_port_add_info_t* add_info)
   3086 {
   3087     int rv, tvco_pll_index;
   3088     phymod_core_init_config_t core_conf;
   3089     phymod_core_status_t core_status;
   3090     uint32_t core_is_initialized;
   3091     uint32_t init_flags = 0;
   3092     uint32_t pll0 = 0, pll1 = 0;
   3093     uint32_t tx_lane_map = 0, rx_lane_map = 0, i;
   3094     portmod_vco_type_t ovco = 0, tvco = 0;
   3095 
   3096     SOC_INIT_FUNC_DEFS;
   3097 
   3098     rv = PM8x50_IS_CORE_INITIALIZED_GET(unit, pm_info, &core_is_initialized)
   3099     _SOC_IF_ERR_EXIT(rv);
   3100 
   3101     _SOC_IF_ERR_EXIT(phymod_core_init_config_t_init(&core_conf));
   3102     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   3103 
   3104     
   3105     core_conf.firmware_load_method = PM_8x50_INFO(pm_info)->fw_load_method;
   3106     core_conf.firmware_loader = PM_8x50_INFO(pm_info)->external_fw_loader;
   3107     core_conf.lane_map = PM_8x50_INFO(pm_info)->lane_map;
   3108     core_conf.polarity_map = PM_8x50_INFO(pm_info)->polarity;
   3109 
   3110     /* next translate the lane map into encoded format for RLM usage */
   3111     for (i = 0; i < core_conf.lane_map.num_of_lanes; i++) {
   3112         tx_lane_map |= core_conf.lane_map.lane_map_tx[i] << (4 * i);
   3113         rx_lane_map |= core_conf.lane_map.lane_map_rx[i] << (4 * i);
   3114     }
   3115 
   3116     core_conf.afe_pll.afe_pll_change_default = PM_8x50_INFO(pm_info)->afe_pll.afe_pll_change_default;
   3117     core_conf.afe_pll.ams_pll_iqp = PM_8x50_INFO(pm_info)->afe_pll.ams_pll_iqp;
   3118     core_conf.afe_pll.ams_pll_en_hrz = PM_8x50_INFO(pm_info)->afe_pll.ams_pll_en_hrz;
   3119 
   3120     _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&core_conf.interface));
   3121     core_conf.interface.ref_clock = PM_8x50_INFO(pm_info)->ref_clk;
   3122 
   3123     if (PORTMOD_PORT_ADD_F_SKIP_SPEED_INIT_GET(add_info)) {
   3124         /* If PORTMOD_PORT_ADD_F_SKIP_SPEED_INIT flag is set, do not bring up PLLs */
   3125         if (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(core_is_initialized)) {
   3126             /* Only if core is not initilized - put tvco and ovco as invalid */
   3127             ovco = portmodVCOInvalid;
   3128             tvco = portmodVCOInvalid;
   3129             PM_8x50_INFO(pm_info)->ovco = ovco;
   3130             PM_8x50_INFO(pm_info)->tvco = tvco;
   3131         }
   3132     } else if ((PM_8x50_INFO(pm_info)->ovco == portmodVCOInvalid) && (PM_8x50_INFO(pm_info)->tvco == portmodVCOInvalid)) {
   3133         ovco = add_info->ovco;
   3134         tvco = add_info->tvco;
   3135         PM_8x50_INFO(pm_info)->ovco = ovco;
   3136         PM_8x50_INFO(pm_info)->tvco = tvco;
   3137     } else {
   3138         ovco = PM_8x50_INFO(pm_info)->ovco;
   3139         tvco = PM_8x50_INFO(pm_info)->tvco;
   3140     }
   3141     if ((tvco < portmodVCOInvalid) || (tvco >= portmodVCOCount)) {
   3142         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("TVCO configuration is invalid.")));
   3143     }
   3144 
   3145     if (tvco_pll_index == 1) {
   3146         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(core_conf.interface.ref_clock, tvco, &pll1));
   3147         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(core_conf.interface.ref_clock, ovco, &pll0));
   3148     } else {
   3149         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(core_conf.interface.ref_clock, tvco, &pll0));
   3150         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(core_conf.interface.ref_clock, ovco, &pll1));
   3151     }
   3152 
   3153     core_conf.pll0_div_init_value = pll0;
   3154     core_conf.pll1_div_init_value = pll1;
   3155 
   3156     _SOC_IF_ERR_EXIT(phymod_core_status_t_init(&core_status));
   3157     core_status.pmd_active = 0;
   3158     init_flags = PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) | PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info);
   3159 
   3160     if (PORTMOD_PORT_ADD_F_FIRMWARE_LOAD_VERIFY_GET(add_info)) {
   3161         PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_SET(&core_conf);
   3162     }
   3163     if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) {
   3164         PHYMOD_CORE_INIT_F_EXECUTE_PASS1_SET(&core_conf);
   3165     }
   3166     if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) {
   3167         PHYMOD_CORE_INIT_F_EXECUTE_PASS2_SET(&core_conf);
   3168     }
   3169     if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) {
   3170         PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&core_conf);
   3171     }
   3172 
   3173     if (PORTMOD_PORT_ADD_F_BYPASS_FW_CRC_CHECK_GET(add_info)) {
   3174         PHYMOD_CORE_INIT_F_BYPASS_CRC_CHECK_SET(&core_conf);
   3175     }
   3176 
   3177 #ifdef FW_BCAST_DOWNLOAD
   3178     if (PORTMOD_PORT_ADD_F_FIRMWARE_DOWNLOAD_BCAST_GET(add_info)) {
   3179         PHYMOD_CORE_INIT_F_SERDES_FW_BCAST_SET(&core_conf);
   3180     }
   3181 #endif
   3182 
   3183 
   3184     if (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(core_is_initialized)) {
   3185          /* firmware load will happen after pass 1 */
   3186          if (!PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_GET(core_is_initialized) ||
   3187              PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) {
   3188 #if 0
   3189             
   3190             if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_flags == 0) {
   3191                 if (PM_8x50_INFO(pm_info)->rescal != -1) {
   3192                     sal_memcpy(&serdes_access, &(PM_8x50_INFO(pm_info)->int_core_access), sizeof(phymod_phy_access_t));
   3193                     _SOC_IF_ERR_EXIT(phymod_phy_rescal_set(&serdes_access, 1, PM_8x50_INFO(pm_info)->rescal));
   3194                 }
   3195             }
   3196 #endif
   3197              _SOC_IF_ERR_EXIT(phymod_core_init(&PM_8x50_INFO(pm_info)->int_core_access,
   3198                                                &core_conf,
   3199                                                &core_status));
   3200 
   3201             if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_flags == 0) {
   3202                 PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_SET(core_is_initialized);
   3203                 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD,
   3204                                             pm_info->wb_vars_ids[isCoreInitialized],
   3205                                             &core_is_initialized);
   3206                 _SOC_IF_ERR_EXIT(rv);
   3207 
   3208                 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD,
   3209                                             pm_info->wb_vars_ids[originalTxLaneSwap],
   3210                                             &tx_lane_map);
   3211                 _SOC_IF_ERR_EXIT(rv);
   3212 
   3213                 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD,
   3214                                             pm_info->wb_vars_ids[originalRxLaneSwap],
   3215                                             &rx_lane_map);
   3216                 _SOC_IF_ERR_EXIT(rv);
   3217             }
   3218             if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info) || init_flags == 0) {
   3219                 PORTMOD_CORE_INIT_FLAG_INITIALZIED_SET(core_is_initialized);
   3220                 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD,
   3221                                             pm_info->wb_vars_ids[isCoreInitialized],
   3222                                             &core_is_initialized);
   3223                 _SOC_IF_ERR_EXIT(rv);
   3224             }
   3225         }
   3226     }
   3227 
   3228 exit:
   3229     SOC_FUNC_RETURN;
   3230 }
   3231 
   3232 /*PM Core init routine*/
   3233 /* PM core init has 3 phase:
   3234  * 1. Core probe: Probe serdes dispatch type.
   3235  * 2. Pass1: Download FW, program ref_clk, polarity, lane map, etc.
   3236  * 3. Pass2: PLL configuration, program UC core config, load PCS tables etc.
   3237  */
   3238 int pm8x50_pm_serdes_core_init(int unit,
   3239                                int pm_id,
   3240                                pm_info_t pm_info,
   3241                                const portmod_port_add_info_t* add_info)
   3242 {
   3243     int init_all = 0;
   3244     int rv = SOC_E_NONE;
   3245 
   3246     SOC_INIT_FUNC_DEFS;
   3247 
   3248     /* Update per core based database */
   3249     if (add_info->init_config.polarity_overwrite == 1) {
   3250         sal_memcpy(&PM_8x50_INFO(pm_info)->polarity,
   3251             &add_info->init_config.polarity[0], sizeof(phymod_polarity_t));
   3252     }
   3253     if (add_info->init_config.lane_map_overwrite == 1) {
   3254         sal_memcpy(&PM_8x50_INFO(pm_info)->lane_map,
   3255             &add_info->init_config.lane_map[0], sizeof(phymod_lane_map_t));
   3256     }
   3257     if (add_info->init_config.fw_load_method_overwrite == 1) {
   3258         PM_8x50_INFO(pm_info)->fw_load_method =
   3259             add_info->init_config.fw_load_method[0];
   3260     }
   3261     if (add_info->init_config.ref_clk_overwrite == 1) {
   3262         PM_8x50_INFO(pm_info)->ref_clk = add_info->init_config.ref_clk;
   3263     }
   3264 
   3265     init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) &&
   3266                 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) &&
   3267                 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) ? 1 : 0;
   3268 
   3269     /* probe serdes core */
   3270     if (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) || init_all) {
   3271         rv = _pm8x50_pm_core_probe(unit, pm_info, add_info);
   3272         _SOC_IF_ERR_EXIT(rv);
   3273     }
   3274 
   3275     /* Return here if caller only request Core Probe */
   3276     if (!(PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) &&
   3277         (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info))) {
   3278         return (rv);
   3279     }
   3280 
   3281     /* core config for internal serdes. */
   3282     rv = _pm8x50_pm_serdes_core_init(unit, pm_info, add_info);
   3283     _SOC_IF_ERR_EXIT(rv);
   3284 
   3285 exit:
   3286     SOC_FUNC_RETURN;
   3287 }
   3288 
   3289 STATIC
   3290 int _pm8x50_pm_port_init(int unit,
   3291                          int port,
   3292                          pm_info_t pm_info,
   3293                          int internal_port,
   3294                          const portmod_port_add_info_t* add_info,
   3295                          int enable)
   3296 {
   3297     int rv, phy_acc;
   3298     uint32 reg_val, flags;
   3299     uint32 rsv_mask;
   3300     SOC_INIT_FUNC_DEFS;
   3301 
   3302     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   3303     if (internal_port == -1)  {
   3304         _SOC_EXIT_WITH_ERR(SOC_E_PORT, (_SOC_MSG("Invalid internal Port %d"),
   3305                                 internal_port));
   3306     }
   3307 
   3308     if (enable) {
   3309         /* RSV Mask */
   3310         rsv_mask = 0;
   3311         SHR_BITSET(&rsv_mask, 3); /* Receive terminate/code error */
   3312         SHR_BITSET(&rsv_mask, 4); /* CRC error */
   3313         SHR_BITSET(&rsv_mask, 6); /* Truncated/Frame out of Range */
   3314         SHR_BITSET(&rsv_mask, 17); /* RUNT detected*/
   3315         _SOC_IF_ERR_EXIT(pm8x50_port_mac_rsv_mask_set(unit, phy_acc, pm_info, rsv_mask));
   3316 
   3317         /* Init MAC */
   3318         flags = 0;
   3319         if(PORTMOD_PORT_ADD_F_RX_SRIP_CRC_GET(add_info)) {
   3320             flags |= CDMAC_INIT_F_RX_STRIP_CRC;
   3321 
   3322        }
   3323 
   3324         if(PORTMOD_PORT_ADD_F_TX_APPEND_CRC_GET(add_info)) {
   3325             flags |= CDMAC_INIT_F_TX_APPEND_CRC;
   3326         }
   3327 
   3328         if(PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_GET(add_info)) {
   3329             flags |= CDMAC_INIT_F_TX_REPLACE_CRC;
   3330         }
   3331 
   3332         if(PORTMOD_PORT_ADD_F_TX_PASS_THROUGH_CRC_GET(add_info)) {
   3333             flags |= CDMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE;
   3334         }
   3335 
   3336         /* MIB counters are cleared in cdmac_init */
   3337         rv = cdmac_init(unit, phy_acc, flags);
   3338         _SOC_IF_ERR_EXIT(rv);
   3339 
   3340         /* LSS */
   3341         _SOC_IF_ERR_EXIT(READ_CDPORT_FAULT_LINK_STATUSr(unit, phy_acc, &reg_val));
   3342         soc_reg_field_set(unit, CDPORT_FAULT_LINK_STATUSr, &reg_val, REMOTE_FAULTf, 1);
   3343         soc_reg_field_set(unit, CDPORT_FAULT_LINK_STATUSr, &reg_val, LOCAL_FAULTf, 1);
   3344         _SOC_IF_ERR_EXIT(WRITE_CDPORT_FAULT_LINK_STATUSr(unit, phy_acc, reg_val));
   3345 
   3346         /* Counter MAX size */
   3347         _SOC_IF_ERR_EXIT(pm8x50_port_cntmaxsize_set(unit, phy_acc, pm_info, 1518));
   3348     }
   3349 
   3350 exit:
   3351     SOC_FUNC_RETURN;
   3352 }
   3353 
   3354 /*
   3355  * Perfom MAC soft reset, including drain cells procedure.
   3356  *
   3357  * Supported reset modes: IN, OUT, IN-OUT
   3358  *
   3359  *    IN - set MAC in soft reset. 
   3360  *         When reset_mode=IN the parameters saved_rx_enable, saved_mac_ctrl are outputs, 
   3361  *         and should be sent back to this function when called with OUT.
   3362  *    OUT - get MAC out of soft reset.
   3363  *         When reset_mode=OUT the parameters saved_rx_enable, saved_mac_ctrl are inputs,
   3364  *         the values that should be passed in are the values returned from IN.
   3365  *         Example sequnece: 
   3366  *          int saved_rx_enablel uint64 saved_mac_ctrl;
   3367  *          pm8x50_port_soft_reset(unit, port, pinfo, PM8X50_PORT_SOFT_RESET_MODE_IN, &saved_rx_enablel, &saved_mac_ctrl);
   3368  *          ... here the MAC is in reset ...
   3369  *          pm8x50_port_soft_reset(unit, port, pinfo, PM8X50_PORT_SOFT_RESET_MODE_OUT, &saved_rx_enablel, &saved_mac_ctrl);
   3370  *     IN-OUT - get MAC IN reset and then out of reset. 
   3371  *          When  reset_mode=INOUT, saved_rx_enable, saved_mac_ctrl can be set to NULL.
   3372  */
   3373 STATIC
   3374 int pm8x50_port_soft_reset(int unit,
   3375                                  int port,
   3376                                  pm_info_t pm_info,
   3377                                  pm8x50_port_soft_reset_mode_t reset_mode,
   3378                                  int *saved_rx_enable,
   3379                                  uint64 *saved_mac_ctrl)
   3380 {
   3381 
   3382     int rv, rx_enable = 0;
   3383     portmod_drain_cells_t drain_cells;
   3384     uint32 cell_count;
   3385     uint64 mac_ctrl;
   3386     soc_timeout_t to;
   3387     SOC_INIT_FUNC_DEFS;
   3388 
   3389     /* Callback soft reset function */
   3390     if (PM_8x50_INFO(pm_info)->portmod_mac_soft_reset) {
   3391         rv = PM_8x50_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePre);
   3392         _SOC_IF_ERR_EXIT(rv);
   3393     }
   3394 
   3395     if (PM8X50_PORT_SOFT_RESET_MODE_OUT != reset_mode) {
   3396         rv = cdmac_egress_queue_drain_get(unit, port, &mac_ctrl, &rx_enable);
   3397         _SOC_IF_ERR_EXIT(rv);
   3398 
   3399         /* return MAC state if required */
   3400         if ((NULL != saved_rx_enable) && (NULL != saved_mac_ctrl)) {
   3401             *saved_rx_enable = rx_enable;
   3402             COMPILER_64_COPY(*saved_mac_ctrl, mac_ctrl);
   3403         }
   3404 
   3405         /* Drain cells */
   3406          rv = cdmac_drain_cell_get(unit, port, &drain_cells);
   3407          _SOC_IF_ERR_EXIT(rv);
   3408 
   3409         /* Start TX FIFO draining */
   3410         rv = cdmac_drain_cell_start(unit, port);
   3411         _SOC_IF_ERR_EXIT(rv);
   3412 
   3413         /* De-assert SOFT_RESET to let the drain start */
   3414         rv = cdmac_soft_reset_set(unit, port, 0);
   3415         _SOC_IF_ERR_EXIT(rv);
   3416 
   3417         if (!SAL_BOOT_SIMULATION){
   3418             /* Wait until TX fifo cell count is 0 */
   3419             soc_timeout_init(&to, 250000, 0);
   3420             for (;;) {
   3421                 rv = cdmac_txfifo_cell_cnt_get(unit, port, &cell_count);
   3422                 _SOC_IF_ERR_EXIT(rv);
   3423                 if (cell_count == 0) {
   3424                     break;
   3425                 }
   3426                 if (soc_timeout_check(&to)) {
   3427                     LOG_ERROR(BSL_LS_SOC_PORT,(BSL_META_UP(unit, port,
   3428                                                "ERROR: u=%d p=%d timeout draining TX FIFO (%d cells remain)\n"), unit, port, cell_count));
   3429                     return SOC_E_INTERNAL;
   3430                 }
   3431             }
   3432         } else {
   3433             rv = cdmac_txfifo_cell_cnt_get(unit, port, &cell_count);
   3434             _SOC_IF_ERR_EXIT(rv);
   3435         }
   3436 
   3437         /* Stop TX FIFO draining */
   3438         rv = cdmac_drain_cell_stop(unit, port, &drain_cells);
   3439         _SOC_IF_ERR_EXIT(rv);
   3440 
   3441         /* Put port into SOFT_RESET */
   3442         rv = cdmac_soft_reset_set(unit, port, 1);
   3443         _SOC_IF_ERR_EXIT(rv);
   3444     }
   3445 
   3446     if(PM8X50_PORT_SOFT_RESET_MODE_IN != reset_mode) {
   3447         if (PM_8x50_INFO(pm_info)->portmod_mac_soft_reset) {
   3448             rv = PM_8x50_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypeDuring);
   3449             _SOC_IF_ERR_EXIT(rv);
   3450         }
   3451 
   3452         /* For out of reset only operation, use MAC state from input */
   3453         if (PM8X50_PORT_SOFT_RESET_MODE_OUT == reset_mode) {
   3454             SOC_NULL_CHECK(saved_rx_enable);
   3455             SOC_NULL_CHECK(saved_mac_ctrl);
   3456             rx_enable = *saved_rx_enable;
   3457             COMPILER_64_COPY(mac_ctrl, *saved_mac_ctrl);
   3458         }
   3459 
   3460         soc_reg64_field32_set(unit, CDMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); /*make sure restored data wont put mac back in reset*/
   3461 
   3462         /* Enable TX, restore RX, de-assert SOFT_RESET */
   3463         rv = cdmac_egress_queue_drain_rx_en(unit, port, rx_enable);
   3464         _SOC_IF_ERR_EXIT(rv);
   3465 
   3466         /* Restore clmac_CTRL to original value */
   3467         rv = cdmac_mac_ctrl_set(unit, port, mac_ctrl);
   3468         _SOC_IF_ERR_EXIT(rv);
   3469 
   3470         /* Callback soft reset function */
   3471         if (PM_8x50_INFO(pm_info)->portmod_mac_soft_reset) {
   3472             rv = PM_8x50_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePost);
   3473             _SOC_IF_ERR_EXIT(rv);
   3474         }
   3475     }
   3476 
   3477 exit:
   3478    SOC_FUNC_RETURN;
   3479 }
   3480 
   3481 STATIC
   3482 int _pm8x50_port_mac_drain_soft_reset(int unit, int port)
   3483 {
   3484     int rv;
   3485     portmod_drain_cells_t drain_cells;
   3486     uint32 cell_count;
   3487     soc_timeout_t to;
   3488     SOC_INIT_FUNC_DEFS;
   3489 
   3490     /* Drain cells */
   3491     rv = cdmac_drain_cell_get(unit, port, &drain_cells);
   3492     _SOC_IF_ERR_EXIT(rv);
   3493 
   3494     /* Start TX FIFO draining */
   3495     rv = cdmac_drain_cell_start(unit, port);
   3496     _SOC_IF_ERR_EXIT(rv);
   3497 
   3498     /* De-assert SOFT_RESET to let the drain start */
   3499     rv = cdmac_soft_reset_set(unit, port, 0);
   3500     _SOC_IF_ERR_EXIT(rv);
   3501     
   3502     if (!SAL_BOOT_SIMULATION){
   3503         /* Wait until TX fifo cell count is 0 */
   3504         soc_timeout_init(&to, 250000, 0);
   3505         for (;;) {
   3506             rv = cdmac_txfifo_cell_cnt_get(unit, port, &cell_count);
   3507             _SOC_IF_ERR_EXIT(rv);
   3508             if (cell_count == 0) {
   3509                 break;
   3510             }
   3511             if (soc_timeout_check(&to)) {
   3512                 LOG_ERROR(BSL_LS_SOC_PORT,(BSL_META_UP(unit, port,
   3513                                            "ERROR: u=%d p=%d timeout draining TX FIFO (%d cells remain)\n"), unit, port, cell_count));
   3514                 return SOC_E_INTERNAL;
   3515             }
   3516         }
   3517     } else {
   3518         rv = cdmac_txfifo_cell_cnt_get(unit, port, &cell_count);
   3519         _SOC_IF_ERR_EXIT(rv);
   3520     }
   3521     /* Stop TX FIFO draining */
   3522     rv = cdmac_drain_cell_stop(unit, port, &drain_cells);
   3523     _SOC_IF_ERR_EXIT(rv);
   3524 
   3525     /* Put port into SOFT_RESET */
   3526     rv = cdmac_soft_reset_set(unit, port, 1);
   3527     _SOC_IF_ERR_EXIT(rv);
   3528 
   3529 exit:
   3530     SOC_FUNC_RETURN;
   3531 }
   3532 
   3533 STATIC
   3534 int _pm8x50_port_rx_restore_mac_out_of_reset(int unit, int port, int rx_enable)
   3535 {
   3536     int rv;
   3537     SOC_INIT_FUNC_DEFS;
   3538 
   3539     /* Enable RX, de-assert SOFT_RESET */
   3540     rv = cdmac_egress_queue_drain_rx_en(unit, port, rx_enable);
   3541     _SOC_IF_ERR_EXIT(rv);
   3542 
   3543 exit:
   3544     SOC_FUNC_RETURN;
   3545 }
   3546 
   3547 
   3548 /*Add new port*/
   3549 int pm8x50_port_attach(int unit, int port, pm_info_t pm_info,
   3550                        const portmod_port_add_info_t* add_info)
   3551 {
   3552     int port_index = -1, pm_is_active = 0, is_pcs_bypassed = 0;
   3553     int rv = 0, port_i, my_i, found_first_active_lane;
   3554     int phy, ii, nof_phys;
   3555     portmod_pbmp_t port_phys_in_pm;
   3556     phymod_phy_init_config_t init_config;
   3557     portmod_access_get_params_t params;
   3558     phymod_phy_access_t phy_access;
   3559     phymod_phy_signalling_method_t signalling_mode;
   3560     phymod_an_mode_type_t init_an_mode = phymod_AN_MODE_NONE;
   3561     const portmod_speed_config_t *speed_config = &add_info->speed_config;
   3562     int usr_cfg_idx, rlm_enabled = 0, rlm_state = PORTMOD_PORT_RLM_FSM_COUNT;
   3563     uint32 timesync_enable_default = 0;
   3564     SOC_INIT_FUNC_DEFS;
   3565 
   3566     /* Get the first phy related to this port */
   3567     PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys);
   3568     PORTMOD_PBMP_AND(port_phys_in_pm, PM_8x50_INFO(pm_info)->phys);
   3569 
   3570     ii = 0;
   3571     PORTMOD_PBMP_ITER(PM_8x50_INFO(pm_info)->phys, phy) {
   3572         if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) {
   3573             rv = PM8x50_LANE2PORT_SET(unit, pm_info, ii, port);
   3574             _SOC_IF_ERR_EXIT(rv);
   3575             port_index = (port_index == -1 ? ii : port_index);
   3576         }
   3577         ii++;
   3578     }
   3579 
   3580     is_pcs_bypassed = PORTMOD_PORT_ADD_F_PCS_BYPASSED_GET(add_info) ? 1 : 0;
   3581     rv = PM8x50_PORT_IS_PCS_BYPASSED_SET(unit, pm_info, is_pcs_bypassed, port_index);
   3582     _SOC_IF_ERR_EXIT(rv);
   3583 
   3584     /* initalize port */
   3585     rv = _pm8x50_pm_port_init(unit, port, pm_info, port_index, add_info, 1);
   3586     _SOC_IF_ERR_EXIT(rv);
   3587 
   3588     /* initialze phy */
   3589     _SOC_IF_ERR_EXIT(phymod_phy_init_config_t_init(&init_config));
   3590     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   3591     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   3592                                 &params, 1, &phy_access, &nof_phys, NULL));
   3593 
   3594     
   3595     init_config.an_en = add_info->autoneg_en;
   3596     init_config.cl72_en = add_info->link_training_en;
   3597     init_config.op_mode = add_info->interface_config.port_op_mode;
   3598     my_i = 0, usr_cfg_idx = 0;
   3599     found_first_active_lane = 0;
   3600     for(ii=0; ii<PM8X50_LANES_PER_CORE; ii++) {
   3601         rv = PM8x50_LANE2PORT_GET(unit, pm_info, ii, &port_i);
   3602         _SOC_IF_ERR_EXIT(rv);
   3603 
   3604         if(port_i != port) {
   3605             /* There is a difference between XGS and DNX devices. For DNX, a port can consist inconsecutive physical lanes.
   3606              * For example, a port can consist lane 1 and 3 of the same core. For XGS, on the other hand, a port always consist
   3607              * consecutive physical lanes. Therefore my_i below needs not be incremented for XGS devices.
   3608              */
   3609             if(PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy_access.device_op_mode) && found_first_active_lane){
   3610                 my_i++;
   3611             }
   3612             continue;
   3613         } else{
   3614             found_first_active_lane = 1;
   3615         }
   3616 
   3617         _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access, phymodMediaTypeChipToChip, &init_config.tx[my_i]));
   3618 
   3619         if (PORTMOD_PORT_ADD_F_SKIP_SPEED_INIT_GET(add_info)) {
   3620             /* If PORTMOD_PORT_ADD_F_SKIP_SPEED_INIT is set, set tx_taps to NRZ default */
   3621             signalling_mode = phymodSignallingMethodNRZ;
   3622         } else {
   3623             _pm8x50_signalling_method_get(is_pcs_bypassed, speed_config, &signalling_mode);
   3624         }
   3625 
   3626         if (PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG_GET(add_info->init_config.tx_params_user_flag[usr_cfg_idx])) {
   3627             init_config.tx[my_i].pre = add_info->init_config.tx_params[usr_cfg_idx].pre;
   3628             init_config.tx[my_i].main = add_info->init_config.tx_params[usr_cfg_idx].main;
   3629             init_config.tx[my_i].post = add_info->init_config.tx_params[usr_cfg_idx].post;
   3630             init_config.tx[my_i].pre2 = add_info->init_config.tx_params[usr_cfg_idx].pre2;
   3631             init_config.tx[my_i].post2 = add_info->init_config.tx_params[usr_cfg_idx].post2;
   3632             init_config.tx[my_i].post3 = add_info->init_config.tx_params[usr_cfg_idx].post3;
   3633             init_config.tx[my_i].tap_mode = add_info->init_config.tx_params[usr_cfg_idx].tap_mode;
   3634             init_config.tx[my_i].sig_method = add_info->init_config.tx_params[usr_cfg_idx].sig_method;
   3635         } else {
   3636             /* Need to get the default values for tx taps */
   3637             _SOC_IF_ERR_EXIT(phymod_phy_tx_taps_default_get(&phy_access, signalling_mode, &init_config.tx[my_i]));
   3638         }
   3639 
   3640         usr_cfg_idx++;
   3641         my_i++;
   3642     }
   3643 
   3644     _SOC_IF_ERR_EXIT(phymod_phy_init(&phy_access, &init_config));
   3645 
   3646     /* MAC SOFT_RESET will be released within pm8x50_port_speed_config_set */
   3647     if (!PORTMOD_PORT_ADD_F_SKIP_SPEED_INIT_GET(add_info)) {
   3648         rv = pm8x50_port_speed_config_set(unit, port, pm_info, speed_config);
   3649     }
   3650     else if (!is_pcs_bypassed)
   3651     {
   3652        _SOC_IF_ERR_EXIT(pm8x50_port_soft_reset(unit, port, pm_info, PM8X50_PORT_SOFT_RESET_MODE_IN_OUT, NULL, NULL));
   3653     }
   3654 
   3655     _SOC_IF_ERR_EXIT(rv);
   3656 
   3657     /* Update WB DB */
   3658     rv = PM8x50_IS_ACTIVE_GET(unit, pm_info, &pm_is_active);
   3659     _SOC_IF_ERR_EXIT(rv);
   3660     if (!pm_is_active) {
   3661         pm_is_active = 1;
   3662         rv = PM8x50_IS_ACTIVE_SET(unit, pm_info, pm_is_active);
   3663         _SOC_IF_ERR_EXIT(rv);
   3664     }
   3665 
   3666     rv = PM8x50_AN_MODE_SET(unit, pm_info, init_an_mode, port_index);
   3667     _SOC_IF_ERR_EXIT(rv);
   3668 
   3669     rv = PM8x50_MAX_SPEED_SET(unit, pm_info, add_info->interface_config.max_speed, port_index);
   3670     _SOC_IF_ERR_EXIT(rv);
   3671 
   3672     rv = PM8x50_TIMESYNC_ENABLE_SET(unit, pm_info, timesync_enable_default, port_index);
   3673     _SOC_IF_ERR_EXIT(rv);
   3674 
   3675     _SOC_IF_ERR_EXIT
   3676         (PM8x50_RLM_ENABLE_SET(unit, pm_info, rlm_enabled, port_index));
   3677 
   3678     _SOC_IF_ERR_EXIT
   3679         (PM8x50_RLM_STATE_SET(unit, pm_info, rlm_state, port_index));
   3680 
   3681     if (add_info->init_config.parity_enable) {
   3682         _pm8x50_port_interrupt_all_enable_set(unit, port, 1);
   3683 
   3684     }
   3685 
   3686 exit:
   3687     SOC_FUNC_RETURN;
   3688 }
   3689 
   3690 /*get port cores' phymod access*/
   3691 int pm8x50_pm_core_info_get(int unit, pm_info_t pm_info, int phyn,
   3692                             portmod_pm_core_info_t* core_info)
   3693 {
   3694     SOC_INIT_FUNC_DEFS;
   3695 
   3696     if(phyn < 0) {
   3697         phyn = PM8X50_MAX_NUM_PHYS;
   3698     }
   3699 
   3700     core_info->ref_clk = PM_8x50_INFO(pm_info)->ref_clk;
   3701     sal_memcpy(&core_info->lane_map, &(PM_8x50_INFO(pm_info)->lane_map),
   3702                sizeof(phymod_lane_map_t));
   3703 
   3704     SOC_FUNC_RETURN;
   3705 }
   3706 
   3707 /*Get PM phys.*/
   3708 int pm8x50_pm_phys_get(int unit, pm_info_t pm_info, portmod_pbmp_t* phys)
   3709 {
   3710     SOC_INIT_FUNC_DEFS;
   3711     PORTMOD_PBMP_ASSIGN(*phys, PM_8x50_INFO(pm_info)->phys);
   3712     SOC_FUNC_RETURN;
   3713 }
   3714 
   3715 /*Port remove in PM level*/
   3716 int pm8x50_port_detach(int unit, int port, pm_info_t pm_info)
   3717 {
   3718     int enable, invalid_port = -1, tmp_port, i = 0, flags = 0, pm_id;
   3719     int is_last_one = TRUE, port_index = -1, fec_null = 0;
   3720     const uint32 is_active = 0;
   3721     int tvco_pll_index, ovco_pll_index;
   3722     uint8_t ovco_pll_active_lane_bm, tvco_pll_active_lane_bm;
   3723     uint8_t ovco_pll_adv_lane_bm, tvco_pll_adv_lane_bm, eth_active_lanes;
   3724     portmod_access_get_params_t params;
   3725     phymod_phy_access_t phy_access;
   3726     int nof_phys;
   3727     portmod_phy_timesync_config_t config;
   3728 
   3729     SOC_INIT_FUNC_DEFS;
   3730 
   3731     _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_unregister(unit, port));
   3732 
   3733     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   3734     ovco_pll_index = (tvco_pll_index == 1)? 0: 1;
   3735 
   3736     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   3737     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   3738                                 &params, 1, &phy_access, &nof_phys, NULL));
   3739     _SOC_IF_ERR_EXIT(pm8x50_port_enable_get(unit, port, pm_info, flags, &enable));
   3740     if (enable)
   3741         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("can't detach active port %d"), port));
   3742 
   3743     /* Disable 1588 */
   3744     config.flags = 0;
   3745     _SOC_IF_ERR_EXIT(pm8x50_port_timesync_config_set(unit, port, pm_info, &config));
   3746 
   3747     /* Disable PCS for the port */
   3748     _SOC_IF_ERR_EXIT(phymod_phy_pcs_enable_set(&phy_access, 0));
   3749     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bm));
   3750     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_active_lane_bm));
   3751     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bm));
   3752     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_adv_lane_bm));
   3753 
   3754     /* flexport workaround for 16nm  flexportHW issue */
   3755     /* first get the port index */
   3756     for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   3757         _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port));
   3758         if (tmp_port == port) {
   3759             port_index = (port_index == -1 ? i : port_index);
   3760         }
   3761     }
   3762     /* call port level port mode update */
   3763     _SOC_IF_ERR_EXIT(_pm8x50_pm_port_mode_update(unit, port, pm_info, port_index, 1));
   3764     /* call speed toggle workaround */
   3765     _SOC_IF_ERR_EXIT(phymod_phy_pcs_enable_set(&phy_access, FLEXPORT_SW_WAR_ENABLE));
   3766     /*-- Flexport workaround ends here. --*/
   3767 
   3768 
   3769     for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   3770         _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port));
   3771         if (tmp_port == port) {
   3772             port_index = (port_index == -1 ? i : port_index);
   3773             _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_SET(unit, pm_info, i, invalid_port));
   3774             _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec_null));
   3775             ovco_pll_active_lane_bm &= ~(1 << i);
   3776             tvco_pll_active_lane_bm &= ~(1 << i);
   3777             ovco_pll_adv_lane_bm &= ~(1 << i);
   3778             tvco_pll_adv_lane_bm &= ~(1 << i);
   3779         } else if (tmp_port != invalid_port) {
   3780             is_last_one = FALSE;
   3781         }
   3782     }
   3783 
   3784     if (port_index == -1)
   3785         _SOC_EXIT_WITH_ERR(SOC_E_PORT, (_SOC_MSG("Port %d wasn't found"), port));
   3786 
   3787     if ((!ovco_pll_active_lane_bm) && (!ovco_pll_adv_lane_bm)) {
   3788         /* Power down OVCO if it's not in use */
   3789         _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, ovco_pll_index, 1));
   3790         PM_8x50_INFO(pm_info)->ovco = portmodVCOInvalid;
   3791     }
   3792 
   3793     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, ovco_pll_active_lane_bm));
   3794     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, tvco_pll_active_lane_bm));
   3795     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, ovco_pll_adv_lane_bm));
   3796     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, tvco_pll_adv_lane_bm));
   3797 
   3798     _SOC_IF_ERR_EXIT(_pm8x50_pm_active_eth_lanes_get(unit, pm_info, &eth_active_lanes));
   3799 
   3800     if (!eth_active_lanes && !tvco_pll_active_lane_bm) {
   3801         /*
   3802          * Power down TVCO if
   3803          * 1. No active ethernet ports, and
   3804          * 2. No ILKN port is using TVCO.
   3805          * Note: Since no active eth port -> there are no adv ports -> no need to check tvco_pll_adv_lane_bm
   3806          */
   3807         _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, tvco_pll_index, 1));
   3808         PM_8x50_INFO(pm_info)->tvco = portmodVCOInvalid;
   3809     }
   3810 
   3811     /*deinit PM in case of last one*/
   3812     if (is_last_one) {
   3813         _SOC_IF_ERR_EXIT(portmod_port_pm_id_get(unit, port, &pm_id));
   3814         _SOC_IF_ERR_EXIT(pm8x50_pm_enable(unit, pm_id, pm_info, 0));
   3815         _SOC_IF_ERR_EXIT(PM8x50_IS_ACTIVE_SET(unit, pm_info, is_active));
   3816         _SOC_IF_ERR_EXIT(PM8x50_IS_CORE_INITIALIZED_SET(unit, pm_info, is_active));
   3817 
   3818         PM_8x50_INFO(pm_info)->int_core_access.type = phymodDispatchTypeInvalid;
   3819     }
   3820 
   3821 exit:
   3822     SOC_FUNC_RETURN;
   3823 }
   3824 
   3825 /*Port replace in PM level*/
   3826 int pm8x50_port_replace(int unit, int port, pm_info_t pm_info, int new_port)
   3827 {
   3828     int i, tmp_port;
   3829     int rv = 0;
   3830     SOC_INIT_FUNC_DEFS;
   3831 
   3832     /* replace old port with new port */
   3833     for(i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
   3834         rv = PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port);
   3835         _SOC_IF_ERR_EXIT(rv);
   3836         if (tmp_port == port) {
   3837             rv = PM8x50_LANE2PORT_SET(unit, pm_info, i, new_port);
   3838             _SOC_IF_ERR_EXIT(rv);
   3839         }
   3840     }
   3841 
   3842 exit:
   3843     SOC_FUNC_RETURN;
   3844 }
   3845 
   3846 
   3847 /*Port enable*/
   3848 int pm8x50_port_enable_set(int unit, int port, pm_info_t pm_info,
   3849                            int flags, int enable)
   3850 {
   3851     int actual_flags = flags;
   3852     int cdmac_flags = 0, port_index;
   3853     uint32 is_bypassed = 0, bitmap[1];
   3854     phymod_phy_access_t phy_access;
   3855     portmod_access_get_params_t params;
   3856     int nof_phys = 0;
   3857     SOC_INIT_FUNC_DEFS;
   3858 
   3859     /* If no RX\TX flags - set both*/
   3860     if((!PORTMOD_PORT_ENABLE_TX_GET(flags)) &&
   3861        (!PORTMOD_PORT_ENABLE_RX_GET(flags))) {
   3862         PORTMOD_PORT_ENABLE_RX_SET(actual_flags);
   3863         PORTMOD_PORT_ENABLE_TX_SET(actual_flags);
   3864     }
   3865 
   3866     /* if no MAC\Phy flags - set both*/
   3867     if((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) &&
   3868        (!PORTMOD_PORT_ENABLE_MAC_GET(flags))) {
   3869         PORTMOD_PORT_ENABLE_PHY_SET(actual_flags);
   3870         PORTMOD_PORT_ENABLE_MAC_SET(actual_flags);
   3871     }
   3872 
   3873     /*
   3874      * if MAC is set and having only either RX or TX set
   3875      * is invalid combination
   3876      */
   3877     if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) &&
   3878        (!PORTMOD_PORT_ENABLE_PHY_GET(actual_flags))) {
   3879 
   3880         if((!PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) ||
   3881            (!PORTMOD_PORT_ENABLE_RX_GET(actual_flags))) {
   3882            _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   3883                       (_SOC_MSG("MAC RX and TX can't be enabled separately")));
   3884         }
   3885     }
   3886 
   3887     if(PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) {
   3888         /* Only internal phy supported. */
   3889         _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   3890         _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port,
   3891                                      pm_info, &params, 1, &phy_access,
   3892                                      &nof_phys, NULL));
   3893     }
   3894     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, bitmap));
   3895     _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index));
   3896 
   3897     if(enable){
   3898         if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)) {
   3899 
   3900             if(!PM_8x50_INFO(pm_info)->portmod_mac_soft_reset)
   3901             {
   3902                 _SOC_IF_ERR_EXIT(cdmac_enable_set(unit, port, cdmac_flags, 1));
   3903             }
   3904             else
   3905             {
   3906                 /* Enable CDMAC RX,TX, skip SOFT_RESET */
   3907                 _SOC_IF_ERR_EXIT(cdmac_tx_enable_set (unit, port, 1));
   3908                 _SOC_IF_ERR_EXIT(cdmac_rx_enable_set (unit, port, 1));
   3909                 _SOC_IF_ERR_EXIT(pm8x50_port_soft_reset(unit, port, pm_info, PM8X50_PORT_SOFT_RESET_MODE_IN_OUT, NULL, NULL));
   3910             }
   3911         }
   3912 
   3913         if(PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) {
   3914             if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) {
   3915                 _SOC_IF_ERR_EXIT(
   3916                     phymod_phy_tx_lane_control_set(&phy_access,
   3917                                                    phymodTxSquelchOff));
   3918             }
   3919             if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) {
   3920                 _SOC_IF_ERR_EXIT(
   3921                     phymod_phy_rx_lane_control_set(&phy_access,
   3922                                                    phymodRxSquelchOff));
   3923             }
   3924         } /* PORTMOD_PORT_ENABLE_PHY_GET */
   3925     } else {/* disable */
   3926         if (PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) {
   3927 
   3928             if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) {
   3929                 _SOC_IF_ERR_EXIT(
   3930                     phymod_phy_tx_lane_control_set(&phy_access,
   3931                                                    phymodTxSquelchOn));
   3932             }
   3933 
   3934             if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) {
   3935                 _SOC_IF_ERR_EXIT(
   3936                     phymod_phy_rx_lane_control_set(&phy_access,
   3937                                                    phymodRxSquelchOn));
   3938             }
   3939         }
   3940 
   3941         if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags))  && (!is_bypassed)) {
   3942             _SOC_IF_ERR_EXIT(cdmac_enable_set(unit, port, cdmac_flags, 0));
   3943         }
   3944     }
   3945 
   3946 exit:
   3947     SOC_FUNC_RETURN;
   3948 }
   3949 
   3950 int pm8x50_port_enable_get(int unit, int port, pm_info_t pm_info,
   3951                            int flags, int* enable)
   3952 {
   3953     int nof_phys = 0, port_index;
   3954     int phy_enable = 1, mac_enable = 1;
   3955     int mac_rx_enable = 0, mac_tx_enable = 0;
   3956     uint32 is_bypassed = 0, bitmap[1];
   3957     int actual_flags = flags;
   3958     phymod_phy_access_t phy_access;
   3959     portmod_access_get_params_t params;
   3960     phymod_phy_tx_lane_control_t tx_control = phymodTxSquelchOn;
   3961     phymod_phy_rx_lane_control_t rx_control = phymodRxSquelchOn;
   3962     SOC_INIT_FUNC_DEFS;
   3963     SOC_NULL_CHECK(pm_info);
   3964 
   3965     /* If no RX\TX flags - set both*/
   3966     if((!PORTMOD_PORT_ENABLE_TX_GET(flags)) &&
   3967        (!PORTMOD_PORT_ENABLE_RX_GET(flags))) {
   3968         PORTMOD_PORT_ENABLE_RX_SET(actual_flags);
   3969         PORTMOD_PORT_ENABLE_TX_SET(actual_flags);
   3970     }
   3971 
   3972     /* if no MAC\Phy flags - set both*/
   3973     if((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) &&
   3974        (!PORTMOD_PORT_ENABLE_MAC_GET(flags))) {
   3975         PORTMOD_PORT_ENABLE_PHY_SET(actual_flags);
   3976         PORTMOD_PORT_ENABLE_MAC_SET(actual_flags);
   3977     }
   3978 
   3979     if(PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) {
   3980         /* Only internal phy supported. */
   3981         _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   3982         _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port,
   3983                                      pm_info, &params, 1, &phy_access,
   3984                                      &nof_phys, NULL));
   3985     }
   3986 
   3987     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, bitmap));
   3988     _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index));
   3989 
   3990     if (PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) {
   3991         _SOC_IF_ERR_EXIT(phymod_phy_tx_lane_control_get(&phy_access,
   3992                                                         &tx_control));
   3993         _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_get(&phy_access,
   3994                                                         &rx_control));
   3995 
   3996         /* TBD - set phy_enable to 1 for SIM */
   3997         phy_enable = 0;
   3998 
   3999         if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) {
   4000             phy_enable |= (rx_control == phymodRxSquelchOn) ? 0 : 1;
   4001         }
   4002         if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) {
   4003             phy_enable |= (tx_control == phymodTxSquelchOn) ? 0 : 1;
   4004         }
   4005     }
   4006 
   4007     if ((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)) {
   4008         mac_enable = 0;
   4009 
   4010         if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) {
   4011             _SOC_IF_ERR_EXIT(cdmac_enable_get(unit, port,
   4012                                               CDMAC_ENABLE_SET_FLAGS_RX_EN,
   4013                                               &mac_rx_enable));
   4014             mac_enable |= (mac_rx_enable)? 1: 0;
   4015         }
   4016 
   4017         if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) {
   4018             _SOC_IF_ERR_EXIT(cdmac_enable_get(unit, port,
   4019                                               CDMAC_ENABLE_SET_FLAGS_TX_EN,
   4020                                               &mac_tx_enable));
   4021             mac_enable |= (mac_tx_enable)? 1: 0;
   4022         }
   4023     }
   4024 
   4025     *enable = (mac_enable && phy_enable);
   4026 
   4027 exit:
   4028     SOC_FUNC_RETURN;
   4029 }
   4030 
   4031 /*
   4032  * Function:
   4033  * _pm8x50_vcos_request_allocate_internal.
   4034  *
   4035  * Purpose:
   4036  *      Function gets current TVCO, OVCO and tries to accommodate input VCO requests.
   4037  *
   4038  * Inputs:
   4039  *     unit:                 unit number
   4040  *     flags:                Special flags for vco allocation. (PM8X50_TVCO_SUPPORT_20P625G)
   4041  *     required_vcos_bmp:    required VCO bitmap
   4042  *     current_tvco:         current TVCO value
   4043  *     current_ovco:         current OVCO value
   4044  * Output:
   4045  *     current_tvco:         if validation pass, current_tvco will indicate new value TVCO value
   4046  *     current_ovco:         if validation pass, current_ovco will indicate new value OVCO value
   4047  */
   4048 STATIC
   4049 int _pm8x50_vcos_request_allocate_internal(
   4050         int unit,
   4051         uint32 flags,
   4052         const pm8x50_vcos_bmp_t required_vcos_bmp,
   4053         portmod_vco_type_t *current_tvco,
   4054         portmod_vco_type_t *current_ovco)
   4055 {
   4056     pm8x50_vcos_bmp_t required_vcos_bmp_temp;
   4057     int is_tvco_in_use, is_ovco_in_use, is_eth_drv_tvco;
   4058     portmod_vco_type_t required_vco;
   4059     int required_pcs_bypass;
   4060 
   4061     SOC_INIT_FUNC_DEFS;
   4062 
   4063     is_tvco_in_use = (*current_tvco == portmodVCOInvalid) ? 0 : 1;
   4064     is_ovco_in_use = (*current_ovco == portmodVCOInvalid) ? 0 : 1;
   4065 
   4066     required_vcos_bmp_temp = required_vcos_bmp;
   4067 
   4068     while (!PM8x50_VCO_BMP_EMPTY(required_vcos_bmp_temp)) {
   4069         is_eth_drv_tvco = _pm8x50_ethernet_tvco_check(unit, flags, *current_tvco);
   4070         /*
   4071          *  1. Get next required VCO.
   4072          *  2. Clear VCO from temp bitmap
   4073          */
   4074         _SOC_IF_ERR_EXIT(
   4075                 _pm8x50_required_vco_value_iter(unit, &required_vcos_bmp_temp, &required_vco, &required_pcs_bypass));
   4076 
   4077         /* Try to match with TVCO current configuration */
   4078         if (is_tvco_in_use) {
   4079             if (required_vco == *current_tvco) {
   4080                 /*
   4081                  * If tvco match AND eth port is requried AND request is not TVCO supported => there is no match.
   4082                  * For pcs bypass no restrictions.
   4083                  */
   4084                 if (required_pcs_bypass || (!required_pcs_bypass && is_eth_drv_tvco)) {
   4085                     continue;
   4086                 }
   4087             }
   4088         }
   4089 
   4090         /* Try to match with OVCO current configuration */
   4091         if (is_ovco_in_use) {
   4092             if (required_vco == *current_ovco) {
   4093                 /*
   4094                  * If ovco match AND eth port is requried AND tvco is not eth => there is no match.
   4095                  * For pcs bypass no restrictions.
   4096                  */
   4097                 if (required_pcs_bypass || (!required_pcs_bypass && is_eth_drv_tvco)) {
   4098                     continue;
   4099                 }
   4100             }
   4101         }
   4102 
   4103         /* For TVCO ethernet rates, try first to lock TVCO. For non-TVCO ethernet rate - try to first lock OVCO*/
   4104         if (_pm8x50_ethernet_tvco_check(unit, flags, required_vco)) {
   4105             if (!is_tvco_in_use) {
   4106                 *current_tvco = required_vco;
   4107                 is_tvco_in_use = 1;
   4108                 continue;
   4109             } else if (!is_ovco_in_use) {
   4110                 /*
   4111                  * Can use OVCO for ILKN ports with no condition,
   4112                  * Can use OVCO for ETH only if TVCO is ETH
   4113                  */
   4114                 if (required_pcs_bypass || (!required_pcs_bypass && is_eth_drv_tvco)) {
   4115                     *current_ovco = required_vco;
   4116                     is_ovco_in_use = 1;
   4117                     continue;
   4118                 }
   4119             }
   4120         } else {
   4121             /* non-TVCO ethernet rate */
   4122             if (!is_ovco_in_use) {
   4123                 if ((required_pcs_bypass) || (!required_pcs_bypass && is_eth_drv_tvco)) {
   4124                     *current_ovco = required_vco;
   4125                     is_ovco_in_use = 1;
   4126                     continue;
   4127                 }
   4128             } else if (!is_tvco_in_use) {
   4129                 if (required_pcs_bypass) {
   4130                     /*
   4131                      * Support setting TVCO if bypass
   4132                      */
   4133                     *current_tvco = required_vco;
   4134                     is_tvco_in_use = 1;
   4135                     continue;
   4136                 }
   4137             }
   4138         }
   4139 
   4140         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4141                 (_SOC_MSG("Can not accommodate VCO settings.\n request [VCO %d, PCS bypass %d], state [TVCO %d, OVCO %d]\n"), required_vco, required_pcs_bypass, *current_tvco, *current_ovco));
   4142 
   4143     }
   4144 
   4145  exit:
   4146     SOC_FUNC_RETURN;
   4147 }
   4148 
   4149 
   4150 /*
   4151  * Function:
   4152  * pm8x50_vcos_request_allocate.
   4153  *
   4154  * Purpose:
   4155  *      Function gets current TVCO, OVCO and tries to accommodate input VCO requests.
   4156  *      Function splits required VCO bitmap into 2 bitmaps -
   4157  *         - VCO rates existing in current state
   4158  *         - new VCO rates.
   4159  *      Function first tries serve new VCO rates and then existing VCO rates.
   4160  *
   4161  * Inputs:
   4162  *     unit:                 unit number
   4163  *     flags:                special flag for allocation. (PM8X50_TVCO_SUPPORT_20P625G)
   4164  *     required_vcos_bmp:    required VCO bitmap
   4165  *     current_tvco:         current TVCO value
   4166  *     current_ovco:         current OVCO value
   4167  * Output:
   4168  *     current_tvco:         If validation pass, current_tvco will indicate new value TVCO value
   4169  *     current_ovco:         If validation pass, current_ovco will indicate new value OVCO value
   4170  */
   4171 
   4172 int pm8x50_vcos_request_allocate(
   4173         int unit,
   4174         uint32 flags,
   4175         const pm8x50_vcos_bmp_t required_vcos_bmp,
   4176         portmod_vco_type_t *current_tvco,
   4177         portmod_vco_type_t *current_ovco)
   4178 {
   4179     pm8x50_vcos_bmp_t vco_bmp, required_new_vcos_bmp = 0,  required_existing_vcos_bmp = 0;
   4180     pm8x50_vcos_bmp_t required_vcos_bmp_temp;
   4181     portmod_vco_type_t required_vco;
   4182     int required_pcs_bypass;
   4183 
   4184     SOC_INIT_FUNC_DEFS;
   4185 
   4186     /* Copy request bitmap */
   4187     required_vcos_bmp_temp = required_vcos_bmp;
   4188 
   4189     /* Handle special case of 20.625G Ethernet only request --> Add 25.871 VCO to request to drive TVCO*/
   4190     if (!PM8X50_TVCO_SUPPORT_20P625G_GET(flags) &&
   4191         PM8x50_VCO_BMP_20P625G_ETH_ONLY(required_vcos_bmp) &&
   4192         (*current_tvco == portmodVCOInvalid) && ((*current_ovco == portmodVCOInvalid) || (*current_ovco == portmodVCO20P625G)))
   4193     {
   4194         PM8x50_VCO_ETH_25P781G_SET(required_vcos_bmp_temp);
   4195     }
   4196 
   4197     /* Handle special case of 25G Ethernet only request --> Add 25.871 VCO request to drive TVCO */
   4198     if (PM8x50_VCO_BMP_25G_ETH_ONLY(required_vcos_bmp) &&
   4199         (*current_tvco == portmodVCOInvalid) &&
   4200         ((*current_ovco == portmodVCOInvalid) || (*current_ovco == portmodVCO25G))) {
   4201         PM8x50_VCO_ETH_25P781G_SET(required_vcos_bmp_temp);
   4202     }
   4203 
   4204     /*
   4205      * Split required VCOs bitmap into new/existing requests bitmaps
   4206      */
   4207 
   4208     while (!PM8x50_VCO_BMP_EMPTY(required_vcos_bmp_temp))
   4209     {
   4210         /*
   4211          *  1. Get next required VCO.
   4212          *  2. Clear VCO from temp bitmap
   4213          */
   4214         _SOC_IF_ERR_EXIT(
   4215                 _pm8x50_required_vco_value_iter(unit, &required_vcos_bmp_temp, &required_vco, &required_pcs_bypass));
   4216 
   4217         /* Get VCO bitmap */
   4218         _SOC_IF_ERR_EXIT(_pm8x50_required_vco_bitmap_get(unit, required_vco, required_pcs_bypass, &vco_bmp));
   4219 
   4220         if (required_vco == *current_tvco || required_vco == *current_ovco)
   4221         {
   4222             /* Add to existing VCO bitmap */
   4223             required_existing_vcos_bmp |= vco_bmp;
   4224         }
   4225         else
   4226         {
   4227             /* Add to new VCO bitmap */
   4228             required_new_vcos_bmp |= vco_bmp;
   4229         }
   4230     }
   4231 
   4232     /* Serve new VCOs */
   4233     _SOC_IF_ERR_EXIT(
   4234             _pm8x50_vcos_request_allocate_internal(unit, flags, required_new_vcos_bmp, current_tvco, current_ovco));
   4235 
   4236     /* Serve existing VCOs */
   4237     _SOC_IF_ERR_EXIT(
   4238             _pm8x50_vcos_request_allocate_internal(unit, flags, required_existing_vcos_bmp, current_tvco, current_ovco));
   4239 
   4240 exit:
   4241     SOC_FUNC_RETURN;
   4242 }
   4243 
   4244 STATIC
   4245 int _pm8x50_fec_lanebitmap_get(int unit,
   4246                                pm_info_t pm_info,
   4247                                uint8 *rs528_bitmap,
   4248                                uint8 *rs544_bitmap,
   4249                                uint8 *rs272_bitmap)
   4250 {
   4251     int i, rv;
   4252     portmod_fec_t tmp_fec;
   4253 
   4254     SOC_INIT_FUNC_DEFS;
   4255 
   4256     *rs528_bitmap = 0;
   4257     *rs544_bitmap = 0;
   4258     *rs272_bitmap = 0;
   4259     /* Get RS528, RS544, RS272 usage bitmap from WB */
   4260     for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++){
   4261         rv = PM8x50_LANE2FEC_GET(unit, pm_info, i, &tmp_fec);
   4262         _SOC_IF_ERR_EXIT(rv);
   4263         if (tmp_fec == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   4264             *rs528_bitmap |= 1 << i;
   4265         } else if ((tmp_fec == PORTMOD_PORT_PHY_FEC_RS_544) ||
   4266                    (tmp_fec == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   4267             *rs544_bitmap |= 1 << i;
   4268         } else if ((tmp_fec == PORTMOD_PORT_PHY_FEC_RS_272) ||
   4269                    (tmp_fec == PORTMOD_PORT_PHY_FEC_RS_272_2XN)) {
   4270             *rs272_bitmap |= 1 << i;
   4271         }
   4272     }
   4273 exit:
   4274     SOC_FUNC_RETURN;
   4275 }
   4276 
   4277 /*
   4278  * Function:
   4279  *_pm8x50_vcos_setting_validate
   4280  *
   4281  * Purpose:
   4282  *     VCOs setting validation.
   4283  *
   4284  * Inputs:
   4285  *     unit:               unit number;
   4286  *     pm_info:            pm_info data structure;
   4287  *     ports:              Logical port bitmaps which reqiring the input vcos;
   4288  *     required_vcos_bmp:  Required vcos bitmap;
   4289  *     flag:               PLL switch flag;
   4290  * Output:
   4291  *     vco_setting:    If validation pass, vco_setting will indicating
   4292  *                     what's the new vco rates and whether they are new or not;
   4293  *                     vco_setting.num_speeds and vco_setting.speed_config_list
   4294  *                     are no care in this function.
   4295  */
   4296 int _pm8x50_vcos_setting_validate(int unit,
   4297                                   pm_info_t pm_info,
   4298                                   const portmod_pbmp_t* ports,
   4299                                   pm8x50_vcos_bmp_t required_vcos_bmp,
   4300                                   int flag,
   4301                                   portmod_pm_vco_setting_t* vco_setting)
   4302 {
   4303     uint8_t ovco_pll_active_lane_bitmap, tvco_pll_active_lane_bitmap, ovco_pll_adv_lane_bitmap, tvco_pll_adv_lane_bitmap;
   4304     int is_tvco_in_use, is_ovco_in_use;
   4305     portmod_vco_type_t current_tvco, current_ovco;
   4306     uint32_t port_lane_mask = 0, lane_bitmap[1];
   4307     int port, port_index;
   4308     uint8_t active_eth_lanes;
   4309     uint32 flags = 0;
   4310 
   4311     SOC_INIT_FUNC_DEFS;
   4312 
   4313     _SOC_IF_ERR_EXIT(
   4314             PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bitmap));
   4315     _SOC_IF_ERR_EXIT(
   4316             PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_active_lane_bitmap));
   4317     _SOC_IF_ERR_EXIT(
   4318             PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bitmap));
   4319     _SOC_IF_ERR_EXIT(
   4320             PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_adv_lane_bitmap));
   4321     _SOC_IF_ERR_EXIT(
   4322             _pm8x50_pm_active_eth_lanes_get(unit, pm_info, &active_eth_lanes));
   4323 
   4324     /*
   4325      * Get lane mask for the input ports
   4326      */
   4327     PORTMOD_PBMP_ITER(*ports, port) {
   4328         _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, lane_bitmap));
   4329         port_lane_mask |= lane_bitmap[0];
   4330     }
   4331 
   4332     /* Remove input lanes from ovco and check if it is in use */
   4333     ovco_pll_active_lane_bitmap &= ~port_lane_mask;
   4334     ovco_pll_adv_lane_bitmap &= ~port_lane_mask;
   4335     is_ovco_in_use = ((ovco_pll_active_lane_bitmap | ovco_pll_adv_lane_bitmap) == 0) ? 0 : 1;
   4336     if (is_ovco_in_use)
   4337     {
   4338         /* ovco in use (not refering to the ports that are currently requested) */
   4339         current_ovco = PM_8x50_INFO(pm_info)->ovco;
   4340     }
   4341     else
   4342     {
   4343         /*
   4344          *  ovco not in use (not refering to the ports that are currently requested)
   4345          *  currently set as invalid (ovco might be allcoate by VCO algorithm)
   4346          */
   4347         current_ovco = portmodVCOInvalid;
   4348     }
   4349 
   4350     /* Remove input lanes from tvco and check if it is in use */
   4351     tvco_pll_active_lane_bitmap &= ~port_lane_mask;
   4352     tvco_pll_adv_lane_bitmap &= ~port_lane_mask;
   4353     active_eth_lanes &= ~port_lane_mask;
   4354     is_tvco_in_use = ((tvco_pll_active_lane_bitmap | tvco_pll_adv_lane_bitmap | active_eth_lanes) == 0) ? 0 : 1;
   4355     if (is_tvco_in_use)
   4356     {
   4357         /* tvco in use (not refering to the ports that are currently requested) */
   4358         current_tvco = PM_8x50_INFO(pm_info)->tvco;
   4359     }
   4360     else
   4361     {
   4362         /*
   4363          *  tvco not in use (not refering to the ports that are currently requested)
   4364          *  currently set as invalid (tvco might be allcoate by VCO algorithm)
   4365          */
   4366         current_tvco = portmodVCOInvalid;
   4367     }
   4368 
   4369     if (PM_8x50_INFO(pm_info)->allow_20p625g_tvco) {
   4370         PM8X50_TVCO_SUPPORT_20P625G_SET(flags);
   4371     }
   4372     /* Try to allocate required VCOs */
   4373     _SOC_IF_ERR_EXIT(
   4374             pm8x50_vcos_request_allocate(unit, flags, required_vcos_bmp, &current_tvco, &current_ovco));
   4375 
   4376     /* Set output */
   4377     vco_setting->tvco = current_tvco;
   4378     vco_setting->is_tvco_new = (PM_8x50_INFO(pm_info)->tvco == current_tvco) ? 0 : 1;
   4379     vco_setting->ovco = current_ovco;
   4380     vco_setting->is_ovco_new = (PM_8x50_INFO(pm_info)->ovco == current_ovco) ? 0 : 1;
   4381 
   4382 exit:
   4383     SOC_FUNC_RETURN;
   4384 }
   4385 
   4386 /*
   4387  * Validate if a set of speed can be configured for given PORTMACRO without
   4388  * affecting the other active ports.
   4389  *
   4390  * Inputs:
   4391  *     unit:           unit number;
   4392  *     pm_id           portmacro ID;
   4393  *     pm_info:        pm_info data structure;
   4394  *     ports:          Logical port bitmaps which reqiring the input vcos;
   4395  *     flag:           PLL switch flag.
   4396  *
   4397  * Output:
   4398  *     vco_setting:    If validation pass, vco_setting will indicating
   4399  *                     what's the new vco rates and whether they are new or not;
   4400  */
   4401 int pm8x50_pm_speed_config_validate(int unit,
   4402                                     int pm_id,
   4403                                     pm_info_t pm_info,
   4404                                     const portmod_pbmp_t* ports,
   4405                                     int flag,
   4406                                     portmod_pm_vco_setting_t* vco_setting)
   4407 {
   4408     int i, rv, pam4_eth_req = 0;
   4409     portmod_vco_type_t vco;
   4410     pm8x50_vcos_bmp_t required_vcos_bmp = 0, required_vco_bmp_temp = 0;
   4411     int is_pcs_bypass;
   4412     uint8_t rs528_bm = 0, rs544_bm = 0, rs272_bm = 0, affected_bm = 0;
   4413     int nof_phys, port;
   4414     phymod_phy_access_t phy_access;
   4415     portmod_access_get_params_t params;
   4416     pm_version_t version;
   4417     uint32 fec_validate_flags = 0;
   4418     phymod_phy_signalling_method_t signalling_method;
   4419     SOC_INIT_FUNC_DEFS;
   4420 
   4421     /* Get RS FEC usage bitmaps from WB */
   4422     _SOC_IF_ERR_EXIT(_pm8x50_fec_lanebitmap_get(unit, pm_info, &rs528_bm, &rs544_bm, &rs272_bm));
   4423 
   4424     _SOC_IF_ERR_EXIT(_pm8x50_pm_version_get(unit, pm_info, &version));
   4425     if (version.tech_process == PM_TECH_16NM) {
   4426         PM8X50_PM_VERSION_F_REV0_16NM_SET(fec_validate_flags);
   4427     }
   4428     /* Remove the input ports from FEC usage bitmaps*/
   4429     PORTMOD_PBMP_ITER(*ports, port) {
   4430         _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   4431         _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   4432                                     &params, 1, &phy_access, &nof_phys, NULL));
   4433         rs528_bm &= ~phy_access.access.lane_mask;
   4434         rs544_bm &= ~phy_access.access.lane_mask;
   4435         rs272_bm &= ~phy_access.access.lane_mask;
   4436     }
   4437 
   4438     /* Get the VCOs required by the input speed config list */
   4439     for (i = 0; i < vco_setting->num_speeds; i++) {
   4440         vco = portmodVCOInvalid;
   4441         rv = _pm8x50_port_speed_config_to_vco_get(&(vco_setting->speed_config_list[i]),
   4442                                                   vco_setting->speed_for_pcs_bypass_port[i], &vco);
   4443         if (rv == SOC_E_CONFIG) {
   4444             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   4445                       (_SOC_MSG("Can not support speed: %d num_lane: %d fec: %d"),
   4446                       vco_setting->speed_config_list[i].speed,
   4447                       vco_setting->speed_config_list[i].num_lane,
   4448                       vco_setting->speed_config_list[i].fec));
   4449         }
   4450 
   4451         is_pcs_bypass = vco_setting->speed_for_pcs_bypass_port[i];
   4452         _SOC_IF_ERR_EXIT(_pm8x50_required_vco_bitmap_get(unit, vco, is_pcs_bypass, &required_vco_bmp_temp));
   4453         required_vcos_bmp |= required_vco_bmp_temp;
   4454 
   4455         _pm8x50_signalling_method_get(vco_setting->speed_for_pcs_bypass_port[i],
   4456                                       &(vco_setting->speed_config_list[i]),
   4457                                       &signalling_method);
   4458         if ((signalling_method == phymodSignallingMethodPAM4) &&
   4459              !vco_setting->speed_for_pcs_bypass_port[i]) {
   4460             pam4_eth_req = 1;
   4461         }
   4462 
   4463         if ((vco_setting->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_272) ||
   4464             (vco_setting->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_272_2XN)) {
   4465             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_setting->port_starting_lane_list[i],
   4466                                                     vco_setting->speed_config_list[i].num_lane,
   4467                                                     &rs272_bm));
   4468         } else if ((vco_setting->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_544) ||
   4469                    (vco_setting->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   4470             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_setting->port_starting_lane_list[i],
   4471                                                     vco_setting->speed_config_list[i].num_lane,
   4472                                                     &rs544_bm));
   4473         } else if (vco_setting->speed_config_list[i].fec == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   4474             _SOC_IF_ERR_EXIT(_pm8x50_lanebitmap_set(vco_setting->port_starting_lane_list[i],
   4475                                                     vco_setting->speed_config_list[i].num_lane,
   4476                                                     &rs528_bm));
   4477         }
   4478 
   4479     }
   4480 
   4481     /* Validate FEC settings for RS528, RS544 and RS272 */
   4482     _SOC_IF_ERR_EXIT(_pm8x50_fec_validate(unit, fec_validate_flags, rs528_bm, rs544_bm, rs272_bm, &affected_bm));
   4483 
   4484     _SOC_IF_ERR_EXIT(_pm8x50_vcos_setting_validate(unit, pm_info, ports, required_vcos_bmp, flag, vco_setting));
   4485 
   4486     if (pam4_eth_req && (vco_setting->tvco == portmodVCO20P625G)) {
   4487        _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4488             (_SOC_MSG("Can not accommodate VCO settings.\n Current TVCO does not support Ethernet PAM4 speeds.\n")));
   4489     }
   4490 exit:
   4491     SOC_FUNC_RETURN;
   4492 }
   4493 
   4494 /*Port speed validation.*/
   4495 int pm8x50_port_speed_config_validate(int unit,
   4496                                       int port,
   4497                                       pm_info_t pm_info,
   4498                                       const portmod_speed_config_t* speed_config,
   4499                                       portmod_pbmp_t* affected_pbmp)
   4500 {
   4501     int rv, i, tmp_port, port_num_lanes, port_index, port_is_pcs_bypassed;
   4502     portmod_vco_type_t required_vco;
   4503     uint8_t ovco_pll_active_lane_bitmap, tvco_pll_active_lane_bitmap, ovco_pll_adv_lane_bitmap, tvco_pll_adv_lane_bitmap;
   4504     uint32_t port_lane_mask[1];
   4505     uint8_t affected_lane_bitmap = 0, pm_is_full_bypassed, active_eth_lanes;
   4506     uint8_t rs528_bm = 0, rs544_bm = 0, rs272_bm = 0;
   4507     pm_version_t version;
   4508     uint32 flags = 0;
   4509     phymod_phy_signalling_method_t signalling_method;
   4510     SOC_INIT_FUNC_DEFS;
   4511 
   4512     /* clear the affected_pbmp first */
   4513     PORTMOD_PBMP_CLEAR(*affected_pbmp);
   4514 
   4515     /* Get lane_mask and number of lanes for the port from DB */
   4516     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, port_lane_mask));
   4517     _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &port_is_pcs_bypassed, port_index));
   4518 
   4519     /* Check speed_config->lane_num against lane number stored in DB */
   4520     if (!port_is_pcs_bypassed)
   4521     {
   4522         PORTMOD_BIT_COUNT(port_lane_mask[0], port_num_lanes);
   4523         if (port_num_lanes != speed_config->num_lane) {
   4524             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4525                               (_SOC_MSG("Invalid lane number request on exising logical port.")));
   4526         }
   4527     }
   4528 
   4529     /* Get RS528, RS544, RS272 usage bitmap from WB */
   4530     _SOC_IF_ERR_EXIT(_pm8x50_fec_lanebitmap_get(unit, pm_info, &rs528_bm, &rs544_bm, &rs272_bm));
   4531 
   4532     rs528_bm &= ~port_lane_mask[0];
   4533     rs544_bm &= ~port_lane_mask[0];
   4534     rs272_bm &= ~port_lane_mask[0];
   4535     if (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   4536         rs528_bm |= port_lane_mask[0];
   4537     } else if ((speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_544) ||
   4538                (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   4539         rs544_bm |= port_lane_mask[0];
   4540     } else if ((speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_272) ||
   4541                (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_272_2XN)) {
   4542         rs272_bm |= port_lane_mask[0];
   4543     }
   4544 
   4545     _SOC_IF_ERR_EXIT(_pm8x50_pm_version_get(unit, pm_info, &version));
   4546     if (version.tech_process == PM_TECH_16NM) {
   4547         PM8X50_PM_VERSION_F_REV0_16NM_SET(flags);
   4548     }
   4549 
   4550     /* Validate FEC settings for RS528, RS544 and RS272 */
   4551     rv = _pm8x50_fec_validate(unit, flags, rs528_bm, rs544_bm, rs272_bm, &affected_lane_bitmap);
   4552     if (rv != SOC_E_NONE) {
   4553         /* If FEC validate fails, return affected port bit map */
   4554         affected_lane_bitmap &= ~port_lane_mask[0];
   4555         for(i = 0 ; i < MAX_PORTS_PER_PM8X50; i++){
   4556             if ((affected_lane_bitmap >> i) & 1) {
   4557                 _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port));
   4558                 PORTMOD_PBMP_PORT_ADD(*affected_pbmp, tmp_port);
   4559             }
   4560         }
   4561         return rv;
   4562     }
   4563 
   4564     _SOC_IF_ERR_EXIT(
   4565         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bitmap));
   4566     _SOC_IF_ERR_EXIT(
   4567         PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_active_lane_bitmap));
   4568     _SOC_IF_ERR_EXIT(
   4569         PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bitmap));
   4570     _SOC_IF_ERR_EXIT(
   4571         PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_adv_lane_bitmap));
   4572     _SOC_IF_ERR_EXIT(
   4573         _pm8x50_pm_active_eth_lanes_get(unit, pm_info, &active_eth_lanes));
   4574 
   4575     /* Remove port lane mask from ovco_pll_active_lane_bitmap, ovco_pll_adv_lane_bitmap */
   4576     ovco_pll_active_lane_bitmap &= ~port_lane_mask[0];
   4577     ovco_pll_adv_lane_bitmap &= ~port_lane_mask[0];
   4578 
   4579     /* Remove port lane mask from tvco_pll_active_lane_bitmap, tvco_pll_adv_lane_bitmap */
   4580     tvco_pll_active_lane_bitmap &= ~port_lane_mask[0];
   4581     tvco_pll_adv_lane_bitmap &= ~port_lane_mask[0];
   4582 
   4583     pm_is_full_bypassed = ((active_eth_lanes & ~port_lane_mask[0]) == 0) ? 1 : 0;
   4584 
   4585     /* Verify and get the required VCO */
   4586     rv = _pm8x50_port_speed_config_to_vco_get(speed_config, port_is_pcs_bypassed, &required_vco);
   4587     if (rv == SOC_E_CONFIG) {
   4588         _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   4589                   (_SOC_MSG("Speed config is not supported")));
   4590     }
   4591 
   4592     _pm8x50_signalling_method_get(port_is_pcs_bypassed, speed_config, &signalling_method);
   4593     if (!port_is_pcs_bypassed &&
   4594         (signalling_method == phymodSignallingMethodPAM4) &&
   4595         (PM_8x50_INFO(pm_info)->tvco == portmodVCO20P625G) &&
   4596         (tvco_pll_adv_lane_bitmap || tvco_pll_active_lane_bitmap ||
   4597          ovco_pll_adv_lane_bitmap || ovco_pll_active_lane_bitmap)) {
   4598         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4599                           (_SOC_MSG("Can not support Ethernet PAM4 speeds when TVCO is 20.625G.")));
   4600     } else if (PORTMOD_VCO_PCS_BYPASS_DEDICATED(PM_8x50_INFO(pm_info)->tvco) && !port_is_pcs_bypassed) {
   4601         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4602                            (_SOC_MSG("Can not accommodate VCO settings. TVCO is dedicated for PCS bypassed ports! \n")));
   4603     } else if (required_vco == PM_8x50_INFO(pm_info)->tvco
   4604         || required_vco == PM_8x50_INFO(pm_info)->ovco
   4605         || (ovco_pll_active_lane_bitmap == 0 && ovco_pll_adv_lane_bitmap == 0)
   4606         || (pm_is_full_bypassed && tvco_pll_active_lane_bitmap == 0 && tvco_pll_adv_lane_bitmap == 0)) {
   4607         /*
   4608          * 1. no vco change required
   4609          * 2. OR, ovco is free to change
   4610          * 3. OR, tvco is free to change if previous PM bypass mode is full bypass
   4611          */
   4612         return SOC_E_NONE;
   4613     } else if (ovco_pll_active_lane_bitmap & ovco_pll_adv_lane_bitmap) {
   4614         /* OVCO is used by resolved AN port */
   4615         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4616                           (_SOC_MSG("Can not accommodate VCO settings due to resolved AN port(s).")));
   4617     } else if (ovco_pll_active_lane_bitmap || ovco_pll_adv_lane_bitmap) {
   4618         /* OVCO is used by FS port or is advertiesd by AN port */
   4619         /* affected_lane_bitmap in this case should include ports that are actively using ovco or advertising the ovco */
   4620         affected_lane_bitmap = ovco_pll_active_lane_bitmap | ovco_pll_adv_lane_bitmap;
   4621         for( i = 0 ; i < MAX_PORTS_PER_PM8X50; i++){
   4622             if ((affected_lane_bitmap >> i) & 1) {
   4623                 rv = PM8x50_LANE2PORT_GET(unit, pm_info, i, &tmp_port);
   4624                 _SOC_IF_ERR_EXIT(rv);
   4625                 PORTMOD_PBMP_PORT_ADD(*affected_pbmp, tmp_port);
   4626             }
   4627         }
   4628         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4629                           (_SOC_MSG("Can not accommodate VCO settings.")));
   4630     } else {
   4631         /* coverity[dead_error_line] */
   4632         return SOC_E_PARAM;
   4633     }
   4634 
   4635 exit:
   4636     SOC_FUNC_RETURN;
   4637 }
   4638 
   4639 /*
   4640  * This API reconfig the VCO rates of the PM.
   4641  *
   4642  * 'pm8x50_pm_speed_config_validate' need to be called before this function.
   4643  * Only when pm8x50_pm_speed_config_validate reuturns E_NONE and indicates
   4644  * VCO change requirement, user can call this API to change VCOs.
   4645  *
   4646  * Two VCO values are always
   4647  * required by this API regardless of whether the caller intends to change
   4648  * one or two VCO rates.
   4649  * vco[0]: TVCO.
   4650  * vco[1]: OVCO.
   4651  */
   4652 int pm8x50_pm_vco_reconfig(int unit,
   4653                            int pm_id,
   4654                            pm_info_t pm_info,
   4655                            const portmod_vco_type_t* vco)
   4656 {
   4657     uint8_t active_eth_lanes, new_ovco_active_lanes;
   4658     uint8_t ovco_pll_active_lane_bm, tvco_pll_active_lane_bm;
   4659     uint8_t ovco_pll_adv_lane_bm, tvco_pll_adv_lane_bm, zero = 0;
   4660     portmod_vco_type_t cur_tvco = PM_8x50_INFO(pm_info)->tvco;
   4661     portmod_vco_type_t cur_ovco = PM_8x50_INFO(pm_info)->ovco;
   4662     uint32_t pll_div;
   4663     int tvco_pll_index, ovco_pll_index;
   4664     phymod_phy_access_t phy_access;
   4665     int fec_null = 0, i;
   4666     uint8_t ovco_active_lanes_bitmap, ovco_adv_lanes_bitmap, ovco_lanes_bitmap;
   4667     SOC_INIT_FUNC_DEFS;
   4668 
   4669     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   4670     ovco_pll_index = (tvco_pll_index == 1)? 0: 1;
   4671     
   4672     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_active_lane_bm));
   4673     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_active_lane_bm));
   4674     _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_adv_lane_bm));
   4675     _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_adv_lane_bm));
   4676     _SOC_IF_ERR_EXIT(_pm8x50_pm_active_eth_lanes_get(unit, pm_info, &active_eth_lanes));
   4677 
   4678     if (cur_tvco != vco[0]) {
   4679         /* TVCO need to be changed */
   4680         PM_8x50_INFO(pm_info)->tvco = vco[0];
   4681         /* Get PLL_DIV */
   4682         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(PM_8x50_INFO(pm_info)->ref_clk, vco[0], &pll_div));
   4683 
   4684         sal_memcpy (&phy_access, &(PM_8x50_INFO(pm_info)->int_core_access),
   4685                     sizeof(phymod_phy_access_t));
   4686 
   4687         if (pll_div != phymod_TSCBH_PLL_DIVNONE) {
   4688             if (active_eth_lanes == (tvco_pll_adv_lane_bm | tvco_pll_active_lane_bm |
   4689                                      ovco_pll_adv_lane_bm | ovco_pll_active_lane_bm)) {
   4690                 /*
   4691                  * Set lane_mask to 0xFF for the following two cases:
   4692                  *
   4693                  * 1. If active_eth_lanes != 0, meaning there are only ethernet ports
   4694                  *    in the PM, it is safe to set lane_mask to 0xFF.
   4695                  * 2. If active_eth_lanes == 0, meaning there is no active ports in
   4696                  *    the PM, it is safe to set lane_mask to 0xFF.
   4697                  */
   4698                 phy_access.access.lane_mask = 0xFF;
   4699             } else {
   4700                 /*
   4701                  * There are ILKN ports in the PM, lane_mask should include:
   4702                  *
   4703                  * 1. All ethernet lanes
   4704                  * 2. ILKN lanes using TVCO.
   4705                  */
   4706                 phy_access.access.lane_mask = active_eth_lanes | tvco_pll_active_lane_bm;
   4707             }
   4708             _SOC_IF_ERR_EXIT(
   4709                 phymod_phy_pll_reconfig(&phy_access, tvco_pll_index, pll_div));
   4710         } else {
   4711              /* will pwoer down this PLL */
   4712              _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, tvco_pll_index, 1));
   4713         }
   4714 
   4715         /* For Ethernet mode, TVCO change will reset the whole serdes core.
   4716          * So we will clear:
   4717          *     1. the lane bitmaps for both PLLs.
   4718          *     2. FEC type for all lanes.
   4719          */
   4720         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, zero));
   4721         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, zero));
   4722         _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, zero));
   4723         _SOC_IF_ERR_EXIT(PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, zero));
   4724         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   4725             _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec_null));
   4726         }
   4727         /*
   4728          * Since TVCO has been changed, need to remove the Ethernet lanes in
   4729          * ovco_pll_active_lane_bm.
   4730  */
   4731         new_ovco_active_lanes = ovco_pll_active_lane_bm & ~active_eth_lanes;
   4732         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, new_ovco_active_lanes));
   4733         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, zero));
   4734     }
   4735 
   4736     if (cur_ovco != vco[1]) {
   4737         /* OVCO need to be changed */
   4738         PM_8x50_INFO(pm_info)->ovco = vco[1];
   4739         /* next get the OVCO's PLL divider */
   4740         _SOC_IF_ERR_EXIT(_pm8x50_vco_to_pll_get(PM_8x50_INFO(pm_info)->ref_clk, vco[1], &pll_div));
   4741 
   4742         sal_memcpy (&phy_access, &(PM_8x50_INFO(pm_info)->int_core_access),
   4743                     sizeof(phymod_phy_access_t));
   4744         /*once ilkn support is added, the phy_access lane mask needs to be adjusted */
   4745         if (pll_div !=phymod_TSCBH_PLL_DIVNONE) {
   4746             _SOC_IF_ERR_EXIT(
   4747                 phymod_phy_pll_reconfig(&phy_access, ovco_pll_index, pll_div));
   4748         } else {
   4749              _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, ovco_pll_index, 1));
   4750         }
   4751 
   4752         /* Clear FEC usage for all the OVCO lanes */
   4753         _SOC_IF_ERR_EXIT(
   4754             PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_active_lanes_bitmap));
   4755         _SOC_IF_ERR_EXIT(
   4756             PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_adv_lanes_bitmap));
   4757         ovco_lanes_bitmap = ovco_active_lanes_bitmap | ovco_adv_lanes_bitmap;
   4758         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   4759             if ((ovco_lanes_bitmap >> i) & 0x1) {
   4760               _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec_null));
   4761             }
   4762         }
   4763 
   4764         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, zero));
   4765         _SOC_IF_ERR_EXIT(PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, zero));
   4766     }
   4767 
   4768 exit:
   4769     SOC_FUNC_RETURN;
   4770 }
   4771 
   4772 /* set/get the speed config for the specified port.*/
   4773 int pm8x50_port_speed_config_set(int unit, int port, pm_info_t pm_info, const portmod_speed_config_t* speed_config)
   4774 {
   4775     portmod_access_get_params_t params;
   4776     phymod_phy_access_t phy_access;
   4777     uint64 mac_ctrl;
   4778     phymod_phy_signalling_method_t signalling_mode;
   4779     int nof_phys, i, rx_enable = 0, port_is_pcs_bypassed;
   4780     portmod_pbmp_t affected_pbmp;
   4781     portmod_pmd_lane_config_t portmod_lane_config;
   4782     phymod_phy_speed_config_t phy_speed_config;
   4783     phymod_phy_pll_state_t old_pll_state, new_pll_state;
   4784     uint32 lane_config, port_lane_mask;
   4785     uint8 tvco_pll_lanes_bitmap, ovco_pll_lanes_bitmap;
   4786     portmod_vco_type_t required_vco;
   4787     phymod_an_mode_type_t an_mode = phymod_AN_MODE_NONE;
   4788     int port_index;
   4789     uint32 is_bypassed = 0;
   4790     uint32 bitmap[1];
   4791 
   4792     SOC_INIT_FUNC_DEFS;
   4793 
   4794     COMPILER_64_ZERO(mac_ctrl);
   4795     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_t_init(&phy_speed_config));
   4796 
   4797     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, bitmap));
   4798     _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index));
   4799 
   4800     if(!PM_8x50_INFO(pm_info)->portmod_mac_soft_reset)
   4801     {
   4802         /* Get original MAC CTRL */
   4803         _SOC_IF_ERR_EXIT(cdmac_egress_queue_drain_get(unit, port, &mac_ctrl, &rx_enable));
   4804 
   4805         
   4806         /* Disable MAC RX, drain MAC FIFO, assert MAC SOFT_RESET */
   4807         _SOC_IF_ERR_EXIT(_pm8x50_port_mac_drain_soft_reset(unit, port));
   4808     }
   4809     else if (!is_bypassed)
   4810     {
   4811        _SOC_IF_ERR_EXIT(pm8x50_port_soft_reset(unit, port, pm_info, PM8X50_PORT_SOFT_RESET_MODE_IN, &rx_enable, &mac_ctrl));
   4812     }
   4813 
   4814     /* Validate speed_config */
   4815     _SOC_IF_ERR_EXIT(pm8x50_port_speed_config_validate(unit, port, pm_info, speed_config, &affected_pbmp));
   4816 
   4817     /* Update port_mode */
   4818     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &port_lane_mask));
   4819     _SOC_IF_ERR_EXIT(_pm8x50_pm_port_mode_update(unit, port, pm_info, port_index, speed_config->num_lane));
   4820 
   4821     _SOC_IF_ERR_EXIT(
   4822         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_lanes_bitmap));
   4823     _SOC_IF_ERR_EXIT(
   4824         PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_lanes_bitmap));
   4825 
   4826     
   4827     old_pll_state.pll0_lanes_bitmap = ovco_pll_lanes_bitmap;
   4828     old_pll_state.pll1_lanes_bitmap = tvco_pll_lanes_bitmap;
   4829 
   4830     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   4831     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   4832                                 &params, 1, &phy_access, &nof_phys, NULL));
   4833 
   4834     port_is_pcs_bypassed = PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy_access.device_op_mode);
   4835     _SOC_IF_ERR_EXIT(_pm8x50_port_speed_config_to_vco_get(speed_config, port_is_pcs_bypassed, &required_vco));
   4836 
   4837     port_lane_mask = phy_access.access.lane_mask;
   4838 
   4839     if (required_vco == PM_8x50_INFO(pm_info)->tvco) {
   4840         tvco_pll_lanes_bitmap |= port_lane_mask;
   4841         ovco_pll_lanes_bitmap &= ~port_lane_mask;
   4842     } else if (required_vco == PM_8x50_INFO(pm_info)->ovco) {
   4843         ovco_pll_lanes_bitmap |= port_lane_mask;
   4844         tvco_pll_lanes_bitmap &= ~port_lane_mask;
   4845     } else {
   4846         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4847                            (_SOC_MSG("VCO need to be reconfigured before changing speed.")));
   4848     }
   4849     /* Decode the lane_config in speed_config */
   4850     lane_config = speed_config->lane_config;
   4851     /* Retrieve the default lane config */
   4852     _pm8x50_signalling_method_get(is_bypassed, speed_config, &signalling_mode);
   4853     if (lane_config == -1) {
   4854         _SOC_IF_ERR_EXIT(
   4855             phymod_phy_lane_config_default_get(&phy_access, signalling_mode, &portmod_lane_config.pmd_firmware_lane_config));
   4856         portmod_lane_config.pam4_channel_loss = 0;
   4857     } else {
   4858         if (signalling_mode == phymodSignallingMethodPAM4) {
   4859             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_PAM4_SET(lane_config);
   4860             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NRZ_CLEAR(lane_config);
   4861         } else {
   4862             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NRZ_SET(lane_config);
   4863             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_PAM4_CLEAR(lane_config);
   4864             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_ES_CLEAR(lane_config);
   4865             PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NS_CLEAR(lane_config);
   4866         }
   4867         _SOC_IF_ERR_EXIT(
   4868             portmod_common_pmd_lane_config_decode(lane_config, &portmod_lane_config));
   4869     }
   4870 
   4871     if (!is_bypassed) {
   4872         if (speed_config->fec == PORTMOD_PORT_PHY_FEC_NONE) {
   4873             phy_speed_config.fec_type = phymod_fec_None;
   4874         } else if (speed_config->fec == PORTMOD_PORT_PHY_FEC_BASE_R) {
   4875             phy_speed_config.fec_type = phymod_fec_CL74;
   4876         } else if (speed_config->fec ==  PORTMOD_PORT_PHY_FEC_RS_FEC) {
   4877             phy_speed_config.fec_type = phymod_fec_CL91;
   4878         } else if (speed_config->fec ==  PORTMOD_PORT_PHY_FEC_RS_544) {
   4879             phy_speed_config.fec_type = phymod_fec_RS544;
   4880         } else if (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_272) {
   4881             phy_speed_config.fec_type = phymod_fec_RS272;
   4882         } else if (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_544_2XN) {
   4883             phy_speed_config.fec_type = phymod_fec_RS544_2XN;
   4884         } else if (speed_config->fec == PORTMOD_PORT_PHY_FEC_RS_272_2XN) {
   4885             phy_speed_config.fec_type = phymod_fec_RS272_2XN;
   4886         }
   4887     }
   4888 
   4889     phy_speed_config.data_rate = speed_config->speed;
   4890     phy_speed_config.linkTraining = speed_config->link_training;
   4891     phy_speed_config.PAM4_channel_loss = portmod_lane_config.pam4_channel_loss;
   4892     phy_speed_config.pmd_lane_config = portmod_lane_config.pmd_firmware_lane_config;
   4893 
   4894     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_set(&phy_access, &phy_speed_config, &old_pll_state, &new_pll_state));
   4895 
   4896     if(!PM_8x50_INFO(pm_info)->portmod_mac_soft_reset)
   4897     {
   4898         /* Enable MAC RX, De-assert MAC SOFT_RESET */
   4899         _SOC_IF_ERR_EXIT(_pm8x50_port_rx_restore_mac_out_of_reset(unit, port, rx_enable));
   4900         /* Restore original MAC CONTROL */
   4901         _SOC_IF_ERR_EXIT(cdmac_mac_ctrl_set(unit, port, mac_ctrl));
   4902     }
   4903     else if (!is_bypassed)
   4904     {
   4905         _SOC_IF_ERR_EXIT(pm8x50_port_soft_reset(unit, port, pm_info, PM8X50_PORT_SOFT_RESET_MODE_OUT, &rx_enable, &mac_ctrl));
   4906     }
   4907 
   4908     /* Update PLL active lane bitmaps */
   4909     _SOC_IF_ERR_EXIT(
   4910         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, ovco_pll_lanes_bitmap));
   4911     _SOC_IF_ERR_EXIT(
   4912         PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, tvco_pll_lanes_bitmap));
   4913 
   4914     /* Clear the adv lane bitmap for the port because it's configured as a force speed port */
   4915     _SOC_IF_ERR_EXIT(
   4916         PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &ovco_pll_lanes_bitmap));
   4917     _SOC_IF_ERR_EXIT(
   4918         PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &tvco_pll_lanes_bitmap));
   4919     ovco_pll_lanes_bitmap &= ~port_lane_mask;
   4920     tvco_pll_lanes_bitmap &= ~port_lane_mask;
   4921     _SOC_IF_ERR_EXIT(
   4922         PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, ovco_pll_lanes_bitmap));
   4923     _SOC_IF_ERR_EXIT(
   4924         PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, tvco_pll_lanes_bitmap));
   4925 
   4926     /* Clear an_mode for the port to force user set new abilities before enable AN later on */
   4927     _SOC_IF_ERR_EXIT(PM8x50_AN_MODE_SET(unit, pm_info, an_mode, port_index));
   4928 
   4929     if (!is_bypassed) {
   4930         /* Update FEC usage in WB */
   4931         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   4932             if ((port_lane_mask >> i) & 0x1) {
   4933                 _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, speed_config->fec));
   4934             }
   4935         }
   4936     }
   4937 
   4938     /* update FEC type for RLM usage */
   4939     _SOC_IF_ERR_EXIT(PM8x50_ORIGINAL_FEC_SET(unit, pm_info, phy_speed_config.fec_type, port_index));
   4940 
   4941 exit:
   4942     SOC_FUNC_RETURN;
   4943 }
   4944 
   4945 int pm8x50_port_speed_config_get(int unit, int port, pm_info_t pm_info, portmod_speed_config_t* speed_config)
   4946 {
   4947     portmod_access_get_params_t params;
   4948     phymod_phy_access_t phy_access;
   4949     int nof_phys, port_num_lanes;
   4950     uint32_t lane_config;
   4951     portmod_pmd_lane_config_t portmod_lane_config;
   4952     phymod_phy_speed_config_t phy_speed_config;
   4953     phymod_autoneg_status_t an_status;
   4954 
   4955     SOC_INIT_FUNC_DEFS;
   4956 
   4957     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   4958     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   4959                                 &params, 1, &phy_access, &nof_phys, NULL));
   4960     PORTMOD_BIT_COUNT(phy_access.access.lane_mask, port_num_lanes);
   4961 
   4962     _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_status_get(unit, port, pm_info, &an_status));
   4963 
   4964     if (an_status.enabled && an_status.locked) {
   4965         speed_config->num_lane = an_status.resolved_num_lane;
   4966     } else {
   4967         speed_config->num_lane = port_num_lanes;
   4968     }
   4969 
   4970     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_t_init(&phy_speed_config));
   4971     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_get(&phy_access, &phy_speed_config));
   4972 
   4973     /* for the RLM speed mode, need to update the num_lane */
   4974     if ((phy_speed_config.data_rate == 150000) ||
   4975         (phy_speed_config.data_rate == 350000) ||
   4976         (phy_speed_config.data_rate == 300000)) {
   4977         speed_config->num_lane = phy_speed_config.data_rate / 50000;
   4978     }
   4979 
   4980     portmod_lane_config.pam4_channel_loss = phy_speed_config.PAM4_channel_loss;
   4981     portmod_lane_config.pmd_firmware_lane_config = phy_speed_config.pmd_lane_config;
   4982     /* Encode the lane_config in speed_config */
   4983     _SOC_IF_ERR_EXIT(
   4984         portmod_common_pmd_lane_config_encode(&portmod_lane_config, &lane_config));
   4985 
   4986     if (phy_speed_config.fec_type == phymod_fec_None) {
   4987         speed_config->fec = PORTMOD_PORT_PHY_FEC_NONE;
   4988     } else if (phy_speed_config.fec_type == phymod_fec_CL74) {
   4989         speed_config->fec = PORTMOD_PORT_PHY_FEC_BASE_R;
   4990     } else if (phy_speed_config.fec_type == phymod_fec_CL91) {
   4991         speed_config->fec = PORTMOD_PORT_PHY_FEC_RS_FEC;
   4992     } else if (phy_speed_config.fec_type == phymod_fec_RS544) {
   4993         speed_config->fec = PORTMOD_PORT_PHY_FEC_RS_544;
   4994     } else if (phy_speed_config.fec_type == phymod_fec_RS272) {
   4995         speed_config->fec = PORTMOD_PORT_PHY_FEC_RS_272;
   4996     } else if (phy_speed_config.fec_type == phymod_fec_RS544_2XN) {
   4997         speed_config->fec = PORTMOD_PORT_PHY_FEC_RS_544_2XN;
   4998     } else if (phy_speed_config.fec_type == phymod_fec_RS272_2XN) {
   4999         speed_config->fec = PORTMOD_PORT_PHY_FEC_RS_272_2XN;
   5000     }
   5001 
   5002     speed_config->speed = phy_speed_config.data_rate;
   5003     speed_config->link_training = phy_speed_config.linkTraining;
   5004     speed_config->lane_config = lane_config;
   5005 
   5006 exit:
   5007     SOC_FUNC_RETURN;
   5008 }
   5009 
   5010 /*Port cl72 set\get*/
   5011 int pm8x50_port_cl72_set(int unit, int port, pm_info_t pm_info, uint32 enable)
   5012 {
   5013     int nof_phys;
   5014     portmod_access_get_params_t params;
   5015     phymod_phy_access_t phy_access;
   5016     SOC_INIT_FUNC_DEFS;
   5017 
   5018     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5019     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5020                                 &params, 1, &phy_access, &nof_phys, NULL));
   5021     if (!SAL_BOOT_SIMULATION) {
   5022         _SOC_IF_ERR_EXIT
   5023             (phymod_phy_cl72_set(&phy_access, enable));
   5024     }
   5025 
   5026 exit:
   5027     SOC_FUNC_RETURN;
   5028 }
   5029 
   5030 int pm8x50_port_cl72_get(int unit, int port, pm_info_t pm_info, uint32* enable)
   5031 {
   5032     int nof_phys;
   5033     portmod_access_get_params_t params;
   5034     phymod_phy_access_t phy_access;
   5035     SOC_INIT_FUNC_DEFS;
   5036 
   5037     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5038     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5039                                 &params, 1, &phy_access, &nof_phys, NULL));
   5040 
   5041     if (!SAL_BOOT_SIMULATION) {
   5042         _SOC_IF_ERR_EXIT
   5043             (phymod_phy_cl72_get(&phy_access, enable));
   5044     }
   5045 
   5046 exit:
   5047     SOC_FUNC_RETURN;
   5048 }
   5049 
   5050 /*Get port cl72 status*/
   5051 int pm8x50_port_cl72_status_get(int unit, int port, pm_info_t pm_info,
   5052                                 phymod_cl72_status_t* status)
   5053 {
   5054     int nof_phys;
   5055     portmod_access_get_params_t params;
   5056     phymod_phy_access_t phy_access;
   5057     SOC_INIT_FUNC_DEFS;
   5058 
   5059     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5060     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5061                                 &params, 1, &phy_access, &nof_phys, NULL));
   5062 
   5063     if (!SAL_BOOT_SIMULATION) {
   5064         _SOC_IF_ERR_EXIT
   5065             (phymod_phy_cl72_status_get(&phy_access, status));
   5066     }
   5067 
   5068 exit:
   5069     SOC_FUNC_RETURN;
   5070 }
   5071 
   5072 /*Port loopback set\get*/
   5073 int pm8x50_port_loopback_set(int unit, int port, pm_info_t pm_info,
   5074                              portmod_loopback_mode_t loopback_type, int enable)
   5075 {
   5076     phymod_loopback_mode_t phymod_lb_type;
   5077     int nof_phys;
   5078     portmod_access_get_params_t params;
   5079     phymod_phy_access_t phy_access;
   5080     int phy_acc;
   5081     SOC_INIT_FUNC_DEFS;
   5082 
   5083     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   5084 
   5085     /* loopback type validation*/
   5086     switch(loopback_type){
   5087         case portmodLoopbackMacOuter:
   5088             _SOC_IF_ERR_EXIT(cdmac_loopback_set(unit, phy_acc, loopback_type, enable));
   5089             break;
   5090         case portmodLoopbackPhyRloopPCS:
   5091         case portmodLoopbackPhyRloopPMD:
   5092         case portmodLoopbackPhyGloopPMD:
   5093         case portmodLoopbackPhyGloopPCS:
   5094             if (enable) {
   5095                 _SOC_IF_ERR_EXIT(cdmac_loopback_set(unit, phy_acc, portmodLoopbackMacOuter, 0));
   5096             }
   5097             _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit,
   5098                              loopback_type, &phymod_lb_type));
   5099             _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5100             _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5101                              &params, 1, &phy_access, &nof_phys, NULL));
   5102             _SOC_IF_ERR_EXIT(phymod_phy_loopback_set(&phy_access, phymod_lb_type, enable));
   5103             break;
   5104         default:
   5105             _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (
   5106                       _SOC_MSG("unsupported loopback type %d"), loopback_type));
   5107             break;
   5108     }
   5109 
   5110     if (enable) {
   5111         _SOC_IF_ERR_EXIT(pm8x50_port_lag_failover_status_toggle(unit, port, pm_info));
   5112     }
   5113 
   5114 exit:
   5115     SOC_FUNC_RETURN;
   5116 }
   5117 
   5118 int pm8x50_port_loopback_get(int unit, int port, pm_info_t pm_info,
   5119                              portmod_loopback_mode_t loopback_type,
   5120                              int* enable)
   5121 {
   5122     phymod_loopback_mode_t phymod_lb_type;
   5123     portmod_access_get_params_t params;
   5124     int nof_phys;
   5125     phymod_phy_access_t phy_access;
   5126     uint32 tmp_enable = 0;
   5127     int rv = PHYMOD_E_NONE;
   5128 
   5129     SOC_INIT_FUNC_DEFS;
   5130 
   5131     switch(loopback_type){
   5132         case portmodLoopbackMacOuter:
   5133             _SOC_IF_ERR_EXIT(cdmac_loopback_get(unit, port, loopback_type, enable));
   5134             break;
   5135         case portmodLoopbackPhyRloopPCS:
   5136         case portmodLoopbackPhyRloopPMD:
   5137         case portmodLoopbackPhyGloopPMD:
   5138         case portmodLoopbackPhyGloopPCS:
   5139             _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit,
   5140                              loopback_type, &phymod_lb_type));
   5141             _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5142             _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5143                              &params, 1, &phy_access, &nof_phys, NULL));
   5144             rv = phymod_phy_loopback_get(&phy_access, phymod_lb_type, &tmp_enable);
   5145             if (rv == PHYMOD_E_UNAVAIL) {
   5146                 rv = PHYMOD_E_NONE;
   5147                 tmp_enable = 0;
   5148             }
   5149             _SOC_IF_ERR_EXIT(rv);
   5150             *enable = tmp_enable;
   5151             break;
   5152         default:
   5153             (*enable) = 0; /* not supported --> no loopback */
   5154             break;
   5155     }
   5156 
   5157 exit:
   5158     SOC_FUNC_RETURN;
   5159 }
   5160 
   5161 /*Port RX MAC ENABLE set\get*/
   5162 int pm8x50_port_rx_mac_enable_set(int unit, int port,
   5163                                   pm_info_t pm_info, int enable)
   5164 {
   5165     SOC_INIT_FUNC_DEFS;
   5166 
   5167     _SOC_IF_ERR_EXIT(cdmac_rx_enable_set(unit, port, enable));
   5168 exit:
   5169     SOC_FUNC_RETURN;
   5170 }
   5171 
   5172 int pm8x50_port_rx_mac_enable_get(int unit, int port,
   5173                                   pm_info_t pm_info, int* enable)
   5174 {
   5175     SOC_INIT_FUNC_DEFS;
   5176 
   5177     _SOC_IF_ERR_EXIT(cdmac_rx_enable_get(unit, port, enable));
   5178 exit:
   5179     SOC_FUNC_RETURN;
   5180 }
   5181 
   5182 /*Port TX MAC ENABLE set\get*/
   5183 int pm8x50_port_tx_mac_enable_set(int unit, int port,
   5184                                   pm_info_t pm_info,
   5185                                   int enable)
   5186 {
   5187     SOC_INIT_FUNC_DEFS;
   5188 
   5189     _SOC_IF_ERR_EXIT(cdmac_tx_enable_set(unit, port, enable));
   5190 
   5191 exit:
   5192     SOC_FUNC_RETURN;
   5193 }
   5194 
   5195 int pm8x50_port_tx_mac_enable_get(int unit, int port,
   5196                                   pm_info_t pm_info,
   5197                                   int* enable)
   5198 {
   5199     SOC_INIT_FUNC_DEFS;
   5200 
   5201     _SOC_IF_ERR_EXIT(cdmac_tx_enable_get(unit, port, enable));
   5202 
   5203 exit:
   5204     SOC_FUNC_RETURN;
   5205 }
   5206 
   5207 /*
   5208  * This API looks at the current port's number of lanes and max speed,
   5209  * returns the complete list of force-speed abilities with the same number
   5210  * of lanes and speed that is <= max speed, and the complete list of autoneg
   5211  * abilities with number of lanes <= current port's number of lanes and
   5212  * speed <= max speed.
   5213  */
   5214 int pm8x50_port_speed_ability_local_get(int unit, int port, pm_info_t pm_info,
   5215                                         int max_num_abilities,
   5216                                         portmod_port_speed_ability_t* abilities,
   5217                                         int* num_abilities)
   5218 {
   5219     phymod_phy_access_t phy_access;
   5220     portmod_access_get_params_t params;
   5221     int nof_phys, port_num_lanes, i;
   5222     int port_index, max_speed;
   5223     uint32 bitmap;
   5224     uint32_t port_lane_mask;
   5225     pm8x50_fs_ability_table_entry_t fs_table_entry;
   5226     pm8x50_an_ability_table_entry_t an_table_entry;
   5227     SOC_INIT_FUNC_DEFS;
   5228 
   5229     *num_abilities = 0;
   5230 
   5231     /* find the max speed of the port */
   5232     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get (unit, port, pm_info, &port_index, &bitmap));
   5233     _SOC_IF_ERR_EXIT(PM8x50_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index));
   5234 
   5235     /* find number of lanes of the port */
   5236     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5237     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5238                                 &params, 1, &phy_access, &nof_phys, NULL));
   5239     port_lane_mask = phy_access.access.lane_mask;
   5240     PORTMOD_BIT_COUNT(port_lane_mask, port_num_lanes);
   5241 
   5242     for (i = 0; i < PM8x50_FS_ABILITY_TABLE_SIZE; i++) {
   5243         _SOC_IF_ERR_EXIT
   5244             (_pm8x50_fs_ability_table_read_entry(i, &fs_table_entry));
   5245 
   5246         if (fs_table_entry.num_lanes == port_num_lanes && fs_table_entry.speed <= max_speed) {
   5247             if (*num_abilities < max_num_abilities) {
   5248                 abilities[*num_abilities].speed     = fs_table_entry.speed;
   5249                 abilities[*num_abilities].num_lanes = fs_table_entry.num_lanes;
   5250                 abilities[*num_abilities].fec_type  = fs_table_entry.fec_type;
   5251                 abilities[*num_abilities].medium    = PORTMOD_PORT_PHY_MEDIUM_ALL;
   5252                 abilities[*num_abilities].pause     = PORTMOD_PORT_PHY_PAUSE_ALL;
   5253                 abilities[*num_abilities].channel   = PORTMOD_PORT_PHY_CHANNEL_ALL;
   5254                 abilities[*num_abilities].an_mode   = PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_NONE;
   5255                 (*num_abilities) += 1;
   5256             } else {
   5257                 break;
   5258             }
   5259         }
   5260     }
   5261 
   5262     for (i = 0; i < PM8x50_AN_ABILITY_TABLE_SIZE; i++) {
   5263         _SOC_IF_ERR_EXIT
   5264             (_pm8x50_an_ability_table_read_entry(i, &an_table_entry));
   5265         if ((an_table_entry.num_lanes <= port_num_lanes) &&
   5266            ( an_table_entry.speed <= max_speed)) {
   5267             if (*num_abilities < max_num_abilities) {
   5268                 abilities[*num_abilities].speed      = an_table_entry.speed;
   5269                 abilities[*num_abilities].num_lanes  = an_table_entry.num_lanes;
   5270                 abilities[*num_abilities].fec_type   = an_table_entry.fec_type;
   5271                 if (an_table_entry.speed == 10000) {
   5272                     /* 10G AN only support Backplane */
   5273                     abilities[*num_abilities].medium = PORTMOD_PORT_PHY_MEDIUM_BACKPLANE;
   5274                 } else {
   5275                     abilities[*num_abilities].medium = PORTMOD_PORT_PHY_MEDIUM_ALL;
   5276                 }
   5277                 abilities[*num_abilities].pause      = PORTMOD_PORT_PHY_PAUSE_ALL;
   5278                 abilities[*num_abilities].channel    = PORTMOD_PORT_PHY_CHANNEL_ALL;
   5279                 abilities[*num_abilities].an_mode    = an_table_entry.an_mode;
   5280                 (*num_abilities) += 1;
   5281             } else {
   5282                 break;
   5283             }
   5284         }
   5285     }
   5286 
   5287 exit:
   5288     SOC_FUNC_RETURN;
   5289 }
   5290 
   5291 /* Translate portmod_port_speed_ability_t to phymod_autoneg_advert_abilities_t */
   5292 int _pm8x50_port_port_to_phy_ability(int num_abilities,
   5293                                      const portmod_port_speed_ability_t* abilities,
   5294                                      phymod_autoneg_advert_abilities_t* an_advert_abilities)
   5295 {
   5296     int i;
   5297 
   5298     an_advert_abilities->num_abilities = num_abilities;
   5299     for (i = 0; i < num_abilities; i++) {
   5300         an_advert_abilities->autoneg_abilities[i].speed = abilities[i].speed;
   5301         an_advert_abilities->autoneg_abilities[i].resolved_num_lanes = abilities[i].num_lanes;
   5302         switch (abilities[i].fec_type) {
   5303             case PORTMOD_PORT_PHY_FEC_NONE:
   5304                 an_advert_abilities->autoneg_abilities[i].fec = phymod_fec_None;
   5305                 break;
   5306             case PORTMOD_PORT_PHY_FEC_BASE_R:
   5307                 an_advert_abilities->autoneg_abilities[i].fec = phymod_fec_CL74;
   5308                 break;
   5309             case PORTMOD_PORT_PHY_FEC_RS_FEC:
   5310                 an_advert_abilities->autoneg_abilities[i].fec = phymod_fec_CL91;
   5311                 break;
   5312             case PORTMOD_PORT_PHY_FEC_RS_544:
   5313                 an_advert_abilities->autoneg_abilities[i].fec = phymod_fec_RS544;
   5314                 break;
   5315             case PORTMOD_PORT_PHY_FEC_RS_544_2XN:
   5316                 an_advert_abilities->autoneg_abilities[i].fec = phymod_fec_RS544_2XN;
   5317                 break;
   5318             default:
   5319                  return SOC_E_CONFIG;
   5320         }
   5321         switch (abilities[i].pause) {
   5322             case PORTMOD_PORT_PHY_PAUSE_NONE:
   5323                 an_advert_abilities->autoneg_abilities[i].pause = phymod_pause_none;
   5324                 break;
   5325             case PORTMOD_PORT_PHY_PAUSE_TX:
   5326                 an_advert_abilities->autoneg_abilities[i].pause = phymod_pause_asym;
   5327                 break;
   5328             case PORTMOD_PORT_PHY_PAUSE_RX:
   5329                 an_advert_abilities->autoneg_abilities[i].pause = phymod_pause_asym_symm;
   5330                 break;
   5331             case PORTMOD_PORT_PHY_PAUSE_SYMM:
   5332                 an_advert_abilities->autoneg_abilities[i].pause = phymod_pause_symm;
   5333                 break;
   5334             default:
   5335                 return SOC_E_CONFIG;
   5336         }
   5337         switch (abilities[i].an_mode) {
   5338             case PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73:
   5339                 an_advert_abilities->autoneg_abilities[i].an_mode = phymod_AN_MODE_CL73;
   5340                 break;
   5341             case PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM:
   5342                 an_advert_abilities->autoneg_abilities[i].an_mode = phymod_AN_MODE_CL73BAM;
   5343                 break;
   5344             case PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA:
   5345                 an_advert_abilities->autoneg_abilities[i].an_mode = phymod_AN_MODE_MSA;
   5346                 break;
   5347             default:
   5348                 return SOC_E_CONFIG;
   5349         }
   5350         if (abilities[i].medium == PORTMOD_PORT_PHY_MEDIUM_COPPER) {
   5351             an_advert_abilities->autoneg_abilities[i].medium = phymodFirmwareMediaTypeCopperCable;
   5352         } else {
   5353             an_advert_abilities->autoneg_abilities[i].medium = phymodFirmwareMediaTypePcbTraceBackPlane;
   5354         }
   5355         if (abilities[i].channel == PORTMOD_PORT_PHY_CHANNEL_SHORT) {
   5356             an_advert_abilities->autoneg_abilities[i].channel = phymod_channel_short;
   5357         } else {
   5358             an_advert_abilities->autoneg_abilities[i].channel = phymod_channel_long;
   5359         }
   5360     }
   5361 
   5362     return SOC_E_NONE;
   5363 }
   5364 
   5365 /* Translate phymod_autoneg_advert_abilities_t to portmod_port_speed_ability_t */
   5366 int _pm8x50_port_phy_to_port_ability(phymod_autoneg_advert_abilities_t* an_advert_abilities,
   5367                                      int* num_abilities,
   5368                                      portmod_port_speed_ability_t* abilities)
   5369 {
   5370     int i;
   5371 
   5372     *num_abilities = an_advert_abilities->num_abilities;
   5373     for (i = 0; i < *num_abilities; i++) {
   5374         abilities[i].speed = an_advert_abilities->autoneg_abilities[i].speed;
   5375         abilities[i].num_lanes = an_advert_abilities->autoneg_abilities[i].resolved_num_lanes;
   5376         switch (an_advert_abilities->autoneg_abilities[i].fec) {
   5377             case phymod_fec_None:
   5378                 abilities[i].fec_type = PORTMOD_PORT_PHY_FEC_NONE;
   5379                 break;
   5380             case phymod_fec_CL74:
   5381                 abilities[i].fec_type = PORTMOD_PORT_PHY_FEC_BASE_R;
   5382                 break;
   5383             case phymod_fec_CL91:
   5384                 abilities[i].fec_type = PORTMOD_PORT_PHY_FEC_RS_FEC;
   5385                 break;
   5386             case phymod_fec_RS544:
   5387                 abilities[i].fec_type = PORTMOD_PORT_PHY_FEC_RS_544;
   5388                 break;
   5389             case phymod_fec_RS544_2XN:
   5390                 abilities[i].fec_type = PORTMOD_PORT_PHY_FEC_RS_544_2XN;
   5391                 break;
   5392             default:
   5393                  return SOC_E_CONFIG;
   5394         }
   5395         switch (an_advert_abilities->autoneg_abilities[i].pause) {
   5396             case phymod_pause_none:
   5397                 abilities[i].pause = PORTMOD_PORT_PHY_PAUSE_NONE;
   5398                 break;
   5399             case phymod_pause_asym:
   5400                 abilities[i].pause = PORTMOD_PORT_PHY_PAUSE_TX;
   5401                 break;
   5402             case phymod_pause_asym_symm:
   5403                 abilities[i].pause = PORTMOD_PORT_PHY_PAUSE_RX;
   5404                 break;
   5405             case phymod_pause_symm:
   5406                 abilities[i].pause = PORTMOD_PORT_PHY_PAUSE_SYMM;
   5407                 break;
   5408             default:
   5409                 return SOC_E_CONFIG;
   5410         }
   5411         switch (an_advert_abilities->autoneg_abilities[i].an_mode) {
   5412             case phymod_AN_MODE_CL73:
   5413                 abilities[i].an_mode = PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73;
   5414                 break;
   5415             case phymod_AN_MODE_CL73BAM:
   5416                 abilities[i].an_mode = PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM;
   5417                 break;
   5418             case phymod_AN_MODE_MSA:
   5419                 abilities[i].an_mode = PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA;
   5420                 break;
   5421             default:
   5422                 return SOC_E_CONFIG;
   5423         }
   5424         if (an_advert_abilities->autoneg_abilities[i].medium == phymodFirmwareMediaTypeCopperCable) {
   5425             abilities[i].medium = PORTMOD_PORT_PHY_MEDIUM_COPPER;
   5426         } else {
   5427             abilities[i].medium = PORTMOD_PORT_PHY_MEDIUM_BACKPLANE;
   5428         }
   5429         if (an_advert_abilities->autoneg_abilities[i].channel == phymod_channel_short) {
   5430             abilities[i].channel = PORTMOD_PORT_PHY_CHANNEL_SHORT;
   5431         } else {
   5432             abilities[i].channel = PORTMOD_PORT_PHY_CHANNEL_LONG;
   5433         }
   5434     }
   5435 
   5436     return SOC_E_NONE;
   5437 }
   5438 
   5439 /*Set/get port auto negotiation ability*/
   5440 int pm8x50_port_autoneg_ability_advert_set(int unit, int port, pm_info_t pm_info,
   5441                                            int num_abilities,
   5442                                            const portmod_port_speed_ability_t* abilities)
   5443 {
   5444     portmod_access_get_params_t params;
   5445     phymod_phy_access_t phy_access, phy_copy;
   5446     int nof_phys, i, port_index, mpp_index;
   5447     uint32 bitmap, flags = 0;
   5448     portmod_vco_type_t request_vco = 0;
   5449     pm8x50_vcos_bmp_t vcos = 0;
   5450     portmod_pm_vco_setting_t vco_setting;
   5451     portmod_speed_config_t speed_config;
   5452     portmod_pbmp_t ports;
   5453     phymod_autoneg_advert_ability_t autoneg_abilities[PM8x50_MAX_AN_ABILITY];
   5454     phymod_autoneg_advert_abilities_t an_advert_abilities;
   5455     int is_msa = 0, is_bam = 0, current_media_type = 0;
   5456     int is_dual_50g = 0, pam4_req = 0, cl73_bam_msa_base_r_req = 0, dual_50g_req = 0;
   5457     int rs544_req = 0, rs528_req = 0;
   5458     phymod_an_mode_type_t an_mode = 0, cur_an_mode = 0;
   5459     int channel_25g = 0, flag;
   5460     int fec_cl73, fec_cl73_25g, fec_cl73bam_msa, fec_rs528_bam_msa;
   5461     phymod_phy_pll_state_t old_pll_state, new_pll_state;
   5462     uint8 pll_lanes_bitmap, rs528_bm = 0, rs544_bm = 0, rs272_bm = 0, affected_bm = 0;
   5463     phymod_firmware_lane_config_t fw_lane_config;
   5464     int tvco_pll_index, ovco_pll_index;
   5465     portmod_fec_t fec;
   5466     pm_version_t version;
   5467 
   5468     SOC_INIT_FUNC_DEFS;
   5469 
   5470     fec_cl73 = PORTMOD_PORT_PHY_FEC_INVALID;
   5471     fec_cl73_25g = PORTMOD_PORT_PHY_FEC_INVALID;
   5472     fec_cl73bam_msa = PORTMOD_PORT_PHY_FEC_INVALID;
   5473     fec_rs528_bam_msa = PORTMOD_PORT_PHY_FEC_INVALID;
   5474 
   5475     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5476     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5477                                 &params, 1, &phy_access, &nof_phys, NULL));
   5478 
   5479     /* 1. Valid media type */
   5480     _SOC_IF_ERR_EXIT(
   5481         phymod_phy_firmware_lane_config_get(&phy_access, &fw_lane_config));
   5482 
   5483     if (fw_lane_config.MediaType == phymodFirmwareMediaTypeCopperCable) {
   5484         current_media_type = PORTMOD_PORT_PHY_MEDIUM_COPPER;
   5485     } else if (fw_lane_config.MediaType == phymodFirmwareMediaTypePcbTraceBackPlane) {
   5486         current_media_type = PORTMOD_PORT_PHY_MEDIUM_BACKPLANE;
   5487     }
   5488 
   5489     /* 2. Validate abilities */
   5490     for (i = 0; i < num_abilities; i++) {
   5491         is_dual_50g = 0;
   5492         _SOC_IF_ERR_EXIT(_pm8x50_an_ability_table_vco_get(abilities[i].speed, abilities[i].num_lanes,
   5493                          abilities[i].fec_type, abilities[i].an_mode, &request_vco));
   5494         if (abilities[i].speed / abilities[i].num_lanes > NRZ_MAX_PER_LANE_SPEED) {
   5495             pam4_req = 1;
   5496         }
   5497         /* 2.1. AN ability is supported by HW */
   5498         if (request_vco == portmodVCOInvalid) {
   5499             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   5500                                (_SOC_MSG("port %d: abilities[%d] is not supported."), port, i));
   5501         }
   5502         if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_544) ||
   5503             (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   5504             rs544_req = 1;
   5505         } else if (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   5506             rs528_req = 1;
   5507         }
   5508 
   5509         /* 2.2. AN abilities do not conflict with each other */
   5510         if (abilities[i].pause != abilities[0].pause) {
   5511             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5512                                (_SOC_MSG("port %d: Pause conflicts among abilities."), port));
   5513         }
   5514         if (abilities[i].medium != current_media_type) {
   5515             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5516                                (_SOC_MSG("port %d: Medium conflicts with current media type."), port));
   5517         }
   5518         if ((abilities[i].speed == 50000) &&
   5519             (abilities[i].num_lanes == 2) &&
   5520             (abilities[i].fec_type != PORTMOD_PORT_PHY_FEC_RS_544)) {
   5521             is_dual_50g = 1;
   5522             dual_50g_req = 1;
   5523         }
   5524         if (abilities[i].an_mode == PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_BAM) {
   5525             is_bam = 1;
   5526             /* CL74 request of 20G-1lane, 25G-1lane, 40G-2lane should be identical */
   5527             if (abilities[i].speed < 50000) {
   5528                 if (((fec_cl73bam_msa == PORTMOD_PORT_PHY_FEC_NONE)
   5529                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R)) ||
   5530                     ((fec_cl73bam_msa == PORTMOD_PORT_PHY_FEC_BASE_R)
   5531                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE))) {
   5532                     _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5533                                        (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5534                 } else {
   5535                     /* only BaseR and FEC_NONE are considered here */
   5536                     if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) ||
   5537                         (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE)) {
   5538                         fec_cl73bam_msa = abilities[i].fec_type;
   5539                     }
   5540                     if (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) {
   5541                         cl73_bam_msa_base_r_req = 1;
   5542                     }
   5543                 }
   5544             }
   5545             /* RS528 request of 25G-1lane, 50G-2lane should be identical */
   5546             if ((abilities[i].speed == 25000) || (is_dual_50g)) {
   5547                 if (((fec_rs528_bam_msa == PORTMOD_PORT_PHY_FEC_NONE)
   5548                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC)) ||
   5549                     ((fec_rs528_bam_msa == PORTMOD_PORT_PHY_FEC_RS_FEC)
   5550                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE))) {
   5551                     _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5552                                        (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5553                 } else {
   5554                     /* only RSFEC and FEC_NONE are considered here */
   5555                     if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC) ||
   5556                         (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE)) {
   5557                         fec_rs528_bam_msa = abilities[i].fec_type;
   5558                     }
   5559                 }
   5560             }
   5561         } else if (abilities[i].an_mode == PORTMOD_PORT_PHY_CONTROL_AUTONEG_MODE_CL73_MSA) {
   5562             is_msa = 1;
   5563             /* CL74 request of 25G-1lane should be identical */
   5564             if (((fec_cl73bam_msa == PORTMOD_PORT_PHY_FEC_NONE)
   5565                  && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R)) ||
   5566                 ((fec_cl73bam_msa == PORTMOD_PORT_PHY_FEC_BASE_R)
   5567                  && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE))) {
   5568                 _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5569                                    (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5570             } else {
   5571                 /* only BaseR and FEC_NONE are considered here */
   5572                 if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) ||
   5573                     (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE)) {
   5574                     fec_cl73bam_msa = abilities[i].fec_type;
   5575                 }
   5576                 if (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) {
   5577                     cl73_bam_msa_base_r_req = 1;
   5578                 }
   5579             }
   5580             /* RS528 request of 25G-1lane, 50G-2lane should be identical */
   5581             if (((fec_rs528_bam_msa == PORTMOD_PORT_PHY_FEC_NONE)
   5582                  && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC)) ||
   5583                 ((fec_rs528_bam_msa == PORTMOD_PORT_PHY_FEC_RS_FEC)
   5584                  && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE))) {
   5585                 _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5586                                    (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5587             } else {
   5588                 /* only RSFEC and FEC_NONE are considered here */
   5589                 if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC) ||
   5590                     (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE)) {
   5591                     fec_rs528_bam_msa = abilities[i].fec_type;
   5592                 }
   5593             }
   5594         } else {
   5595             /* CL73 */
   5596             if (abilities[i].speed == 40000 || abilities[i].speed == 10000) {
   5597                 if (((fec_cl73 == PORTMOD_PORT_PHY_FEC_NONE)
   5598                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R)) ||
   5599                     ((fec_cl73 == PORTMOD_PORT_PHY_FEC_BASE_R)
   5600                      && (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE))) {
   5601                     _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5602                                        (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5603                 } else {
   5604                     /* only BaseR and FEC_NONE are considered here */
   5605                     if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) ||
   5606                         (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_NONE)) {
   5607                         fec_cl73 = abilities[i].fec_type;
   5608                     }
   5609                     /* 50G-2lane shares the same cl74 bit with other CL73,CL73BAM,MSA abilities */
   5610                     /* cl73_bam_msa_base_r_req is used to remember if there is any CL73,BAM,MSA BaseR request */
   5611                     if (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_BASE_R) {
   5612                         cl73_bam_msa_base_r_req = 1;
   5613                     }
   5614                 }
   5615                 if (abilities[i].speed == 10000) {
   5616                     if (abilities[i].medium != PORTMOD_PORT_PHY_MEDIUM_BACKPLANE) {
   5617                         _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   5618                                             (_SOC_MSG("port %d: abilities[%d] is not supported."), port, i));
   5619                     }
   5620                 }
   5621             } else if (abilities[i].speed == 25000) {
   5622                 if (!channel_25g) {
   5623                     channel_25g = abilities[i].channel;
   5624                 } else {
   5625                     if (channel_25g != abilities[i].channel) {
   5626                         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5627                                            (_SOC_MSG("port %d: Channel conflicts among abilities."), port));
   5628                     }
   5629                 }
   5630                 if ((abilities[i].channel == PORTMOD_PORT_PHY_CHANNEL_SHORT) &&
   5631                     (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC)) {
   5632                     _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   5633                                        (_SOC_MSG("port %d: abilities[%d] is not supported."), port, i));
   5634                 }
   5635                 if ((fec_cl73_25g == PORTMOD_PORT_PHY_FEC_NONE)
   5636                     && (abilities[i].fec_type != PORTMOD_PORT_PHY_FEC_NONE)) {
   5637                     _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5638                                        (_SOC_MSG("port %d: FEC conflicts among abilities."), port));
   5639                 } else {
   5640                     fec_cl73_25g = abilities[i].fec_type;
   5641                 }
   5642             }
   5643         }
   5644         if (request_vco == portmodVCO20P625G) {
   5645             PM8x50_VCO_ETH_20P625G_SET(vcos);
   5646         } else if (request_vco == portmodVCO25P781G) {
   5647             PM8x50_VCO_ETH_25P781G_SET(vcos);
   5648         } else if (request_vco == portmodVCO26P562G) {
   5649             PM8x50_VCO_ETH_26P562G_SET(vcos);
   5650         }
   5651     }
   5652 
   5653     /* 50G-2lane does not support Base-R.
   5654        In AN, 50G-2lane shares the same cl74 bit with other CL73,CL73BAM,MSA abilities. */
   5655     if (dual_50g_req && (cl73_bam_msa_base_r_req == 1)) {
   5656         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5657                            (_SOC_MSG("port %d: Base_R cannot be advertised together with 50G-2lane abilities."), port));
   5658     }
   5659 
   5660     if (is_bam && is_msa) {
   5661         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5662                            (_SOC_MSG("port %d: an_mode conflicts among abilities."
   5663                                      "Cannot advertise CL73MSA and CL73BAM at the same time."), port));
   5664     } else if (is_bam) {
   5665         an_mode = phymod_AN_MODE_CL73BAM;
   5666     } else if (is_msa) {
   5667         an_mode = phymod_AN_MODE_CL73_MSA;
   5668     } else {
   5669         an_mode = phymod_AN_MODE_CL73;
   5670     }
   5671 
   5672     /* within same MPP, MSA and BAM can not be exist at same time */
   5673     sal_memcpy(&phy_copy, &phy_access, sizeof(phy_copy));
   5674     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   5675     mpp_index = (int)(port_index / 4);
   5676     for (i = (0 + (mpp_index * 4)); i < (4 + (mpp_index*4)); i++) {
   5677         if (i == port_index) {
   5678             continue;
   5679         }
   5680         _SOC_IF_ERR_EXIT(PM8x50_AN_MODE_GET(unit, pm_info, &cur_an_mode, i));
   5681         if ((an_mode == phymod_AN_MODE_CL73_MSA) && (cur_an_mode == phymod_AN_MODE_CL73BAM)) {
   5682             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5683                 (_SOC_MSG("port %d: CL73_MSA cannot be advertised when current MPP is in CL73_BAM."), port));
   5684         }
   5685         if ((an_mode == phymod_AN_MODE_CL73BAM) && (cur_an_mode == phymod_AN_MODE_CL73_MSA)) {
   5686             _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5687                 (_SOC_MSG("port %d: CL73_BAM cannot be advertised when current MPP is in CL73_MSA."), port));
   5688         }
   5689     }
   5690 
   5691     /* 2.3. FEC arch can be supported within the each MPP */
   5692     if (rs544_req || rs528_req) {
   5693         _SOC_IF_ERR_EXIT(_pm8x50_fec_lanebitmap_get(unit, pm_info, &rs528_bm, &rs544_bm, &rs272_bm));
   5694         rs528_bm &= ~phy_access.access.lane_mask;
   5695         rs544_bm &= ~phy_access.access.lane_mask;
   5696         rs272_bm &= ~phy_access.access.lane_mask;
   5697         if (rs544_req) {
   5698             rs544_bm |= phy_access.access.lane_mask;
   5699         }
   5700         if (rs528_req) {
   5701             rs528_bm |= phy_access.access.lane_mask;
   5702         }
   5703         _SOC_IF_ERR_EXIT(_pm8x50_pm_version_get(unit, pm_info, &version));
   5704         if (version.tech_process == PM_TECH_16NM) {
   5705             PM8X50_PM_VERSION_F_REV0_16NM_SET(flags);
   5706         }
   5707         _SOC_IF_ERR_EXIT(_pm8x50_fec_validate(unit, flags, rs528_bm, rs544_bm, rs272_bm, &affected_bm));
   5708     }
   5709 
   5710     /* 2.4. AN ability can be supported by current VCOs */
   5711     if (pam4_req && (PM_8x50_INFO(pm_info)->tvco == portmodVCO20P625G)) {
   5712         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5713                            (_SOC_MSG("Can not support Ethernet PAM4 speeds when TVCO is 20.625G.")));
   5714     }
   5715 
   5716     _SOC_IF_ERR_EXIT(
   5717         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   5718     if (pll_lanes_bitmap & phy_access.access.lane_mask) {
   5719         /* Current port is using OVCO, so that OVCO can not be changed. */
   5720         flag = PORTMOD_PM_SPEED_VALIDATE_F_PLL_SWITCH_NOT_ALLOWED;
   5721     } else {
   5722         flag = PORTMOD_PM_SPEED_VALIDATE_F_ONE_PLL_SWITCH_ALLOWED;
   5723     }
   5724 
   5725     PORTMOD_PBMP_PORT_SET(ports, port);
   5726     _SOC_IF_ERR_EXIT(
   5727        _pm8x50_vcos_setting_validate(unit, pm_info, &ports, vcos, flag, &vco_setting));
   5728 
   5729     an_advert_abilities.autoneg_abilities = autoneg_abilities;
   5730     _SOC_IF_ERR_EXIT(_pm8x50_port_port_to_phy_ability(num_abilities, abilities, &an_advert_abilities));
   5731 
   5732     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   5733     ovco_pll_index = (tvco_pll_index == 1)? 0: 1;
   5734     _SOC_IF_ERR_EXIT(
   5735         PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   5736     if (ovco_pll_index == 1) {
   5737         old_pll_state.pll1_lanes_bitmap = pll_lanes_bitmap;
   5738     } else {
   5739         old_pll_state.pll0_lanes_bitmap = pll_lanes_bitmap;
   5740     }
   5741 
   5742     _SOC_IF_ERR_EXIT(
   5743         PM8x50_TVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   5744     if (tvco_pll_index == 1) {
   5745         old_pll_state.pll1_lanes_bitmap = pll_lanes_bitmap;
   5746     } else {
   5747         old_pll_state.pll0_lanes_bitmap = pll_lanes_bitmap;
   5748     }
   5749     /* 3. Set AN abilities in HW */
   5750     _SOC_IF_ERR_EXIT(
   5751         phymod_phy_autoneg_advert_ability_set(&phy_access, &an_advert_abilities, &old_pll_state, &new_pll_state));
   5752 
   5753     /* 4. Update DB and WB */
   5754     if (vco_setting.is_ovco_new) {
   5755         PM_8x50_INFO(pm_info)->ovco = vco_setting.ovco;
   5756     }
   5757 
   5758     /* 4.1. Update an_mode in WB */
   5759     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get (unit, port, pm_info, &port_index, &bitmap));
   5760     _SOC_IF_ERR_EXIT(PM8x50_AN_MODE_SET(unit, pm_info, an_mode, port_index));
   5761 
   5762     /* 4.2. Update FEC type in WB for RS528, RS544 case */
   5763     /* If AN request RS544, update DB and this will be treated as FEC arch restriction.
   5764      * Else if PM is 16nm and AN request RS528, update DB and this will be treated as FEC arch restriction.
   5765      * Else if AN request other FEC, keep the force speed FEC restriction. Need to update
   5766      * FEC restrition when AN is enabled.
   5767      */
   5768     if (rs544_req) {
   5769         fec = PORTMOD_PORT_PHY_FEC_RS_544;
   5770         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   5771             if ((phy_access.access.lane_mask >> i) & 0x1) {
   5772                 _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec));
   5773             }
   5774         }
   5775     } else if (rs528_req && PM8X50_PM_VERSION_F_REV0_16NM_GET(flags)) {
   5776         fec = PORTMOD_PORT_PHY_FEC_RS_FEC;
   5777         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   5778             if ((phy_access.access.lane_mask >> i) & 0x1) {
   5779                 _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec));
   5780             }
   5781         }
   5782     } else {
   5783         /* Call speed_config_get to get the FEC type and update the WB */
   5784         /* This is to make sure the DB stores the FS FEC instead of the previous adv FEC */
   5785         _SOC_IF_ERR_EXIT(pm8x50_port_speed_config_get(unit, port, pm_info, &speed_config));
   5786         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   5787             if ((phy_access.access.lane_mask >> i) & 0x1) {
   5788                 _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, speed_config.fec));
   5789             }
   5790         }
   5791     }
   5792 
   5793     /* 4.3. Update PLL lane bit maps in WB, power down OVCO if it's free */
   5794     _SOC_IF_ERR_EXIT(
   5795         PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   5796     if (tvco_pll_index == 1) {
   5797         /* Power down OVCO if it's not being used */
   5798         if (!(pll_lanes_bitmap || new_pll_state.pll0_lanes_bitmap)) {
   5799             _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, ovco_pll_index, 1));
   5800             PM_8x50_INFO(pm_info)->ovco = portmodVCOInvalid;
   5801         }
   5802         pll_lanes_bitmap = (uint8) new_pll_state.pll0_lanes_bitmap;
   5803         _SOC_IF_ERR_EXIT(
   5804             PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   5805         pll_lanes_bitmap = (uint8) new_pll_state.pll1_lanes_bitmap;
   5806         _SOC_IF_ERR_EXIT(
   5807             PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   5808     } else {
   5809         /* Power down OVCO if it's not being used */
   5810         if (!(pll_lanes_bitmap || new_pll_state.pll1_lanes_bitmap)) {
   5811             _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, ovco_pll_index, 1));
   5812             PM_8x50_INFO(pm_info)->ovco = portmodVCOInvalid;
   5813         }
   5814         pll_lanes_bitmap = (uint8) new_pll_state.pll0_lanes_bitmap;
   5815         _SOC_IF_ERR_EXIT(
   5816             PM8x50_TVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   5817         pll_lanes_bitmap = (uint8) new_pll_state.pll1_lanes_bitmap;
   5818         _SOC_IF_ERR_EXIT(
   5819             PM8x50_OVCO_PLL_ADV_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   5820     }
   5821 
   5822 exit:
   5823     SOC_FUNC_RETURN;
   5824 }
   5825 
   5826 int pm8x50_port_autoneg_ability_advert_get(int unit, int port, pm_info_t pm_info,
   5827                                            int max_num_abilities,
   5828                                            portmod_port_speed_ability_t* abilities,
   5829                                            int* actual_num_abilities)
   5830 {
   5831     portmod_access_get_params_t params;
   5832     phymod_phy_access_t phy_access;
   5833     int nof_phys, i;
   5834     phymod_autoneg_advert_ability_t autoneg_abilities[PM8x50_MAX_AN_ABILITY];
   5835     phymod_autoneg_advert_abilities_t an_advert_abilities;
   5836 
   5837     SOC_INIT_FUNC_DEFS;
   5838 
   5839     for (i = 0; i < PM8x50_MAX_AN_ABILITY; i++) {
   5840         _SOC_IF_ERR_EXIT(phymod_autoneg_advert_ability_t_init(&autoneg_abilities[i]));
   5841     }
   5842     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5843     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5844                                 &params, 1, &phy_access, &nof_phys, NULL));
   5845     an_advert_abilities.autoneg_abilities = autoneg_abilities;
   5846     _SOC_IF_ERR_EXIT(phymod_phy_autoneg_advert_ability_get(&phy_access, &an_advert_abilities));
   5847 
   5848     if (an_advert_abilities.num_abilities > max_num_abilities) {
   5849         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5850                           (_SOC_MSG("port %d: There are %d AN abilities. Larger array is needed."),
   5851                            port, an_advert_abilities.num_abilities));
   5852     } else {
   5853         _SOC_IF_ERR_EXIT(_pm8x50_port_phy_to_port_ability(&an_advert_abilities, actual_num_abilities, abilities));
   5854     }
   5855 
   5856 exit:
   5857     SOC_FUNC_RETURN;
   5858 }
   5859 
   5860 /*Port ability remote Adv get*/
   5861 int pm8x50_port_autoneg_ability_remote_get(int unit, int port, pm_info_t pm_info,
   5862                                            int max_num_abilities,
   5863                                            portmod_port_speed_ability_t* abilities,
   5864                                            int* actual_num_abilities)
   5865 {
   5866     portmod_access_get_params_t params;
   5867     phymod_phy_access_t phy_access;
   5868     int nof_phys, i;
   5869     phymod_autoneg_advert_ability_t autoneg_abilities[PM8x50_MAX_AN_ABILITY];
   5870     phymod_autoneg_advert_abilities_t an_advert_abilities;
   5871     int port_index, is_400g_an = 0, remote_pause = 0;
   5872     uint32 bitmap;
   5873     phymod_autoneg_status_t an_status;
   5874 
   5875     SOC_INIT_FUNC_DEFS;
   5876 
   5877     for (i = 0; i < PM8x50_MAX_AN_ABILITY; i++) {
   5878         _SOC_IF_ERR_EXIT(phymod_autoneg_advert_ability_t_init(&autoneg_abilities[i]));
   5879     }
   5880 
   5881     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5882     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5883                                 &params, 1, &phy_access, &nof_phys, NULL));
   5884     an_advert_abilities.autoneg_abilities = autoneg_abilities;
   5885 
   5886     _SOC_IF_ERR_EXIT(phymod_phy_autoneg_remote_advert_ability_get(&phy_access, &an_advert_abilities));
   5887 
   5888     /* next need to check 400G AN enabled or not */
   5889     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   5890     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   5891     _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_status_get(unit, port, pm_info, &an_status));
   5892     if (is_400g_an && an_status.enabled && an_status.locked) {
   5893         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, &remote_pause, port_index));
   5894         an_advert_abilities.num_abilities = 1;
   5895         an_advert_abilities.autoneg_abilities[0].pause = remote_pause;
   5896         an_advert_abilities.autoneg_abilities[0].speed = 400000;
   5897         an_advert_abilities.autoneg_abilities[0].resolved_num_lanes = 8;
   5898         an_advert_abilities.autoneg_abilities[0].fec = phymod_fec_RS544_2XN;
   5899         an_advert_abilities.autoneg_abilities[0].channel = phymod_channel_long;
   5900         an_advert_abilities.autoneg_abilities[0].an_mode = phymod_AN_MODE_MSA;
   5901     }
   5902 
   5903     if (an_advert_abilities.num_abilities > max_num_abilities) {
   5904         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   5905                           (_SOC_MSG("port %d: There are %d AN abilities. Larger array is needed."),
   5906                            port, an_advert_abilities.num_abilities));
   5907     } else {
   5908         _SOC_IF_ERR_EXIT(_pm8x50_port_phy_to_port_ability(&an_advert_abilities, actual_num_abilities, abilities));
   5909     }
   5910 
   5911 exit:
   5912     SOC_FUNC_RETURN;
   5913 }
   5914 
   5915 /*Set\Get autoneg*/
   5916 int pm8x50_port_autoneg_set(int unit, int port, pm_info_t pm_info,
   5917                             uint32 phy_flags,
   5918                             const phymod_autoneg_control_t* an)
   5919 {
   5920     portmod_access_get_params_t params;
   5921     phymod_phy_access_t phy_access;
   5922     int nof_phys, port_num_lanes;
   5923     int port_index, actual_num_abilities = 0, rs544_req = 0, rs528_req = 0, is_400g_an = 0;
   5924     uint32_t bitmap;
   5925     phymod_autoneg_control_t an_control;
   5926     uint8_t pll_lanes_bitmap;
   5927     int tvco_pll_index, ovco_pll_index, i;
   5928     portmod_port_speed_ability_t abilities[PM8x50_MAX_AN_ABILITY];
   5929     portmod_fec_t fec;
   5930     pm_version_t version;
   5931     SOC_INIT_FUNC_DEFS;
   5932 
   5933     _SOC_IF_ERR_EXIT(_pm8x50_pm_version_get(unit, pm_info, &version));
   5934 
   5935     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   5936     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   5937     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   5938                                 &params, 1, &phy_access, &nof_phys, NULL));
   5939     PORTMOD_BIT_COUNT(phy_access.access.lane_mask, port_num_lanes);
   5940     tvco_pll_index = PM8X50_TVCO_PLL_INDEX_GET(pm_info);
   5941     ovco_pll_index = (tvco_pll_index == 1)? 0: 1;
   5942 
   5943     an_control = *an;
   5944 
   5945     an_control.num_lane_adv = port_num_lanes;
   5946 
   5947     /* Get an_mode from WB */
   5948     _SOC_IF_ERR_EXIT(PM8x50_AN_MODE_GET(unit, pm_info, &an_control.an_mode, port_index));
   5949     if (an_control.an_mode == phymod_AN_MODE_NONE) {
   5950         /* Return error only when user want to enable AN without any AN abilities being advertised. */
   5951         if (!an_control.enable) {
   5952             an_control.an_mode = phymod_AN_MODE_CL73;
   5953         } else {
   5954             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   5955                                (_SOC_MSG("port %d: There's no valid AN advertisement for the port."), port));
   5956         }
   5957     }
   5958 
   5959     if (an_control.enable) {
   5960         /* Check if RS544 is required for AN abilities */
   5961         _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_ability_advert_get(unit, port, pm_info,
   5962                                                                 PM8x50_MAX_AN_ABILITY,
   5963                                                                 abilities,
   5964                                                                 &actual_num_abilities));
   5965         for (i = 0; i < actual_num_abilities; i++) {
   5966             /* check if 400G an is enabled */
   5967             if (abilities[i].speed == 400000) {
   5968                 is_400g_an = 1;
   5969             }
   5970             if ((abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_544) ||
   5971                 (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_544_2XN)) {
   5972                 rs544_req = 1;
   5973             }
   5974             if (abilities[i].fec_type == PORTMOD_PORT_PHY_FEC_RS_FEC) {
   5975                 rs528_req = 1;
   5976             }
   5977         }
   5978         if (rs544_req || (rs528_req && version.tech_process == PM_TECH_16NM)) {
   5979             PHYMOD_AN_F_FEC_RS272_CLR_SET(&an_control);
   5980         }
   5981     }
   5982     /*
   5983      * Before enabling serdes AN bit, need to disable the port in PCS
   5984      * and update mac port mode.
   5985      */
   5986     if (an_control.enable) {
   5987         _SOC_IF_ERR_EXIT(phymod_phy_pcs_enable_set(&phy_access, 0));
   5988         /* call port level port mode update */
   5989         _SOC_IF_ERR_EXIT(_pm8x50_pm_port_mode_update(unit, port, pm_info, port_index, 1));
   5990     }
   5991 
   5992     _SOC_IF_ERR_EXIT(phymod_phy_autoneg_set(&phy_access, &an_control));
   5993 
   5994     if (an_control.enable) {
   5995         /* When AN is enable on a port, always connect that port to TVCO */
   5996         _SOC_IF_ERR_EXIT(
   5997             PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   5998         pll_lanes_bitmap &= ~phy_access.access.lane_mask;
   5999         _SOC_IF_ERR_EXIT(
   6000             PM8x50_OVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   6001 
   6002         /* If OVCO is not being used, power down OVCO */
   6003         if (!pll_lanes_bitmap) {
   6004             _SOC_IF_ERR_EXIT(
   6005                 PM8x50_OVCO_PLL_ADV_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   6006             if (!pll_lanes_bitmap) {
   6007                 _SOC_IF_ERR_EXIT(phymod_phy_pll_pwrdn(&phy_access, ovco_pll_index, 1));
   6008                 PM_8x50_INFO(pm_info)->ovco = portmodVCOInvalid;
   6009             }
   6010         }
   6011 
   6012         _SOC_IF_ERR_EXIT(
   6013             PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_GET(unit, pm_info, &pll_lanes_bitmap));
   6014         pll_lanes_bitmap |= phy_access.access.lane_mask;
   6015         _SOC_IF_ERR_EXIT(
   6016             PM8x50_TVCO_PLL_ACTIVE_LANE_BITMAP_SET(unit, pm_info, pll_lanes_bitmap));
   6017         /* Update FEC usage in WB.
   6018          * If AN require RS544, set FEC type to RS544 in WB.
   6019          * Else if AN requrie RS528, set FEC type to RS528 in WB.
   6020          * Otherwise, set to FEC_NONE, indicating the port
   6021          * does not have FEC restriction within the MPP.
   6022          */
   6023         if (rs544_req) {
   6024             fec = PORTMOD_PORT_PHY_FEC_RS_544;
   6025         } else if (rs528_req) {
   6026             fec = PORTMOD_PORT_PHY_FEC_RS_FEC;
   6027         } else {
   6028             fec = PORTMOD_PORT_PHY_FEC_NONE;
   6029         }
   6030         for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   6031             if ((phy_access.access.lane_mask >> i) & 0x1) {
   6032                 _SOC_IF_ERR_EXIT(PM8x50_LANE2FEC_SET(unit, pm_info, i, fec));
   6033             }
   6034         }
   6035 
   6036     }
   6037     /* update the 400G An enabled */
   6038     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_SET(unit, pm_info, is_400g_an, port_index));
   6039     /* if 400G an enabled, needs to enable call back */
   6040     /* call back register should happen after 400G AN ENABLE is set */
   6041     if (is_400g_an) {
   6042          pm8x50_port_400g_an_state_t an_state = PM8X50_PORT_AN_CHECK_PAGE_COMPLETE;
   6043          uint32 an_wait_link_count = 0;
   6044         /* update the 400G An state */
   6045         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_SET(unit, pm_info, an_state));
   6046         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, an_wait_link_count));
   6047         _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_register(unit, port, pm8x50_periodic_callback, PORTMOD_THREAD_INTERVAL_1s));
   6048     }
   6049 
   6050 
   6051 exit:
   6052     SOC_FUNC_RETURN;
   6053 }
   6054 
   6055 int pm8x50_port_autoneg_get(int unit, int port, pm_info_t pm_info,
   6056                             uint32 phy_flags,
   6057                             phymod_autoneg_control_t* an)
   6058 {
   6059     portmod_access_get_params_t params;
   6060     phymod_phy_access_t phy_access;
   6061     int nof_phys, port_index, is_400g_an = 0;
   6062     uint32 bitmap;
   6063     uint32_t an_done;
   6064 
   6065     SOC_INIT_FUNC_DEFS;
   6066 
   6067     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6068     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6069                                 &params, 1, &phy_access, &nof_phys, NULL));
   6070     _SOC_IF_ERR_EXIT(phymod_phy_autoneg_get(&phy_access, an, &an_done));
   6071 
   6072     /* next need to check 400G AN enabled or not */
   6073     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   6074     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   6075     if (is_400g_an) {
   6076          an->enable = 1;
   6077          an->an_mode = phymod_AN_MODE_CL73_MSA;
   6078     }
   6079 
   6080 
   6081 exit:
   6082     SOC_FUNC_RETURN;
   6083 }
   6084 
   6085 /*Get autoneg status*/
   6086 int pm8x50_port_autoneg_status_get(int unit, int port, pm_info_t pm_info,
   6087                                    phymod_autoneg_status_t* an_status)
   6088 {
   6089     portmod_access_get_params_t params;
   6090     phymod_phy_access_t phy_access;
   6091     int nof_phys, port_index, is_400g_an = 0, an_400g_state;
   6092     uint32 bitmap;
   6093 
   6094     SOC_INIT_FUNC_DEFS;
   6095 
   6096     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6097     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6098                                 &params, 1, &phy_access, &nof_phys, NULL));
   6099 
   6100     _SOC_IF_ERR_EXIT(phymod_phy_autoneg_status_get(&phy_access, an_status));
   6101     
   6102     if (!(an_status->enabled && an_status->locked)) {
   6103         /* upper layer should not rely on the
   6104          * data rate if the AN is not locked
   6105          */
   6106         an_status->data_rate = 0;
   6107         an_status->interface = SOC_PORT_IF_NULL;
   6108     }
   6109     /* next need to check 400G AN enabled or not */
   6110     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   6111     _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   6112     if (is_400g_an) {
   6113         an_status->data_rate = 400000;
   6114         an_status->enabled = 1;
   6115         an_status->locked = 0;
   6116         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_GET(unit, pm_info, &an_400g_state));
   6117         if (an_400g_state == PM8X50_PORT_AN_COMPLETE) {
   6118             an_status->locked = 1;
   6119         }
   6120     }
   6121 
   6122 exit:
   6123     SOC_FUNC_RETURN;
   6124 }
   6125 
   6126 /*get link status*/
   6127 int pm8x50_port_link_get(int unit, int port, pm_info_t pm_info,
   6128                          int flags, int* link)
   6129 {
   6130     portmod_speed_config_t speed_config;
   6131     int latch_val = 0;
   6132     uint32 rval, bitmap;
   6133     portmod_access_get_params_t params;
   6134     phymod_phy_access_t phy_access;
   6135     int nof_phys, port_index, is_400g_an = 0, an_400g_state;
   6136 
   6137     SOC_INIT_FUNC_DEFS;
   6138 
   6139     if (SAL_BOOT_SIMULATION){
   6140         *link = 1;
   6141     } else {
   6142         _SOC_IF_ERR_EXIT(pm8x50_port_speed_config_get(unit, port, pm_info, &speed_config));
   6143         if (speed_config.speed == 400000) {
   6144             _SOC_IF_ERR_EXIT(
   6145                 pm8x50_port_link_latch_down_get(unit, port, pm_info, PORTMOD_PORT_LINK_LATCH_DOWN_F_CLEAR, &latch_val));
   6146             if (latch_val) {
   6147                 *link = 0;
   6148             } else {
   6149                 _SOC_IF_ERR_EXIT(
   6150                     READ_CDPORT_XGXS0_LN0_STATUS_REGr(unit, port, &rval));
   6151                 *link = soc_reg_field_get(unit, CDPORT_XGXS0_LN0_STATUS_REGr, rval, LINK_STATUSf);
   6152             }
   6153             /* next need to check 400G AN enabled or not */
   6154             _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   6155             _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   6156             if (is_400g_an) {
   6157                 _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_GET(unit, pm_info, &an_400g_state));
   6158                 if (an_400g_state != PM8X50_PORT_AN_COMPLETE) {
   6159                      *link = 0;
   6160                 } else {
   6161                     /* need to check link status, if down, need to restart 400G AN */
   6162                     if (*link == 0) {
   6163                          pm8x50_port_400g_an_state_t an_state = PM8X50_PORT_AN_DISABLE;
   6164                          uint32 an_wait_link_count = 0;
   6165                         /* update the 400G An state */
   6166                         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_STATE_SET(unit, pm_info, an_state));
   6167                         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, an_wait_link_count));
   6168                         _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_register(unit, port, pm8x50_periodic_callback, PORTMOD_THREAD_INTERVAL_1s));
   6169                    }
   6170                 }
   6171             }
   6172         } else {
   6173             _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6174             _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6175                                         &params, 1, &phy_access, &nof_phys, NULL));
   6176 
   6177             _SOC_IF_ERR_EXIT(phymod_phy_link_status_get(&phy_access,
   6178                                                        (uint32_t *) link));
   6179         }
   6180     }
   6181 exit:
   6182     SOC_FUNC_RETURN;
   6183 }
   6184 
   6185 /*get latch down link status (whether link was ever down since last clear)*/
   6186 int pm8x50_port_link_latch_down_get(int unit, int port,
   6187                                     pm_info_t pm_info,
   6188                                     uint32 flags, int* link)
   6189 {
   6190     int first_index;
   6191     uint32 rval, bitmap;
   6192     soc_field_t status_field;
   6193     SOC_INIT_FUNC_DEFS;
   6194 
   6195     *link = 0;
   6196 
   6197     _SOC_IF_ERR_EXIT(
   6198         _pm8x50_port_index_get(unit, port, pm_info, &first_index, &bitmap));
   6199 
   6200      switch(first_index) {
   6201         case 0:
   6202             status_field = PORT0_LINKSTATUSf;
   6203             break;
   6204 
   6205         case 1:
   6206             status_field = PORT1_LINKSTATUSf;
   6207             break;
   6208 
   6209         case 2:
   6210             status_field = PORT2_LINKSTATUSf;
   6211             break;
   6212 
   6213         case 3:
   6214             status_field = PORT3_LINKSTATUSf;
   6215             break;
   6216 
   6217         case 4:
   6218             status_field = PORT4_LINKSTATUSf;
   6219             break;
   6220 
   6221         case 5:
   6222             status_field = PORT5_LINKSTATUSf;
   6223             break;
   6224 
   6225         case 6:
   6226             status_field = PORT6_LINKSTATUSf;
   6227             break;
   6228 
   6229         case 7:
   6230             status_field = PORT7_LINKSTATUSf;
   6231             break;
   6232 
   6233         default:
   6234             _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL,
   6235                      (_SOC_MSG("Port %d, failed to get port index"), port));
   6236     }
   6237 
   6238     _SOC_IF_ERR_EXIT(READ_CDPORT_LINKSTATUS_DOWNr(unit, port, &rval));
   6239 
   6240     (*link) = soc_reg_field_get(unit, CDPORT_LINKSTATUS_DOWNr,
   6241                                         rval, status_field);
   6242 
   6243     if (PORTMOD_PORT_LINK_LATCH_DOWN_F_CLEAR & flags) {
   6244         /* CDPORT_LINKSTATUS_DOWN is sticky register.
   6245          * Need to write 1b'1 to clear each field.
   6246          */
   6247         rval = 0;
   6248 
   6249         soc_reg_field_set(unit, CDPORT_LINKSTATUS_DOWNr,
   6250                                         &rval, status_field, 1);
   6251 
   6252         _SOC_IF_ERR_EXIT(
   6253                 WRITE_CDPORT_LINKSTATUS_DOWNr(unit, port, rval));
   6254     }
   6255 
   6256 exit:
   6257     SOC_FUNC_RETURN;
   6258 }
   6259 /* link up event */
   6260 /* 1. AN ports: Update port mode based on reslved speed mode.
   6261  *              Program resolved Pause settings.
   6262  * 2. 1588 ports: timesync adjust.
   6263  */
   6264 int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info)
   6265 {
   6266     portmod_access_get_params_t params;
   6267     phymod_phy_access_t phy_access;
   6268     phymod_autoneg_status_t an_status;
   6269     int nof_phys, port_index = -1;
   6270     int mac_stage_id, phy_acc;
   6271     uint32 reg_val;
   6272     uint32 timesync_enable, bitmap, flags = 0;
   6273     int num_advert, num_remote, is_400g_an;
   6274     portmod_port_speed_ability_t advert_ability[PM8x50_MAX_AN_ABILITY];
   6275     portmod_port_speed_ability_t remote_ability[PM8x50_MAX_AN_ABILITY];
   6276     portmod_pause_control_t pause_ctrl;
   6277     portmod_port_phy_pause_t pause_local, pause_remote;
   6278     uint8 rx_pause, tx_pause;
   6279 
   6280     SOC_INIT_FUNC_DEFS;
   6281 
   6282     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6283     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6284                                 &params, 1, &phy_access, &nof_phys, NULL));
   6285     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   6286 
   6287     /* 1. Update for AN ports */
   6288     _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_status_get(unit, port, pm_info, &an_status));
   6289     if ((an_status.enabled && an_status.locked)) {
   6290         /* read the 400G an enabled */
   6291         _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
   6292         /*!
   6293          * 1.1 Update port mode.
   6294          * For PM8x50 autoneg, once the port resolves and link up,
   6295          * cdmac_port_mode needs to be updated based on the PCS final port mode.
   6296          */
   6297         if (!is_400g_an) {
   6298             mac_stage_id = port_index / CDMAC_NUM_LANES;
   6299             _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   6300 
   6301             _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, &reg_val));
   6302 
   6303             if (mac_stage_id) {
   6304                 /* MAC1 is single-port mode */
   6305                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC1_PORT_MODEf, an_status.resolved_port_mode);
   6306             } else {
   6307                 /* MAC0 is single-port mode */
   6308                 soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, an_status.resolved_port_mode);
   6309             }
   6310             _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val));
   6311         }
   6312 
   6313         /*!
   6314          * 1.2 Update pause settings.
   6315          * Please see $SDK/doc/pause-resolution.txt for more information.
   6316          */
   6317         _SOC_IF_ERR_EXIT
   6318             (pm8x50_port_autoneg_ability_advert_get(unit, port, pm_info,
   6319                                                     PM8x50_MAX_AN_ABILITY,
   6320                                                     advert_ability, &num_advert));
   6321         _SOC_IF_ERR_EXIT
   6322             (pm8x50_port_autoneg_ability_remote_get(unit, port, pm_info,
   6323                                                     PM8x50_MAX_AN_ABILITY,
   6324                                                     remote_ability, &num_remote));
   6325 
   6326         if (num_advert && num_remote) {
   6327             pause_local = advert_ability[0].pause;
   6328             pause_remote = remote_ability[0].pause;
   6329             if (
   6330                 ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX) &&
   6331                  (pause_remote == PORTMOD_PORT_PHY_PAUSE_TX)) ||
   6332                 ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX ||
   6333                   pause_local == PORTMOD_PORT_PHY_PAUSE_SYMM) &&
   6334                  (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX ||
   6335                   pause_remote == PORTMOD_PORT_PHY_PAUSE_SYMM))
   6336                ) {
   6337                 rx_pause = 1;
   6338             } else {
   6339                 rx_pause = 0;
   6340             }
   6341             if (
   6342                 ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX ||
   6343                   pause_local == PORTMOD_PORT_PHY_PAUSE_SYMM) &&
   6344                  (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX ||
   6345                   pause_remote == PORTMOD_PORT_PHY_PAUSE_SYMM)) ||
   6346                 ((pause_local == PORTMOD_PORT_PHY_PAUSE_TX) &&
   6347                  (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX))
   6348                ) {
   6349                 tx_pause = 1;
   6350             } else {
   6351                 tx_pause = 0;
   6352             }
   6353         } else {
   6354             tx_pause = 0;
   6355             rx_pause = 0;
   6356         }
   6357 
   6358         _SOC_IF_ERR_EXIT
   6359             (pm8x50_port_pause_control_get(unit, port, pm_info, &pause_ctrl));
   6360         if ((pause_ctrl.rx_enable != rx_pause) ||
   6361             (pause_ctrl.tx_enable != tx_pause)) {
   6362             pause_ctrl.rx_enable = rx_pause;
   6363             pause_ctrl.tx_enable = tx_pause;
   6364             _SOC_IF_ERR_EXIT
   6365                 (pm8x50_port_pause_control_set(unit, port, pm_info, &pause_ctrl));
   6366         }
   6367     }
   6368 
   6369 
   6370     /* 2. Adjust timesync settings for 1588 port. */
   6371     _SOC_IF_ERR_EXIT(PM8x50_TIMESYNC_ENABLE_GET(unit, pm_info, &timesync_enable, port_index));
   6372 
   6373     if (timesync_enable) {
   6374         /* If 1588 is enabled on the port, need to adjust timesync during link up event.
   6375          * rx_ts_update will be enabled at the end of adjust function.
   6376          * Current driver code only support EarliestLane mode.
   6377          */
   6378         _SOC_IF_ERR_EXIT(phymod_timesync_adjust_set(&phy_access, phymodTimesyncCompensationModeEarliestLane));
   6379         PHYMOD_TIMESYNC_ENABLE_F_RX_SET(flags);
   6380         _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 1));
   6381         /* Wait for one AM spacing time */
   6382         sal_usleep(500);
   6383     }
   6384 
   6385 
   6386 exit:
   6387     SOC_FUNC_RETURN;
   6388 }
   6389 
   6390 /* link down event */
   6391 /* 1. 1588 port: Disable rx_ts_update.
   6392  */
   6393 int pm8x50_port_phy_link_down_event(int unit, int port, pm_info_t pm_info)
   6394 {
   6395     portmod_access_get_params_t params;
   6396     phymod_phy_access_t phy_access;
   6397     int nof_phys, port_index = -1;
   6398     uint32 timesync_enable, bitmap, flags = 0;
   6399 
   6400     SOC_INIT_FUNC_DEFS;
   6401 
   6402     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   6403     _SOC_IF_ERR_EXIT(PM8x50_TIMESYNC_ENABLE_GET(unit, pm_info, &timesync_enable, port_index));
   6404 
   6405     if (timesync_enable) {
   6406         /* If link down and 1588 is enabled on the port,
   6407          * Need to disable rx_ts_update.
   6408          */
   6409         _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6410         _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6411                                     &params, 1, &phy_access, &nof_phys, NULL));
   6412         PHYMOD_TIMESYNC_ENABLE_F_RX_SET(flags);
   6413         _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 0));
   6414     }
   6415 
   6416 exit:
   6417     SOC_FUNC_RETURN;
   6418 }
   6419 
   6420 /*PRBS configuration set/get*/
   6421 int pm8x50_port_prbs_config_set(int unit, int port, pm_info_t pm_info,
   6422                                 portmod_prbs_mode_t mode, int flags,
   6423                                 const phymod_prbs_t* config)
   6424 {
   6425     portmod_access_get_params_t params;
   6426     phymod_phy_access_t phy_access;
   6427     int nof_phys;
   6428     SOC_INIT_FUNC_DEFS;
   6429 
   6430     /* MAC */
   6431     if(mode == 1) {
   6432         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6433                           (_SOC_MSG("MAC PRBS is not supported")));
   6434     }
   6435 
   6436     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6437     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6438                                 &params, 1, &phy_access, &nof_phys, NULL));
   6439     _SOC_IF_ERR_EXIT(phymod_phy_prbs_config_set(&phy_access, flags, config));
   6440 
   6441 exit:
   6442     SOC_FUNC_RETURN;
   6443 }
   6444 
   6445 int pm8x50_port_prbs_config_get(int unit, int port, pm_info_t pm_info,
   6446                                 portmod_prbs_mode_t mode, int flags,
   6447                                 phymod_prbs_t* config)
   6448 {
   6449     portmod_access_get_params_t params;
   6450     phymod_phy_access_t phy_access;
   6451     int nof_phys;
   6452     SOC_INIT_FUNC_DEFS;
   6453 
   6454     /* MAC */
   6455     if(mode == 1) {
   6456         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6457                           (_SOC_MSG("MAC PRBS is not supported")));
   6458     }
   6459 
   6460     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6461     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6462                                 &params, 1, &phy_access, &nof_phys, NULL));
   6463     _SOC_IF_ERR_EXIT(phymod_phy_prbs_config_get(&phy_access, flags, config));
   6464 
   6465 exit:
   6466     SOC_FUNC_RETURN;
   6467 }
   6468 
   6469 /*PRBS enable set/get*/
   6470 int pm8x50_port_prbs_enable_set(int unit, int port, pm_info_t pm_info,
   6471                                 portmod_prbs_mode_t mode, int flags,
   6472                                 int enable)
   6473 {
   6474     portmod_access_get_params_t params;
   6475     phymod_phy_access_t phy_access;
   6476     int nof_phys;
   6477     SOC_INIT_FUNC_DEFS;
   6478 
   6479     /* MAC */
   6480     if(mode == 1) {
   6481         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6482                           (_SOC_MSG("MAC PRBS is not supported")));
   6483     }
   6484 
   6485     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6486     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6487                                 &params, 1, &phy_access, &nof_phys, NULL));
   6488     _SOC_IF_ERR_EXIT(phymod_phy_prbs_enable_set(&phy_access, flags, enable));
   6489 
   6490 exit:
   6491     SOC_FUNC_RETURN;
   6492 }
   6493 
   6494 int pm8x50_port_prbs_enable_get(int unit, int port, pm_info_t pm_info,
   6495                                 portmod_prbs_mode_t mode, int flags,
   6496                                 int* enable)
   6497 {
   6498     portmod_access_get_params_t params;
   6499     phymod_phy_access_t phy_access;
   6500     int nof_phys;
   6501     SOC_INIT_FUNC_DEFS;
   6502 
   6503     /* MAC */
   6504     if(mode == 1) {
   6505         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6506                           (_SOC_MSG("MAC PRBS is not supported")));
   6507     }
   6508 
   6509     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6510     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6511                                 &params, 1, &phy_access, &nof_phys, NULL));
   6512     _SOC_IF_ERR_EXIT(phymod_phy_prbs_enable_get(&phy_access, flags,
   6513                                                 (uint32_t *) enable));
   6514 
   6515 exit:
   6516     SOC_FUNC_RETURN;
   6517 }
   6518 
   6519 /*PRBS status get*/
   6520 int pm8x50_port_prbs_status_get(int unit, int port, pm_info_t pm_info,
   6521                                 portmod_prbs_mode_t mode, int flags,
   6522                                 phymod_prbs_status_t* status)
   6523 {
   6524     portmod_access_get_params_t params;
   6525     phymod_phy_access_t phy_access;
   6526     int nof_phys;
   6527     SOC_INIT_FUNC_DEFS;
   6528 
   6529     /* MAC */
   6530     if(mode == 1) {
   6531         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6532                           (_SOC_MSG("MAC PRBS is not supported")));
   6533     }
   6534 
   6535     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6536     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6537                                 &params, 1, &phy_access, &nof_phys, NULL));
   6538     _SOC_IF_ERR_EXIT(phymod_phy_prbs_status_get(&phy_access, flags, status));
   6539 
   6540 exit:
   6541     SOC_FUNC_RETURN;
   6542 }
   6543 
   6544 /*Port tx taps set\get*/
   6545 int pm8x50_port_tx_set(int unit, int port, pm_info_t pm_info, const phymod_tx_t* tx)
   6546 {
   6547     portmod_access_get_params_t params;
   6548     phymod_phy_access_t phy_access;
   6549     int nof_phys;
   6550     SOC_INIT_FUNC_DEFS;
   6551 
   6552     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6553     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6554                                 &params, 1, &phy_access, &nof_phys, NULL));
   6555     _SOC_IF_ERR_EXIT(phymod_phy_tx_set(&phy_access, tx));
   6556 
   6557 exit:
   6558     SOC_FUNC_RETURN;
   6559 }
   6560 
   6561 int pm8x50_port_tx_get(int unit, int port, pm_info_t pm_info, phymod_tx_t* tx)
   6562 {
   6563     portmod_access_get_params_t params;
   6564     phymod_phy_access_t phy_access;
   6565     int nof_phys;
   6566     SOC_INIT_FUNC_DEFS;
   6567 
   6568     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   6569     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   6570                                 &params, 1, &phy_access, &nof_phys, NULL));
   6571     _SOC_IF_ERR_EXIT(phymod_phy_tx_get(&phy_access, tx));
   6572 
   6573 exit:
   6574     SOC_FUNC_RETURN;
   6575 }
   6576 
   6577 /*Number of lanes get*/
   6578 int pm8x50_port_nof_lanes_get(int unit, int port, pm_info_t pm_info,
   6579                               int* nof_lanes)
   6580 {
   6581     int port_index;
   6582     uint32_t bitmap, bcnt = 0;
   6583 
   6584     SOC_INIT_FUNC_DEFS;
   6585 
   6586     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get (unit, port, pm_info, &port_index, &bitmap));
   6587 
   6588     while (bitmap) {
   6589         if (bitmap & 0x1) bcnt++;
   6590         bitmap >>= 1;
   6591     }
   6592     *nof_lanes = bcnt;
   6593 
   6594 exit:
   6595     SOC_FUNC_RETURN;
   6596 }
   6597 
   6598 /*Set port PHYs' firmware mode*/
   6599 int pm8x50_port_firmware_mode_set(int unit, int port, pm_info_t pm_info,
   6600                                   phymod_firmware_mode_t fw_mode)
   6601 {
   6602 
   6603     return (SOC_E_NONE);
   6604 }
   6605 int pm8x50_port_firmware_mode_get(int unit, int port, pm_info_t pm_info,
   6606                                   phymod_firmware_mode_t* fw_mode)
   6607 {
   6608 
   6609     return (SOC_E_NONE);
   6610 }
   6611 
   6612 /*Filter packets smaller than the specified threshold*/
   6613 int pm8x50_port_runt_threshold_set(int unit, int port,
   6614                                    pm_info_t pm_info,
   6615                                    int value)
   6616 {
   6617     SOC_INIT_FUNC_DEFS;
   6618     _SOC_IF_ERR_EXIT(cdmac_runt_threshold_set(unit, port, value));
   6619 exit:
   6620     SOC_FUNC_RETURN;
   6621 }
   6622 
   6623 int pm8x50_port_runt_threshold_get(int unit, int port, pm_info_t pm_info,
   6624                                    int* value)
   6625 {
   6626     SOC_INIT_FUNC_DEFS;
   6627     _SOC_IF_ERR_EXIT(cdmac_runt_threshold_get(unit, port, value));
   6628 exit:
   6629     SOC_FUNC_RETURN;
   6630 }
   6631 
   6632 /*Filter packets bigger than the specified value*/
   6633 int pm8x50_port_max_packet_size_set(int unit, int port, pm_info_t pm_info,
   6634                                     int value)
   6635 {
   6636     SOC_INIT_FUNC_DEFS;
   6637     _SOC_IF_ERR_EXIT(cdmac_rx_max_size_set(unit, port , value));
   6638 exit:
   6639     SOC_FUNC_RETURN;
   6640 }
   6641 int pm8x50_port_max_packet_size_get(int unit, int port, pm_info_t pm_info,
   6642                                     int* value)
   6643 {
   6644     SOC_INIT_FUNC_DEFS;
   6645     _SOC_IF_ERR_EXIT(cdmac_rx_max_size_get(unit, port , value));
   6646 exit:
   6647     SOC_FUNC_RETURN;
   6648 }
   6649 
   6650 /*
   6651  * TX pad packets to the specified size.
   6652  * values smaller than 17 means pad is disabled.
   6653  */
   6654 int pm8x50_port_pad_size_set(int unit, int port, pm_info_t pm_info, int value)
   6655 {
   6656     SOC_INIT_FUNC_DEFS;
   6657     SOC_NULL_CHECK(pm_info);
   6658 
   6659     _SOC_IF_ERR_EXIT(cdmac_pad_size_set(unit, port , value));
   6660 
   6661 exit:
   6662     SOC_FUNC_RETURN;
   6663 }
   6664 
   6665 int pm8x50_port_pad_size_get(int unit, int port, pm_info_t pm_info, int* value)
   6666 {
   6667     SOC_INIT_FUNC_DEFS;
   6668     SOC_NULL_CHECK(pm_info);
   6669 
   6670     _SOC_IF_ERR_EXIT(cdmac_pad_size_get(unit, port , value));
   6671 
   6672 exit:
   6673     SOC_FUNC_RETURN;
   6674 }
   6675 
   6676 /*set/get the MAC source address that will be sent in case of Pause/LLFC*/
   6677 int pm8x50_port_tx_mac_sa_set(int unit, int port, pm_info_t pm_info,
   6678                               sal_mac_addr_t mac_sa)
   6679 {
   6680    SOC_INIT_FUNC_DEFS;
   6681     SOC_NULL_CHECK(pm_info);
   6682 
   6683     _SOC_IF_ERR_EXIT(cdmac_tx_mac_sa_set(unit, port, mac_sa));
   6684 
   6685 exit:
   6686     SOC_FUNC_RETURN;
   6687 }
   6688 int pm8x50_port_tx_mac_sa_get(int unit, int port, pm_info_t pm_info,
   6689                               sal_mac_addr_t mac_sa)
   6690 {
   6691     SOC_INIT_FUNC_DEFS;
   6692     SOC_NULL_CHECK(pm_info);
   6693 
   6694     _SOC_IF_ERR_EXIT(cdmac_tx_mac_sa_get(unit, port, mac_sa));
   6695 
   6696 exit:
   6697     SOC_FUNC_RETURN;
   6698 }
   6699 
   6700 /* set/get SA recognized for MAC control packets
   6701  * in addition to the standard 0x0180C2000001
   6702  */
   6703 int pm8x50_port_rx_mac_sa_set(int unit, int port, pm_info_t pm_info,
   6704                               sal_mac_addr_t mac_sa)
   6705 {
   6706     SOC_INIT_FUNC_DEFS;
   6707     SOC_NULL_CHECK(pm_info);
   6708 
   6709     _SOC_IF_ERR_EXIT(cdmac_rx_mac_sa_set(unit, port, mac_sa));
   6710 
   6711 exit:
   6712     SOC_FUNC_RETURN;
   6713 }
   6714 int pm8x50_port_rx_mac_sa_get(int unit, int port, pm_info_t pm_info,
   6715                               sal_mac_addr_t mac_sa)
   6716 {
   6717     SOC_INIT_FUNC_DEFS;
   6718     SOC_NULL_CHECK(pm_info);
   6719 
   6720     _SOC_IF_ERR_EXIT(cdmac_rx_mac_sa_get(unit, port, mac_sa));
   6721 
   6722 exit:
   6723     SOC_FUNC_RETURN;
   6724 }
   6725 
   6726 /*set/get Average inter-packet gap*/
   6727 int pm8x50_port_tx_average_ipg_set(int unit, int port, pm_info_t pm_info,
   6728                                    int value)
   6729 {
   6730     SOC_INIT_FUNC_DEFS;
   6731     SOC_NULL_CHECK(pm_info);
   6732 
   6733     _SOC_IF_ERR_EXIT(cdmac_tx_average_ipg_set(unit, port, value));
   6734 
   6735 exit:
   6736     SOC_FUNC_RETURN;
   6737 
   6738 
   6739 }
   6740 int pm8x50_port_tx_average_ipg_get(int unit, int port, pm_info_t pm_info,
   6741                                    int* value)
   6742 {
   6743     SOC_INIT_FUNC_DEFS;
   6744     SOC_NULL_CHECK(pm_info);
   6745 
   6746     _SOC_IF_ERR_EXIT(cdmac_tx_average_ipg_get(unit, port, value));
   6747 
   6748 exit:
   6749     SOC_FUNC_RETURN;
   6750 
   6751 }
   6752 
   6753 /*local fault set/get*/
   6754 int pm8x50_port_local_fault_control_set(int unit, int port, pm_info_t pm_info,
   6755                                  const portmod_local_fault_control_t* control)
   6756 {
   6757     SOC_INIT_FUNC_DEFS;
   6758     SOC_NULL_CHECK(pm_info);
   6759 
   6760     _SOC_IF_ERR_EXIT(cdmac_local_fault_control_set(unit, port, control));
   6761 
   6762 exit:
   6763     SOC_FUNC_RETURN;
   6764 }
   6765 
   6766 int pm8x50_port_local_fault_control_get(int unit, int port, pm_info_t pm_info,
   6767                                       portmod_local_fault_control_t* control)
   6768 {
   6769     SOC_INIT_FUNC_DEFS;
   6770     SOC_NULL_CHECK(pm_info);
   6771 
   6772     _SOC_IF_ERR_EXIT(cdmac_local_fault_control_get(unit, port, control));
   6773 
   6774 exit:
   6775     SOC_FUNC_RETURN;
   6776 
   6777 }
   6778 
   6779 /*remote fault set/get*/
   6780 int pm8x50_port_remote_fault_control_set(int unit, int port, pm_info_t pm_info,
   6781                                  const portmod_remote_fault_control_t* control)
   6782 {
   6783     SOC_INIT_FUNC_DEFS;
   6784     SOC_NULL_CHECK(pm_info);
   6785 
   6786     _SOC_IF_ERR_EXIT(cdmac_remote_fault_control_set(unit, port, control));
   6787 
   6788 exit:
   6789     SOC_FUNC_RETURN;
   6790 
   6791 }
   6792 int pm8x50_port_remote_fault_control_get(int unit, int port, pm_info_t pm_info,
   6793                                      portmod_remote_fault_control_t* control)
   6794 {
   6795     SOC_INIT_FUNC_DEFS;
   6796     SOC_NULL_CHECK(pm_info);
   6797 
   6798     _SOC_IF_ERR_EXIT(cdmac_remote_fault_control_get(unit, port, control));
   6799 
   6800 exit:
   6801     SOC_FUNC_RETURN;
   6802 }
   6803 
   6804 /*local fault steatus get*/
   6805 int pm8x50_port_local_fault_status_get(int unit, int port, pm_info_t pm_info,
   6806                                        int* value)
   6807 {
   6808     SOC_INIT_FUNC_DEFS;
   6809     SOC_NULL_CHECK(pm_info);
   6810 
   6811     _SOC_IF_ERR_EXIT(cdmac_local_fault_status_get(unit, port, value));
   6812 
   6813 exit:
   6814     SOC_FUNC_RETURN;
   6815 }
   6816 
   6817 /*remote fault status get*/
   6818 int pm8x50_port_remote_fault_status_get(int unit, int port, pm_info_t pm_info,
   6819                                         int* value)
   6820 {
   6821     SOC_INIT_FUNC_DEFS;
   6822     SOC_NULL_CHECK(pm_info);
   6823 
   6824     _SOC_IF_ERR_EXIT(cdmac_remote_fault_status_get(unit, port, value));
   6825 
   6826 exit:
   6827     SOC_FUNC_RETURN;
   6828 }
   6829 
   6830 /*local fault steatus clear*/
   6831 int pm8x50_port_local_fault_status_clear(int unit, int port, pm_info_t pm_info)
   6832 {
   6833 
   6834     return (SOC_E_NONE);
   6835 }
   6836 
   6837 /*remote fault status clear*/
   6838 int pm8x50_port_remote_fault_status_clear(int unit, int port,
   6839                                           pm_info_t pm_info)
   6840 {
   6841 
   6842     return (SOC_E_NONE);
   6843 }
   6844 
   6845 int pm8x50_port_pause_control_set(int unit, int port, pm_info_t pm_info,
   6846                                   const portmod_pause_control_t* control)
   6847 {
   6848     SOC_INIT_FUNC_DEFS;
   6849     _SOC_IF_ERR_EXIT(cdmac_pause_control_set(unit, port, control));
   6850 exit:
   6851     SOC_FUNC_RETURN;
   6852 }
   6853 
   6854 int pm8x50_port_pause_control_get(int unit, int port, pm_info_t pm_info,
   6855                                   portmod_pause_control_t* control)
   6856 {
   6857     SOC_INIT_FUNC_DEFS;
   6858     _SOC_IF_ERR_EXIT(cdmac_pause_control_get(unit, port, control));
   6859 exit:
   6860     SOC_FUNC_RETURN;
   6861 }
   6862 
   6863 int pm8x50_port_pfc_control_set(int unit, int port, pm_info_t pm_info,
   6864                                 const portmod_pfc_control_t* control)
   6865 {
   6866     SOC_INIT_FUNC_DEFS;
   6867     _SOC_IF_ERR_EXIT(cdmac_pfc_control_set(unit, port, control));
   6868 exit:
   6869     SOC_FUNC_RETURN;
   6870 }
   6871 
   6872 int pm8x50_port_pfc_control_get(int unit, int port, pm_info_t pm_info,
   6873                                 portmod_pfc_control_t* control)
   6874 {
   6875     SOC_INIT_FUNC_DEFS;
   6876     _SOC_IF_ERR_EXIT(cdmac_pfc_control_get(unit, port, control));
   6877 exit:
   6878     SOC_FUNC_RETURN;
   6879 }
   6880 
   6881 /*Routine for MAC\PHY sync.*/
   6882 int pm8x50_port_update(int unit, int port, pm_info_t pm_info,
   6883                        const portmod_port_update_control_t* update_control)
   6884 {
   6885 
   6886     return (SOC_E_NONE);
   6887 }
   6888 
   6889 /*get port cores' phymod access*/
   6890 int pm8x50_port_core_access_get(int unit, int port, pm_info_t pm_info,
   6891                                 int phyn, int max_cores,
   6892                                 phymod_core_access_t* core_access_arr,
   6893                                 int* nof_cores, int* is_most_ext)
   6894 {
   6895     SOC_INIT_FUNC_DEFS;
   6896 
   6897     /* There are only internal phys(1) on PM8x50, setting phyn to 0 */
   6898     if(phyn < 0)
   6899     {
   6900         phyn = 0;
   6901     }
   6902 
   6903     _SOC_IF_ERR_EXIT(phymod_core_access_t_init(&core_access_arr[0]));
   6904 
   6905     if( phyn == 0 ){
   6906         sal_memcpy(&core_access_arr[0],
   6907                    &(PM_8x50_INFO(pm_info)->int_core_access),
   6908                    sizeof(phymod_core_access_t));
   6909         *nof_cores = 1;
   6910     }
   6911 
   6912     if (is_most_ext) {
   6913             *is_most_ext = 1;
   6914     }
   6915 
   6916 exit:
   6917     SOC_FUNC_RETURN;
   6918 }
   6919 
   6920 /*Get lane phymod access structure. can be used for per lane operations*/
   6921 int pm8x50_port_phy_lane_access_get(int unit, int port, pm_info_t pm_info,
   6922                                     const portmod_access_get_params_t* params,
   6923                                     int max_phys,
   6924                                     phymod_phy_access_t* phy_access,
   6925                                     int* nof_phys, int* is_most_ext)
   6926 {
   6927     int rv;
   6928     uint32  iphy_lane_mask = 0;
   6929     int port_index=0;
   6930     int i;
   6931     uint32 is_bypassed = 0;
   6932     int lane_count;
   6933 
   6934     SOC_INIT_FUNC_DEFS;
   6935 
   6936     if(max_phys > MAX_NUM_CORES)
   6937     {
   6938         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   6939                           (_SOC_MSG("max_phys parameter exceeded the "
   6940                           "MAX value. max_phys=%d, max allowed %d."),
   6941                           max_phys, MAX_NUM_CORES));
   6942     }
   6943 
   6944     /* get port index and lane mask */
   6945     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index,
   6946                                             &iphy_lane_mask));
   6947 
   6948     rv = PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index);
   6949     _SOC_IF_ERR_EXIT(rv);
   6950 
   6951 
   6952     for( i = 0 ; i < max_phys; i++) {
   6953         _SOC_IF_ERR_EXIT(phymod_phy_access_t_init(&phy_access[i]));
   6954     }
   6955 
   6956     *nof_phys = 1;
   6957     /* internal core */
   6958     sal_memcpy (&phy_access[0], &(PM_8x50_INFO(pm_info)->int_core_access),
   6959                 sizeof(phymod_phy_access_t));
   6960     phy_access[0].access.lane_mask = iphy_lane_mask;
   6961     if (params->lane != -1) {
   6962         lane_count = 0;
   6963         phy_access[0].access.lane_mask = 0;
   6964         for (i = 0; i < MAX_PORTS_PER_PM8X50; ++i)
   6965         {
   6966             if (iphy_lane_mask & (1 << i))
   6967             {
   6968                 if (lane_count == params->lane)
   6969                 {
   6970                     phy_access[0].access.lane_mask = (1 << i);
   6971                     break;
   6972                 }
   6973 
   6974                 ++lane_count;
   6975             }
   6976         }
   6977         if (phy_access[0].access.lane_mask == 0) {
   6978             *nof_phys = 0;
   6979         }
   6980     }
   6981     /* only line is availabe for internal. */
   6982     phy_access[0].port_loc = phymodPortLocLine;
   6983 
   6984     if (is_bypassed) {
   6985         PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(phy_access[0].device_op_mode);
   6986     }
   6987 
   6988     if (is_most_ext) {
   6989         *is_most_ext = 1;
   6990     }
   6991 
   6992 exit:
   6993     SOC_FUNC_RETURN;
   6994 }
   6995 /*
   6996  * Get lane phymod access structure via pm id.
   6997  * This function can be used for getting phy access
   6998  * when port is not attached.
   6999  *
   7000  * If a single lane access is required, please specify the params.lane.
   7001  * Otherwise, set params.lane = -1, meaning get lane access for all the
   7002  * lanes in the given PM.
   7003  */
   7004 int pm8x50_pm_phy_lane_access_get(
   7005     int unit, int pm_id, pm_info_t pm_info,
   7006     const portmod_access_get_params_t* params,
   7007     int max_phys, phymod_phy_access_t* phy_access,
   7008     int* nof_phys, int* is_most_ext)
   7009 {
   7010     uint32  iphy_lane_mask = 0;
   7011     int port_index=0;
   7012     int i;
   7013     int port = -1;
   7014     uint32 is_bypassed = 0;
   7015 
   7016     SOC_INIT_FUNC_DEFS;
   7017 
   7018     for( i = 0 ; i < max_phys; i++) {
   7019         _SOC_IF_ERR_EXIT(phymod_phy_access_t_init(&phy_access[i]));
   7020     }
   7021 
   7022     *nof_phys = 1;
   7023 
   7024     /* internal core */
   7025     sal_memcpy (&phy_access[0], &(PM_8x50_INFO(pm_info)->int_core_access),
   7026                 sizeof(phymod_phy_access_t));
   7027 
   7028     if (params->lane != -1) {
   7029         /*
   7030          * If lane index is not -1, need to check if there is any port attched on
   7031          * the given lane. If there is active port on the lane, need to check if
   7032          * the lane is working at bypass mode.
   7033          */
   7034         _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, params->lane, &port));
   7035         if (port > 0) {
   7036             _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index,
   7037                                                     &iphy_lane_mask));
   7038             _SOC_IF_ERR_EXIT(PM8x50_PORT_IS_PCS_BYPASSED_GET(unit, pm_info, &is_bypassed, port_index));
   7039             if (is_bypassed) {
   7040                 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(phy_access[0].device_op_mode);
   7041             }
   7042         }
   7043         phy_access[0].access.lane_mask = (0x1 << (params->lane));
   7044     } else {
   7045         /*
   7046          * If lane index is -1, assume all the lanes are accessed
   7047          */
   7048         phy_access[0].access.lane_mask = (0x1 << MAX_PORTS_PER_PM8X50) - 1;
   7049     }
   7050     /* only line is availabe for internal. */
   7051     phy_access[0].port_loc = phymodPortLocLine;
   7052 
   7053     if (is_most_ext) {
   7054         *is_most_ext = 1;
   7055     }
   7056 exit:
   7057     SOC_FUNC_RETURN;
   7058 }
   7059 
   7060 /*Port duplex set\get*/
   7061 int pm8x50_port_duplex_set(int unit, int port, pm_info_t pm_info, int enable)
   7062 {
   7063     SOC_INIT_FUNC_DEFS;
   7064 
   7065     _SOC_IF_ERR_EXIT(cdmac_duplex_set(unit, port, enable));
   7066 exit:
   7067     SOC_FUNC_RETURN
   7068 }
   7069 
   7070 int pm8x50_port_duplex_get(int unit, int port, pm_info_t pm_info, int* enable)
   7071 {
   7072     SOC_INIT_FUNC_DEFS;
   7073 
   7074     _SOC_IF_ERR_EXIT(cdmac_duplex_get(unit, port, enable));
   7075 exit:
   7076     SOC_FUNC_RETURN
   7077 }
   7078 
   7079 /*Port PHY Control register read*/
   7080 int pm8x50_port_phy_reg_read(int unit, int port, pm_info_t pm_info, int lane,
   7081                              int flags, int reg_addr, uint32* value)
   7082 {
   7083     portmod_access_get_params_t params;
   7084     phymod_phy_access_t phy_access;
   7085     int nof_phys;
   7086 
   7087     SOC_INIT_FUNC_DEFS;
   7088 
   7089     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   7090     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   7091                                 &params, 1, &phy_access, &nof_phys, NULL));
   7092 
   7093     PM8X50_PHY_REG_SET(reg_addr);
   7094 
   7095     if (lane >= 0) {
   7096         reg_addr |= PHYMOD_REG_ACC_AER_IBLK_FORCE_LANE;
   7097         reg_addr &= ~(0x7 << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   7098         reg_addr |= ((lane & 0x7) << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   7099     }
   7100     _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, reg_addr, value));
   7101 
   7102 
   7103 exit:
   7104     SOC_FUNC_RETURN;
   7105 }
   7106 
   7107 /*Port PHY Control register write*/
   7108 int pm8x50_port_phy_reg_write(int unit, int port, pm_info_t pm_info,
   7109                               int lane, int flags, int reg_addr, uint32 value)
   7110 {
   7111     portmod_access_get_params_t params;
   7112     phymod_phy_access_t phy_access;
   7113     int nof_phys;
   7114 
   7115     SOC_INIT_FUNC_DEFS;
   7116 
   7117     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   7118     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   7119                                 &params, 1, &phy_access, &nof_phys, NULL));
   7120 
   7121     PM8X50_PHY_REG_SET(reg_addr);
   7122 
   7123     if (lane >= 0) {
   7124         reg_addr |= PHYMOD_REG_ACC_AER_IBLK_FORCE_LANE;
   7125         reg_addr &= ~(0x7 << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   7126         reg_addr |= ((lane & 0x7) << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   7127     }
   7128     _SOC_IF_ERR_EXIT(phymod_phy_reg_write(&phy_access, reg_addr, value));
   7129 
   7130 exit:
   7131     SOC_FUNC_RETURN;
   7132 }
   7133 
   7134 /*Port Reset set\get*/
   7135 int pm8x50_port_reset_set(int unit, int port,
   7136                           pm_info_t pm_info, int mode,
   7137                           int opcode, int value)
   7138 {
   7139     SOC_INIT_FUNC_DEFS;
   7140 
   7141     _SOC_IF_ERR_EXIT(portmod_phy_port_reset_set(unit, port, pm_info,
   7142                                                 mode, opcode, value));
   7143 exit:
   7144     SOC_FUNC_RETURN
   7145 }
   7146 int pm8x50_port_reset_get(int unit, int port,
   7147                           pm_info_t pm_info, int mode,
   7148                           int opcode, int* value)
   7149 {
   7150     SOC_INIT_FUNC_DEFS;
   7151 
   7152     _SOC_IF_ERR_EXIT(portmod_phy_port_reset_get(unit, port, pm_info,
   7153                                                 mode, opcode, value));
   7154 exit:
   7155     SOC_FUNC_RETURN
   7156 }
   7157 
   7158 /*Drv Name Get*/
   7159 int pm8x50_port_drv_name_get(int unit, int port,
   7160                              pm_info_t pm_info,
   7161                              char* name, int len)
   7162 {
   7163     strncpy(name, "PM8X50 Driver", len);
   7164     return (SOC_E_NONE);
   7165 }
   7166 
   7167 /*set/get port fec enable according to local/remote FEC ability*/
   7168 int pm8x50_port_fec_enable_set(int unit, int port, pm_info_t pm_info,
   7169                                uint32 phy_flags, uint32_t enable)
   7170 {
   7171     portmod_access_get_params_t params;
   7172     phymod_phy_access_t phy_access;
   7173     int nof_phys;
   7174 
   7175     SOC_INIT_FUNC_DEFS;
   7176 
   7177     if (phy_flags != PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   7178         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   7179                           (_SOC_MSG("Only internal phys")));
   7180     }
   7181     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   7182     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   7183                                 &params, 1, &phy_access, &nof_phys, NULL));
   7184     _SOC_IF_ERR_EXIT(phymod_phy_fec_enable_set(&phy_access, enable));
   7185 
   7186 exit:
   7187     SOC_FUNC_RETURN;
   7188 }
   7189 int pm8x50_port_fec_enable_get(int unit, int port, pm_info_t pm_info,
   7190                                uint32 phy_flags, uint32_t* enable)
   7191 {
   7192     portmod_access_get_params_t params;
   7193     phymod_phy_access_t phy_access;
   7194     int nof_phys;
   7195 
   7196     SOC_INIT_FUNC_DEFS;
   7197 
   7198     if (phy_flags != PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   7199         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   7200                           (_SOC_MSG("Only internal phys")));
   7201     }
   7202     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   7203     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   7204                                 &params, 1, &phy_access, &nof_phys, NULL));
   7205     _SOC_IF_ERR_EXIT(phymod_phy_fec_enable_get(&phy_access, enable));
   7206 
   7207 exit:
   7208     SOC_FUNC_RETURN;
   7209 }
   7210 
   7211 /*get port auto negotiation local ability*/
   7212 int pm8x50_port_ability_advert_set(int unit, int port, pm_info_t pm_info,
   7213                                    uint32 phy_flags,
   7214                                    portmod_port_ability_t* ability)
   7215 {
   7216 
   7217     return (SOC_E_NONE);
   7218 }
   7219 int pm8x50_port_ability_advert_get(int unit, int port, pm_info_t pm_info,
   7220                                    uint32 phy_flags,
   7221                                    portmod_port_ability_t* ability)
   7222 {
   7223 
   7224     return (SOC_E_NONE);
   7225 }
   7226 
   7227 /*Port ability remote Adv get*/
   7228 int pm8x50_port_ability_remote_get(int unit, int port, pm_info_t pm_info,
   7229                                    uint32 phy_flags,
   7230                                    portmod_port_ability_t* ability)
   7231 {
   7232 
   7233     return (SOC_E_NONE);
   7234 }
   7235 
   7236 /*Port Mac Control Spacing Stretch*/
   7237 int pm8x50_port_frame_spacing_stretch_set(int unit, int port,
   7238                                           pm_info_t pm_info, int spacing)
   7239 {
   7240 
   7241     return (SOC_E_NONE);
   7242 }
   7243 int pm8x50_port_frame_spacing_stretch_get(int unit, int port,
   7244                                           pm_info_t pm_info,
   7245                                           const int* spacing)
   7246 {
   7247 
   7248     return (SOC_E_NONE);
   7249 }
   7250 
   7251 /*get port timestamps in fifo*/
   7252 int pm8x50_port_diag_fifo_status_get(int unit, int port, pm_info_t pm_info,
   7253                                      const portmod_fifo_status_t* diag_info)
   7254 {
   7255 
   7256     return (SOC_E_NONE);
   7257 }
   7258 
   7259 /*set/get pass control frames.*/
   7260 int pm8x50_port_rx_control_set(int unit, int port, pm_info_t pm_info,
   7261                                const portmod_rx_control_t* rx_ctrl)
   7262 {
   7263     SOC_INIT_FUNC_DEFS;
   7264 
   7265     if (rx_ctrl->flags & PORTMOD_MAC_PASS_CONTROL_FRAME) {
   7266         _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_set(unit, port,
   7267                                                     CDMAC_RSV_MASK_CONTROL_FRAME,
   7268                                                     rx_ctrl->pass_control_frames));
   7269         _SOC_IF_ERR_EXIT(cdmac_pass_control_frame_set(unit, port, rx_ctrl->pass_control_frames));
   7270     }
   7271 
   7272     if (rx_ctrl->flags & PORTMOD_MAC_PASS_PFC_FRAME) {
   7273         _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_set(unit, port,
   7274                                                     CDMAC_RSV_MASK_PFC_FRAME,
   7275                                                     rx_ctrl->pass_pfc_frames));
   7276         _SOC_IF_ERR_EXIT(cdmac_pass_pfc_frame_set(unit, port, rx_ctrl->pass_pfc_frames));
   7277     }
   7278 
   7279     if (rx_ctrl->flags & PORTMOD_MAC_PASS_PAUSE_FRAME) {
   7280         _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_set(unit, port,
   7281                                                     CDMAC_RSV_MASK_PAUSE_FRAME,
   7282                                                     rx_ctrl->pass_pause_frames));
   7283         _SOC_IF_ERR_EXIT(cdmac_pass_pause_frame_set(unit, port, rx_ctrl->pass_pause_frames));
   7284     }
   7285 
   7286 exit:
   7287     SOC_FUNC_RETURN;
   7288 }
   7289 
   7290 int pm8x50_port_rx_control_get(int unit, int port, pm_info_t pm_info,
   7291                                portmod_rx_control_t* rx_ctrl)
   7292 {
   7293     int rx_pass_control_frames, rx_pass_pfc_frames, rx_pass_pause_frames;
   7294     uint32 rsv_pass_control_frames, rsv_pass_pfc_frames, rsv_pass_pause_frames;
   7295 
   7296     SOC_INIT_FUNC_DEFS;
   7297 
   7298     _SOC_IF_ERR_EXIT(cdmac_pass_control_frame_get(unit, port, &rx_pass_control_frames));
   7299     _SOC_IF_ERR_EXIT(cdmac_pass_pfc_frame_get(unit, port, &rx_pass_pfc_frames));
   7300     _SOC_IF_ERR_EXIT(cdmac_pass_pause_frame_get(unit, port, &rx_pass_pause_frames));
   7301     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_get(unit, port, CDMAC_RSV_MASK_CONTROL_FRAME,
   7302                                                 &rsv_pass_control_frames));
   7303     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_get(unit, port, CDMAC_RSV_MASK_PFC_FRAME,
   7304                                                 &rsv_pass_pfc_frames));
   7305     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_get(unit, port, CDMAC_RSV_MASK_PAUSE_FRAME,
   7306                                                 &rsv_pass_pause_frames));
   7307 
   7308     rx_ctrl->pass_control_frames = rx_pass_control_frames & rsv_pass_control_frames;
   7309     rx_ctrl->pass_pfc_frames = rx_pass_pfc_frames & rsv_pass_pfc_frames;
   7310     rx_ctrl->pass_pause_frames = rx_pass_pause_frames & rsv_pass_pause_frames;
   7311 exit:
   7312     SOC_FUNC_RETURN;
   7313 }
   7314 
   7315 /*set PFC config registers.*/
   7316 int pm8x50_port_pfc_config_set(int unit, int port, pm_info_t pm_info,
   7317                                const portmod_pfc_config_t* pfc_cfg)
   7318 {
   7319     SOC_INIT_FUNC_DEFS;
   7320 
   7321     if (pfc_cfg->classes != 8) {
   7322         return SOC_E_PARAM;
   7323     }
   7324     _SOC_IF_ERR_EXIT(cdmac_pfc_config_set(unit, port, pfc_cfg));
   7325     /* set the pfc frame control in cdmac rsv */
   7326     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_set(unit, port,
   7327                                                 CDMAC_RSV_MASK_PFC_FRAME,
   7328                                                 pfc_cfg->rxpass));
   7329 exit:
   7330     SOC_FUNC_RETURN;
   7331 }
   7332 
   7333 int pm8x50_port_pfc_config_get(int unit, int port, pm_info_t pm_info,
   7334                                portmod_pfc_config_t* pfc_cfg)
   7335 {
   7336     SOC_INIT_FUNC_DEFS;
   7337 
   7338     pfc_cfg->classes = 8;
   7339     _SOC_IF_ERR_EXIT(cdmac_pfc_config_get(unit, port, pfc_cfg));
   7340     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_control_get(unit, port,
   7341                                                 CDMAC_RSV_MASK_PFC_FRAME,
   7342                                                 &pfc_cfg->rxpass));
   7343 exit:
   7344     SOC_FUNC_RETURN;
   7345 }
   7346 
   7347 /*set EEE Config.*/
   7348 int pm8x50_port_eee_set(int unit, int port, pm_info_t pm_info,
   7349                         const portmod_eee_t* eee)
   7350 {
   7351 
   7352     return (SOC_E_UNAVAIL);
   7353 }
   7354 int pm8x50_port_eee_get(int unit, int port, pm_info_t pm_info,
   7355                         portmod_eee_t* eee)
   7356 {
   7357 
   7358     return (SOC_E_UNAVAIL);
   7359 }
   7360 
   7361 /*set EEE Config.*/
   7362 int pm8x50_port_eee_clock_set(int unit, int port, pm_info_t pm_info,
   7363                               const portmod_eee_clock_t* eee_clk)
   7364 {
   7365 
   7366     return (SOC_E_NONE);
   7367 }
   7368 int pm8x50_port_eee_clock_get(int unit, int port, pm_info_t pm_info,
   7369                               portmod_eee_clock_t* eee_clk)
   7370 {
   7371 
   7372     return (SOC_E_NONE);
   7373 }
   7374 
   7375 /*set Vlan Inner/Outer tag.*/
   7376 int pm8x50_port_vlan_tag_set(int unit, int port, pm_info_t pm_info,
   7377                              const portmod_vlan_tag_t* vlan_tag)
   7378 {
   7379     SOC_INIT_FUNC_DEFS;
   7380     SOC_NULL_CHECK(pm_info);
   7381 
   7382     _SOC_IF_ERR_EXIT(cdmac_rx_vlan_tag_set (unit, port,
   7383                                             vlan_tag->outer_vlan_tag,
   7384                                             vlan_tag->inner_vlan_tag));
   7385 exit:
   7386     SOC_FUNC_RETURN;
   7387 }
   7388 int pm8x50_port_vlan_tag_get(int unit, int port, pm_info_t pm_info,
   7389                              portmod_vlan_tag_t* vlan_tag)
   7390 {
   7391     SOC_INIT_FUNC_DEFS;
   7392     SOC_NULL_CHECK(pm_info);
   7393 
   7394     _SOC_IF_ERR_EXIT(cdmac_rx_vlan_tag_get (unit, port,
   7395                                    (int*)&vlan_tag->outer_vlan_tag,
   7396                                    (int*)&vlan_tag->inner_vlan_tag));
   7397 exit:
   7398     SOC_FUNC_RETURN;
   7399 }
   7400 
   7401 /*set modid field.*/
   7402 int pm8x50_port_modid_set(int unit, int port, pm_info_t pm_info, int value)
   7403 {
   7404 
   7405     return (SOC_E_NONE);
   7406 }
   7407 
   7408 /*set modid field.*/
   7409 int pm8x50_port_led_chain_config(int unit, int port, pm_info_t pm_info,
   7410                                  int value)
   7411 {
   7412 
   7413     return (SOC_E_NONE);
   7414 }
   7415 
   7416 /*set modid field.*/
   7417 int pm8x50_port_clear_rx_lss_status_set(int unit, int port, pm_info_t pm_info,
   7418                                         int lcl_fault, int rmt_fault)
   7419 {
   7420 
   7421     return (SOC_E_NONE);
   7422 }
   7423 int pm8x50_port_clear_rx_lss_status_get(int unit, int port, pm_info_t pm_info,
   7424                                         int* lcl_fault, int* rmt_fault)
   7425 {
   7426 
   7427     return (SOC_E_NONE);
   7428 }
   7429 
   7430 /*Attaches an external phy lane to a specific port macro*/
   7431 int pm8x50_xphy_lane_attach_to_pm(int unit,
   7432                          pm_info_t pm_info, int iphy, int phyn,
   7433                          const portmod_xphy_lane_connection_t* lane_connection)
   7434 {
   7435 
   7436     return (SOC_E_NONE);
   7437 }
   7438 
   7439 /*Attaches an external phy lane to a specific port macro*/
   7440 int pm8x50_xphy_lane_detach_from_pm(int unit,
   7441                                pm_info_t pm_info, int iphy, int phyn,
   7442                                portmod_xphy_lane_connection_t* lane_connection)
   7443 {
   7444 
   7445     return (SOC_E_NONE);
   7446 }
   7447 
   7448 int pm8x50_port_mac_link_get(int unit, int port, pm_info_t pm_info, int* link)
   7449 {
   7450     uint32 reg_val, bitmap;
   7451     int port_index, phy_acc;
   7452     SOC_INIT_FUNC_DEFS;
   7453     SOC_NULL_CHECK(pm_info);
   7454 
   7455     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   7456     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   7457 
   7458     switch(port_index) {
   7459         case 0:
   7460             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN0_STATUS_REGr(unit, phy_acc, &reg_val));
   7461             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN0_STATUS_REGr, reg_val, LINK_STATUSf);
   7462             break;
   7463 
   7464         case 1:
   7465             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN1_STATUS_REGr(unit, phy_acc, &reg_val));
   7466             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN1_STATUS_REGr, reg_val, LINK_STATUSf);
   7467             break;
   7468 
   7469         case 2:
   7470             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN2_STATUS_REGr(unit, phy_acc, &reg_val));
   7471             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN2_STATUS_REGr, reg_val, LINK_STATUSf);
   7472             break;
   7473 
   7474         case 3:
   7475             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN3_STATUS_REGr(unit, phy_acc, &reg_val));
   7476             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN3_STATUS_REGr, reg_val, LINK_STATUSf);
   7477             break;
   7478 
   7479         case 4:
   7480             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN4_STATUS_REGr(unit, phy_acc, &reg_val));
   7481             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN4_STATUS_REGr, reg_val, LINK_STATUSf);
   7482             break;
   7483 
   7484         case 5:
   7485             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN5_STATUS_REGr(unit, phy_acc, &reg_val));
   7486             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN5_STATUS_REGr, reg_val, LINK_STATUSf);
   7487             break;
   7488 
   7489         case 6:
   7490             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN6_STATUS_REGr(unit, phy_acc, &reg_val));
   7491             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN6_STATUS_REGr, reg_val, LINK_STATUSf);
   7492             break;
   7493 
   7494         case 7:
   7495             _SOC_IF_ERR_EXIT(READ_CDPORT_XGXS0_LN7_STATUS_REGr(unit, phy_acc, &reg_val));
   7496             (*link) = soc_reg_field_get(unit, CDPORT_XGXS0_LN7_STATUS_REGr, reg_val, LINK_STATUSf);
   7497             break;
   7498 
   7499         default:
   7500             _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL,
   7501                      (_SOC_MSG("Port %d, failed to get port index"), port));
   7502     }
   7503 
   7504 exit:
   7505     SOC_FUNC_RETURN;
   7506 }
   7507 
   7508 /*Toggle Lag Failover Status.*/
   7509 int pm8x50_port_lag_failover_status_toggle(int unit, int port,
   7510                                            pm_info_t pm_info)
   7511 {
   7512     int phy_acc;
   7513     uint32_t rval;
   7514     int link = 0;
   7515     soc_timeout_t to;
   7516 
   7517     SOC_INIT_FUNC_DEFS;
   7518 
   7519     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   7520 
   7521     /* Link status to IPIPE is updated by H/W and driven based on both the
   7522      * rising edge of CDPORT_LAG_FAILOVER_CONFIG.LINK_STATUS_UP and
   7523      * actual link up status from Serdes.
   7524      * In some loopback scenarios it may take longer time to see Serdes link up status.
   7525      */
   7526     soc_timeout_init(&to, 10000, 0);
   7527 
   7528     do {
   7529         _SOC_IF_ERR_EXIT(pm8x50_port_mac_link_get(unit, port, pm_info, &link));
   7530         if (link) {
   7531             break;
   7532         }
   7533     } while(!soc_timeout_check(&to));
   7534 
   7535     /* Toggle link_status_up bit to notify IPIPE on link up */
   7536     _SOC_IF_ERR_EXIT(READ_CDPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, &rval));
   7537     soc_reg_field_set(unit, CDPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 1);
   7538     _SOC_IF_ERR_EXIT(WRITE_CDPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval));
   7539     soc_reg_field_set(unit, CDPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 0);
   7540     _SOC_IF_ERR_EXIT(WRITE_CDPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval));
   7541 
   7542 exit:
   7543     SOC_FUNC_RETURN;
   7544 }
   7545 
   7546 /*Toggle Lag Failover loopback set / get.*/
   7547 int pm8x50_port_lag_failover_loopback_set(int unit, int port,
   7548                                           pm_info_t pm_info,
   7549                                           int value)
   7550 {
   7551     SOC_INIT_FUNC_DEFS;
   7552     SOC_NULL_CHECK(pm_info);
   7553 
   7554     _SOC_IF_ERR_EXIT(cdmac_lag_failover_loopback_set(unit, port, value));
   7555 exit:
   7556     SOC_FUNC_RETURN;
   7557 }
   7558 int pm8x50_port_lag_failover_loopback_get(int unit, int port,
   7559                                           pm_info_t pm_info,
   7560                                           int* value)
   7561 {
   7562     SOC_INIT_FUNC_DEFS;
   7563     SOC_NULL_CHECK(pm_info);
   7564 
   7565     _SOC_IF_ERR_EXIT(cdmac_lag_failover_loopback_get(unit, port, value));
   7566 exit:
   7567     SOC_FUNC_RETURN;
   7568 }
   7569 
   7570 /*set modid field.*/
   7571 int pm8x50_port_mode_set(int unit, int port, pm_info_t pm_info,
   7572                          const portmod_port_mode_info_t* mode)
   7573 {
   7574 
   7575     return (SOC_E_NONE);
   7576 }
   7577 
   7578 STATIC
   7579 int _cdport_mode_get(int unit, int port, pm_info_t pm_info,
   7580                      int first_phy_index, portmod_port_mode_info_t *p_mode)
   7581 {
   7582     uint32 reg_val = 0, port_mode = 0;
   7583     int phy_acc, mac_id = 0, this_phy_index;
   7584 
   7585     SOC_INIT_FUNC_DEFS;
   7586 
   7587     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   7588 
   7589     _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, &reg_val));
   7590     port_mode = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, SINGLE_PORT_MODE_SPEED_400Gf);
   7591     if (port_mode){
   7592         p_mode->cur_mode = portmodPortModeSingle;
   7593         p_mode->lanes = 8;
   7594         p_mode->port_index = 0;
   7595     } else {
   7596         mac_id = first_phy_index / CDMAC_NUM_LANES;
   7597         this_phy_index = first_phy_index % CDMAC_NUM_LANES;
   7598         if (mac_id) {
   7599             /* CDMAC_1 Port Mode */
   7600             port_mode = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, MAC1_PORT_MODEf);
   7601         } else {
   7602             /* CDMAC_0 Port Mode*/
   7603             port_mode = soc_reg_field_get(unit, CDPORT_MODE_REGr, reg_val, MAC0_PORT_MODEf);
   7604         }
   7605         switch (port_mode) {
   7606             case 0:
   7607                 p_mode->cur_mode = portmodPortModeQuad;
   7608                 p_mode->lanes = 1;
   7609                 p_mode->port_index = this_phy_index;
   7610                 break;
   7611             case 1:
   7612                 p_mode->cur_mode = portmodPortModeTri012;
   7613                 if ((this_phy_index == 0)||(this_phy_index == 1)) {
   7614                     p_mode->lanes = 1;
   7615                 } else {
   7616                     p_mode->lanes = 2;
   7617                 }
   7618                 p_mode->port_index = this_phy_index;
   7619                 break;
   7620             case 2:
   7621                 p_mode->cur_mode = portmodPortModeTri023;
   7622                 if ((this_phy_index == 2)||(this_phy_index == 3)) {
   7623                     p_mode->lanes = 1;
   7624                 } else {
   7625                     p_mode->lanes = 2;
   7626                 }
   7627                 p_mode->port_index = this_phy_index;
   7628                 break;
   7629             case 3:
   7630                 p_mode->cur_mode = portmodPortModeDual;
   7631                 p_mode->lanes = 2;
   7632                 p_mode->port_index = this_phy_index;
   7633                 break;
   7634             case 4:
   7635                 p_mode->cur_mode = portmodPortModeSingle;
   7636                 p_mode->lanes = 4;
   7637                 p_mode->port_index = this_phy_index;
   7638                 break;
   7639             default:
   7640                 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid port mode")));
   7641                 break;
   7642         }
   7643     }
   7644 
   7645 exit:
   7646     SOC_FUNC_RETURN;
   7647 
   7648 }
   7649 
   7650 int pm8x50_port_mode_get(int unit, int port, pm_info_t pm_info,
   7651                          portmod_port_mode_info_t* mode)
   7652 {
   7653     int port_index;
   7654     uint32_t bitmap;
   7655 
   7656     SOC_INIT_FUNC_DEFS;
   7657 
   7658      _SOC_IF_ERR_EXIT(_pm8x50_port_index_get (unit, port, pm_info, &port_index, &bitmap));
   7659      _SOC_IF_ERR_EXIT(_cdport_mode_get(unit, port, pm_info, port_index, mode));
   7660 
   7661 exit:
   7662     SOC_FUNC_RETURN;
   7663 }
   7664 
   7665 /*set port encap.*/
   7666 int pm8x50_port_encap_set(int unit, int port, pm_info_t pm_info,
   7667                           int flags, portmod_encap_t encap)
   7668 {
   7669     SOC_INIT_FUNC_DEFS;
   7670     SOC_NULL_CHECK(pm_info);
   7671 
   7672     _SOC_IF_ERR_EXIT(cdmac_encap_set(unit, port, flags, encap));
   7673 exit:
   7674     SOC_FUNC_RETURN;
   7675 }
   7676 int pm8x50_port_encap_get(int unit, int port, pm_info_t pm_info,
   7677                           int* flags, portmod_encap_t* encap)
   7678 {
   7679     SOC_INIT_FUNC_DEFS;
   7680     SOC_NULL_CHECK(pm_info);
   7681 
   7682     _SOC_IF_ERR_EXIT(cdmac_encap_get(unit, port, flags, encap));
   7683 exit:
   7684     SOC_FUNC_RETURN;
   7685 }
   7686 
   7687 /*set port register higig field.*/
   7688 int pm8x50_port_higig_mode_set(int unit, int port,
   7689                                pm_info_t pm_info,
   7690                                int mode)
   7691 {
   7692 
   7693     return (SOC_E_NONE);
   7694 }
   7695 int pm8x50_port_higig_mode_get(int unit, int port,
   7696                                pm_info_t pm_info,
   7697                                int* mode)
   7698 {
   7699 
   7700     return (SOC_E_NONE);
   7701 }
   7702 
   7703 /*set port register higig field.*/
   7704 int pm8x50_port_higig2_mode_set(int unit, int port,
   7705                                 pm_info_t pm_info,
   7706                                 int mode)
   7707 {
   7708 
   7709     return (SOC_E_NONE);
   7710 }
   7711 int pm8x50_port_higig2_mode_get(int unit, int port,
   7712                                 pm_info_t pm_info,
   7713                                 int* mode)
   7714 {
   7715 
   7716     return (SOC_E_NONE);
   7717 }
   7718 
   7719 /*set port register port type field.*/
   7720 int pm8x50_port_config_port_type_set(int unit, int port,
   7721                                      pm_info_t pm_info,
   7722                                      int type)
   7723 {
   7724 
   7725     return (SOC_E_NONE);
   7726 }
   7727 int pm8x50_port_config_port_type_get(int unit, int port,
   7728                                      pm_info_t pm_info,
   7729                                      int* type)
   7730 {
   7731 
   7732     return (SOC_E_NONE);
   7733 }
   7734 
   7735 /*set/get hwfailover for trident.*/
   7736 int pm8x50_port_trunk_hwfailover_config_set(int unit, int port,
   7737                                             pm_info_t pm_info,
   7738                                             int hw_count)
   7739 {
   7740     int old_failover_en=0, new_failover_en = 0;
   7741     int old_link_status_sel=0, new_link_status_sel=0;
   7742     int old_reset_flow_control=0, new_reset_flow_control = 0;
   7743     int lag_failover_lpbk;
   7744     SOC_INIT_FUNC_DEFS;
   7745 
   7746     if (hw_count) {
   7747         new_failover_en        = 1;
   7748         new_link_status_sel    = 1;
   7749         new_reset_flow_control = 1;
   7750     }
   7751 
   7752     _SOC_IF_ERR_EXIT(cdmac_lag_failover_loopback_get(unit, port,
   7753                                                      &lag_failover_lpbk));
   7754 
   7755     if (lag_failover_lpbk) {
   7756         return (SOC_E_NONE);
   7757     }
   7758 
   7759     _SOC_IF_ERR_EXIT(cdmac_lag_failover_en_get(unit, port,
   7760                                                &old_failover_en));
   7761     _SOC_IF_ERR_EXIT(cdmac_sw_link_status_select_get(unit, port,
   7762                                                  &old_link_status_sel));
   7763 
   7764     if (old_failover_en     != new_failover_en ||
   7765         old_link_status_sel != new_link_status_sel) {
   7766 
   7767         _SOC_IF_ERR_EXIT(cdmac_sw_link_status_select_set(unit, port,
   7768                                                     new_link_status_sel));
   7769         _SOC_IF_ERR_EXIT(cdmac_lag_failover_en_set(unit, port,
   7770                                                    new_failover_en));
   7771     }
   7772 
   7773     _SOC_IF_ERR_EXIT(cdmac_reset_fc_timers_on_link_dn_get(unit,
   7774                                        port, &old_reset_flow_control));
   7775     if (old_reset_flow_control != new_reset_flow_control) {
   7776         _SOC_IF_ERR_EXIT(cdmac_reset_fc_timers_on_link_dn_set(unit,
   7777                                         port, new_reset_flow_control));
   7778     }
   7779 
   7780 exit:
   7781     SOC_FUNC_RETURN;
   7782 }
   7783 int pm8x50_port_trunk_hwfailover_config_get(int unit, int port,
   7784                                             pm_info_t pm_info,
   7785                                             int* enable)
   7786 {
   7787     SOC_INIT_FUNC_DEFS;
   7788 
   7789     _SOC_IF_ERR_EXIT(cdmac_lag_failover_en_get(unit, port, enable));
   7790 exit:
   7791     SOC_FUNC_RETURN;
   7792 }
   7793 
   7794 /*set/get hwfailover for trident.*/
   7795 int pm8x50_port_trunk_hwfailover_status_get(int unit, int port,
   7796                                             pm_info_t pm_info,
   7797                                             int* loopback)
   7798 {
   7799     SOC_INIT_FUNC_DEFS;
   7800 
   7801     _SOC_IF_ERR_EXIT(cdmac_lag_failover_loopback_get(unit, port,
   7802                                                      loopback));
   7803 exit:
   7804     SOC_FUNC_RETURN;
   7805 }
   7806 
   7807 /*set/get hwfailover for trident.*/
   7808 int pm8x50_port_diag_ctrl(int unit, int port, pm_info_t pm_info,
   7809                           uint32 inst, int op_type, int op_cmd,
   7810                           const void* arg)
   7811 {
   7812     phymod_phy_access_t phy_access[1+MAX_PHYN];
   7813     portmod_access_get_params_t params;
   7814     int nof_phys = 0;
   7815 
   7816     SOC_INIT_FUNC_DEFS;
   7817     /* Only internal phy supported. */
   7818     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   7819     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   7820                                       &params, 1, phy_access, &nof_phys, NULL));
   7821 
   7822     _SOC_IF_ERR_EXIT(portmod_phy_port_diag_ctrl(unit, port, phy_access, nof_phys, inst, op_type, op_cmd, arg));
   7823 
   7824 exit:
   7825     SOC_FUNC_RETURN;
   7826 
   7827 }
   7828 
   7829 /*Get/Set InterFrameGap Setting. */
   7830 int pm8x50_port_ifg_set(int unit, int port, pm_info_t pm_info, int speed,
   7831                         soc_port_duplex_t duplex, int ifg, int* real_ifg)
   7832 {
   7833 
   7834     return (SOC_E_NONE);
   7835 }
   7836 int pm8x50_port_ifg_get(int unit, int port, pm_info_t pm_info, int speed,
   7837                         soc_port_duplex_t duplex, int* ifg)
   7838 {
   7839 
   7840     return (SOC_E_NONE);
   7841 }
   7842 
   7843 /*Get the reference clock value 156 or 125.*/
   7844 int pm8x50_port_ref_clk_get(int unit, int port,
   7845                             pm_info_t pm_info,
   7846                             int* ref_clk)
   7847 {
   7848     *ref_clk = pm_info->pm_data.pm8x50_db->ref_clk;
   7849 
   7850     return (SOC_E_NONE);
   7851 }
   7852 
   7853 /*Disable lag failover.*/
   7854 int pm8x50_port_lag_failover_disable(int unit, int port, pm_info_t pm_info)
   7855 {
   7856     SOC_INIT_FUNC_DEFS;
   7857 
   7858     _SOC_IF_ERR_EXIT(cdmac_lag_failover_disable(unit, port));
   7859 
   7860 exit:
   7861     SOC_FUNC_RETURN;
   7862 }
   7863 
   7864 /*Disable lag failover.*/
   7865 int pm8x50_port_lag_remove_failover_lpbk_set(int unit, int port,
   7866                                              pm_info_t pm_info, int val)
   7867 {
   7868    SOC_INIT_FUNC_DEFS;
   7869 
   7870     _SOC_IF_ERR_EXIT(cdmac_lag_remove_failover_lpbk_set(unit, port, val));
   7871 
   7872 exit:
   7873     SOC_FUNC_RETURN;
   7874 }
   7875 int pm8x50_port_lag_remove_failover_lpbk_get(int unit, int port,
   7876                                              pm_info_t pm_info, int* val)
   7877 {
   7878     SOC_INIT_FUNC_DEFS;
   7879 
   7880     _SOC_IF_ERR_EXIT(cdmac_lag_remove_failover_lpbk_get(unit, port, val));
   7881 
   7882 exit:
   7883     SOC_FUNC_RETURN;
   7884 }
   7885 
   7886 int pm8x50_port_cntmaxsize_set(int unit, int port, pm_info_t pm_info, int val)
   7887 {
   7888     return (cdmac_cntmaxsize_set(unit, port, val));
   7889 }
   7890 
   7891 int pm8x50_port_cntmaxsize_get(int unit, int port, pm_info_t pm_info, int* val)
   7892 {
   7893     return (cdmac_cntmaxsize_get(unit, port, val));
   7894 }
   7895 
   7896 /*Get Info needed to restore after drain cells.*/
   7897 int pm8x50_port_drain_cell_get(int unit, int port, pm_info_t pm_info,
   7898                                portmod_drain_cells_t* drain_cells)
   7899 {
   7900     SOC_INIT_FUNC_DEFS;
   7901 
   7902     _SOC_IF_ERR_EXIT(cdmac_drain_cell_get(unit, port, drain_cells));
   7903 
   7904 exit:
   7905     SOC_FUNC_RETURN;
   7906 }
   7907 
   7908 /*Restore informaation after drain cells.*/
   7909 int pm8x50_port_drain_cell_stop(int unit, int port, pm_info_t pm_info,
   7910                                 const portmod_drain_cells_t* drain_cells)
   7911 {
   7912     SOC_INIT_FUNC_DEFS;
   7913 
   7914     _SOC_IF_ERR_EXIT(cdmac_drain_cell_stop(unit, port, drain_cells));
   7915 
   7916 exit:
   7917     SOC_FUNC_RETURN;
   7918 }
   7919 
   7920 /*Restore informaation after drain cells.*/
   7921 int pm8x50_port_drain_cell_start(int unit, int port, pm_info_t pm_info)
   7922 {
   7923     SOC_INIT_FUNC_DEFS;
   7924 
   7925     _SOC_IF_ERR_EXIT(cdmac_drain_cell_start(unit, port));
   7926 
   7927 exit:
   7928     SOC_FUNC_RETURN;
   7929 }
   7930 
   7931 /**/
   7932 int pm8x50_port_drain_cells_rx_enable(int unit, int port,
   7933                                       pm_info_t pm_info,
   7934                                       int rx_en)
   7935 {
   7936     SOC_INIT_FUNC_DEFS;
   7937 
   7938     _SOC_IF_ERR_EXIT(cdmac_drain_cells_rx_enable(unit, port, rx_en));
   7939 
   7940 exit:
   7941     SOC_FUNC_RETURN;
   7942 }
   7943 
   7944 /**/
   7945 int pm8x50_port_egress_queue_drain_rx_en(int unit, int port,
   7946                                          pm_info_t pm_info,
   7947                                          int rx_en)
   7948 {
   7949     SOC_INIT_FUNC_DEFS;
   7950 
   7951     _SOC_IF_ERR_EXIT(cdmac_egress_queue_drain_rx_en(unit, port, rx_en));
   7952 
   7953 exit:
   7954     SOC_FUNC_RETURN;
   7955 }
   7956 
   7957 /**/
   7958 int pm8x50_port_mac_ctrl_set(int unit, int port,
   7959                              pm_info_t pm_info,
   7960                              uint64 ctrl)
   7961 {
   7962     SOC_INIT_FUNC_DEFS;
   7963 
   7964     _SOC_IF_ERR_EXIT(cdmac_mac_ctrl_set(unit, port, ctrl));
   7965 
   7966 exit:
   7967     SOC_FUNC_RETURN;
   7968 }
   7969 
   7970 /**/
   7971 int pm8x50_port_txfifo_cell_cnt_get(int unit, int port,
   7972                                     pm_info_t pm_info,
   7973                                     uint32* cnt)
   7974 {
   7975     SOC_INIT_FUNC_DEFS;
   7976 
   7977     _SOC_IF_ERR_EXIT(cdmac_txfifo_cell_cnt_get(unit, port, cnt));
   7978 
   7979 exit:
   7980     SOC_FUNC_RETURN;
   7981 }
   7982 
   7983 /**/
   7984 int pm8x50_port_egress_queue_drain_get(int unit, int port,
   7985                                        pm_info_t pm_info,
   7986                                        uint64* ctrl, int* rxen)
   7987 {
   7988     SOC_INIT_FUNC_DEFS;
   7989 
   7990     _SOC_IF_ERR_EXIT(cdmac_egress_queue_drain_get(unit, port, ctrl, rxen));
   7991 
   7992 exit:
   7993     SOC_FUNC_RETURN;
   7994 }
   7995 
   7996 /**/
   7997 int pm8x50_port_mac_reset_set(int unit, int port, pm_info_t pm_info, int val)
   7998 {
   7999     SOC_INIT_FUNC_DEFS;
   8000 
   8001     _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, val));
   8002 
   8003 exit:
   8004     SOC_FUNC_RETURN;
   8005 }
   8006 
   8007 int pm8x50_port_mac_reset_get(int unit, int port, pm_info_t pm_info, int* val)
   8008 {
   8009     SOC_INIT_FUNC_DEFS;
   8010 
   8011     _SOC_IF_ERR_EXIT(cdmac_soft_reset_get(unit, port, val));
   8012 
   8013     exit:
   8014         SOC_FUNC_RETURN;
   8015 }
   8016 
   8017 /**/
   8018 int pm8x50_port_soft_reset_toggle(int unit, int port, pm_info_t pm_info, int idx)
   8019 {
   8020 
   8021     return (SOC_E_NONE);
   8022 }
   8023 
   8024 /*Check if MAC needs to be reset.*/
   8025 int pm8x50_port_mac_reset_check(int unit, int port,
   8026                                 pm_info_t pm_info,
   8027                                 int enable, int* reset)
   8028 {
   8029     return (cdmac_reset_check(unit, port, enable, reset));
   8030 }
   8031 
   8032 /**/
   8033 int pm8x50_port_core_num_get(int unit, int port,
   8034                              pm_info_t pm_info,
   8035                              int* core_num)
   8036 {
   8037     *core_num = PM_8x50_INFO(pm_info)->core_num;
   8038     return (SOC_E_NONE);
   8039 }
   8040 
   8041 /**/
   8042 int pm8x50_port_e2ecc_hdr_set(int unit, int port, pm_info_t pm_info,
   8043                               const portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr)
   8044 {
   8045 
   8046     return (SOC_E_NONE);
   8047 }
   8048 int pm8x50_port_e2ecc_hdr_get(int unit, int port, pm_info_t pm_info,
   8049                               portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr)
   8050 {
   8051 
   8052     return (SOC_E_NONE);
   8053 }
   8054 
   8055 /**/
   8056 int pm8x50_port_e2e_enable_set(int unit, int port,
   8057                                pm_info_t pm_info,
   8058                                int enable)
   8059 {
   8060 
   8061     return (SOC_E_NONE);
   8062 }
   8063 int pm8x50_port_e2e_enable_get(int unit, int port,
   8064                                pm_info_t pm_info,
   8065                                int* enable)
   8066 {
   8067 
   8068     return (SOC_E_NONE);
   8069 }
   8070 
   8071 /*get the speed for the specified port*/
   8072 int pm8x50_port_speed_get(int unit, int port, pm_info_t pm_info, int* speed)
   8073 {
   8074     phymod_phy_speed_config_t speed_config;
   8075     phymod_phy_access_t phy_access;
   8076     portmod_access_get_params_t params;
   8077     int nof_phys;
   8078 
   8079     SOC_INIT_FUNC_DEFS;
   8080 
   8081     *speed = 0;
   8082 
   8083     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8084     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8085                                 &params, 1, &phy_access, &nof_phys, NULL));
   8086 
   8087     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8088                    &params, 1, &phy_access, &nof_phys, NULL));
   8089     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_t_init(&speed_config));
   8090     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_get(&phy_access, &speed_config));
   8091 
   8092     *speed = speed_config.data_rate;
   8093 exit:
   8094     SOC_FUNC_RETURN;
   8095 }
   8096 
   8097 /*TSC refere clock input and output set/get*/
   8098 int pm8x50_port_tsc_refclock_set(int unit, int port,
   8099                                  pm_info_t pm_info,
   8100                                  int ref_in, int ref_out)
   8101 {
   8102 
   8103     return (SOC_E_NONE);
   8104 }
   8105 int pm8x50_port_tsc_refclock_get(int unit, int port,
   8106                                  pm_info_t pm_info,
   8107                                  int* ref_in, int* ref_out)
   8108 {
   8109 
   8110     return (SOC_E_NONE);
   8111 }
   8112 
   8113 /*Port discard set*/
   8114 int pm8x50_port_discard_set(int unit, int port, pm_info_t pm_info, int discard)
   8115 {
   8116     SOC_INIT_FUNC_DEFS;
   8117 
   8118     _SOC_IF_ERR_EXIT(cdmac_discard_set(unit, port, discard));
   8119 
   8120 exit:
   8121     SOC_FUNC_RETURN;
   8122 }
   8123 
   8124 /*Port soft reset set set*/
   8125 int pm8x50_port_soft_reset_set(int unit, int port, pm_info_t pm_info,
   8126                                int idx, int val, int flags)
   8127 {
   8128 
   8129     return (SOC_E_NONE);
   8130 }
   8131 
   8132 /*Port tx_en=0 and softreset mac*/
   8133 int pm8x50_port_tx_down(int unit, int port, pm_info_t pm_info)
   8134 {
   8135     SOC_INIT_FUNC_DEFS;
   8136 
   8137     _SOC_IF_ERR_EXIT(cdmac_tx_enable_set(unit, port, 0));
   8138     _SOC_IF_ERR_EXIT(cdmac_discard_set(unit, port, 0));
   8139     _SOC_IF_ERR_EXIT(cdmac_soft_reset_set(unit, port, 1));
   8140 
   8141 exit:
   8142     SOC_FUNC_RETURN;
   8143 }
   8144 
   8145 /*reconfig pgw.*/
   8146 int pm8x50_port_pgw_reconfig(int unit, int port, pm_info_t pm_info,
   8147                              const portmod_port_mode_info_t* pmode,
   8148                              int phy_port, int flags)
   8149 {
   8150 
   8151     return (SOC_E_NONE);
   8152 }
   8153 
   8154 /*Routine to notify internal phy of external phy link state.*/
   8155 int pm8x50_port_notify(int unit, int port, pm_info_t pm_info, int link)
   8156 {
   8157 
   8158     return (SOC_E_NONE);
   8159 }
   8160 
   8161 /*port control phy timesync config set/get*/
   8162 int pm8x50_port_control_phy_timesync_set(int unit,
   8163                                          int port, pm_info_t pm_info,
   8164                                          portmod_port_control_phy_timesync_t config,
   8165                                          uint64 value)
   8166 {
   8167     portmod_access_get_params_t params;
   8168     phymod_phy_access_t phy_access;
   8169     int nof_phys;
   8170     uint32_t flags = 0;
   8171 
   8172     SOC_INIT_FUNC_DEFS;
   8173 
   8174     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8175     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8176                                 &params, 1, &phy_access, &nof_phys, NULL));
   8177 
   8178     if (config == SOC_PORT_CONTROL_PHY_TIMESYNC_TIMESTAMP_ADJUST) {
   8179         PHYMOD_TIMESYNC_ENABLE_F_RX_SET(flags);
   8180         _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 0));
   8181 
   8182     }
   8183     _SOC_IF_ERR_EXIT(portmod_common_control_phy_timesync_set(&phy_access, config, value));
   8184 
   8185     if (config == SOC_PORT_CONTROL_PHY_TIMESYNC_TIMESTAMP_ADJUST) {
   8186         _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 1));
   8187         /* Wait for one AM spacing time */
   8188         sal_usleep(500);
   8189     }
   8190 exit:
   8191     SOC_FUNC_RETURN;
   8192 }
   8193 
   8194 int pm8x50_port_control_phy_timesync_get(int unit,
   8195                                          int port, pm_info_t pm_info,
   8196                                          portmod_port_control_phy_timesync_t config,
   8197                                          uint64* value)
   8198 {
   8199     portmod_access_get_params_t params;
   8200     phymod_phy_access_t phy_access;
   8201     int nof_phys;
   8202 
   8203     SOC_INIT_FUNC_DEFS;
   8204 
   8205     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8206     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8207                                 &params, 1, &phy_access, &nof_phys, NULL));
   8208 
   8209     _SOC_IF_ERR_EXIT(portmod_common_control_phy_timesync_get(&phy_access, config, value));
   8210 
   8211 exit:
   8212     SOC_FUNC_RETURN;
   8213 }
   8214 
   8215 /*"port timesync config set/get"*/
   8216 int pm8x50_port_timesync_config_set(int unit, int port, pm_info_t pm_info,
   8217                               const portmod_phy_timesync_config_t* config)
   8218 {
   8219     int port_index, ts_enable_port_count;
   8220     uint32 bitmap, one_step_req, is_one_step = 0, flags = 0;
   8221     portmod_access_get_params_t params;
   8222     phymod_phy_access_t phy_access;
   8223     int nof_phys, enable, is_enable;
   8224     SOC_INIT_FUNC_DEFS;
   8225 
   8226     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   8227     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8228     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8229                                 &params, 1, &phy_access, &nof_phys, NULL));
   8230 
   8231     enable = (config->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) ? 1 : 0;
   8232 
   8233     _SOC_IF_ERR_EXIT(PM8x50_TIMESYNC_ENABLE_GET(unit, pm_info, &is_enable, port_index));
   8234     _SOC_IF_ERR_EXIT(PM8x50_TS_ENABLE_PORT_COUNT_GET(unit, pm_info, &ts_enable_port_count));
   8235 
   8236     if (!enable) {
   8237         /* Disable 1588 */
   8238         if (is_enable) {
   8239             /* If 1588 is currently enabled on the port */
   8240             /* 1. Disable One Stpe pipeline if it is enabled. */
   8241             PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags);
   8242             _SOC_IF_ERR_EXIT(phymod_timesync_enable_get(&phy_access, flags, &is_one_step));
   8243             if (!is_one_step) {
   8244                 flags = 0;
   8245             }
   8246 
   8247             /* 2. Disable RX timestamp. */
   8248             PHYMOD_TIMESYNC_ENABLE_F_RX_SET(flags);
   8249 
   8250             ts_enable_port_count--;
   8251             /* 3. Disable FCLK if no port will using 1588 on the PM. */
   8252             if (ts_enable_port_count == 0) {
   8253                 PHYMOD_TIMESYNC_ENABLE_F_CORE_SET(flags);
   8254             }
   8255 
   8256             _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 0));
   8257         }
   8258     } else {
   8259         /* Enable 1588 */
   8260         if (is_enable) {
   8261             /* Clear current 1588 configs if the port has 1588 enabled */
   8262             PHYMOD_TIMESYNC_ENABLE_F_RX_SET(flags);
   8263             PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags);
   8264             _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 0));
   8265             flags = 0;
   8266         } else {
   8267             /* 1588 is not enabled on the port */
   8268             if (ts_enable_port_count == 0) {
   8269                 /* This is the first 1588 port on the PM */
   8270                 PHYMOD_TIMESYNC_ENABLE_F_CORE_SET(flags);
   8271             }
   8272             ts_enable_port_count++;
   8273         }
   8274 
   8275         one_step_req = (config->flags & SOC_PORT_PHY_TIMESYNC_ONE_STEP_ENABLE) ? 1 : 0;
   8276         if (one_step_req) {
   8277             PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags);
   8278         }
   8279 
   8280         /* Rx enable can only be done on link up as per programming requirement */
   8281         _SOC_IF_ERR_EXIT(phymod_timesync_enable_set(&phy_access, flags, 1));
   8282 
   8283     }
   8284 
   8285     /* Update Timesync Enable Status in WB */
   8286     _SOC_IF_ERR_EXIT(PM8x50_TS_ENABLE_PORT_COUNT_SET(unit, pm_info, ts_enable_port_count));
   8287     _SOC_IF_ERR_EXIT(PM8x50_TIMESYNC_ENABLE_SET(unit, pm_info, enable, port_index));
   8288 
   8289 exit:
   8290     SOC_FUNC_RETURN;
   8291 }
   8292 
   8293 int pm8x50_port_timesync_config_get(int unit, int port, pm_info_t pm_info,
   8294                                     portmod_phy_timesync_config_t* config)
   8295 {
   8296     portmod_access_get_params_t params;
   8297     phymod_phy_access_t phy_access;
   8298     int nof_phys, timesync_enable;
   8299     int port_index;
   8300     uint32 bitmap, is_one_step, flags = 0;
   8301     SOC_INIT_FUNC_DEFS;
   8302 
   8303     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   8304     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8305     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8306                                 &params, 1, &phy_access, &nof_phys, NULL));
   8307 
   8308     _SOC_IF_ERR_EXIT(PM8x50_TIMESYNC_ENABLE_GET(unit, pm_info, &timesync_enable, port_index));
   8309     PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags);
   8310     _SOC_IF_ERR_EXIT(phymod_timesync_enable_get(&phy_access, flags, &is_one_step));
   8311     config->flags |= is_one_step? SOC_PORT_PHY_TIMESYNC_ONE_STEP_ENABLE : 0;
   8312     config->flags |= timesync_enable ? SOC_PORT_PHY_TIMESYNC_ENABLE : 0;
   8313 
   8314 exit:
   8315     SOC_FUNC_RETURN;
   8316 }
   8317 
   8318 /*"port timesync enable set/get"*/
   8319 int pm8x50_port_timesync_enable_set(int unit, int port,
   8320                                     pm_info_t pm_info,
   8321                                     uint32 enable)
   8322 {
   8323 
   8324     return (SOC_E_NONE);
   8325 }
   8326 int pm8x50_port_timesync_enable_get(int unit, int port,
   8327                                     pm_info_t pm_info,
   8328                                      uint32* enable)
   8329 {
   8330 
   8331     return (SOC_E_NONE);
   8332 }
   8333 
   8334 /*"port timesync nco addend  set/get"*/
   8335 int pm8x50_port_timesync_nco_addend_set(int unit, int port,
   8336                                         pm_info_t pm_info,
   8337                                         uint32 freq_step)
   8338 {
   8339 
   8340     return (SOC_E_NONE);
   8341 }
   8342 int pm8x50_port_timesync_nco_addend_get(int unit, int port,
   8343                                         pm_info_t pm_info,
   8344                                         uint32* freq_step)
   8345 {
   8346 
   8347     return (SOC_E_NONE);
   8348 }
   8349 
   8350 /*"port timesync framesync info  set/get"*/
   8351 int pm8x50_port_timesync_framesync_mode_set(int unit,
   8352                                 int port, pm_info_t pm_info,
   8353                                 const portmod_timesync_framesync_t* framesync)
   8354 {
   8355 
   8356     return (SOC_E_NONE);
   8357 }
   8358 int pm8x50_port_timesync_framesync_mode_get(int unit,
   8359                                      int port, pm_info_t pm_info,
   8360                                      portmod_timesync_framesync_t* framesync)
   8361 {
   8362 
   8363     return (SOC_E_NONE);
   8364 }
   8365 
   8366 /*"port timesync local time  set/get"*/
   8367 int pm8x50_port_timesync_local_time_set(int unit, int port,
   8368                                         pm_info_t pm_info,
   8369                                         uint64 local_time)
   8370 {
   8371 
   8372     return (SOC_E_NONE);
   8373 }
   8374 int pm8x50_port_timesync_local_time_get(int unit, int port,
   8375                                         pm_info_t pm_info,
   8376                                         uint64* local_time)
   8377 {
   8378 
   8379     return (SOC_E_NONE);
   8380 }
   8381 
   8382 /*"port timesync framesync info  set/get"*/
   8383 int pm8x50_port_timesync_load_ctrl_set(int unit, int port, pm_info_t pm_info,
   8384                                        uint32 load_once, uint32 load_always)
   8385 {
   8386 
   8387     return (SOC_E_NONE);
   8388 }
   8389 int pm8x50_port_timesync_load_ctrl_get(int unit, int port, pm_info_t pm_info,
   8390                                        uint32* load_once, uint32* load_always)
   8391 {
   8392 
   8393     return (SOC_E_NONE);
   8394 }
   8395 
   8396 /*"port timesync tx timestamp offset set/get"*/
   8397 int pm8x50_port_timesync_tx_timestamp_offset_set(int unit, int port,
   8398                                                  pm_info_t pm_info,
   8399                                                  uint32 ts_offset)
   8400 {
   8401 
   8402     return (SOC_E_NONE);
   8403 }
   8404 int pm8x50_port_timesync_tx_timestamp_offset_get(int unit, int port,
   8405                                                  pm_info_t pm_info,
   8406                                                  uint32* ts_offset)
   8407 {
   8408 
   8409     return (SOC_E_NONE);
   8410 }
   8411 
   8412 /*"port timesync rx timestamp offset set/get"*/
   8413 int pm8x50_port_timesync_rx_timestamp_offset_set(int unit, int port,
   8414                                                  pm_info_t pm_info,
   8415                                                  uint32 ts_offset)
   8416 {
   8417 
   8418     return (SOC_E_NONE);
   8419 }
   8420 int pm8x50_port_timesync_rx_timestamp_offset_get(int unit, int port,
   8421                                                  pm_info_t pm_info,
   8422                                                  uint32* ts_offset)
   8423 {
   8424 
   8425     return (SOC_E_NONE);
   8426 }
   8427 
   8428 /*set/get interrupt enable value. */
   8429 int pm8x50_port_interrupt_enable_set(int unit, int port,
   8430                                      pm_info_t pm_info,
   8431                                      int intr_type, uint32 val)
   8432 {
   8433     uint32 reg_val;
   8434     int phy_acc;
   8435     SOC_INIT_FUNC_DEFS;
   8436 
   8437     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   8438     _SOC_IF_ERR_EXIT(READ_CDPORT_INTR_ENABLEr(unit, phy_acc, &reg_val));
   8439 
   8440     switch(intr_type) {
   8441         case portmodIntrTypeLinkdown:
   8442             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, LINK_DOWNf, val);
   8443             break;
   8444         case portmodIntrTypeMacErr:
   8445             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, MAC_ERRf, val);
   8446             break;
   8447         case portmodIntrTypeTscCore0Err:
   8448             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, TSC_CORE0_ERRf, val);
   8449             break;
   8450         case portmodIntrTypeTscCore1Err:
   8451             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, TSC_CORE1_ERRf, val);
   8452             break;
   8453         case portmodIntrTypePmdErr:
   8454             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, PMD_ERRf, val);
   8455             break;
   8456         case portmodIntrTypeFcReqFull:
   8457             soc_reg_field_set(unit, CDPORT_INTR_ENABLEr, &reg_val, FLOWCONTROL_REQ_FULLf, val);
   8458             break;
   8459         case portmodIntrTypeTxPktUnderflow:
   8460         case portmodIntrTypeTxPktOverflow:
   8461         case portmodIntrTypeTxCdcSingleBitErr:
   8462         case portmodIntrTypeTxCdcDoubleBitErr:
   8463         case portmodIntrTypeLocalFaultStatus:
   8464         case portmodIntrTypeRemoteFaultStatus:
   8465         case portmodIntrTypeLinkInterruptionStatus:
   8466         case portmodIntrTypeMibMemSingleBitErr:
   8467         case portmodIntrTypeMibMemDoubleBitErr:
   8468         case portmodIntrTypeMibMemMultipleBitErr:
   8469             _SOC_IF_ERR_EXIT(cdmac_interrupt_enable_set(unit, port, intr_type, val));
   8470             break;
   8471         default:
   8472             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type")));
   8473             break;
   8474     }
   8475     _SOC_IF_ERR_EXIT(WRITE_CDPORT_INTR_ENABLEr(unit, phy_acc, reg_val));
   8476 
   8477 exit:
   8478     SOC_FUNC_RETURN;
   8479 }
   8480 
   8481 STATIC
   8482 int _pm8x50_phy_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info)
   8483 {
   8484     phymod_phy_access_t phy_access;
   8485     int nof_phys;
   8486     portmod_access_get_params_t params;
   8487     phymod_ts_fifo_status_t phy_ts_tx_info;
   8488     SOC_INIT_FUNC_DEFS;
   8489 
   8490     _SOC_IF_ERR_EXIT(phymod_ts_fifo_status_t_init(&phy_ts_tx_info));
   8491     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8492     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8493                                 &params, 1, &phy_access, &nof_phys, NULL));
   8494 
   8495     _SOC_IF_ERR_EXIT(phymod_timesync_tx_info_get(&phy_access, &phy_ts_tx_info));
   8496 
   8497     tx_info->timestamps_in_fifo = phy_ts_tx_info.ts_in_fifo_lo;
   8498     tx_info->timestamps_in_fifo_hi = phy_ts_tx_info.ts_in_fifo_hi;
   8499     tx_info->sequence_id = phy_ts_tx_info.ts_seq_id;
   8500     tx_info->timestamp_sub_nanosec = phy_ts_tx_info.ts_sub_nanosec;
   8501 
   8502 exit:
   8503     SOC_FUNC_RETURN;
   8504 }
   8505 
   8506 /*!
   8507  * pm8x50_port_timesync_tx_info_get
   8508  *
   8509  * @brief get port timestamps in fifo
   8510  *
   8511  * @param [in]  unit            - unit id
   8512  * @param [in]  port            - logical port
   8513  * @param [inout]  tx_info         - timestamp and seq id form fifo
   8514  */
   8515 
   8516 int pm8x50_port_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info)
   8517 {
   8518     SOC_INIT_FUNC_DEFS;
   8519 
   8520     _SOC_IF_ERR_EXIT(_pm8x50_phy_timesync_tx_info_get(unit, port, pm_info, tx_info));
   8521 
   8522 exit:
   8523     SOC_FUNC_RETURN;
   8524 }
   8525 
   8526 int pm8x50_port_interrupt_enable_get(int unit, int port,
   8527                                      pm_info_t pm_info,
   8528                                      int intr_type, uint32* val)
   8529 {
   8530     uint32 reg_val;
   8531     int phy_acc;
   8532     SOC_INIT_FUNC_DEFS;
   8533 
   8534     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   8535     _SOC_IF_ERR_EXIT(READ_CDPORT_INTR_ENABLEr(unit, phy_acc, &reg_val));
   8536 
   8537     switch(intr_type) {
   8538         case portmodIntrTypeLinkdown:
   8539             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, LINK_DOWNf);
   8540             break;
   8541         case portmodIntrTypeMacErr:
   8542             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, MAC_ERRf);
   8543             break;
   8544         case portmodIntrTypeTscCore0Err:
   8545             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, TSC_CORE0_ERRf);
   8546             break;
   8547         case portmodIntrTypeTscCore1Err:
   8548             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, TSC_CORE1_ERRf);
   8549             break;
   8550         case portmodIntrTypePmdErr:
   8551             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, PMD_ERRf);
   8552             break;
   8553         case portmodIntrTypeFcReqFull:
   8554             *val = soc_reg_field_get(unit, CDPORT_INTR_ENABLEr, reg_val, FLOWCONTROL_REQ_FULLf);
   8555             break;
   8556         case portmodIntrTypeTxPktUnderflow:
   8557         case portmodIntrTypeTxPktOverflow:
   8558         case portmodIntrTypeTxCdcSingleBitErr:
   8559         case portmodIntrTypeTxCdcDoubleBitErr:
   8560         case portmodIntrTypeLocalFaultStatus:
   8561         case portmodIntrTypeRemoteFaultStatus:
   8562         case portmodIntrTypeLinkInterruptionStatus:
   8563         case portmodIntrTypeMibMemSingleBitErr:
   8564         case portmodIntrTypeMibMemDoubleBitErr:
   8565         case portmodIntrTypeMibMemMultipleBitErr:
   8566             _SOC_IF_ERR_EXIT(cdmac_interrupt_enable_get(unit, port, intr_type, val));
   8567             break;
   8568         default:
   8569             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type")));
   8570             break;
   8571     }
   8572 
   8573 exit:
   8574     SOC_FUNC_RETURN;
   8575 }
   8576 
   8577 /*get interrupt status value. */
   8578 int pm8x50_port_interrupt_get(int unit, int port, pm_info_t pm_info, int intr_type, uint32* val)
   8579 {
   8580     uint32 reg_val;
   8581     int phy_acc;
   8582     SOC_INIT_FUNC_DEFS;
   8583 
   8584     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   8585     _SOC_IF_ERR_EXIT(READ_CDPORT_INTR_STATUSr(unit, phy_acc, &reg_val));
   8586 
   8587     switch(intr_type) {
   8588         case portmodIntrTypeLinkdown:
   8589             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, LINK_DOWNf);
   8590             break;
   8591         case portmodIntrTypeMacErr:
   8592             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, MAC_ERRf);
   8593             break;
   8594         case portmodIntrTypeTscCore0Err:
   8595             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, TSC_CORE0_ERRf);
   8596             break;
   8597         case portmodIntrTypeTscCore1Err:
   8598             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, TSC_CORE1_ERRf);
   8599             break;
   8600         case portmodIntrTypePmdErr:
   8601             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, PMD_ERRf);
   8602             break;
   8603         case portmodIntrTypeFcReqFull:
   8604             *val = soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, FLOWCONTROL_REQ_FULLf);
   8605             break;
   8606         case portmodIntrTypeTxPktUnderflow:
   8607         case portmodIntrTypeTxPktOverflow:
   8608         case portmodIntrTypeTxCdcSingleBitErr:
   8609         case portmodIntrTypeTxCdcDoubleBitErr:
   8610         case portmodIntrTypeLocalFaultStatus:
   8611         case portmodIntrTypeRemoteFaultStatus:
   8612         case portmodIntrTypeLinkInterruptionStatus:
   8613         case portmodIntrTypeMibMemSingleBitErr:
   8614         case portmodIntrTypeMibMemDoubleBitErr:
   8615         case portmodIntrTypeMibMemMultipleBitErr:
   8616             _SOC_IF_ERR_EXIT(cdmac_interrupt_status_get(unit, port, intr_type, val));
   8617             break;
   8618         default:
   8619             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type")));
   8620             break;
   8621     }
   8622 
   8623 exit:
   8624     SOC_FUNC_RETURN;
   8625 }
   8626 
   8627 /*get interrupt value array. */
   8628 int pm8x50_port_interrupts_get(int unit, int port, pm_info_t pm_info,
   8629                                int arr_max_size, uint32* intr_arr,
   8630                                uint32* size)
   8631 {
   8632     uint32 reg_val, cnt=0;
   8633     int phy_acc;
   8634     uint32 mac_intr_cnt = 0;
   8635     SOC_INIT_FUNC_DEFS;
   8636 
   8637     _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
   8638     _SOC_IF_ERR_EXIT(READ_CDPORT_INTR_STATUSr(unit, phy_acc, &reg_val));
   8639 
   8640     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, LINK_DOWNf)) {
   8641         if (cnt >= arr_max_size) {
   8642             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8643         }
   8644         intr_arr[cnt++] = portmodIntrTypeLinkdown;
   8645     }
   8646 
   8647     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, MAC_ERRf)) {
   8648         if (cnt >= arr_max_size) {
   8649             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8650         }
   8651         intr_arr[cnt++] = portmodIntrTypeMacErr;
   8652     }
   8653 
   8654     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, TSC_CORE0_ERRf)) {
   8655         if (cnt >= arr_max_size) {
   8656             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8657         }
   8658         intr_arr[cnt++] = portmodIntrTypeTscCore0Err;
   8659     }
   8660 
   8661     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, TSC_CORE1_ERRf)) {
   8662         if (cnt >= arr_max_size) {
   8663             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8664         }
   8665         intr_arr[cnt++] = portmodIntrTypeTscCore1Err;
   8666     }
   8667 
   8668     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, PMD_ERRf)) {
   8669         if (cnt >= arr_max_size) {
   8670             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8671         }
   8672         intr_arr[cnt++] = portmodIntrTypePmdErr;
   8673     }
   8674 
   8675     if (soc_reg_field_get(unit, CDPORT_INTR_STATUSr, reg_val, FLOWCONTROL_REQ_FULLf)) {
   8676         if (cnt >= arr_max_size) {
   8677             _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size")));
   8678         }
   8679         intr_arr[cnt++] = portmodIntrTypeFcReqFull;
   8680     }
   8681 
   8682     _SOC_IF_ERR_EXIT(cdmac_interrupts_status_get(unit, port, (arr_max_size - cnt), (intr_arr + cnt), &mac_intr_cnt));
   8683     cnt += mac_intr_cnt;
   8684     *size = cnt;
   8685 
   8686 exit:
   8687     SOC_FUNC_RETURN;
   8688 }
   8689 
   8690 /* portmod check if external phy is legacy*/
   8691 int pm8x50_port_check_legacy_phy(int unit, int port,
   8692                                  pm_info_t pm_info,
   8693                                  int* legacy_phy)
   8694 {
   8695 
   8696     return (SOC_E_NONE);
   8697 }
   8698 
   8699 /* portmod phy failover mode*/
   8700 int pm8x50_port_failover_mode_set(int unit, int port,
   8701                                   pm_info_t pm_info,
   8702                                   phymod_failover_mode_t failover)
   8703 {
   8704 
   8705     return (SOC_E_NONE);
   8706 }
   8707 int pm8x50_port_failover_mode_get(int unit, int port,
   8708                                   pm_info_t pm_info,
   8709                                   phymod_failover_mode_t* failover)
   8710 {
   8711 
   8712     return (SOC_E_NONE);
   8713 }
   8714 
   8715 /* portmod port rsv mask set*/
   8716 int pm8x50_port_mac_rsv_mask_set(int unit, int port,
   8717                                  pm_info_t pm_info,
   8718                                  uint32 rsv_mask)
   8719 {
   8720     SOC_INIT_FUNC_DEFS;
   8721 
   8722     _SOC_IF_ERR_EXIT(cdmac_rsv_mask_set(unit, port, rsv_mask));
   8723 
   8724 exit:
   8725     SOC_FUNC_RETURN;
   8726 }
   8727 
   8728 /* portmod restore information after warmboot*/
   8729 int pm8x50_port_warmboot_db_restore(int unit, int port, pm_info_t pm_info,
   8730                         const portmod_port_interface_config_t* intf_config,
   8731                         const portmod_port_init_config_t* init_config,
   8732                         phymod_operation_mode_t phy_op_mode)
   8733 {
   8734 
   8735     return (SOC_E_NONE);
   8736 }
   8737 
   8738 /* portmod port flow control config*/
   8739 int pm8x50_port_flow_control_set(int unit, int port,
   8740                                  pm_info_t pm_info,
   8741                                  int merge_mode_en,
   8742                                  int parallel_fc_en)
   8743 {
   8744 
   8745     return (SOC_E_NONE);
   8746 }
   8747 
   8748 /*Portmod state for any logical port dynamixc settings*/
   8749 int pm8x50_port_update_dynamic_state(int unit, int port,
   8750                                      pm_info_t pm_info,
   8751                                      uint32_t port_dynamic_state)
   8752 {
   8753 
   8754     return (SOC_E_NONE);
   8755 }
   8756 
   8757 /*get phy operation mode. */
   8758 int pm8x50_port_phy_op_mode_get(int unit, int port, pm_info_t pm_info,
   8759                                 phymod_operation_mode_t* val)
   8760 {
   8761 
   8762     return (SOC_E_NONE);
   8763 }
   8764 
   8765 /*Returns if the PortMacro associated with the port is initialized or not*/
   8766 int pm8x50_pm_is_initialized(int unit, int pm_id, pm_info_t pm_info, int* is_initialized)
   8767 {
   8768     int is_core_initialized = 0, rv;
   8769      rv = PM8x50_IS_CORE_INITIALIZED_GET(unit, pm_info, &is_core_initialized);
   8770      *is_initialized = is_core_initialized;
   8771 
   8772     return rv;
   8773 }
   8774 
   8775 /* get the logical port bitmap of the current PM */
   8776 int pm8x50_pm_logical_pbmp_get(int unit, int pm_id, pm_info_t pm_info,
   8777                                portmod_pbmp_t* logical_pbmp)
   8778 {
   8779     int i, port;
   8780     SOC_INIT_FUNC_DEFS;
   8781 
   8782     PORTMOD_PBMP_CLEAR(*logical_pbmp);
   8783     for (i = 0 ; i < MAX_PORTS_PER_PM8X50; i++) {
   8784         _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, i, &port));
   8785         /*
   8786          * A physical lane can be associated with a logical port number
   8787          * -1 if the port was previously detached.
   8788          */
   8789         if (port >= 0) {
   8790             PORTMOD_PBMP_PORT_ADD(*logical_pbmp, port);
   8791         }
   8792     }
   8793 
   8794 exit:
   8795     SOC_FUNC_RETURN;
   8796 }
   8797 
   8798 int pm8x50_core_add(int unit, int pm_id, pm_info_t pm_info, const portmod_port_add_info_t* add_info)
   8799 {
   8800     int is_initialized = 0;
   8801     SOC_INIT_FUNC_DEFS;
   8802 
   8803     _SOC_IF_ERR_EXIT(pm8x50_pm_is_initialized(unit, pm_id, pm_info, &is_initialized));
   8804 
   8805     if (!is_initialized) {
   8806         _SOC_IF_ERR_EXIT(pm8x50_pm_enable(unit, pm_id, pm_info, 1));
   8807     }
   8808 
   8809     _SOC_IF_ERR_EXIT(pm8x50_pm_serdes_core_init(unit, pm_id, pm_info, add_info));
   8810 
   8811 exit:
   8812     SOC_FUNC_RETURN;
   8813 }
   8814 
   8815 int pm8x50_port_lane_map_set(int unit, int port, pm_info_t pm_info, uint32 flags, const phymod_lane_map_t* lane_map)
   8816 {
   8817 
   8818     return (SOC_E_UNAVAIL);
   8819 }
   8820 
   8821 int pm8x50_port_lane_map_get(int unit, int port, pm_info_t pm_info, uint32 flags, phymod_lane_map_t* lane_map)
   8822 {
   8823     SOC_INIT_FUNC_DEFS;
   8824 
   8825     *lane_map = PM_8x50_INFO(pm_info)->lane_map;
   8826 
   8827     SOC_FUNC_RETURN;
   8828 }
   8829 
   8830 int pm8x50_port_synce_clk_ctrl_set(int unit, int port, pm_info_t pm_info,
   8831                                    const portmod_port_synce_clk_ctrl_t* cfg)
   8832 {
   8833     phymod_synce_clk_ctrl_t phy_synce_cfg;
   8834     portmod_access_get_params_t params;
   8835     phymod_phy_access_t phy_access;
   8836     int nof_phys;
   8837     int config_valid = 0;
   8838 
   8839     SOC_INIT_FUNC_DEFS;
   8840 
   8841     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8842     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8843                                 &params, 1, &phy_access, &nof_phys, NULL));
   8844 
   8845     phymod_synce_clk_ctrl_t_init(&phy_synce_cfg);
   8846     phy_synce_cfg.stg0_mode = cfg->stg0_mode;
   8847     phy_synce_cfg.stg1_mode = cfg->stg1_mode;
   8848     phy_synce_cfg.sdm_val = cfg->sdm_val;
   8849 
   8850     /* next validate the stage0/1 config */
   8851     /* first check legacy mode */
   8852     if (cfg->stg0_mode == 0x0) {
   8853         config_valid = 1;
   8854     } else if ((cfg->stg0_mode == 0x1) && (cfg->stg1_mode == 0x2)) {
   8855         config_valid = 1;
   8856     } else if ((cfg->stg0_mode == 0x2) && (cfg->stg1_mode == 0x0)) {
   8857         config_valid = 1;
   8858     }
   8859 
   8860     if (config_valid) {
   8861         _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_set(&phy_access,
   8862                                                        phy_synce_cfg));
   8863     } else {
   8864         _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   8865                   (_SOC_MSG("SyncE config is not valid \n")));
   8866     }
   8867 
   8868 exit:
   8869     SOC_FUNC_RETURN;
   8870 }
   8871 
   8872 int pm8x50_port_synce_clk_ctrl_get(int unit, int port, pm_info_t pm_info,
   8873                                    portmod_port_synce_clk_ctrl_t* cfg)
   8874 {
   8875     phymod_synce_clk_ctrl_t phy_synce_cfg;
   8876     portmod_access_get_params_t params;
   8877     phymod_phy_access_t phy_access;
   8878     int nof_phys;
   8879 
   8880     SOC_INIT_FUNC_DEFS;
   8881 
   8882     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   8883     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   8884                                 &params, 1, &phy_access, &nof_phys, NULL));
   8885 
   8886     phymod_synce_clk_ctrl_t_init(&phy_synce_cfg);
   8887 
   8888     _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_get(&phy_access,
   8889                                                     &phy_synce_cfg));
   8890 
   8891     cfg->stg0_mode = phy_synce_cfg.stg0_mode;
   8892     cfg->stg1_mode = phy_synce_cfg.stg1_mode;
   8893     cfg->sdm_val = phy_synce_cfg.sdm_val;
   8894 
   8895 exit:
   8896     SOC_FUNC_RETURN;
   8897 }
   8898 
   8899 STATIC
   8900 int _pm8x50_pm_tsc_interrupt_type_get(int unit, int intr_val, uint32 flags,
   8901                               pm8x50_tsc_err_intr_phymod_map_t *tsc_intr_info)
   8902 {
   8903     pm8x50_tsc_intr_type_t iter = pm8x50TscIntrEccNone;
   8904     pm8x50_tsc_intr_type_t iter_start = pm8x50TscIntrEccNone;
   8905     pm8x50_tsc_intr_type_t iter_end = pm8x50TscIntrEccNone;
   8906 
   8907     /* Check is 1-bit or 2-bit ECC interrupt type */
   8908     if (flags & PM8x50_TSC_ECC_1B_INTR) {
   8909         iter_start = pm8x50TscIntrEcc1bErr;
   8910         iter_end = pm8x50TscIntrEcc1bErrCount;
   8911     } else if (flags & PM8x50_TSC_ECC_2B_INTR) {
   8912         iter_start = pm8x50TscIntrEcc2bErr;
   8913         iter_end = pm8x50TscIntrEcc2bErrCount;
   8914     } else {
   8915         return SOC_E_INTERNAL;
   8916     }
   8917 
   8918     for(iter = iter_start; iter <= iter_end; iter++) {
   8919         if (intr_val & pm8x50_tsc_ecc_intr_info[iter].flags) {
   8920             /* return phymod tsc interrupt type */
   8921             sal_memcpy(tsc_intr_info, &pm8x50_tsc_ecc_intr_info[iter],
   8922                         sizeof(pm8x50_tsc_err_intr_phymod_map_t));
   8923             break;
   8924         }
   8925     }
   8926 
   8927     return SOC_E_NONE;
   8928 }
   8929 
   8930 int pm8x50_pm_interrupt_process(int unit, int pm_id, pm_info_t pm_info,
   8931                                 portmod_ecc_intr_info_t *ecc_info)
   8932 {
   8933     int i = 0, ii = 0, j = 0;
   8934     int lport = 0;
   8935     int prev_lport = 0;
   8936     int first_lport = 0;
   8937     uint32 val = 0, rval = 0, fval = 0;
   8938     uint32 tsc_intr_flags = 0x0, is_handled = 0;
   8939     uint64 rval64;
   8940     pm8x50_tsc_err_intr_phymod_map_t tsc_intr_info;
   8941     portmod_pm_intr_info_t *p_intr_info = &pm8x50_pm_intr_info[0];
   8942     portmod_intr_reg_info_t *p_intr_grp_info = NULL;
   8943     portmod_intr_type_t intr_type;
   8944     phymod_phy_access_t phy_access;
   8945     portmod_access_get_params_t params;
   8946     int nof_phys = 0;
   8947     int is_intr_found = 0;
   8948     SOC_INIT_FUNC_DEFS;
   8949 
   8950     COMPILER_64_ZERO(rval64);
   8951     /* Get the first physical port of the pm core */
   8952     for(ii=0; ii < PM8X50_LANES_PER_CORE; ii++) {
   8953         /* get the logical port associated with the physical port */
   8954         _SOC_IF_ERR_EXIT(PM8x50_LANE2PORT_GET(unit, pm_info, ii, &lport));
   8955 
   8956         /* skip if invalid or its the same logical port */
   8957         if ((lport == -1) || (prev_lport == lport)) {
   8958             /*LOG_CLI(("Port(%s) - Skipping interrupt processing for same logical port!\n",
   8959                      SOC_PORT_NAME(unit, lport)));*/
   8960             continue;
   8961         }
   8962 
   8963         /* Remember the first port */
   8964         if (first_lport == 0) {
   8965             first_lport = lport;
   8966         }
   8967         prev_lport = lport;
   8968 
   8969         /*
   8970          * Following is the sequence for processing the interrupts.
   8971          * 1. Check the top level interrupt status register of the
   8972          *    PM8x50 to determine if its a MAC interrupt or a 
   8973          *    TSC interrupti,
   8974          * 2. If its a MAC interrupt, MAC interrupt status register
   8975          *    is read, to determine the MAC interrupt type, This is
   8976          *    is a per-port register and the function returns on the 
   8977          *    determining the first interrupt.
   8978          * 3. If its a TSC interrupt, the TSC interrupt status 
   8979          *    register is read to determine the TSC inetrrupt type.
   8980          */
   8981 
   8982         /*
   8983          * Read the top level interrupt status only once, since its 
   8984          * only a single copy register.
   8985          */
   8986         if (first_lport == prev_lport) {
   8987             for (i = 0; i < sizeof(pm8x50_pm_intr_info)/
   8988                             sizeof(portmod_pm_intr_info_t); i++) {
   8989                 p_intr_info = &pm8x50_pm_intr_info[i];
   8990                 intr_type = p_intr_info->intr_type;
   8991                 _SOC_IF_ERR_EXIT(pm8x50_port_interrupt_get(unit, lport,
   8992                                             pm_info, intr_type, &val));
   8993 
   8994                 /* continue if interrupt is not set. */
   8995                 if (!val) {
   8996                     continue;
   8997                 }
   8998 
   8999                 /* Either MAC, TSC, PMD Interrupt is set, */
   9000                 /*
   9001                  * Iterate through the individual interrupt status
   9002                  * based on the list of status registers.
   9003                  */
   9004                 if (p_intr_info->is_intr_status_group) {
   9005                     p_intr_grp_info = &p_intr_info->intr_list_status_reg[0];
   9006                     intr_type = p_intr_grp_info->intr_type;
   9007                     is_intr_found = 1;
   9008                 }
   9009                 /*LOG_CLI(("%s\n", p_intr_info->mem_str));*/
   9010                 break;
   9011             }
   9012 
   9013             if (!is_intr_found) {
   9014                 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL,
   9015                   (_SOC_MSG("Port(%s) - Interrupt not found!\n"),
   9016                             SOC_PORT_NAME(unit, lport)));
   9017             }
   9018 
   9019             /*
   9020              * Below logic determines the specific interrupt type
   9021              * in MAC, TSC Core0, TSC Core1,
   9022              */
   9023             while (intr_type != portmodIntrTypeCount) {
   9024                 if (SOC_REG_IS_64(unit, p_intr_grp_info->st_reg)) {
   9025                     uint64 fval64;
   9026 
   9027                     _SOC_IF_ERR_EXIT(soc_reg64_get(unit,
   9028                                                    p_intr_grp_info->st_reg,
   9029                                                    lport, 0, &rval64));
   9030                     fval64 = soc_reg64_field_get(unit, p_intr_grp_info->st_reg,
   9031                                                  rval64, p_intr_grp_info->st_fld);
   9032                     COMPILER_64_TO_32_LO(fval, fval64);
   9033                 } else {
   9034                     _SOC_IF_ERR_EXIT(soc_reg32_get(unit,
   9035                                                    p_intr_grp_info->st_reg,
   9036                                                    lport, 0, &rval));
   9037                     fval = soc_reg_field_get(unit, p_intr_grp_info->st_reg,
   9038                                              rval, p_intr_grp_info->st_fld);
   9039                 }
   9040 
   9041                 /* If not set skip to the next interrupt type. */ 
   9042                 if (!fval) {
   9043                     j++;
   9044                     p_intr_grp_info = &p_intr_info->intr_list_status_reg[j];
   9045                     intr_type = p_intr_info->intr_list_status_reg[j].intr_type;
   9046                     continue;
   9047                 }
   9048                     
   9049                 LOG_VERBOSE(BSL_LS_SOC_PORT, (BSL_META_U(unit, "Port - %s "
   9050                            "Reg - %s, Field - %s fval - %d\n"), 
   9051                            SOC_PORT_NAME(unit, lport),
   9052                            SOC_REG_NAME(unit,  p_intr_grp_info->st_reg),
   9053                            SOC_FIELD_NAME(unit, p_intr_grp_info->st_fld), fval));
   9054 
   9055                 /* If interrupt status is set, and status is clear-on-read */
   9056                 if (p_intr_grp_info->flags & PORTMOD_INTR_STATUS_COR) {
   9057 
   9058                     /* If its per-port clear status register */
   9059                     if (!(p_intr_grp_info->flags &
   9060                             PORTMOD_INTR_BLOCK_CLEAR_REG)) {
   9061                         _SOC_IF_ERR_EXIT(soc_reg32_get(unit,
   9062                                                p_intr_grp_info->clr_reg,
   9063                                                lport, 0, &rval));
   9064                 LOG_ERROR(BSL_LS_SOC_PORT,
   9065                       (BSL_META_U(unit, "NOT BLOCK_CLEAR_REG\n")));
   9066                     } else {
   9067                         /* If its per-port clear status register */
   9068                         uint32 raddr;
   9069                         int phy_port, block;
   9070                         uint8 at;
   9071 
   9072                         PORTMOD_PBMP_ITER(PM_8x50_INFO(pm_info)->phys,
   9073                                           phy_port) {
   9074                             break;
   9075                         }
   9076 
   9077                         raddr = soc_reg_addr_get(unit,
   9078                                      p_intr_grp_info->clr_reg, phy_port, 0,
   9079                                      SOC_REG_ADDR_OPTION_PRESERVE_PORT,
   9080                                      &block, &at);
   9081                         _SOC_IF_ERR_EXIT(_soc_reg32_get(unit, block, at,
   9082                                                         raddr, &rval));
   9083                 LOG_CLI(("BLOCK_CLEAR_REG\n"));
   9084                     }
   9085 
   9086                     fval = soc_reg_field_get(unit,
   9087                                      p_intr_grp_info->clr_reg,
   9088                                      rval, p_intr_grp_info->clr_fld);
   9089                 } else if (((intr_type == portmodIntrTypeTscCore0Err) ||
   9090                            (intr_type == portmodIntrTypeTscCore1Err)) &&
   9091                            (p_intr_grp_info->flags &
   9092                             PORTMOD_INTR_STATUS_W1TC)) {
   9093 
   9094                     if (p_intr_grp_info->st_fld == TSC_ECC_1B_ERRf) {
   9095                         tsc_intr_flags = PM8x50_TSC_ECC_1B_INTR;
   9096                     } else if (p_intr_grp_info->st_fld == TSC_ECC_2B_ERRf) {
   9097                         tsc_intr_flags = PM8x50_TSC_ECC_2B_INTR;
   9098                     }
   9099                     _SOC_IF_ERR_EXIT(_pm8x50_pm_tsc_interrupt_type_get(unit,
   9100                                                 fval, tsc_intr_flags,
   9101                                                 &tsc_intr_info));
   9102                     /* Only internal phy supported. */
   9103                     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit,
   9104                                                                      &params));
   9105                     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit,
   9106                                                 lport, pm_info, &params, 1,
   9107                                                 &phy_access, &nof_phys, NULL));
   9108 
   9109                 LOG_VERBOSE(BSL_LS_SOC_PORT,
   9110                       (BSL_META_U(unit, "TSC Core Error - %d\n"), 
   9111                                    tsc_intr_info.phymod_intr_map));
   9112                     /* clear tsc interrupt */
   9113                     _SOC_IF_ERR_EXIT(phymod_intr_handler(&phy_access,
   9114                                              tsc_intr_info.phymod_intr_map,
   9115                                              &is_handled));
   9116                     if (!is_handled) {
   9117                         /*LOG_CLI(("Cannot handle - %s\n", tsc_intr_info.str));*/
   9118                     } else {
   9119                         /*LOG_CLI(("Phymod interrupt handled - %d(%s)\n",
   9120                                           is_handled, tsc_intr_info.str));*/
   9121                     }
   9122                     ecc_info->mem_str = tsc_intr_info.str;
   9123                 }
   9124 
   9125                 ecc_info->port = lport;
   9126                 ecc_info->ecc_num_bits_err =
   9127                        (p_intr_grp_info->flags & PORTMOD_INTR_ECC_1B_ERR) ?
   9128                         PORTMOD_INTR_ECC_1B_ERR:
   9129                        (p_intr_grp_info->flags & PORTMOD_INTR_ECC_2B_ERR) ?
   9130                         PORTMOD_INTR_ECC_2B_ERR:
   9131                        (p_intr_grp_info->flags & PORTMOD_INTR_ECC_MULTIB_ERR) ?
   9132                         PORTMOD_INTR_ECC_MULTIB_ERR: PORTMOD_PM_ECC_ERR_NONE;
   9133                 SOC_EXIT;
   9134             } /* intr_type != portmodIntrTypeCount */
   9135         } /* Interate through the interrupt types */
   9136     } /* Iterate through logical ports */
   9137 
   9138 exit:
   9139     SOC_FUNC_RETURN;
   9140 }
   9141 
   9142 int pm8x50_pm_core_num_get(int unit, pm_info_t pm_info, int* core_num)
   9143 {
   9144     *core_num = PM_8x50_INFO(pm_info)->core_num;
   9145     return (SOC_E_NONE);
   9146 }
   9147 
   9148 int _portmod_rlm_config_validate(int unit, int port, int speed, int port_index,  uint32 active_lane_map)
   9149 {
   9150     int i, num_lane = 8, active_lane_num = 0;
   9151     SOC_INIT_FUNC_DEFS;
   9152 
   9153     for (i = 0; i < num_lane; i++) {
   9154         if (active_lane_map &  1 << (port_index + i)) {
   9155             active_lane_num++;
   9156         }
   9157     }
   9158 
   9159     /* first check 200G case */
   9160     switch (speed) {
   9161     case 150000:
   9162         if ((active_lane_map != 0xf0) && (active_lane_map != 0xf)) {
   9163             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9164                       (_SOC_MSG("Active lane map is not valid")));
   9165         }
   9166         break;
   9167     case 200000:
   9168         if (active_lane_num != 3) {
   9169             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9170                       (_SOC_MSG("Active lane map is not valid")));
   9171         } else if ((port_index == 0) && (active_lane_map  & 0xf0)) {
   9172             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9173                       (_SOC_MSG("Active lane map is not valid")));
   9174         } else if ((port_index == 4) && (active_lane_map  & 0x0f)) {
   9175             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9176                       (_SOC_MSG("Active lane map is not valid")));
   9177         }
   9178         break;
   9179     case 300000:
   9180     case 350000:
   9181         if (active_lane_map != 0xff) {
   9182             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9183                       (_SOC_MSG("Active lane map is not valid")));
   9184         }
   9185         break;
   9186     case 400000:
   9187         if ((active_lane_num != 6) && (active_lane_num != 7)) {
   9188             _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9189                       (_SOC_MSG("Active lane map is not valid")));
   9190         }
   9191         break;
   9192     default:
   9193         break;
   9194     }
   9195 exit:
   9196     SOC_FUNC_RETURN;
   9197 
   9198 }
   9199 
   9200 int pm8x50_port_rlm_config_set(int unit, int port, pm_info_t pm_info,
   9201                                int enable,
   9202                                const portmod_port_rlm_config_t* rlm_config)
   9203 {
   9204     portmod_access_get_params_t params;
   9205     phymod_phy_access_t phy_access;
   9206     uint32_t  is_initiator, pcs_is_reconfigured, active_lane_map_local;
   9207     phymod_fec_type_t FecType;
   9208     uint32_t txLaneSwap, rxLaneSwap, bitmap, port_lane_mask;
   9209     portmod_port_rlm_state_t local_port_rlm_state;
   9210     int nof_phys,  port_index = -1, rlm_enabled;
   9211     phymod_phy_speed_config_t phy_speed_config;
   9212 
   9213 
   9214     SOC_INIT_FUNC_DEFS;
   9215 
   9216     _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, &params));
   9217     _SOC_IF_ERR_EXIT(pm8x50_port_phy_lane_access_get(unit, port, pm_info,
   9218                                 &params, 1, &phy_access, &nof_phys, NULL));
   9219 
   9220     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &port_lane_mask));
   9221 
   9222     /* first get the current port speed */
   9223     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_t_init(&phy_speed_config));
   9224     _SOC_IF_ERR_EXIT(phymod_phy_speed_config_get(&phy_access, &phy_speed_config));
   9225 
   9226     /* only 150G/300G/350G/200G/400G can enable RLM mode */
   9227     if ((phy_speed_config.data_rate == 150000) ||
   9228         ((phy_speed_config.data_rate == 200000) && (phy_speed_config.fec_type != phymod_fec_None)) ||
   9229         (phy_speed_config.data_rate == 300000) ||
   9230         (phy_speed_config.data_rate == 350000) ||
   9231         (phy_speed_config.data_rate == 400000)) {
   9232         /* first get all the RLM warmboot variable */
   9233         _SOC_IF_ERR_EXIT
   9234             (PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, port_index));
   9235 
   9236         _SOC_IF_ERR_EXIT
   9237             (PM8x50_INITIATOR_GET(unit, pm_info, &is_initiator, port_index));
   9238 
   9239         _SOC_IF_ERR_EXIT
   9240             (PM8x50_PCS_RECONFIG_GET(unit, pm_info, &pcs_is_reconfigured, port_index));
   9241 
   9242         _SOC_IF_ERR_EXIT
   9243             (PM8x50_ACTIVE_LANE_MAP_GET(unit, pm_info, &active_lane_map_local, port_index));
   9244 
   9245         _SOC_IF_ERR_EXIT
   9246             (PM8x50_RLM_STATE_GET(unit, pm_info, &local_port_rlm_state.rlm_state, port_index));
   9247 
   9248         _SOC_IF_ERR_EXIT
   9249             (PM8x50_ORIGINAL_FEC_GET(unit, pm_info, &FecType, port_index));
   9250 
   9251         _SOC_IF_ERR_EXIT
   9252             (PM8x50_ORIG_TX_LANE_MAP_GET(unit, pm_info, &txLaneSwap));
   9253 
   9254         _SOC_IF_ERR_EXIT
   9255             (PM8x50_ORIG_RX_LANE_MAP_GET(unit, pm_info, &rxLaneSwap));
   9256     } else {
   9257         /* RLM is not supported */
   9258         _SOC_EXIT_WITH_ERR(SOC_E_CONFIG,
   9259                   (_SOC_MSG("RLM mode is not supported on this speed")));
   9260     }
   9261 
   9262     /* set the rlm_enabled */
   9263     rlm_enabled = enable;
   9264 
   9265     /* if to enable RLM */
   9266     if (enable) {
   9267         is_initiator = rlm_config->is_initiator;
   9268         /* set the RLM variable and state accordingly */
   9269         pcs_is_reconfigured = FALSE;
   9270         /* next check if initiator is set */
   9271         /*if so need to get the active_lane_map */
   9272         if (is_initiator) {
   9273             _SOC_IF_ERR_EXIT(_portmod_rlm_config_validate(unit, port,
   9274                                                           phy_speed_config.data_rate,
   9275                                                           port_index,
   9276                                                           rlm_config->active_lane_bit_map));
   9277             active_lane_map_local = rlm_config->active_lane_bit_map;
   9278         } else {
   9279             active_lane_map_local = 0x0;
   9280         }
   9281         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_SEND_PACKET_DATA;
   9282     } else {
   9283         uint32_t is_400g_port = 0, tmp_active_lane_map = 0x0f;
   9284         portmod_speed_config_t  local_speed_config;
   9285 
   9286         /* is RLM disable, then clear both initiator and active lane map */
   9287         is_initiator = FALSE;
   9288         active_lane_map_local = 0x0;
   9289         /* need to know if 4 lane or 8 lane port and also start lane of this port */
   9290         _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
   9291         /*next based on the port index, need to get mpp index */
   9292         if (port_index == 4) {
   9293             tmp_active_lane_map = 0xf0;
   9294         } else if (bitmap == 0xff) {
   9295             is_400g_port = 1;
   9296             tmp_active_lane_map = 0xff;
   9297         }
   9298         /* next need to restore the tx/rx original lane swap */
   9299         _SOC_IF_ERR_EXIT(phymod_phy_pcs_lane_swap_adjust(&phy_access,
   9300                                                          tmp_active_lane_map,
   9301                                                          txLaneSwap,
   9302                                                          rxLaneSwap));
   9303 
   9304         /*then disable PRBS tx/rx  */
   9305         _SOC_IF_ERR_EXIT(phymod_phy_prbs_enable_set(&phy_access, 0, 0));
   9306         /* next disable all the PMD override */
   9307         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDRxLock, 0, 0));
   9308         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDSignalDetect, 0, 0));
   9309         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDTxDisable, 0, 0));
   9310         _SOC_IF_ERR_EXIT(phymod_phy_pmd_override_enable_set(&phy_access, phymodPMDLaneReset, 0, 0));
   9311 
   9312         /* next disable LI  */
   9313         _SOC_IF_ERR_EXIT(cdmac_link_interrupt_ordered_set_enable(unit, port, 0));
   9314 
   9315         /* next read the current PMD lane config info */
   9316         _SOC_IF_ERR_EXIT(pm8x50_port_speed_config_get(unit, port, pm_info, &local_speed_config));
   9317         if (is_400g_port) {
   9318             local_speed_config.num_lane = 8;
   9319             local_speed_config.speed = 400000;
   9320         } else {
   9321             local_speed_config.num_lane = 4;
   9322             local_speed_config.speed = 200000;
   9323         }
   9324 
   9325         /* based on the saved PHYMOD  FEctype, get the portmod enum */
   9326         _SOC_IF_ERR_EXIT(_pm8x50_port_phy_to_port_fec(FecType, &local_speed_config.fec));
   9327 
   9328         /* then do a forced speed config to restore original speed/fec mode */
   9329         _SOC_IF_ERR_EXIT(pm8x50_port_speed_config_set(unit, port, pm_info, &local_speed_config));
   9330 
   9331         pcs_is_reconfigured = FALSE;
   9332         active_lane_map_local = 0x0;
   9333         local_port_rlm_state.rlm_state = PORTMOD_PORT_RLM_FSM_COUNT;
   9334     }
   9335 
   9336     /* finally restore all the Warm boot variables */
   9337     _SOC_IF_ERR_EXIT
   9338         (PM8x50_RLM_ENABLE_SET(unit, pm_info, rlm_enabled, port_index));
   9339 
   9340     _SOC_IF_ERR_EXIT
   9341         (PM8x50_INITIATOR_SET(unit, pm_info, is_initiator, port_index));
   9342 
   9343     _SOC_IF_ERR_EXIT
   9344         (PM8x50_PCS_RECONFIG_SET(unit, pm_info, pcs_is_reconfigured, port_index));
   9345 
   9346     _SOC_IF_ERR_EXIT
   9347         (PM8x50_ACTIVE_LANE_MAP_SET(unit, pm_info, active_lane_map_local, port_index));
   9348 
   9349     _SOC_IF_ERR_EXIT
   9350         (PM8x50_RLM_STATE_SET(unit, pm_info, local_port_rlm_state.rlm_state, port_index));
   9351 
   9352     /* call back register should happen after RLM ENABLE is set */
   9353     if (enable) {
   9354         _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_register(unit, port, pm8x50_periodic_callback, PORTMOD_THREAD_INTERVAL_1s));
   9355     }
   9356 
   9357 
   9358 exit:
   9359     SOC_FUNC_RETURN;
   9360 }
   9361 
   9362 int pm8x50_port_rlm_config_get(int unit, int port, pm_info_t pm_info,
   9363                                int* enable,
   9364                                portmod_port_rlm_config_t* rlm_config)
   9365 {
   9366     uint32_t  is_initiator, active_lane_map_local, port_lane_mask;
   9367     int rlm_enabled, port_index;
   9368 
   9369     SOC_INIT_FUNC_DEFS;
   9370 
   9371     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &port_lane_mask));
   9372 
   9373     /* first get all the RLM warmboot variable */
   9374     _SOC_IF_ERR_EXIT
   9375         (PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, port_index));
   9376 
   9377     _SOC_IF_ERR_EXIT
   9378         (PM8x50_INITIATOR_GET(unit, pm_info, &is_initiator, port_index));
   9379 
   9380     _SOC_IF_ERR_EXIT
   9381         (PM8x50_ACTIVE_LANE_MAP_GET(unit, pm_info, &active_lane_map_local, port_index));
   9382 
   9383     *enable = rlm_enabled;
   9384     rlm_config->is_initiator = is_initiator;
   9385     rlm_config->active_lane_bit_map = active_lane_map_local;
   9386 
   9387 exit:
   9388     SOC_FUNC_RETURN;
   9389 }
   9390 
   9391 int pm8x50_port_rlm_status_get(int unit, int port, pm_info_t pm_info,
   9392                                portmod_port_rlm_status_t *rlm_status)
   9393 {
   9394     uint32_t rlm_state, port_lane_mask;
   9395     int rlm_enabled, port_index;
   9396 
   9397     SOC_INIT_FUNC_DEFS;
   9398 
   9399     _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &port_lane_mask));
   9400 
   9401     _SOC_IF_ERR_EXIT
   9402         (PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, port_index));
   9403     _SOC_IF_ERR_EXIT
   9404         (PM8x50_RLM_STATE_GET(unit, pm_info, &rlm_state, port_index));
   9405 
   9406     /* first initialize the status */
   9407     rlm_status->rlm_disabled = !rlm_enabled;
   9408     rlm_status->rlm_busy = FALSE;
   9409     rlm_status->rlm_failed  = FALSE;
   9410     rlm_status->rlm_done = FALSE;
   9411 
   9412 
   9413     /* first check rlm_state */
   9414     if (rlm_state == PORTMOD_PORT_RLM_ERROR) {
   9415         rlm_status->rlm_failed  = TRUE;
   9416     } else if (rlm_state == PORTMOD_PORT_RLM_DONE) {
   9417         rlm_status->rlm_done = TRUE;
   9418     } else if ((rlm_state < PORTMOD_PORT_RLM_FSM_COUNT) && (rlm_enabled)) {
   9419         rlm_status->rlm_busy = TRUE;
   9420     }
   9421 
   9422 exit:
   9423     SOC_FUNC_RETURN;
   9424 }
   9425 #endif