pm4x25.c (382240B)
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/mcm/memregs.h> 20 #include <soc/portmod/portmod_legacy_phy.h> 21 #include <soc/portmod/portmod_system.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_PM4X25_SUPPORT 29 30 #include <soc/portmod/clmac.h> 31 #include <soc/portmod/pm4x25.h> 32 #include <soc/portmod/pm4x25_shared.h> 33 34 #ifdef PORTMOD_PM4X25TD_SUPPORT 35 #include <soc/portmod/pm4x25td_int.h> 36 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 37 38 39 #define PM_4x25_INFO(pm_info) ((pm_info)->pm_data.pm4x25_db) 40 41 /* WB defines */ 42 43 #define PM4x25_WB_BUFFER_VERSION (13) 44 45 #define PM4x25_IS_ACTIVE_SET(unit, pm_info, is_active) \ 46 SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isActive], &is_active) 47 #define PM4x25_IS_ACTIVE_GET(unit, pm_info, is_active) \ 48 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isActive], is_active) 49 50 #define PM4x25_IS_INITIALIZED_SET(unit, pm_info, is_initialized) \ 51 SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isInitialized], &is_initialized) 52 #define PM4x25_IS_INITIALIZED_GET(unit, pm_info, is_initialized) \ 53 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isInitialized], is_initialized) 54 55 #define PM4x25_IS_BYPASSED_SET(unit, pm_info, is_bypass) \ 56 SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &is_bypass) 57 #define PM4x25_IS_BYPASSED_GET(unit, pm_info, is_bypass) \ 58 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], is_bypass) 59 60 #define PM4x25_LANE2PORT_SET(unit, pm_info, lane, port) \ 61 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[lane2portMap], &port, lane) 62 #define PM4x25_LANE2PORT_GET(unit, pm_info, lane, port) \ 63 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[lane2portMap], port, lane) 64 65 #define PM4x25_THREE_PORTS_MODE_SET(unit, pm_info, three_ports_mode) \ 66 SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[threePortsMode], &three_ports_mode) 67 #define PM4x25_THREE_PORTS_MODE_GET(unit, pm_info, three_ports_mode) \ 68 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[threePortsMode], three_ports_mode) 69 70 #define PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index) \ 71 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[maxSpeed], &max_speed, port_index) 72 #define PM4x25_MAX_SPEED_GET(unit, pm_info, max_speed, port_index) \ 73 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[maxSpeed], max_speed, port_index) 74 75 #define PM4x25_INTERFACE_TYPE_SET(unit, pm_info, interface_type, port_index) \ 76 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceType], &interface_type, port_index) 77 #define PM4x25_INTERFACE_TYPE_GET(unit, pm_info, interface_type, port_index) \ 78 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceType], interface_type, port_index) 79 80 #define PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface_type, port_index) \ 81 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 82 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], \ 83 &interface_type, port_index) 84 #define PM4x25_OUTMOST_PHY_INTERFACE_TYPE_GET(unit, pm_info, interface_type, port_index) \ 85 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 86 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], \ 87 interface_type, port_index) 88 89 #define PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index) \ 90 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceModes], &interface_modes, port_index) 91 #define PM4x25_INTERFACE_MODES_GET(unit, pm_info, interface_modes, port_index) \ 92 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceModes], interface_modes, port_index) 93 94 #define PM4x25_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, port_index) \ 95 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isInterfaceRestore], &is_interface_restore, port_index) 96 #define PM4x25_IS_INTERFACE_RESTORE_GET(unit, pm_info, is_interface_restore, port_index) \ 97 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isInterfaceRestore], is_interface_restore, port_index) 98 99 #define PM4x25_IS_HG_SET(unit, pm_info, is_hg, port_index) \ 100 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isHg], &is_hg, port_index) 101 #define PM4x25_IS_HG_GET(unit, pm_info, is_hg, port_index) \ 102 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isHg], is_hg, port_index) 103 104 #define PM4x25_AN_MODE_SET(unit, pm_info, an_mode, port_index) \ 105 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMode], &an_mode, port_index) 106 #define PM4x25_AN_MODE_GET(unit, pm_info, an_mode, port_index) \ 107 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMode], an_mode, port_index) 108 109 #define PM4x25_FS_CL72_SET(unit, pm_info, fs_cl72, port_index) \ 110 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[fsCl72], &fs_cl72, port_index) 111 #define PM4x25_FS_CL72_GET(unit, pm_info, fs_cl72, port_index) \ 112 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[fsCl72], fs_cl72, port_index) 113 114 #define PM4x25_CX4_10G_SET(unit, pm_info, cx4_10G, port_index) \ 115 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[cx4In10G], &cx4_10G, port_index) 116 #define PM4x25_CX4_10G_GET(unit, pm_info, cx4_10G, port_index) \ 117 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[cx4In10G], cx4_10G, port_index) 118 119 #define PM4x25_AN_CL72_SET(unit, pm_info, an_cl72, port_index) \ 120 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anCl72], &an_cl72, port_index) 121 #define PM4x25_AN_CL72_GET(unit, pm_info, an_cl72, port_index) \ 122 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anCl72], an_cl72, port_index) 123 124 #define PM4x25_AN_FEC_SET(unit, pm_info, an_fec, port_index) \ 125 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anFec], &an_fec, port_index) 126 #define PM4x25_AN_FEC_GET(unit, pm_info, an_fec, port_index) \ 127 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anFec], an_fec, port_index) 128 129 #define PM4x25_AN_MASTER_LANE_SET(unit, pm_info, an_master_lane, port_index) \ 130 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMasterLane], &an_master_lane, port_index) 131 #define PM4x25_AN_MASTER_LANE_GET(unit, pm_info, an_master_lane, port_index) \ 132 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMasterLane], an_master_lane, port_index) 133 134 #define PM4x25_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, lane_connection_db, xphy_idx, lane) \ 135 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[laneConnectionDb], \ 136 (uint8 *)lane_connection_db, lane, xphy_idx) 137 #define PM4x25_PORT_LANE_CONNECTION_DB_GET(unit, pm_info, lane_connection_db, xphy_idx, lane) \ 138 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[laneConnectionDb], \ 139 (uint8 *)lane_connection_db, lane, xphy_idx) 140 141 #define PM4x25_PORT_NUM_PHYS_SET(unit, pm_info, nof_phys, lane) \ 142 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[nofPhys], &nof_phys, lane) 143 #define PM4x25_PORT_NUM_PHYS_GET(unit, pm_info, nof_phys, lane) \ 144 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[nofPhys], nof_phys, lane) 145 146 #define PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, dynamic_state, \ 147 port_index) \ 148 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 149 pm_info->wb_vars_ids[portDynamicState], \ 150 &dynamic_state, port_index) 151 #define PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, dynamic_state, \ 152 port_index) \ 153 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 154 pm_info->wb_vars_ids[portDynamicState], \ 155 dynamic_state, port_index) 156 #define PM4x25_PORT_TIME_STAMP_ADJUST_OLD_SET(unit, pm_info, \ 157 port_ts_adjust, \ 158 adjust_index, \ 159 port_index) \ 160 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 161 pm_info->wb_vars_ids[tsAdjustOld], \ 162 (uint8 *)port_ts_adjust, adjust_index, port_index) 163 164 #define PM4x25_PORT_TIME_STAMP_ADJUST_OLD_GET(unit, pm_info, \ 165 port_ts_adjust, \ 166 adjust_index, \ 167 port_index) \ 168 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 169 pm_info->wb_vars_ids[tsAdjustOld], \ 170 (uint8 *)port_ts_adjust, adjust_index, port_index) 171 172 #define PM4x25_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, \ 173 port_ts_adjust, \ 174 adjust_index, \ 175 port_index) \ 176 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 177 pm_info->wb_vars_ids[tsAdjust], \ 178 (uint8 *)port_ts_adjust, adjust_index, port_index) 179 180 #define PM4x25_PORT_TIME_STAMP_ADJUST_GET(unit, pm_info, \ 181 port_ts_adjust, \ 182 adjust_index, \ 183 port_index) \ 184 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 185 pm_info->wb_vars_ids[tsAdjust], \ 186 (uint8 *)port_ts_adjust, adjust_index, port_index) 187 188 #define PM4x25_PORT_PLL_DIVIDER_REQ_SET(unit, pm_info, \ 189 pll_divider_req, \ 190 port_index) \ 191 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 192 pm_info->wb_vars_ids[pllDividerReq], \ 193 &pll_divider_req, port_index) 194 #define PM4x25_PORT_PLL_DIVIDER_REQ_GET(unit, pm_info, \ 195 pll_divider_req, \ 196 port_index) \ 197 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 198 pm_info->wb_vars_ids[pllDividerReq], \ 199 pll_divider_req, port_index) 200 201 #define PM4x25_PORT_1000X_AT_25G_SET(unit, pm_info, \ 202 serdes_1000x_at_25g_vco, \ 203 port_index) \ 204 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 205 pm_info->wb_vars_ids[serdes1000xAt25gVco], \ 206 &serdes_1000x_at_25g_vco, port_index) 207 #define PM4x25_PORT_1000X_AT_25G_GET(unit, pm_info, \ 208 serdes_1000x_at_25g_vco, \ 209 port_index) \ 210 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 211 pm_info->wb_vars_ids[serdes1000xAt25gVco], \ 212 serdes_1000x_at_25g_vco, port_index) 213 214 #define PM4x25_PORT_10G_AT_25G_SET(unit, pm_info, \ 215 serdes_10g_at_25g_vco, \ 216 port_index) \ 217 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 218 pm_info->wb_vars_ids[serdes10gAt25gVco], \ 219 &serdes_10g_at_25g_vco, port_index) 220 #define PM4x25_PORT_10G_AT_25G_GET(unit, pm_info, \ 221 serdes_10g_at_25g_vco, \ 222 port_index) \ 223 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 224 pm_info->wb_vars_ids[serdes10gAt25gVco], \ 225 serdes_10g_at_25g_vco, port_index) 226 #define PM4x25_CPRI_PORT_VSD_ACTIVE_GROUP_SET(unit, pm_info, group_list, port_index) \ 227 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[cpriVsdActiveGrp], group_list, port_index) 228 #define PM4x25_CPRI_PORT_VSD_ACTIVE_GROUP_GET(unit, pm_info, group_list, port_index) \ 229 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[cpriVsdActiveGrp], group_list, port_index) 230 231 #define PM4x25_PORT_LINK_RECOVERY_SET(unit, pm_info, \ 232 link_recovery, \ 233 port_index) \ 234 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 235 pm_info->wb_vars_ids[linkRecovery], \ 236 &link_recovery, port_index) 237 #define PM4x25_PORT_LINK_RECOVERY_GET(unit, pm_info, \ 238 link_recovery, \ 239 port_index) \ 240 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 241 pm_info->wb_vars_ids[linkRecovery], \ 242 link_recovery, port_index) 243 244 245 246 typedef enum pm4x25_fabric_wb_vars{ 247 isActive = 0, /* specify the PM4x25 core is active (at least one port has been attached) */ 248 isBypassed, /*specify the PM is in Bypass mode - the MAC is not in use, some configurations do not apply*/ 249 isInitialized, /* specify initialization of all SerDes have been done */ 250 lane2portMap, /* map each lane in the PM to a logical port */ 251 threePortsMode, 252 phy_type, /* Phy type in PHYMOD dispatch phymod_dispatch_type_t */ 253 interfaceConfig, /* portmod_port_interface_config_t **removed** */ 254 portInitConfig, /* portmod_port_init_config_t **removed** */ 255 nofPhys,/* keep track of nun of phys (including internal Serdes. */ 256 maxSpeed, /* Max Port Speed Supported */ 257 interfaceType, /* interface of type soc_port_if_t */ 258 interfaceModes, /* see PHYMOD_INTF_MODES_ */ 259 isInterfaceRestore, /* interface should be restored from DB (otherwise retrieved from HW), replace PHYMOD_INTF_F_INTF_PARAM_SET_ONLY */ 260 isHg, /* specify wheather the port is higig port */ 261 anMode, /* spn_PHY_AN_MODE - Specify the AN mode */ 262 fsCl72, /* spn_FORCED_INIT_CL72 - if trainig should be enabled in Forced speed mode */ 263 cx4In10G, /* see PHYMOD_BAM_CL37_CAP_10G_CX4 */ 264 anCl72, /* spn_PHY_AN_C72 - Specify if the link training should be enabled */ 265 anFec, /* spn_FORCED_INIT_FEC specify if FEC should be enabled in AN mode */ 266 anMasterLane, /* spn_PHY_AUTONEG_MASTER_LANE - Specify the AN master lane */ 267 laneConnectionDb, /* represents the physical topology of the serdes and ext phy lanes */ 268 interfaceWrittenIntoOutmostPhy, /* the interface type written into the outmost PHY */ 269 portDynamicState, 270 tsAdjustOld, /* the time stamp adjust setting on MAC ** removed ** */ 271 pllDividerReq, /*pll_divider_req setting on the port */ 272 serdes1000xAt25gVco, /*1G working at 25g*/ 273 serdes10gAt25gVco, /*10G Base-R working at 25g*/ 274 cpriVsdActiveGrp, /* CPRI TX VSD active group */ 275 tsAdjust, /* the time stamp adjust setting on MAC */ 276 linkRecovery /* Used by the link recovery WAR */ 277 }pm4x25_wb_vars_t; 278 279 #define PM4x25_QUAD_MODE_IF(interface) \ 280 (interface == SOC_PORT_IF_CAUI || interface == SOC_PORT_IF_XLAUI) 281 282 #define PM4x25_DUAL_MODE_IF(interface) \ 283 (interface == SOC_PORT_IF_XLAUI2) 284 285 #define PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc) \ 286 do { \ 287 uint32 is_bypass; \ 288 phy_acc = 0; \ 289 PM4x25_IS_BYPASSED_GET(unit, pm_info, &is_bypass); \ 290 phy_acc = (is_bypass && PM_4x25_INFO(pm_info)->first_phy != -1) ? (PM_4x25_INFO(pm_info)->first_phy | SOC_REG_ADDR_PHY_ACC_MASK) : port ; \ 291 } while (0) 292 293 #define PORTMOD_PM4x25_IS_GEN1(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && (pm_version.gen == PM_GEN1)) 294 #define PORTMOD_PM4x25_IS_GEN1_GEN2(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && ((pm_version.gen == PM_GEN1) || (pm_version.gen == PM_GEN2))) 295 #define PORTMOD_PM4x25_IS_GEN2_16nm(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && (pm_version.gen == PM_GEN2) && (pm_version.tech_process == PM_TECH_16NM)) 296 #define PORTMOD_PM4x25_IS_GEN2_28nm(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && (pm_version.gen == PM_GEN2) && (pm_version.tech_process == PM_TECH_28NM)) 297 #define PORTMOD_PM4x25_IS_GEN3_16nm(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && (pm_version.gen == PM_GEN3) && (pm_version.tech_process == PM_TECH_16NM)) 298 #define PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) ((pm_version.type == PM_TYPE_PM4X25) && (pm_version.gen == PM_GEN3) && (pm_version.tech_process == PM_TECH_28NM)) 299 #define PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version) ((pm_version.type == PM_TYPE_CPM4X25) && (pm_version.gen == PM_GEN3) && (pm_version.tech_process == PM_TECH_28NM)) 300 #define PORTMOD_PM4x25_REVISION_IS_A0(pm_version) ((pm_version.revision_letter == PM_REVISION_A) && (pm_version.revision_number == PM_REVISION_0)) 301 /* Add other revision check here */ 302 303 #define TXPI_DSM_VALUE_1PPM_HI (uint32) 0x29 /* 1ppm value is 1.80144E+11 (0x29F16B11C7) in register */ 304 #define TXPI_DSM_VALUE_1PPM_LO (uint32) 0xF16B11C7 305 #define PFC_FRAME_DETECTED_RSV_MASK 0x40000 306 307 #define DEFAULT_OSR2P5_SET 1 308 309 STATIC 310 int pm4x25_port_soft_reset(int unit, int port, pm_info_t pm_info, int enable); 311 312 STATIC int 313 _pm4x25_pm_ext_tsc_clk_set(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info); 314 315 STATIC int 316 _pm4x25_init_plls_get(int unit, int port, pm_info_t pm_info, portmod_vcos_speed_config_t *speed_config, int size, phymod_dual_plls_t *init_plls); 317 318 STATIC int 319 _pm4x25_port_tsc_is_master_pll(int unit, int port, pm_info_t pm_info); 320 321 322 STATIC 323 int _pm4x25_pm_version_get(int unit, pm_info_t pm_info, pm_version_t *version) 324 { 325 uint32 raddr, reg_val, pm_type; 326 int phy_port, block; 327 uint8 access_type; 328 329 SOC_INIT_FUNC_DEFS; 330 331 version->type = PM_TYPE_INVALID; 332 version->gen = PM_GEN_INVALID; 333 version->tech_process = PM_TECH_INVALID; 334 version->revision_number = PM_REVISION_NUM_INVALID; 335 version->revision_letter = PM_REVISION_LETTER_INVALID; 336 337 /* 338 * PM version ID register is not defined in PM GEN1. 339 * PM12x10 only has gen1 now. To be fixed if support PM12X10 gen2. 340 */ 341 if (SOC_REG_IS_VALID(unit, CLPORT_PM_VERSION_IDr) && 342 (!PM_4x25_INFO(pm_info)->in_pm12x10)) { 343 344 /* Get the first physical port of the pm core */ 345 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy_port) { 346 break; 347 } 348 349 raddr = soc_reg_addr_get(unit, CLPORT_PM_VERSION_IDr, phy_port, 0, 350 SOC_REG_ADDR_OPTION_PRESERVE_PORT, &block, &access_type); 351 _SOC_IF_ERR_EXIT(_soc_reg32_get(unit, block, access_type, raddr, ®_val)); 352 353 pm_type = soc_reg_field_get(unit, CLPORT_PM_VERSION_IDr, reg_val, PM_TYPEf); 354 if (pm_type == 1) { 355 version->type = PM_TYPE_PM4X25; 356 version->gen = PM_GEN2; 357 } 358 else if (pm_type == 6) { 359 version->type = PM_TYPE_PM4X25; 360 version->gen = PM_GEN3; 361 } 362 else if (pm_type == 7) { 363 version->type = PM_TYPE_CPM4X25; 364 version->gen = PM_GEN3; 365 } 366 /* The hardware value of techology/revision starts from 0 */ 367 version->tech_process = soc_reg_field_get(unit, CLPORT_PM_VERSION_IDr, reg_val, TECH_PROCESSf) + 1; 368 version->revision_number = soc_reg_field_get(unit, CLPORT_PM_VERSION_IDr, reg_val, REV_NUMBERf) + 1; 369 version->revision_letter = soc_reg_field_get(unit, CLPORT_PM_VERSION_IDr, reg_val, REV_LETTERf) + 1; 370 } else { 371 version->type = PM_TYPE_PM4X25; 372 version->gen = PM_GEN1; 373 } 374 375 exit: 376 SOC_FUNC_RETURN; 377 } 378 379 380 int pm4x25_pm_interface_type_is_supported(int unit, soc_port_if_t interface, 381 int* is_supported) 382 { 383 SOC_INIT_FUNC_DEFS; 384 385 switch(interface){ 386 case SOC_PORT_IF_CAUI: 387 case SOC_PORT_IF_XLAUI2: 388 case SOC_PORT_IF_XLAUI: 389 case SOC_PORT_IF_XFI: 390 case SOC_PORT_IF_SFI: 391 case SOC_PORT_IF_RXAUI: 392 case SOC_PORT_IF_DNX_XAUI: 393 case SOC_PORT_IF_SR: 394 case SOC_PORT_IF_SR2: 395 case SOC_PORT_IF_SR4: 396 case SOC_PORT_IF_KR: 397 case SOC_PORT_IF_KR2: 398 case SOC_PORT_IF_KR4: 399 case SOC_PORT_IF_CR: 400 case SOC_PORT_IF_CR2: 401 case SOC_PORT_IF_CR4: 402 case SOC_PORT_IF_SGMII: 403 case SOC_PORT_IF_GMII: 404 case SOC_PORT_IF_CAUI4: 405 *is_supported = TRUE; 406 break; 407 default: 408 *is_supported = FALSE; 409 break; 410 } 411 SOC_FUNC_RETURN; 412 } 413 414 STATIC 415 int _pm4x25_port_index_get(int unit, int port, pm_info_t pm_info, 416 int *first_index, uint32 *bitmap) 417 { 418 int i, rv = 0, tmp_port = 0; 419 420 SOC_INIT_FUNC_DEFS; 421 422 *first_index = -1; 423 *bitmap = 0; 424 425 for( i = 0 ; i < MAX_PORTS_PER_PM4X25; i++){ 426 rv = PM4x25_LANE2PORT_GET(unit, pm_info, i, &tmp_port); 427 _SOC_IF_ERR_EXIT(rv); 428 429 if(tmp_port == port){ 430 *first_index = (*first_index == -1 ? i : *first_index); 431 SHR_BITSET(bitmap, i); 432 } 433 } 434 435 if(*first_index == -1) { 436 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 437 (_SOC_MSG("port was not found in internal DB %d"), port)); 438 } 439 440 exit: 441 SOC_FUNC_RETURN; 442 } 443 444 /* 445 * Function: 446 * portmod_pm4x25_wb_upgrade_func 447 * Purpose: 448 * This function will take care of the warmboot variable manipulation 449 * in case of upgrade case, when variable definition got change or 450 * unspoorted varaible from previous version. 451 * Parameters: 452 * unit -(IN) Device unit number . 453 * arg -(IN) Generic pointer for a specific module to be used. 454 * recovered_version -(IN) Warmboot version of the existing data. 455 * new_version -(IN) Warmboot version of new data. 456 * Returns: 457 * Status 458 */ 459 460 int portmod_pm4x25_wb_upgrade_func(int unit, void *arg, int recovered_version, int new_version) 461 { 462 pm_info_t pm_info; 463 int i, adjust_index; 464 int nof_phys, dynamic_state, pll_divider_req, serdes_1000x_at_25g_vco, serdes_10g_at_25g_vco; 465 portmod_port_ts_adjust_t port_ts_adjust; 466 soc_port_if_t interface; 467 uint32 vsd_active_group[4]={0}; 468 portmod_link_recovery_t link_recovery; 469 SOC_INIT_FUNC_DEFS; 470 471 pm_info = arg; 472 473 /* 474 * skip the warmboot db restore, it is only needed for 475 * upgrades for version below 7. 476 */ 477 478 if (recovered_version <= 6) { 479 PM_4x25_INFO(pm_info)->warmboot_skip_db_restore = FALSE; 480 } else { 481 PM_4x25_INFO(pm_info)->warmboot_skip_db_restore = TRUE; 482 } 483 484 if ((recovered_version <= 5) && 485 (new_version >= 6)) { 486 487 /* 488 * in version 4 or earlier, nof_phys was not populated properly. 489 * It need to initialize to 1 to count for internal phy. 1 may not 490 * be proper value as some port may have ext phy. 491 */ 492 if(!PM_4x25_INFO(pm_info)->in_pm12x10){ 493 nof_phys = 1; 494 } else { 495 nof_phys = 0; 496 } 497 for(i = 0 ; i < PM4X25_LANES_PER_CORE ; i++){ 498 _SOC_IF_ERR_EXIT(PM4x25_PORT_NUM_PHYS_SET(unit, pm_info, nof_phys, i)); 499 PM_4x25_INFO(pm_info)->nof_phys[i] = nof_phys; 500 } 501 } 502 503 if ((recovered_version <= 6) && 504 (new_version >= 7)) { 505 /* interface_written_into_outmost_phy does not exist in version 6 or earlier */ 506 interface = SOC_PORT_IF_COUNT; 507 for (i = 0 ; i < MAX_PORTS_PER_PM4X25 ; i++) { 508 _SOC_IF_ERR_EXIT( 509 PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, i)); 510 } 511 } 512 513 if ((recovered_version <= 7) && 514 (new_version >= 8)) { 515 dynamic_state = 0; 516 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 517 _SOC_IF_ERR_EXIT( 518 PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, dynamic_state, i)); 519 } 520 } 521 522 if ((recovered_version <= 8) && 523 (new_version >= 9)) { 524 sal_memset(&port_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 525 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 526 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM_OLD; adjust_index++) { 527 _SOC_IF_ERR_EXIT( 528 PM4x25_PORT_TIME_STAMP_ADJUST_OLD_SET(unit, pm_info, &port_ts_adjust, 529 adjust_index, i)); 530 } 531 } 532 } 533 534 if ((recovered_version <= 9) && 535 (new_version >= 10)) { 536 pll_divider_req = 0; 537 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 538 _SOC_IF_ERR_EXIT( 539 PM4x25_PORT_PLL_DIVIDER_REQ_SET(unit, pm_info, pll_divider_req, i)); 540 } 541 } 542 543 if ((recovered_version <= 10) && 544 (new_version >= 11)) { 545 serdes_1000x_at_25g_vco = 0; 546 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 547 _SOC_IF_ERR_EXIT( 548 PM4x25_PORT_1000X_AT_25G_SET(unit, pm_info, serdes_1000x_at_25g_vco, i)); 549 } 550 551 serdes_10g_at_25g_vco = 0; 552 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 553 _SOC_IF_ERR_EXIT( 554 PM4x25_PORT_10G_AT_25G_SET(unit, pm_info, serdes_10g_at_25g_vco, i)); 555 } 556 } 557 if ((recovered_version <= 11) && 558 (new_version >= 12)) { 559 sal_memset(vsd_active_group, 0, sizeof(uint32_t)*NUM_VSD_ACTIVE_GROUP_WORD); 560 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 561 _SOC_IF_ERR_EXIT( 562 PM4x25_CPRI_PORT_VSD_ACTIVE_GROUP_SET(unit, pm_info, vsd_active_group, i)); 563 } 564 } 565 566 if ((recovered_version <= 11) && 567 (new_version >= 12)) { 568 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 569 /* Copy existing timestamp adjust configs from old WB variable. */ 570 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM_OLD; adjust_index++) { 571 _SOC_IF_ERR_EXIT( 572 PM4x25_PORT_TIME_STAMP_ADJUST_OLD_GET(unit, pm_info, &port_ts_adjust, 573 adjust_index, i)); 574 _SOC_IF_ERR_EXIT( 575 PM4x25_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, &port_ts_adjust, 576 adjust_index, i)); 577 } 578 /* Initialize new timestamp adjust configs as 0. */ 579 while (adjust_index < PORTMOD_TS_ADJUST_NUM) { 580 sal_memset(&port_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 581 _SOC_IF_ERR_EXIT( 582 PM4x25_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, &port_ts_adjust, 583 adjust_index, i)); 584 adjust_index++; 585 } 586 } 587 } 588 589 if ((recovered_version <= 12) && 590 (new_version >= 13)) { 591 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK; 592 link_recovery.enabled = TRUE; 593 link_recovery.tick_cnt = 0; 594 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 595 _SOC_IF_ERR_EXIT( 596 PM4x25_PORT_LINK_RECOVERY_SET(unit, pm_info, link_recovery, i)); 597 } 598 } 599 600 601 exit: 602 SOC_FUNC_RETURN; 603 } 604 605 /* 606 * Initialize the buffer to support warmboot 607 * The state of warmboot is store in the variables like 608 * isInitialized, isActive, isBypassed, ports.. etc., 609 * All of these variables need to be added to warmboot 610 * any variables added to save the state of warmboot should be 611 * included here. 612 */ 613 STATIC 614 int pm4x25_wb_buffer_init(int unit, int wb_buffer_index, pm_info_t pm_info) 615 { 616 /* Declare the common variables needed for warmboot */ 617 WB_ENGINE_INIT_TABLES_DEFS; 618 int wb_var_id, rv; 619 int buffer_id = wb_buffer_index; /*required by SOC_WB_ENGINE_ADD_ Macros*/ 620 SOC_INIT_FUNC_DEFS; 621 622 COMPILER_REFERENCE(buffer_is_dynamic); 623 624 SOC_WB_ENGINE_ADD_BUFF(SOC_WB_ENGINE_PORTMOD, wb_buffer_index, "pm4x25", portmod_pm4x25_wb_upgrade_func, pm_info, PM4x25_WB_BUFFER_VERSION, 1, SOC_WB_ENGINE_PRE_RELEASE); 625 _SOC_IF_ERR_EXIT(rv); 626 627 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 628 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "lane2portMap", wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM4X25, VERSION(1)); 629 _SOC_IF_ERR_EXIT(rv); 630 pm_info->wb_vars_ids[lane2portMap] = wb_var_id; 631 632 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 633 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_active", wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 634 _SOC_IF_ERR_EXIT(rv); 635 pm_info->wb_vars_ids[isActive] = wb_var_id; 636 637 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 638 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_initialized", wb_buffer_index, sizeof(uint32), NULL, VERSION(2)); 639 _SOC_IF_ERR_EXIT(rv); 640 pm_info->wb_vars_ids[isInitialized] = wb_var_id; 641 642 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 643 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_bypassed", wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 644 _SOC_IF_ERR_EXIT(rv); 645 pm_info->wb_vars_ids[isBypassed] = wb_var_id; 646 647 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 648 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "three_ports_mode", wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 649 _SOC_IF_ERR_EXIT(rv); 650 pm_info->wb_vars_ids[threePortsMode] = wb_var_id; 651 652 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 653 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "phy_type", wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM4X25, VERSION(1)); 654 _SOC_IF_ERR_EXIT(rv); 655 pm_info->wb_vars_ids[phy_type] = wb_var_id; 656 657 /* Deleting the below WB structures since most likely to be added in the future in a diffrent format */ 658 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 659 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_config", wb_buffer_index, sizeof(portmod_port_interface_config_t), NULL, 1, 1, 0xffffffff, 0xffffffff, VERSION(3), VERSION(4), NULL); 660 _SOC_IF_ERR_EXIT(rv); 661 pm_info->wb_vars_ids[interfaceConfig] = wb_var_id; 662 663 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 664 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, "port_init_config", wb_buffer_index, sizeof(portmod_port_init_config_t), NULL, 1, 1, 0xffffffff, 0xffffffff, VERSION(3), VERSION(4), NULL); 665 _SOC_IF_ERR_EXIT(rv); 666 pm_info->wb_vars_ids[portInitConfig] = wb_var_id; 667 668 /* Keeping the below WB arr since most likely to be used in the future */ 669 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 670 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "nof_phys", wb_buffer_index, sizeof(int), NULL, PM4X25_LANES_PER_CORE, VERSION(3)); 671 _SOC_IF_ERR_EXIT(rv); 672 pm_info->wb_vars_ids[nofPhys] = wb_var_id; 673 674 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 675 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "max_speed", wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM4X25, VERSION(5)); 676 _SOC_IF_ERR_EXIT(rv); 677 pm_info->wb_vars_ids[maxSpeed] = wb_var_id; 678 679 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 680 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_type", wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM4X25, VERSION(5)); 681 _SOC_IF_ERR_EXIT(rv); 682 pm_info->wb_vars_ids[interfaceType] = wb_var_id; 683 684 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 685 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_modes", wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM4X25, VERSION(5)); 686 _SOC_IF_ERR_EXIT(rv); 687 pm_info->wb_vars_ids[interfaceModes] = wb_var_id; 688 689 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 690 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_interface_restore", wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM4X25, VERSION(5)); 691 _SOC_IF_ERR_EXIT(rv); 692 pm_info->wb_vars_ids[isInterfaceRestore] = wb_var_id; 693 694 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 695 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_hg", wb_buffer_index, sizeof(uint32), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 696 _SOC_IF_ERR_EXIT(rv); 697 pm_info->wb_vars_ids[isHg] = wb_var_id; 698 699 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 700 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_mode", wb_buffer_index, sizeof(int), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 701 _SOC_IF_ERR_EXIT(rv); 702 pm_info->wb_vars_ids[anMode] = wb_var_id; 703 704 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 705 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "fs_cl72", wb_buffer_index, sizeof(uint32), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 706 _SOC_IF_ERR_EXIT(rv); 707 pm_info->wb_vars_ids[fsCl72] = wb_var_id; 708 709 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 710 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "cx4_10G", wb_buffer_index, sizeof(uint32), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 711 _SOC_IF_ERR_EXIT(rv); 712 pm_info->wb_vars_ids[cx4In10G] = wb_var_id; 713 714 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 715 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_cl72", wb_buffer_index, sizeof(uint32), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 716 _SOC_IF_ERR_EXIT(rv); 717 pm_info->wb_vars_ids[anCl72] = wb_var_id; 718 719 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 720 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_fec", wb_buffer_index, sizeof(uint32), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 721 _SOC_IF_ERR_EXIT(rv); 722 pm_info->wb_vars_ids[anFec] = wb_var_id; 723 724 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 725 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_master_lane", wb_buffer_index, sizeof(int), NULL, PM4X25_LANES_PER_CORE, VERSION(5)); 726 _SOC_IF_ERR_EXIT(rv); 727 pm_info->wb_vars_ids[anMasterLane] = wb_var_id; 728 729 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 730 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "lane_connection_db", 731 wb_buffer_index, sizeof(portmod_xphy_lane_connection_t), NULL, 732 PM4X25_LANES_PER_CORE, MAX_PHYN, VERSION(6)); 733 _SOC_IF_ERR_EXIT(rv); 734 pm_info->wb_vars_ids[laneConnectionDb] = wb_var_id; 735 736 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 737 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_written_into_outmost_phy", 738 wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM4X25, VERSION(7)); 739 _SOC_IF_ERR_EXIT(rv); 740 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy] = wb_var_id; 741 742 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 743 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 744 "port_dynamic_state", wb_buffer_index, 745 sizeof(uint32_t), NULL, MAX_PORTS_PER_PM4X25, 746 VERSION(8)); 747 _SOC_IF_ERR_EXIT(rv); 748 pm_info->wb_vars_ids[portDynamicState] = wb_var_id; 749 750 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 751 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 752 "time stamp adjust setting on MAC", wb_buffer_index, 753 sizeof(portmod_port_ts_adjust_t), NULL, 754 PORTMOD_TS_ADJUST_NUM_OLD, MAX_PORTS_PER_PM4X25, 755 VERSION(9)); 756 _SOC_IF_ERR_EXIT(rv); 757 pm_info->wb_vars_ids[tsAdjustOld] = wb_var_id; 758 759 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 760 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 761 "pll_divider_req", wb_buffer_index, 762 sizeof(uint32_t), NULL, MAX_PORTS_PER_PM4X25, 763 VERSION(10)); 764 _SOC_IF_ERR_EXIT(rv); 765 pm_info->wb_vars_ids[pllDividerReq] = wb_var_id; 766 767 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 768 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 769 "serdes_1000x_at_25g_vco", wb_buffer_index, 770 sizeof(uint32_t), NULL, MAX_PORTS_PER_PM4X25, 771 VERSION(11)); 772 _SOC_IF_ERR_EXIT(rv); 773 pm_info->wb_vars_ids[serdes1000xAt25gVco] = wb_var_id; 774 775 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 776 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 777 "serdes_10g_at_25g_vco", wb_buffer_index, 778 sizeof(uint32_t), NULL, MAX_PORTS_PER_PM4X25, 779 VERSION(11)); 780 _SOC_IF_ERR_EXIT(rv); 781 pm_info->wb_vars_ids[serdes10gAt25gVco] = wb_var_id; 782 783 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 784 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 785 "cpri_tx_vsd_active_grp", wb_buffer_index, 786 sizeof(uint32_t)*NUM_VSD_ACTIVE_GROUP_WORD, NULL, MAX_PORTS_PER_PM4X25, 787 VERSION(12)); 788 _SOC_IF_ERR_EXIT(rv); 789 pm_info->wb_vars_ids[cpriVsdActiveGrp] = wb_var_id; 790 791 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 792 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 793 "new time stamp adjust setting on MAC", wb_buffer_index, 794 sizeof(portmod_port_ts_adjust_t), NULL, 795 PORTMOD_TS_ADJUST_NUM, MAX_PORTS_PER_PM4X25, 796 VERSION(12)); 797 _SOC_IF_ERR_EXIT(rv); 798 pm_info->wb_vars_ids[tsAdjust] = wb_var_id; 799 800 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 801 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 802 "link_recovery", wb_buffer_index, 803 sizeof(portmod_link_recovery_t), NULL, MAX_PORTS_PER_PM4X25, 804 VERSION(13)); 805 _SOC_IF_ERR_EXIT(rv); 806 pm_info->wb_vars_ids[linkRecovery] = wb_var_id; 807 808 _SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD, wb_buffer_index, FALSE)); 809 if(!SOC_WARM_BOOT(unit)){ 810 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[lane2portMap], -1); 811 _SOC_IF_ERR_EXIT(rv); 812 813 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[maxSpeed], 0); 814 _SOC_IF_ERR_EXIT(rv); 815 816 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceType], _SHR_PORT_IF_COUNT); 817 _SOC_IF_ERR_EXIT(rv); 818 819 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceModes], 0); 820 _SOC_IF_ERR_EXIT(rv); 821 822 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isInterfaceRestore], 0); 823 _SOC_IF_ERR_EXIT(rv); 824 825 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isHg], _SHR_PORT_IF_COUNT); 826 _SOC_IF_ERR_EXIT(rv); 827 828 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMode], phymod_AN_MODE_Count); 829 _SOC_IF_ERR_EXIT(rv); 830 831 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[fsCl72], 0); 832 _SOC_IF_ERR_EXIT(rv); 833 834 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[cx4In10G], 0); 835 _SOC_IF_ERR_EXIT(rv); 836 837 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anCl72], 0); 838 _SOC_IF_ERR_EXIT(rv); 839 840 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anFec], 0); 841 _SOC_IF_ERR_EXIT(rv); 842 843 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[anMasterLane], -1); 844 _SOC_IF_ERR_EXIT(rv); 845 846 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], _SHR_PORT_IF_COUNT); 847 _SOC_IF_ERR_EXIT(rv); 848 849 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 850 pm_info->wb_vars_ids[portDynamicState], 0); 851 852 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 853 pm_info->wb_vars_ids[pllDividerReq], 0); 854 855 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 856 pm_info->wb_vars_ids[serdes1000xAt25gVco], 0); 857 858 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 859 pm_info->wb_vars_ids[serdes10gAt25gVco], 0); 860 861 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 862 pm_info->wb_vars_ids[cpriVsdActiveGrp], 0); 863 _SOC_IF_ERR_EXIT(rv); 864 865 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 866 pm_info->wb_vars_ids[linkRecovery], 0); 867 _SOC_IF_ERR_EXIT(rv); 868 } 869 870 exit: 871 SOC_FUNC_RETURN; 872 } 873 874 STATIC portmod_ucode_buf_t pm4x25_ucode_buf[SOC_MAX_NUM_DEVICES] = {{NULL, 0}}; 875 STATIC portmod_ucode_buf_t pm4x25_ucode_buf_2nd[SOC_MAX_NUM_DEVICES] = {{NULL, 0}}; 876 877 int pm4x25_pm_destroy(int unit, pm_info_t pm_info) 878 { 879 SOC_INIT_FUNC_DEFS; 880 881 if(pm_info->pm_data.pm4x25_db != NULL){ 882 sal_free(pm_info->pm_data.pm4x25_db); 883 pm_info->pm_data.pm4x25_db = NULL; 884 } 885 886 /* free pm4x25_ucode_buf */ 887 if(pm4x25_ucode_buf[unit].ucode_dma_buf != NULL){ 888 portmod_sys_dma_free(unit, pm4x25_ucode_buf[unit].ucode_dma_buf); 889 pm4x25_ucode_buf[unit].ucode_dma_buf = NULL; 890 } 891 pm4x25_ucode_buf[unit].ucode_alloc_size = 0; 892 893 if(pm4x25_ucode_buf_2nd[unit].ucode_dma_buf != NULL){ 894 portmod_sys_dma_free(unit, pm4x25_ucode_buf_2nd[unit].ucode_dma_buf); 895 pm4x25_ucode_buf_2nd[unit].ucode_dma_buf = NULL; 896 } 897 pm4x25_ucode_buf_2nd[unit].ucode_alloc_size = 0; 898 899 SOC_FUNC_RETURN; 900 } 901 902 int 903 pm4x25_default_fw_loader(const phymod_core_access_t* core, uint32_t length, const uint8_t* data) 904 { 905 int rv, bcast_en = 0; 906 portmod_default_user_access_t *user_data; 907 int unit = ((portmod_default_user_access_t*)core->access.user_acc)->unit; 908 portmod_ucode_buf_order_t load_order; 909 SOC_INIT_FUNC_DEFS; 910 911 user_data = (portmod_default_user_access_t*)core->access.user_acc; 912 913 if (PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_GET(user_data)) { 914 load_order = portmod_ucode_buf_order_reversed; 915 } else { 916 load_order = portmod_ucode_buf_order_straight; 917 } 918 919 #ifdef FW_BCAST_DOWNLOAD 920 if (PORTMOD_USER_ACCESS_FW_LOAD_BROADCAST_GET(user_data)) { 921 bcast_en = 1; 922 } 923 #endif 924 925 rv = portmod_firmware_set(unit, 926 user_data->blk_id, 927 data, 928 length, 929 load_order, 930 bcast_en, 931 &(pm4x25_ucode_buf[unit]), 932 &(pm4x25_ucode_buf_2nd[unit]), 933 CLPORT_WC_UCMEM_DATAm, 934 CLPORT_WC_UCMEM_CTRLr); 935 _SOC_IF_ERR_EXIT(rv); 936 937 exit: 938 SOC_FUNC_RETURN; 939 } 940 941 STATIC 942 int 943 pm4x25_default_bus_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 944 { 945 return portmod_common_phy_sbus_reg_write(CLPORT_WC_UCMEM_DATAm, user_acc, core_addr, reg_addr, val); 946 } 947 948 STATIC 949 int 950 pm4x25_default_bus_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 951 { 952 return portmod_common_phy_sbus_reg_read(CLPORT_WC_UCMEM_DATAm, user_acc, core_addr, reg_addr, val); 953 } 954 955 STATIC 956 int _pm4x25_port_soft_reset_set(int unit, int port, pm_info_t pm_info, int idx, int val) 957 { 958 int phy_acc; 959 uint32 reg_val; 960 961 SOC_INIT_FUNC_DEFS; 962 963 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 964 965 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 966 967 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT0f, val); 968 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT1f, val); 969 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT2f, val); 970 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT3f, val); 971 972 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 973 974 exit: 975 SOC_FUNC_RETURN; 976 } 977 int pm4x25_port_soft_reset_toggle(int unit, int port, pm_info_t pm_info, int idx) 978 { 979 int phy_acc; 980 uint32 reg_val, old_val; 981 982 SOC_INIT_FUNC_DEFS; 983 984 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 985 986 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 987 old_val = reg_val; 988 989 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT0f, 1); 990 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT1f, 1); 991 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT2f, 1); 992 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, PORT3f, 1); 993 994 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 995 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, old_val)); 996 997 exit: 998 SOC_FUNC_RETURN; 999 } 1000 1001 phymod_bus_t pm4x25_default_bus = { 1002 "PM4x25 Bus", 1003 pm4x25_default_bus_read, 1004 pm4x25_default_bus_write, 1005 NULL, 1006 portmod_common_mutex_take, 1007 portmod_common_mutex_give, 1008 NULL, 1009 NULL, 1010 PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL 1011 }; 1012 1013 int pm4x25_pm_init(int unit, 1014 const portmod_pm_create_info_internal_t* pm_add_info, 1015 int wb_buffer_index, pm_info_t pm_info) 1016 { 1017 const portmod_pm4x25_create_info_t *info = &pm_add_info->pm_specific_info.pm4x25; 1018 pm4x25_t pm4x25_data = NULL; 1019 int i,j, pm_is_active, rv, three_ports_mode; 1020 int bypass_enable; 1021 int pm_is_initialized; 1022 portmod_xphy_lane_connection_t lane_conn; 1023 portmod_xphy_lane_connection_t *db_lane_conn; 1024 int lane, phyn; 1025 SOC_INIT_FUNC_DEFS; 1026 1027 pm_info->type = pm_add_info->type; 1028 pm_info->unit = unit; 1029 pm_info->wb_buffer_id = wb_buffer_index; 1030 1031 /* PM4x25 specific info */ 1032 pm4x25_data = sal_alloc(sizeof(struct pm4x25_s), "specific_db"); 1033 SOC_NULL_CHECK(pm4x25_data); 1034 pm_info->pm_data.pm4x25_db = pm4x25_data; 1035 1036 PORTMOD_PBMP_ASSIGN(pm4x25_data->phys, pm_add_info->phys); 1037 pm4x25_data->int_core_access.type = phymodDispatchTypeInvalid; 1038 pm4x25_data->portmod_mac_soft_reset = pm_add_info->pm_specific_info.pm4x25.portmod_mac_soft_reset; 1039 pm4x25_data->first_phy = -1; 1040 pm4x25_data->warmboot_skip_db_restore = TRUE; 1041 pm4x25_data->rescal = pm_add_info->pm_specific_info.pm4x25.rescal; 1042 1043 for(i = 0 ; i < PM4X25_LANES_PER_CORE; i++){ 1044 pm4x25_data->nof_phys[i] = 0; 1045 } 1046 1047 /* init intertnal SerDes core access */ 1048 phymod_core_access_t_init(&pm4x25_data->int_core_access); 1049 1050 /* initialize lane connections */ 1051 for(i = 0 ; i < MAX_PHYN ; i++){ 1052 for(j = 0 ; j < PM4X25_LANES_PER_CORE ; j++){ 1053 portmod_xphy_lane_connection_t_init(unit, &pm4x25_data->lane_conn[i][j]); 1054 } 1055 } 1056 1057 if(!info->in_pm_12x10){ 1058 sal_memcpy(&pm4x25_data->polarity, &info->polarity, sizeof(phymod_polarity_t)); 1059 sal_memcpy(&(pm4x25_data->int_core_access.access), &info->access, 1060 sizeof(phymod_access_t)); 1061 1062 sal_memcpy(&pm4x25_data->lane_map, &info->lane_map, 1063 sizeof(pm4x25_data->lane_map)); 1064 pm4x25_data->ref_clk = info->ref_clk; 1065 pm4x25_data->fw_load_method = info->fw_load_method; 1066 pm4x25_data->external_fw_loader = info->external_fw_loader; 1067 1068 if(info->access.bus == NULL) { 1069 /* if null - use default */ 1070 pm4x25_data->int_core_access.access.bus = &pm4x25_default_bus; 1071 } 1072 1073 if(pm4x25_data->external_fw_loader == NULL) { 1074 /* if null - use default */ 1075 pm4x25_data->external_fw_loader = pm4x25_default_fw_loader; 1076 } 1077 1078 for(i = 0 ; i < PM4X25_LANES_PER_CORE; i++){ 1079 pm4x25_data->nof_phys[i] = 1; /* Internal Phy */ 1080 } 1081 } 1082 pm4x25_data->in_pm12x10 = info->in_pm_12x10; 1083 pm4x25_data->core_num = info->core_num; 1084 pm4x25_data->afe_pll = info->afe_pll; 1085 1086 /*init wb buffer*/ 1087 _SOC_IF_ERR_EXIT(pm4x25_wb_buffer_init(unit, wb_buffer_index, pm_info)); 1088 1089 if(SOC_WARM_BOOT(unit)){ 1090 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1091 pm_info->wb_vars_ids[phy_type], &pm4x25_data->int_core_access.type ); 1092 _SOC_IF_ERR_EXIT(rv); 1093 1094 /* restore nof_phys from wb */ 1095 for(i = 0 ; i < PM4X25_LANES_PER_CORE ; i++){ 1096 _SOC_IF_ERR_EXIT(PM4x25_PORT_NUM_PHYS_GET(unit, pm_info, &pm4x25_data->nof_phys[i], i)); 1097 } 1098 1099 for(phyn = 0 ; phyn < MAX_PHYN ; phyn++){ 1100 for(lane = 0 ; lane < PM4X25_LANES_PER_CORE ; lane++){ 1101 db_lane_conn = &(PM_4x25_INFO(pm_info)->lane_conn[phyn][lane]); 1102 _SOC_IF_ERR_EXIT(PM4x25_PORT_LANE_CONNECTION_DB_GET(unit, pm_info, 1103 db_lane_conn, phyn, lane)); 1104 } 1105 } 1106 } 1107 1108 if(!SOC_WARM_BOOT(unit)){ 1109 pm_is_active = 0; 1110 rv = PM4x25_IS_ACTIVE_SET(unit, pm_info, pm_is_active); 1111 _SOC_IF_ERR_EXIT(rv); 1112 1113 pm_is_initialized = 0; 1114 rv = PM4x25_IS_INITIALIZED_SET(unit, pm_info, pm_is_initialized); 1115 _SOC_IF_ERR_EXIT(rv); 1116 1117 bypass_enable = 0; 1118 rv = PM4x25_IS_BYPASSED_SET(unit, pm_info, bypass_enable); 1119 _SOC_IF_ERR_EXIT(rv); 1120 1121 three_ports_mode = (info->port_mode_aux_info == portmodModeInfoThreePorts) ? 1 : 0; 1122 rv = PM4x25_THREE_PORTS_MODE_SET(unit, pm_info, three_ports_mode); 1123 _SOC_IF_ERR_EXIT(rv); 1124 1125 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1126 pm_info->wb_vars_ids[phy_type], 1127 &PM_4x25_INFO(pm_info)->int_core_access.type, 0); 1128 _SOC_IF_ERR_EXIT(rv); 1129 1130 for(i = 0 ; i < PM4X25_LANES_PER_CORE ; i++){ 1131 rv = PM4x25_PORT_NUM_PHYS_SET(unit, pm_info, pm4x25_data->nof_phys[i], i); 1132 _SOC_IF_ERR_EXIT(rv); 1133 } 1134 1135 portmod_xphy_lane_connection_t_init(unit, &lane_conn); 1136 for(phyn = 0 ; phyn < MAX_PHYN ; phyn++){ 1137 for(lane = 0 ; lane < PM4X25_LANES_PER_CORE ; lane++){ 1138 _SOC_IF_ERR_EXIT(PM4x25_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, 1139 &lane_conn, phyn, lane)); 1140 } 1141 } 1142 } 1143 1144 exit: 1145 if(SOC_FUNC_ERROR){ 1146 pm4x25_pm_destroy(unit, pm_info); 1147 } 1148 SOC_FUNC_RETURN; 1149 } 1150 1151 int pm4x25_port_tsc_reset_set(int unit, int phy_acc, int in_reset) 1152 { 1153 uint32 reg_val; 1154 SOC_INIT_FUNC_DEFS; 1155 1156 /* Bring Internal Phy OOR */ 1157 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1158 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, RSTB_HWf, in_reset ? 0 : 1); 1159 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, PWRDWNf, in_reset ? 1 : 0); 1160 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, IDDQf, in_reset ? 1 : 0); 1161 _SOC_IF_ERR_EXIT(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val)); 1162 1163 /* Based on the feedback from SJ pmd support team, ~10-15usecs would be sufficient 1164 * for the PLL/AFE to settle down out of IDDQ reset. 1165 */ 1166 sal_usleep(10); 1167 1168 exit: 1169 SOC_FUNC_RETURN; 1170 } 1171 1172 STATIC 1173 int _pm4x25_port_tsc_refclock_set(int unit, int phy_acc, int ref_in, int ref_out) 1174 { 1175 uint32 reg_val; 1176 SOC_INIT_FUNC_DEFS; 1177 1178 /* choose refclk into this TSC PLL : 0 - PAD or 1- LCREF */ 1179 /* enable ref_out: LCREFout which connects to other PM blocks */ 1180 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1181 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, REFIN_ENf, ref_in ? 1 : 0); 1182 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, REFOUT_ENf, ref_out ? 1 : 0); 1183 _SOC_IF_ERR_EXIT(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val)); 1184 1185 exit: 1186 SOC_FUNC_RETURN; 1187 } 1188 1189 STATIC 1190 int _pm4x25_port_tsc_refclock_get(int unit, int phy_acc, int *ref_in, int *ref_out) 1191 { 1192 uint32 reg_val; 1193 SOC_INIT_FUNC_DEFS; 1194 1195 /* choose refin : PAD or LCREF */ 1196 /* enable ref_out: LCREFout which connects to other PM blocks */ 1197 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1198 *ref_in = soc_reg_field_get(unit, CLPORT_XGXS0_CTRL_REGr, reg_val, REFIN_ENf); 1199 *ref_out = soc_reg_field_get(unit, CLPORT_XGXS0_CTRL_REGr, reg_val, REFOUT_ENf); 1200 1201 exit: 1202 SOC_FUNC_RETURN; 1203 } 1204 1205 /* 1206 * Set PM TSC refer clock source and enable refer clock output to other TSC. 1207 * ref_in: Selects between pad and LCREF as source of refclk into this TSC PLL. 0 - PAD or 1- LCREF 1208 * ref_out: Enables LCREFOUT to be driven by this TSC. 0 - disable, 1 - enable 1209 * Note: If enable LCREF_out to other PMs TSC, this PM TSC work as master PM. 1210 * This TSC should be reset at in level before this port attaching. 1211 */ 1212 int pm4x25_port_tsc_refclock_set(int unit, int port, pm_info_t pm_info, int ref_in, int ref_out) 1213 { 1214 int phy_acc; 1215 1216 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1217 1218 return _pm4x25_port_tsc_refclock_set(unit, phy_acc, ref_in, ref_out); 1219 } 1220 1221 /* 1222 * Get PM TSC refer clock source and enable status of refer clock output to other TSC. 1223 * ref_in: 0 - PAD or 1- LCREF 1224 * ref_out: 1 - enable LCREF_out which connects to other PM blocks 1225 */ 1226 int pm4x25_port_tsc_refclock_get(int unit, int port, pm_info_t pm_info, int *ref_in, int *ref_out) 1227 { 1228 int phy_acc; 1229 1230 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1231 1232 return _pm4x25_port_tsc_refclock_get(unit, phy_acc, ref_in, ref_out); 1233 } 1234 1235 /* 1236 * Check the PM is a master PLL or not 1237 * For GEN1/GEN2, only need to check one PLL 1238 * For GEN3, need to check PLL0 and PLL1 1239 */ 1240 STATIC 1241 int _pm4x25_port_tsc_is_master_pll(int unit, int port, pm_info_t pm_info) 1242 { 1243 int phy_acc; 1244 uint32 reg_val; 1245 uint32 refclk_out_en_0 = 0, refclk_out_en_1 = 0; 1246 pm_version_t pm_version; 1247 SOC_INIT_FUNC_DEFS; 1248 1249 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1250 1251 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 1252 1253 if (PORTMOD_PM4x25_IS_GEN1_GEN2(pm_version)) { 1254 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1255 refclk_out_en_0 = soc_reg_field_get(unit, CLPORT_XGXS0_CTRL_REGr, reg_val, REFOUT_ENf); 1256 } else if (PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) { 1257 /* Valid only for G3 28nm PMD_28_FC, don't care for 16nm */ 1258 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1259 refclk_out_en_0 = soc_reg_field_get(unit, CLPORT_XGXS0_CTRL_REGr, reg_val, PLL0_REFOUT_ENf); 1260 refclk_out_en_1 = soc_reg_field_get(unit, CLPORT_XGXS0_CTRL_REGr, reg_val, PLL1_REFOUT_ENf); 1261 } else { 1262 refclk_out_en_0 = 0; 1263 refclk_out_en_1 = 0; 1264 } 1265 1266 if (refclk_out_en_0 || refclk_out_en_1) { 1267 return TRUE; 1268 } 1269 1270 return FALSE; 1271 1272 exit: 1273 SOC_FUNC_RETURN; 1274 } 1275 1276 static int _clport_mode_get(int unit, int phy_acc, int bindex, 1277 portmod_core_port_mode_t *core_mode, int *cur_lanes) 1278 { 1279 uint32_t rval; 1280 1281 SOC_INIT_FUNC_DEFS; 1282 1283 _SOC_IF_ERR_EXIT(READ_CLPORT_MODE_REGr(unit, phy_acc, &rval)); 1284 1285 *core_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval, XPORT0_CORE_PORT_MODEf); 1286 1287 switch (*core_mode) { 1288 case portmodPortModeQuad: 1289 *cur_lanes = 1; 1290 break; 1291 1292 case portmodPortModeTri012: 1293 *cur_lanes = bindex == 2 ? 2 : 1; 1294 break; 1295 1296 case portmodPortModeTri023: 1297 *cur_lanes = bindex == 0 ? 2 : 1; 1298 break; 1299 1300 case portmodPortModeDual: 1301 *cur_lanes = 2; 1302 break; 1303 1304 case portmodPortModeSingle: 1305 *cur_lanes = 4; 1306 break; 1307 1308 default: 1309 return SOC_E_FAIL; 1310 } 1311 exit: 1312 SOC_FUNC_RETURN; 1313 } 1314 1315 int pm4x25_port_cntmaxsize_get(int unit, int port, pm_info_t pm_info, int *val) 1316 { 1317 int phy_acc; 1318 SOC_INIT_FUNC_DEFS; 1319 1320 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1321 1322 _SOC_IF_ERR_EXIT(READ_CLPORT_CNTMAXSIZEr(unit, phy_acc, (uint32_t *)val)); 1323 1324 exit: 1325 SOC_FUNC_RETURN; 1326 } 1327 1328 int pm4x25_port_cntmaxsize_set(int unit, int port, pm_info_t pm_info, int val) 1329 { 1330 uint32 reg_val; 1331 int phy_acc; 1332 SOC_INIT_FUNC_DEFS; 1333 1334 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1335 1336 _SOC_IF_ERR_EXIT(READ_CLPORT_CNTMAXSIZEr(unit, phy_acc, ®_val)); 1337 1338 soc_reg_field_set(unit, CLPORT_CNTMAXSIZEr, ®_val, CNTMAXSIZEf, val); 1339 1340 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CNTMAXSIZEr(unit, phy_acc, reg_val)); 1341 1342 exit: 1343 SOC_FUNC_RETURN; 1344 } 1345 1346 int pm4x25_port_modid_set (int unit, int port, pm_info_t pm_info, int value) 1347 { 1348 uint32_t rval, modid; 1349 int flen, phy_acc; 1350 SOC_INIT_FUNC_DEFS; 1351 1352 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1353 1354 flen = soc_reg_field_length(unit, CLPORT_CONFIGr, MY_MODIDf)? value : 0; 1355 modid = (value < (1 << flen))? value : 0; 1356 1357 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1358 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, MY_MODIDf, modid); 1359 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CONFIGr(unit, phy_acc, rval)); 1360 1361 exit: 1362 SOC_FUNC_RETURN; 1363 } 1364 1365 int pm4x25_port_higig2_mode_set (int unit, int port, pm_info_t pm_info, int mode) 1366 { 1367 int phy_acc; 1368 uint32_t rval; 1369 SOC_INIT_FUNC_DEFS; 1370 1371 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1372 1373 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1374 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG2_MODEf, mode); 1375 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CONFIGr(unit, phy_acc, rval)); 1376 1377 exit: 1378 SOC_FUNC_RETURN; 1379 } 1380 1381 int pm4x25_port_higig2_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 1382 { 1383 int phy_acc; 1384 uint32_t rval; 1385 SOC_INIT_FUNC_DEFS; 1386 1387 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1388 1389 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1390 *(mode) = soc_reg_field_get(unit, CLPORT_CONFIGr, rval, HIGIG2_MODEf); 1391 1392 exit: 1393 SOC_FUNC_RETURN; 1394 } 1395 1396 int pm4x25_port_higig_mode_set (int unit, int port, pm_info_t pm_info, int mode) 1397 { 1398 int phy_acc; 1399 uint32_t rval; 1400 SOC_INIT_FUNC_DEFS; 1401 1402 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1403 1404 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1405 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG_MODEf, mode); 1406 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CONFIGr(unit, phy_acc, rval)); 1407 1408 exit: 1409 SOC_FUNC_RETURN; 1410 } 1411 1412 int pm4x25_port_higig_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 1413 { 1414 int phy_acc; 1415 uint32_t rval; 1416 SOC_INIT_FUNC_DEFS; 1417 1418 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1419 1420 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1421 *(mode) = soc_reg_field_get(unit, CLPORT_CONFIGr, rval, HIGIG_MODEf); 1422 1423 exit: 1424 SOC_FUNC_RETURN; 1425 } 1426 1427 int pm4x25_port_encap_set (int unit, int port, pm_info_t pm_info, 1428 int flags, portmod_encap_t encap) 1429 { 1430 return (clmac_encap_set(unit, port, flags, encap)); 1431 1432 } 1433 1434 int pm4x25_port_encap_get (int unit, int port, pm_info_t pm_info, 1435 int *flags, portmod_encap_t *encap) 1436 { 1437 return (clmac_encap_get(unit, port, flags, encap)); 1438 } 1439 1440 int pm4x25_port_config_port_type_set (int unit, int port, pm_info_t pm_info, int type) 1441 { 1442 int phy_acc; 1443 uint32_t rval; 1444 SOC_INIT_FUNC_DEFS; 1445 1446 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1447 1448 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1449 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, PORT_TYPEf, type); 1450 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CONFIGr(unit, phy_acc, rval)); 1451 1452 exit: 1453 SOC_FUNC_RETURN; 1454 } 1455 1456 int pm4x25_port_config_port_type_get (int unit, int port, pm_info_t pm_info, int *type) 1457 { 1458 int phy_acc; 1459 uint32_t rval; 1460 SOC_INIT_FUNC_DEFS; 1461 1462 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1463 1464 _SOC_IF_ERR_EXIT(READ_CLPORT_CONFIGr(unit, phy_acc, &rval)); 1465 *(type) = soc_reg_field_get(unit, CLPORT_CONFIGr, rval, PORT_TYPEf); 1466 1467 exit: 1468 SOC_FUNC_RETURN; 1469 } 1470 1471 int pm4x25_port_led_chain_config (int unit, int port, pm_info_t pm, int value) 1472 { 1473 int phy_acc; 1474 SOC_INIT_FUNC_DEFS; 1475 1476 PM4x25_PHY_ACCESS_GET(unit, port, pm, phy_acc); 1477 1478 _SOC_IF_ERR_EXIT(WRITE_CLPORT_LED_CHAIN_CONFIGr (unit, phy_acc, value)); 1479 1480 exit: 1481 SOC_FUNC_RETURN; 1482 } 1483 1484 int pm4x25_port_phy_lane_access_get(int unit, int port, pm_info_t pm_info, 1485 const portmod_access_get_params_t* params, 1486 int max_phys, 1487 phymod_phy_access_t* phy_access, 1488 int* nof_phys, 1489 int* is_most_ext) 1490 { 1491 int phyn = 0, rv; 1492 uint32 iphy_lane_mask; 1493 int port_index=0; 1494 int serdes_lane=0; 1495 int xphy_lane_mask=0; 1496 uint32 xphy_id = 0; 1497 phymod_core_access_t core_access; 1498 uint32 lane_mask[MAX_NUM_CORES]; 1499 uint32 pm_is_bypassed = 0; 1500 phymod_port_loc_t port_loc[MAX_NUM_CORES]; 1501 int i, is_legacy_phy; 1502 uint32 xphy_idx; 1503 int num_of_phys; 1504 int done; 1505 1506 SOC_INIT_FUNC_DEFS; 1507 1508 if(max_phys > MAX_NUM_CORES) 1509 { 1510 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1511 (_SOC_MSG("max_phys parameter exceeded the MAX value. max_phys=%d, max allowed %d."), 1512 max_phys, MAX_NUM_CORES)); 1513 } 1514 1515 if(PM_4x25_INFO(pm_info)->in_pm12x10){ 1516 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("phy access get cannot be called for PM4X25 which is part of PM12X10"))); 1517 } 1518 1519 /* get port index and lane mask */ 1520 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, 1521 &iphy_lane_mask)); 1522 1523 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &pm_is_bypassed); 1524 _SOC_IF_ERR_EXIT(rv); 1525 1526 if(params->phyn >= PM_4x25_INFO(pm_info)->nof_phys[port_index]){ 1527 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1528 (_SOC_MSG("phyn exceeded. max allowed %d. got %d"), 1529 PM_4x25_INFO(pm_info)->nof_phys[port_index] - 1, params->phyn)); 1530 } 1531 1532 for( i = 0 ; i < max_phys; i++) { 1533 lane_mask[i] = 0; 1534 _SOC_IF_ERR_EXIT(phymod_phy_access_t_init(&phy_access[i])); 1535 } 1536 1537 phyn = params->phyn; 1538 1539 /* if phyn is -1, it is looking for outer most phy. 1540 assumption is that all lane has same phy depth. */ 1541 if(phyn < 0) { 1542 phyn = PM_4x25_INFO(pm_info)->nof_phys[port_index] - 1; 1543 } 1544 1545 1546 if( phyn == 0 ) { 1547 *nof_phys = 1; 1548 /* internal core */ 1549 sal_memcpy (&phy_access[0], &(PM_4x25_INFO(pm_info)->int_core_access), 1550 sizeof(phymod_phy_access_t)); 1551 phy_access[0].access.lane_mask = iphy_lane_mask; 1552 if (params->lane != -1) { 1553 serdes_lane = port_index + params->lane; 1554 phy_access[0].access.lane_mask &= (0x1 << serdes_lane ); 1555 if (phy_access[0].access.lane_mask == 0) { 1556 *nof_phys = 0; 1557 } 1558 } 1559 phy_access[0].port_loc = phymodPortLocLine; /* only line is availabe for internal. */ 1560 1561 /* PCS bypass flag is set when the underlying device is DNX */ 1562 if ((pm_is_bypassed) && (!PM_4x25_INFO(pm_info)->in_pm12x10)) { 1563 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(phy_access[0].device_op_mode); 1564 } 1565 1566 /* if it is warm boot, get probed information from wb db instead of re-probing. */ 1567 if(SOC_WARM_BOOT(unit)) { 1568 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[phy_type], &(phy_access[0].type)); 1569 _SOC_IF_ERR_EXIT(rv); 1570 } 1571 1572 } else { 1573 1574 /* external phy */ 1575 num_of_phys = 0; 1576 1577 /* xphy idx is 1 less than phyn since internal core does not count */ 1578 xphy_idx = phyn-1; 1579 1580 if (params->lane != -1){ /* specific lane */ 1581 serdes_lane = port_index + params->lane; 1582 xphy_id = PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].xphy_id; 1583 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 1584 sal_memcpy (&phy_access[num_of_phys], &core_access, 1585 sizeof(phymod_phy_access_t)); 1586 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 1587 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 1588 if( xphy_lane_mask != -1 ){ 1589 phy_access[0].access.lane_mask |= xphy_lane_mask; 1590 } 1591 phy_access[0].port_loc = ( params->sys_side == PORTMOD_SIDE_SYSTEM) ? 1592 phymodPortLocSys : phymodPortLocLine; 1593 *nof_phys = 1; 1594 } else { /* all lanes */ 1595 /* go thru all the lanes related to this port. */ 1596 serdes_lane = 0; 1597 1598 for (serdes_lane = 0; serdes_lane < MAX_PORTS_PER_PM4X25; serdes_lane++) 1599 if (iphy_lane_mask & (1U<<serdes_lane)) { 1600 xphy_id = PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].xphy_id; 1601 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 1602 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 1603 if(num_of_phys == 0 ) {/* first one */ 1604 sal_memcpy (&phy_access[num_of_phys], &core_access, 1605 sizeof(phymod_phy_access_t)); 1606 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 1607 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 1608 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 1609 if( xphy_lane_mask != -1) { 1610 lane_mask[num_of_phys] |= xphy_lane_mask; 1611 } 1612 port_loc[num_of_phys] = (params->sys_side == PORTMOD_SIDE_SYSTEM) ? 1613 phymodPortLocSys : phymodPortLocLine; 1614 1615 num_of_phys++; 1616 } else { 1617 /* if not the first one, see if this one sharing core with other 1618 lanes. */ 1619 done = 0; 1620 for( i = 0 ; (i < num_of_phys) &&(!done) ; i++) { 1621 if((!sal_memcmp (&phy_access[i], &core_access, 1622 sizeof(phymod_phy_access_t)))) { /* found a match */ 1623 /* update lane */ 1624 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 1625 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 1626 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 1627 if( xphy_lane_mask != -1) { 1628 lane_mask[i] |= xphy_lane_mask; 1629 } 1630 done = 1; 1631 } 1632 } 1633 if((!done) && (num_of_phys < max_phys)){ 1634 sal_memcpy (&phy_access[num_of_phys], &core_access, 1635 sizeof(phymod_phy_access_t)); 1636 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 1637 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 1638 PM_4x25_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 1639 if( xphy_lane_mask != -1) { 1640 lane_mask[num_of_phys] |= xphy_lane_mask; 1641 } 1642 port_loc[num_of_phys] = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 1643 phymodPortLocSys : phymodPortLocLine ; 1644 num_of_phys++; 1645 } 1646 } 1647 } 1648 } 1649 *nof_phys = num_of_phys; 1650 for( i = 0 ; (i < *nof_phys) ; i++) { 1651 phy_access[i].access.lane_mask = lane_mask[i]; 1652 phy_access[i].port_loc = port_loc[i]; 1653 } 1654 } 1655 } /* ext phys */ 1656 1657 /* assumption is that all logical port have same phy depths, that 1658 will not true when simplex introduced , until then we can keep 1659 this code. */ 1660 if (is_most_ext) { 1661 if (phyn == PM_4x25_INFO(pm_info)->nof_phys[port_index]-1) { 1662 *is_most_ext = 1; 1663 } else { 1664 *is_most_ext = 0; 1665 } 1666 } 1667 exit: 1668 SOC_FUNC_RETURN; 1669 1670 } 1671 1672 typedef enum clmac_port_mode_e{ 1673 CLMAC_4_LANES_SEPARATE = 0, 1674 CLMAC_3_TRI_0_1_2_2 = 1, 1675 CLMAC_3_TRI_0_0_2_3 = 2, 1676 CLMAC_2_LANES_DUAL = 3, 1677 CLMAC_4_LANES_TOGETHER = 4 1678 } clmac_port_mode_t; 1679 1680 static phymod_dispatch_type_t pm4x25_serdes_list[] = 1681 { 1682 phymodDispatchTypeTscf, 1683 phymodDispatchTypeTscf16, 1684 phymodDispatchTypeTscf_gen3, 1685 phymodDispatchTypeInvalid 1686 }; 1687 1688 STATIC 1689 int _pm4x25_pm_core_probe(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 1690 { 1691 int rv = SOC_E_NONE; 1692 int temp, phy; 1693 portmod_pbmp_t port_phys_in_pm; 1694 int probe =0; 1695 uint32 xphy_id; 1696 uint32 nof_ext_phys =0; 1697 int i, is_legacy_phy; 1698 portmod_xphy_lane_connection_t lane_conn; 1699 phymod_core_access_t core_access; 1700 int core_probed; 1701 SOC_INIT_FUNC_DEFS; 1702 1703 sal_memset(&lane_conn,0,sizeof(portmod_xphy_lane_connection_t)); 1704 1705 /* probe phys (both internal and external cores. */ 1706 1707 /* Get the first phy related to this port */ 1708 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 1709 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x25_INFO(pm_info)->phys); 1710 1711 /* if internal core is not probe, probe it. Currently checking to type to see 1712 phymodDispatchTypeInvalid, later need to move to WB. */ 1713 _SOC_IF_ERR_EXIT(portmod_common_serdes_probe(pm4x25_serdes_list, &PM_4x25_INFO(pm_info)->int_core_access, &probe)); 1714 1715 /* save probed phy type to wb. */ 1716 if(probe) { 1717 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 1718 pm_info->wb_vars_ids[phy_type], 1719 &PM_4x25_INFO(pm_info)->int_core_access.type); 1720 _SOC_IF_ERR_EXIT(rv); 1721 } 1722 1723 /* probe ext core related to this logical port. */ 1724 temp = 0; 1725 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy) { 1726 if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) { 1727 if( PM_4x25_INFO(pm_info)->nof_phys[temp] >= 2 ){ 1728 nof_ext_phys = PM_4x25_INFO(pm_info)->nof_phys[temp]-1; 1729 for(i=0 ; i<nof_ext_phys ; i++) { 1730 xphy_id = PM_4x25_INFO(pm_info)->lane_conn[i][temp].xphy_id; 1731 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 1732 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 1733 _SOC_IF_ERR_EXIT(portmod_common_ext_phy_probe(unit, port, &core_access, &probe)); 1734 if ((probe == 0) && 1735 (core_access.type == phymodDispatchTypeInvalid)){ 1736 pm4x25_xphy_lane_detach_from_pm(unit, pm_info, phy, i+1, &lane_conn); 1737 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 1738 "Warning: EXT PHY p=%d xphy_id=%d can't be probed\n"), port, xphy_id)); 1739 } else { 1740 core_probed = 1; 1741 _SOC_IF_ERR_EXIT(portmod_xphy_core_probed_set(unit, xphy_id, core_probed)); 1742 /* Check if after the probe the ext phy is legacy, so we dont overrun the current value */ 1743 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 1744 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_set(unit, xphy_id, &core_access, is_legacy_phy)); 1745 } 1746 } 1747 } 1748 } 1749 } 1750 temp++; 1751 } 1752 1753 /*update warmboot engine*/ 1754 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1755 pm_info->wb_vars_ids[phy_type], 1756 &PM_4x25_INFO(pm_info)->int_core_access.type, 0); 1757 _SOC_IF_ERR_EXIT(rv); 1758 1759 exit: 1760 SOC_FUNC_RETURN; 1761 } 1762 1763 STATIC 1764 int _pm4x25_pm_serdes_core_init(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 1765 { 1766 int rv; 1767 phymod_core_init_config_t core_conf; 1768 phymod_core_status_t core_status; 1769 phymod_phy_access_t serdes_access; 1770 const portmod_port_interface_config_t* config; 1771 uint32 core_is_initialized; 1772 soc_port_if_t interface = SOC_PORT_IF_NULL; 1773 uint32 init_flags = 0, is_bypass; 1774 pm_version_t pm_version; 1775 SOC_INIT_FUNC_DEFS; 1776 1777 config = &(add_info->interface_config); 1778 1779 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &is_bypass); 1780 _SOC_IF_ERR_EXIT(rv); 1781 1782 _SOC_IF_ERR_EXIT(phymod_core_init_config_t_init(&core_conf)); 1783 1784 core_conf.firmware_load_method = PM_4x25_INFO(pm_info)->fw_load_method; 1785 core_conf.firmware_loader = PM_4x25_INFO(pm_info)->external_fw_loader; 1786 core_conf.lane_map = PM_4x25_INFO(pm_info)->lane_map; 1787 1788 core_conf.afe_pll.afe_pll_change_default = PM_4x25_INFO(pm_info)->afe_pll.afe_pll_change_default; 1789 core_conf.afe_pll.ams_pll_iqp = PM_4x25_INFO(pm_info)->afe_pll.ams_pll_iqp; 1790 core_conf.afe_pll.ams_pll_en_hrz = PM_4x25_INFO(pm_info)->afe_pll.ams_pll_en_hrz; 1791 1792 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&core_conf.interface)); 1793 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(config, &interface)); 1794 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, config->speed, 1795 interface, &core_conf.interface.interface_type)); 1796 core_conf.interface.data_rate = config->speed; 1797 core_conf.interface.interface_modes = config->interface_modes; 1798 core_conf.interface.ref_clock = PM_4x25_INFO(pm_info)->ref_clk; 1799 core_conf.interface.pll_divider_req = config->pll_divider_req; 1800 1801 _SOC_IF_ERR_EXIT(phymod_core_status_t_init(&core_status)); 1802 core_status.pmd_active = 0; 1803 1804 init_flags = PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) | PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info); 1805 1806 if (PORTMOD_PORT_ADD_F_FIRMWARE_LOAD_VERIFY_GET(add_info)) { 1807 PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_SET(&core_conf); 1808 } 1809 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 1810 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_SET(&core_conf); 1811 } 1812 if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 1813 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_SET(&core_conf); 1814 } 1815 if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 1816 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&core_conf); 1817 } 1818 #ifdef FW_BCAST_DOWNLOAD 1819 if (PORTMOD_PORT_ADD_F_FIRMWARE_DOWNLOAD_BCAST_GET(add_info)) { 1820 PHYMOD_CORE_INIT_F_SERDES_FW_BCAST_SET(&core_conf); 1821 } 1822 #endif 1823 1824 if (PORTMOD_PORT_ADD_F_IS_ENHANCED_PM4X25_GEN2_GET(add_info)) { 1825 PHYMOD_CORE_INIT_F_CLK4PCS_3BIT_40T_SET(&core_conf); 1826 } 1827 #ifdef DEFAULT_OSR2P5_SET 1828 if (PORTMOD_PORT_ADD_F_DEFAULT_OSR2P5_GET(add_info)) { 1829 PHYMOD_CORE_INIT_F_DEFAULT_OSR2P5_SET(&core_conf); 1830 } 1831 #endif /* DEFAULT_OSR2P5_SET */ 1832 1833 core_conf.op_datapath = add_info->phy_op_datapath; 1834 1835 rv = PM4x25_IS_INITIALIZED_GET(unit, pm_info, &core_is_initialized); 1836 _SOC_IF_ERR_EXIT(rv); 1837 1838 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 1839 1840 if ((PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) 1841 && PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info) 1842 && (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(core_is_initialized))) { 1843 portmod_vcos_speed_config_t speed_config; 1844 phymod_dual_plls_t init_plls; 1845 1846 portmod_vcos_speed_config_t_init(unit, &speed_config); 1847 speed_config.higig_mode = add_info->init_config.is_hg; 1848 speed_config.speed = add_info->interface_config.speed; 1849 speed_config.num_lanes = add_info->interface_config.port_num_lanes; 1850 if(add_info->init_config.cpm_core_mode == portmodCpmMixEthCpri) { 1851 speed_config.port_type = portmodCpmPrtEthOfMixedMode; 1852 } 1853 rv = _pm4x25_init_plls_get(unit, 0 , pm_info, &speed_config, 1, &init_plls); 1854 _SOC_IF_ERR_EXIT(rv); 1855 core_conf.pll0_div_init_value = init_plls.pll0_div; 1856 core_conf.pll1_div_init_value = init_plls.pll1_div; 1857 } 1858 1859 if (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(core_is_initialized)) { 1860 /* firmware load will happen after pass 1 */ 1861 if (!PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_GET(core_is_initialized) || 1862 PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 1863 if ((is_bypass) && (!PM_4x25_INFO(pm_info)->in_pm12x10)) { 1864 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(PM_4x25_INFO(pm_info)->int_core_access.device_op_mode); 1865 } 1866 1867 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_flags == 0) { 1868 if (PM_4x25_INFO(pm_info)->rescal != -1) { 1869 sal_memcpy(&serdes_access, &(PM_4x25_INFO(pm_info)->int_core_access), sizeof(phymod_phy_access_t)); 1870 phymod_phy_rescal_set(&serdes_access, 1, PM_4x25_INFO(pm_info)->rescal); 1871 } 1872 } 1873 if (add_info->init_config.cpm_core_mode == portmodCpmMixEthCpri) { 1874 PM_4x25_INFO(pm_info)->int_core_access.type = phymodDispatchTypeTscf_gen3; 1875 } 1876 _SOC_IF_ERR_EXIT(phymod_core_init(&PM_4x25_INFO(pm_info)->int_core_access, 1877 &core_conf, 1878 &core_status)); 1879 1880 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_flags == 0) { 1881 PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_SET(core_is_initialized); 1882 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1883 pm_info->wb_vars_ids[isInitialized], 1884 &core_is_initialized); 1885 _SOC_IF_ERR_EXIT(rv); 1886 } 1887 if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info) || init_flags == 0) { 1888 PORTMOD_CORE_INIT_FLAG_INITIALZIED_SET(core_is_initialized); 1889 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1890 pm_info->wb_vars_ids[isInitialized], 1891 &core_is_initialized); 1892 _SOC_IF_ERR_EXIT(rv); 1893 } 1894 1895 } 1896 } 1897 1898 exit: 1899 SOC_FUNC_RETURN; 1900 } 1901 1902 STATIC 1903 int _pm4x25_pm_ext_phy_core_init(int unit, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 1904 { 1905 int temp, phy; 1906 phymod_core_init_config_t core_conf; 1907 phymod_core_status_t core_status; 1908 const portmod_port_interface_config_t* config; 1909 portmod_pbmp_t port_phys_in_pm; 1910 phymod_firmware_load_method_t fw_load_method; 1911 phymod_lane_map_t lane_map; 1912 phymod_core_access_t core_access; 1913 uint32 primary_core_num; 1914 soc_port_if_t interface = SOC_PORT_IF_NULL; 1915 uint32 xphy_id; 1916 int is_legacy_phy = 0; 1917 uint32 nof_ext_phys = 0; 1918 int force_fw_load, is_initialized = 0; 1919 int init_all = 0, lane, i; 1920 1921 SOC_INIT_FUNC_DEFS; 1922 1923 config = &(add_info->interface_config); 1924 1925 init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) && 1926 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) && 1927 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) ? 1 : 0; 1928 1929 /* Get the first phy related to this port */ 1930 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 1931 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x25_INFO(pm_info)->phys); 1932 1933 _SOC_IF_ERR_EXIT(phymod_core_init_config_t_init(&core_conf)); 1934 1935 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 1936 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_SET(&core_conf); 1937 } 1938 1939 if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 1940 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_SET(&core_conf); 1941 } 1942 1943 core_conf.afe_pll.afe_pll_change_default = PM_4x25_INFO(pm_info)->afe_pll.afe_pll_change_default; 1944 core_conf.afe_pll.ams_pll_iqp = PM_4x25_INFO(pm_info)->afe_pll.ams_pll_iqp; 1945 core_conf.afe_pll.ams_pll_en_hrz = PM_4x25_INFO(pm_info)->afe_pll.ams_pll_en_hrz; 1946 1947 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&core_conf.interface)); 1948 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(config, &interface)); 1949 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, config->speed, 1950 interface, &core_conf.interface.interface_type)); 1951 core_conf.interface.data_rate = config->speed; 1952 core_conf.interface.interface_modes = config->interface_modes; 1953 core_conf.interface.ref_clock = PM_4x25_INFO(pm_info)->ref_clk; 1954 1955 core_conf.op_datapath = add_info->phy_op_datapath; 1956 1957 core_conf.firmware_load_method = (PM_4x25_INFO(pm_info)->fw_load_method == 1958 phymodFirmwareLoadMethodNone) ? 1959 phymodFirmwareLoadMethodNone : 1960 phymodFirmwareLoadMethodInternal; 1961 core_conf.firmware_loader = NULL; 1962 1963 /* config "no swap" for external phys.set later using APIs*/ 1964 for (lane=0 ; lane < PM4X25_LANES_PER_CORE; lane++) { 1965 core_conf.lane_map.lane_map_rx[lane] = lane; 1966 core_conf.lane_map.lane_map_tx[lane] = lane; 1967 } 1968 1969 temp = 0; 1970 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy) { 1971 if (PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) { 1972 if (PM_4x25_INFO(pm_info)->nof_phys[temp] >= 2 ) { 1973 nof_ext_phys = PM_4x25_INFO(pm_info)->nof_phys[temp]-1; 1974 for (i=0 ; i<nof_ext_phys; i++) { 1975 xphy_id = PM_4x25_INFO(pm_info)->lane_conn[i][temp].xphy_id; 1976 if (xphy_id != PORTMOD_XPHY_ID_INVALID) { 1977 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 1978 _SOC_IF_ERR_EXIT(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 1979 _SOC_IF_ERR_EXIT(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 1980 _SOC_IF_ERR_EXIT(portmod_xphy_lane_map_get(unit, xphy_id, &lane_map)); 1981 _SOC_IF_ERR_EXIT(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 1982 1983 _SOC_IF_ERR_EXIT(phymod_core_status_t_init(&core_status)); 1984 core_status.pmd_active = 0; 1985 1986 if (force_fw_load == phymodFirmwareLoadForce) { 1987 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_conf); 1988 } else if (force_fw_load == phymodFirmwareLoadAuto) { 1989 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_conf); 1990 } 1991 1992 if ((PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_all) && 1993 (is_initialized & PHYMOD_CORE_INIT_F_EXECUTE_PASS1)) 1994 continue; 1995 1996 if ((PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)|| init_all) && 1997 (is_initialized & PHYMOD_CORE_INIT_F_EXECUTE_PASS2)) 1998 continue; 1999 2000 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 2001 if (is_legacy_phy) { 2002 /* Dont do a core init for legacy Phys.*/ 2003 } else { 2004 _SOC_IF_ERR_EXIT(phymod_core_init(&core_access, 2005 &core_conf, 2006 &core_status)); 2007 } 2008 2009 if (init_all) { 2010 is_initialized = (PHYMOD_CORE_INIT_F_EXECUTE_PASS2 | PHYMOD_CORE_INIT_F_EXECUTE_PASS1); 2011 } else if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 2012 is_initialized |= PHYMOD_CORE_INIT_F_EXECUTE_PASS2; 2013 } else { 2014 is_initialized = PHYMOD_CORE_INIT_F_EXECUTE_PASS1; 2015 } 2016 2017 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2018 } 2019 } 2020 } 2021 } 2022 temp++; 2023 } 2024 2025 exit: 2026 SOC_FUNC_RETURN; 2027 } 2028 2029 STATIC 2030 int _pm4x25_pm_core_init(int unit, int port, pm_info_t pm_info, 2031 const portmod_port_add_info_t* add_info, int enable) 2032 { 2033 SOC_INIT_FUNC_DEFS; 2034 2035 if (enable) { 2036 _SOC_IF_ERR_EXIT(_pm4x25_pm_serdes_core_init(unit, port, pm_info, add_info)); 2037 _SOC_IF_ERR_EXIT(_pm4x25_pm_ext_phy_core_init(unit, pm_info, add_info)); 2038 } 2039 2040 exit: 2041 SOC_FUNC_RETURN; 2042 } 2043 2044 STATIC 2045 int _pm4x25_pm_enable(int unit, int port, pm_info_t pm_info, int port_index, const portmod_port_add_info_t* add_info, int enable) 2046 { 2047 uint32 reg_val, port_mode; 2048 int caui_mode, three_ports_mode; 2049 int rv, phy_acc; 2050 int pm_ver_is_d0 = 0; 2051 int is_master_pll = FALSE; 2052 pm_version_t pm_version; 2053 SOC_INIT_FUNC_DEFS; 2054 2055 /* The below code is to distinguish PM4x25, before D0 versus D0 and beyond. This is since some sequences were modified in PM4x25 D0 */ 2056 rv = READ_CLPORT_GENERAL_SPARE1_REGr(unit, port, ®_val); 2057 if(rv == SOC_E_NONE) { 2058 pm_ver_is_d0 = 1; 2059 }else if (rv != SOC_E_PARAM) { /* rv == SOC_E_PARAM is OK, since it means CLPORT_GENERAL_SPARE1_REG register doesn't exist -> pm_ver_is_d0=FALSE */ 2060 _SOC_EXIT_WITH_ERR(rv, (_SOC_MSG("Port %d: We were trying to read CLPORT_GENERAL_SPARE1_REG but recieved an error that is not SOC_E_PARAM!\n"), 2061 port)); 2062 } 2063 2064 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 2065 2066 #ifdef PORTMOD_PM4X25TD_SUPPORT 2067 if (pm_info->type == portmodDispatchTypePm4x25td) { 2068 rv = _pm4x25td_pm_enable(unit, port, pm_info, port_index, add_info, enable); 2069 _SOC_IF_ERR_EXIT(rv); 2070 } else 2071 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 2072 { 2073 is_master_pll = _pm4x25_port_tsc_is_master_pll(unit, port, pm_info); 2074 2075 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 2076 2077 if(enable) { 2078 /* Power Save */ 2079 _SOC_IF_ERR_EXIT(READ_CLPORT_POWER_SAVEr(unit, phy_acc, ®_val)); 2080 soc_reg_field_set(unit, CLPORT_POWER_SAVEr, ®_val, XPORT_CORE0f, 0); 2081 _SOC_IF_ERR_EXIT(WRITE_CLPORT_POWER_SAVEr(unit, phy_acc, reg_val)); 2082 2083 /* Port configuration */ 2084 rv = PM4x25_THREE_PORTS_MODE_GET(unit, pm_info, &three_ports_mode); 2085 _SOC_IF_ERR_EXIT(rv); 2086 2087 caui_mode = (add_info->interface_config.interface == SOC_PORT_IF_CAUI ? 1 : 0); 2088 /* if(PM4x25_QUAD_MODE_IF(add_info->interface_config.interface)) */ 2089 if(add_info->interface_config.port_num_lanes >= 4) { 2090 port_mode = CLMAC_4_LANES_TOGETHER; 2091 /*} else if(PM4x25_DUAL_MODE_IF(add_info->interface_config.interface)){ */ 2092 } else if(add_info->interface_config.port_num_lanes == 2){ 2093 if(!three_ports_mode) { 2094 port_mode = CLMAC_2_LANES_DUAL; 2095 } else { 2096 if(port_index < 2) { 2097 port_mode = CLMAC_3_TRI_0_0_2_3; 2098 } else { 2099 port_mode = CLMAC_3_TRI_0_1_2_2; 2100 } 2101 } 2102 } else { /*single mode*/ 2103 if(!three_ports_mode) { 2104 port_mode = CLMAC_4_LANES_SEPARATE; 2105 } else { 2106 if(port_index < 2) { 2107 port_mode = CLMAC_3_TRI_0_1_2_2; 2108 } else { 2109 port_mode = CLMAC_3_TRI_0_0_2_3; 2110 } 2111 } 2112 } 2113 2114 _SOC_IF_ERR_EXIT(READ_CLPORT_MODE_REGr(unit, phy_acc, ®_val)); 2115 if (SOC_REG_FIELD_VALID(unit, CLPORT_MODE_REGr, FIELD_10_10f)) { 2116 soc_reg_field_set(unit, CLPORT_MODE_REGr, ®_val, FIELD_10_10f, caui_mode); 2117 } else if (SOC_REG_FIELD_VALID(unit, CLPORT_MODE_REGr, SINGLE_PORT_MODE_SPEED_100Gf)) { 2118 soc_reg_field_set(unit, CLPORT_MODE_REGr, ®_val, SINGLE_PORT_MODE_SPEED_100Gf, caui_mode); 2119 } 2120 soc_reg_field_set(unit, CLPORT_MODE_REGr, ®_val, XPORT0_CORE_PORT_MODEf, port_mode); 2121 soc_reg_field_set(unit, CLPORT_MODE_REGr, ®_val, XPORT0_PHY_PORT_MODEf, port_mode); 2122 soc_reg_field_set(unit, CLPORT_MODE_REGr, ®_val, EGR_1588_TIMESTAMPING_MODEf, 2123 add_info->flags & PORTMOD_PORT_ADD_F_EGR_1588_TIMESTAMP_MODE_48BIT ? 1 : 0); 2124 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MODE_REGr(unit, phy_acc, reg_val)); 2125 2126 if(PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)){ 2127 /* Set txpi sdm scheme */ 2128 _SOC_IF_ERR_EXIT(_pm4x25_txpi_sdm_scheme_set(unit, port, pm_info, add_info->init_config.txpi_sdm_scheme)); 2129 /* Set txpi lane select */ 2130 _SOC_IF_ERR_EXIT(_pm4x25_txpi_lane_select_set(unit, port, pm_info, (uint32 *)add_info->init_config.lane_map[0].lane_map_tx)); 2131 } 2132 2133 if (PM_4x25_INFO(pm_info)->nof_phys[0] > 0) { 2134 /* Get Serdes OOR */ 2135 if(is_master_pll != TRUE) { /* This PM is not master PM, reset it. */ 2136 _SOC_IF_ERR_EXIT(pm4x25_port_tsc_reset_set(unit, phy_acc, 1)); 2137 _SOC_IF_ERR_EXIT(pm4x25_port_tsc_reset_set(unit, phy_acc, 0)); 2138 } 2139 } 2140 2141 /* Bring MAC OOR */ 2142 _SOC_IF_ERR_EXIT(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 2143 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 0); 2144 if (PORTMOD_PORT_ADD_F_SYS_16B_INTF_MODE_GET(add_info)) { 2145 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, 2146 SYS_16B_INTF_MODEf)) { 2147 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, ®_val, 2148 SYS_16B_INTF_MODEf, 1); 2149 } 2150 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 2151 } 2152 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 2153 } else { /* disable */ 2154 /* put MAC in reset */ 2155 _SOC_IF_ERR_EXIT(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 2156 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 1); 2157 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 2158 2159 if (pm_ver_is_d0 == 1){ /* At PM4x25 D0 and beyond - put MAC in reset - here */ 2160 /* put MAC in reset */ 2161 _SOC_IF_ERR_EXIT(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 2162 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 1); 2163 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 2164 } 2165 2166 /* Put Serdes in reset*/ 2167 if(is_master_pll != TRUE) { /* This PM is not master PM, reset it. */ 2168 _SOC_IF_ERR_EXIT(pm4x25_port_tsc_reset_set(unit, phy_acc, 1)); 2169 } 2170 2171 /* Turn on Power Save */ 2172 _SOC_IF_ERR_EXIT(READ_CLPORT_POWER_SAVEr(unit, phy_acc, ®_val)); 2173 soc_reg_field_set(unit, CLPORT_POWER_SAVEr, ®_val, XPORT_CORE0f, 1); 2174 _SOC_IF_ERR_EXIT(WRITE_CLPORT_POWER_SAVEr(unit, phy_acc, reg_val)); 2175 } 2176 } 2177 2178 exit: 2179 SOC_FUNC_RETURN; 2180 } 2181 2182 int pm4x25_to_cpm_pm_enable(int unit, int port, pm_info_t pm_info, int port_index, 2183 const portmod_port_add_info_t* add_info, 2184 int enable) { 2185 int rv; 2186 SOC_INIT_FUNC_DEFS; 2187 rv = _pm4x25_pm_enable(unit, port, pm_info, port_index, add_info, enable); 2188 _SOC_IF_ERR_EXIT(rv); 2189 2190 exit: 2191 SOC_FUNC_RETURN; 2192 } 2193 2194 STATIC 2195 int _pm4x25_pm_port_init(int unit, int port, pm_info_t pm_info, int internal_port, 2196 const portmod_port_add_info_t* add_info, int enable) 2197 { 2198 int rv, phy_acc; 2199 uint32 reg_val, flags; 2200 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 2201 uint32 rsv_mask, rsv_pfc_mask; 2202 pm_version_t pm_version; 2203 SOC_INIT_FUNC_DEFS; 2204 2205 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 2206 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 2207 2208 #ifdef PORTMOD_PM4X25TD_SUPPORT 2209 if (pm_info->type == portmodDispatchTypePm4x25td) { 2210 rv = _pm4x25td_pm_port_init(unit, port, internal_port, add_info, enable); 2211 _SOC_IF_ERR_EXIT(rv); 2212 } else 2213 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 2214 { 2215 if (internal_port == -1) { 2216 _SOC_EXIT_WITH_ERR(SOC_E_PORT, (_SOC_MSG("Invalid internal Port %d"), 2217 internal_port)); 2218 } 2219 if(enable) { 2220 2221 /* RSV Mask */ 2222 rsv_mask = 0; 2223 rsv_pfc_mask = 0; 2224 _SOC_IF_ERR_EXIT(READ_CLPORT_MAC_RSV_MASKr(unit, phy_acc, &rsv_pfc_mask)); 2225 if (rsv_pfc_mask & PFC_FRAME_DETECTED_RSV_MASK) { 2226 rsv_mask |= PFC_FRAME_DETECTED_RSV_MASK; 2227 } 2228 SHR_BITSET(&rsv_mask, 3); /* Receive terminate/code error */ 2229 SHR_BITSET(&rsv_mask, 4); /* CRC error */ 2230 SHR_BITSET(&rsv_mask, 6); /* Truncated/Frame out of Range */ 2231 SHR_BITSET(&rsv_mask, 17); /* RUNT detected*/ 2232 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MAC_RSV_MASKr(unit, phy_acc, rsv_mask)); 2233 2234 /* Soft reset */ 2235 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 2236 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, port_fields[internal_port], 1); 2237 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2238 2239 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, port_fields[internal_port], 0); 2240 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2241 2242 /* Port enable */ 2243 _SOC_IF_ERR_EXIT(READ_CLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 2244 soc_reg_field_set(unit, CLPORT_ENABLE_REGr, ®_val, port_fields[internal_port], 1); 2245 _SOC_IF_ERR_EXIT(WRITE_CLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 2246 2247 /* Init MAC */ 2248 flags = 0; 2249 if(PORTMOD_PORT_ADD_F_RX_SRIP_CRC_GET(add_info)) { 2250 flags |= CLMAC_INIT_F_RX_STRIP_CRC; 2251 } 2252 2253 if(PORTMOD_PORT_ADD_F_TX_APPEND_CRC_GET(add_info)) { 2254 flags |= CLMAC_INIT_F_TX_APPEND_CRC; 2255 } 2256 2257 if(PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_GET(add_info)) { 2258 flags |= CLMAC_INIT_F_TX_REPLACE_CRC; 2259 } 2260 2261 if(PORTMOD_PORT_ADD_F_TX_PASS_THROUGH_CRC_GET(add_info)) { 2262 flags |= CLMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE; 2263 } 2264 2265 if (IS_HG_PORT(unit, port)){ 2266 flags |= CLMAC_INIT_F_IPG_CHECK_DISABLE; 2267 } else { 2268 flags &= ~CLMAC_INIT_F_IPG_CHECK_DISABLE; 2269 } 2270 2271 if(PHYMOD_INTF_MODES_HIGIG_GET(&(add_info->interface_config))) { 2272 flags |= CLMAC_INIT_F_IS_HIGIG; 2273 } 2274 rv = clmac_init(unit, port, flags); 2275 _SOC_IF_ERR_EXIT(rv); 2276 2277 /* LSS */ 2278 _SOC_IF_ERR_EXIT(READ_CLPORT_FAULT_LINK_STATUSr(unit, phy_acc, ®_val)); 2279 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, ®_val, REMOTE_FAULTf, 1); 2280 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, ®_val, LOCAL_FAULTf, 1); 2281 _SOC_IF_ERR_EXIT(WRITE_CLPORT_FAULT_LINK_STATUSr(unit, phy_acc, reg_val)); 2282 2283 /* Counter MAX size */ 2284 _SOC_IF_ERR_EXIT(READ_CLPORT_CNTMAXSIZEr(unit, phy_acc, ®_val)); 2285 soc_reg_field_set(unit, CLPORT_CNTMAXSIZEr, ®_val, CNTMAXSIZEf, 1518); 2286 _SOC_IF_ERR_EXIT(WRITE_CLPORT_CNTMAXSIZEr(unit, phy_acc, reg_val)); 2287 2288 /* Reset MIB counters */ 2289 _SOC_IF_ERR_EXIT(READ_CLPORT_MIB_RESETr(unit, phy_acc, ®_val)); 2290 /* coverity[ptr_arith:FALSE] */ 2291 SHR_BITSET(®_val, internal_port); 2292 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MIB_RESETr(unit, phy_acc, reg_val)); 2293 SHR_BITCLR((uint32 *)®_val, internal_port); 2294 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MIB_RESETr(unit, phy_acc, reg_val)); 2295 2296 /* Disable MAC timestamp by default */ 2297 if (PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) { 2298 _SOC_IF_ERR_EXIT(pm4x25_port_mac_timestamp_enable_set(unit, port, pm_info, 0)); 2299 } 2300 } else { 2301 /* Port disable */ 2302 _SOC_IF_ERR_EXIT(READ_CLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 2303 soc_reg_field_set(unit, CLPORT_ENABLE_REGr, ®_val, port_fields[internal_port], 0); 2304 _SOC_IF_ERR_EXIT(WRITE_CLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 2305 2306 /* Soft reset */ 2307 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 2308 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, port_fields[internal_port], 1); 2309 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2310 } 2311 } 2312 2313 exit: 2314 SOC_FUNC_RETURN; 2315 } 2316 2317 STATIC 2318 int _pm4x25_an_mode_update (int unit, int port, pm_info_t pm_info, int port_index, int num_lanes, int an_cl73) 2319 { 2320 int is_hg, rv; 2321 phymod_an_mode_type_t an_mode; 2322 2323 SOC_INIT_FUNC_DEFS; 2324 2325 rv = PM4x25_IS_HG_GET(unit, pm_info, &is_hg, port_index); 2326 _SOC_IF_ERR_EXIT(rv); 2327 rv = PM4x25_AN_MODE_GET(unit, pm_info, &an_mode, port_index); 2328 _SOC_IF_ERR_EXIT(rv); 2329 2330 if(is_hg) { 2331 an_mode = phymod_AN_MODE_CL73BAM; 2332 } else if (an_cl73) { 2333 switch (an_cl73) { 2334 case PORTMOD_CL73_W_BAM: 2335 an_mode = phymod_AN_MODE_CL73BAM; 2336 break ; 2337 case PORTMOD_CL73_WO_BAM: 2338 an_mode = phymod_AN_MODE_CL73; 2339 break ; 2340 case PORTMOD_CL73_HPAM_VS_SW: 2341 an_mode = phymod_AN_MODE_HPAM; 2342 break ; /* against TD+ */ 2343 case PORTMOD_CL73_HPAM: 2344 an_mode = phymod_AN_MODE_HPAM; 2345 break ; /* against TR3 */ 2346 case PORTMOD_CL73_CL37: 2347 an_mode = phymod_AN_MODE_CL73; 2348 break ; 2349 case PORTMOD_MSA: 2350 an_mode = phymod_AN_MODE_MSA; 2351 break; 2352 case PORTMOD_CL73_MSA: 2353 an_mode = phymod_AN_MODE_CL73_MSA; 2354 default: 2355 break; 2356 } 2357 } else { 2358 an_mode = phymod_AN_MODE_CL73; /* default mode */ 2359 } 2360 2361 rv = PM4x25_AN_MODE_SET(unit, pm_info, an_mode, port_index); 2362 _SOC_IF_ERR_EXIT(rv); 2363 2364 exit: 2365 SOC_FUNC_RETURN; 2366 } 2367 2368 STATIC 2369 int _pm4x25_ext_phy_interface_check(int unit, int port, pm_info_t pm_info, phymod_phy_access_t *phy_acc, 2370 const portmod_port_interface_config_t *interface_config, 2371 soc_port_if_t interface, int *is_valid) 2372 { 2373 int rv = 0; 2374 int num_lanes = 0, data_rate = 0; 2375 uint32_t interface_mode = 0; 2376 phymod_interface_t phymod_intf; 2377 int is_legacy_phy = 0; 2378 int xphy_id; 2379 SOC_INIT_FUNC_DEFS; 2380 2381 _SOC_IF_ERR_EXIT 2382 (pm4x25_port_lane_count_get(unit, port, pm_info, 2383 PORTMOD_SIDE_LINE, &num_lanes)); 2384 interface_mode = interface_config->interface_modes; 2385 data_rate = interface_config->speed; 2386 2387 xphy_id = phy_acc->access.addr; 2388 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 2389 2390 if (is_legacy_phy) { 2391 /* if its a legacy PHY let the PHY driver decide the valid interface types */ 2392 *is_valid = 1; 2393 rv = SOC_E_NONE; 2394 SOC_EXIT; 2395 } 2396 2397 /* convert portmod interface tophymod interface */ 2398 rv = portmod_intf_to_phymod_intf(unit, data_rate, interface, &phymod_intf); 2399 _SOC_IF_ERR_EXIT(rv); 2400 2401 rv = portmod_port_line_interface_is_valid(unit, phy_acc, port, data_rate, phymod_intf, 2402 num_lanes, interface_mode, is_valid); 2403 _SOC_IF_ERR_EXIT(rv); 2404 2405 if (!*is_valid) { 2406 LOG_ERROR(BSL_LS_BCM_PORT, 2407 (BSL_META_UP(unit, port, 2408 "ERROR: u=%d p=%d interface type %d not supported by external PHY for this speed %d \n"), 2409 unit, port, interface, data_rate)); 2410 rv = SOC_E_PARAM; 2411 _SOC_IF_ERR_EXIT(rv); 2412 } 2413 2414 exit: 2415 SOC_FUNC_RETURN; 2416 } 2417 2418 STATIC 2419 int _pm4x25_interface_check(int unit, int port, 2420 const portmod_port_interface_config_t *interface_config, 2421 soc_port_if_t interface, int *is_valid) 2422 { 2423 int is_higig; 2424 int num_lanes, nof_cores = 0; 2425 phymod_core_info_t core_info; 2426 uint32_t rev_letter = 0; 2427 phymod_core_access_t core_acc[1+MAX_NUM_CORES]; 2428 SOC_INIT_FUNC_DEFS; 2429 2430 *is_valid = 0; 2431 num_lanes = interface_config->port_num_lanes; 2432 is_higig = ((interface_config->encap_mode == SOC_ENCAP_HIGIG2) || 2433 (interface_config->encap_mode == SOC_ENCAP_HIGIG) || 2434 PHYMOD_INTF_MODES_HIGIG_GET(interface_config)) ? 1 : 0; 2435 2436 if (SOC_PORT_IF_ILKN == interface) { 2437 *is_valid = 1; 2438 return SOC_E_NONE; 2439 } 2440 2441 switch (interface_config->speed) { 2442 case 0: 2443 /* When AN=1 the input speed to portmod may be 0. At 2444 * this moment the speed is still undecided so there 2445 * is no reason to invalidate the interface type. 2446 */ 2447 *is_valid = 1; 2448 break; 2449 case 1000: 2450 if (num_lanes == 1) { 2451 if ((SOC_PORT_IF_SGMII == interface) || 2452 (SOC_PORT_IF_GMII == interface) || 2453 (SOC_PORT_IF_KX == interface)) { 2454 *is_valid = 1; 2455 } 2456 } 2457 break; 2458 case 2500: 2459 if (num_lanes == 1) { 2460 if ((SOC_PORT_IF_SGMII == interface) || 2461 (SOC_PORT_IF_GMII == interface)) { 2462 *is_valid = 1; 2463 } 2464 } 2465 break; 2466 case 5000: 2467 if (num_lanes == 1) { 2468 if ((SOC_PORT_IF_KR == interface) || 2469 (SOC_PORT_IF_CR == interface)) { 2470 *is_valid = 1; 2471 } 2472 } 2473 break; 2474 case 10000: 2475 case 11000: 2476 case 12000: 2477 if (is_higig) { 2478 if (num_lanes == 1) { 2479 if ((SOC_PORT_IF_XFI == interface) || 2480 (SOC_PORT_IF_KR == interface) || 2481 (SOC_PORT_IF_CR == interface)) { 2482 *is_valid = 1; 2483 } 2484 } 2485 } else { 2486 if (num_lanes == 1) { 2487 if ((SOC_PORT_IF_SFI == interface) || 2488 (SOC_PORT_IF_XFI == interface) || 2489 (SOC_PORT_IF_KR == interface) || 2490 (SOC_PORT_IF_CR == interface) || 2491 (SOC_PORT_IF_SR == interface) || 2492 (SOC_PORT_IF_LR == interface)) { 2493 *is_valid = 1; 2494 } 2495 } else if (num_lanes == 4) { 2496 _SOC_IF_ERR_EXIT 2497 (portmod_port_core_access_get(unit, port, 0, 2498 (1+MAX_NUM_CORES), 2499 core_acc, &nof_cores, NULL)); 2500 _SOC_IF_ERR_EXIT(phymod_core_info_get(core_acc, &core_info)); 2501 rev_letter = (core_info.serdes_id & 0xc000) >> 14; 2502 /* 10G XAUI is only avialable in TSCF Rev C0 of the PM4x25. */ 2503 if (((core_info.serdes_id & 0x3f) == 0x14) && (rev_letter == 2)) { 2504 if ((SOC_PORT_IF_DNX_XAUI == interface) || 2505 (SOC_PORT_IF_XAUI == interface)) { 2506 *is_valid = 1; 2507 } 2508 } 2509 } 2510 } 2511 break; 2512 case 20000: 2513 case 21000: 2514 if (is_higig) { 2515 if (num_lanes == 1) { 2516 if ((SOC_PORT_IF_KR == interface) || 2517 (SOC_PORT_IF_CR == interface)) { 2518 *is_valid = 1; 2519 } 2520 } else if (num_lanes == 2) { 2521 if ((SOC_PORT_IF_KR2 == interface) || 2522 (SOC_PORT_IF_CR2 == interface)) { 2523 *is_valid = 1; 2524 } 2525 } 2526 } else { 2527 if (num_lanes == 1) { 2528 if ((SOC_PORT_IF_KR == interface) || 2529 (SOC_PORT_IF_CR == interface) || 2530 (SOC_PORT_IF_SR == interface) || 2531 (SOC_PORT_IF_LR == interface)) { 2532 *is_valid = 1; 2533 } 2534 } else if (num_lanes == 2) { 2535 if ((SOC_PORT_IF_KR2 == interface) || 2536 (SOC_PORT_IF_CR2 == interface) || 2537 (SOC_PORT_IF_SR2 == interface) || 2538 (SOC_PORT_IF_LR2 == interface)) { 2539 *is_valid = 1; 2540 } 2541 } 2542 } 2543 break; 2544 case 25000: 2545 case 27000: 2546 if (is_higig) { 2547 if (num_lanes == 1) { 2548 if ((SOC_PORT_IF_KR == interface) || 2549 (SOC_PORT_IF_CR == interface)) { 2550 *is_valid = 1; 2551 } 2552 } 2553 } else { 2554 if (num_lanes == 1) { 2555 if ((SOC_PORT_IF_KR == interface) || 2556 (SOC_PORT_IF_CR == interface) || 2557 (SOC_PORT_IF_SR == interface) || 2558 (SOC_PORT_IF_LR == interface) || 2559 (SOC_PORT_IF_XFI == interface) || 2560 (SOC_PORT_IF_SFI == interface)) { 2561 *is_valid = 1; 2562 } 2563 } 2564 } 2565 break; 2566 case 40000: 2567 case 42000: 2568 if (is_higig) { 2569 if (num_lanes == 4) { 2570 if ((SOC_PORT_IF_KR4 == interface) || 2571 (SOC_PORT_IF_CR4 == interface)) { 2572 *is_valid = 1; 2573 } 2574 } else if (num_lanes == 2) { 2575 if ((SOC_PORT_IF_KR2 == interface) || 2576 (SOC_PORT_IF_CR2 == interface)) { 2577 *is_valid = 1; 2578 } 2579 } 2580 } else { 2581 if (num_lanes == 4) { 2582 if ((SOC_PORT_IF_KR4 == interface) || 2583 (SOC_PORT_IF_CR4 == interface) || 2584 (SOC_PORT_IF_SR4 == interface) || 2585 (SOC_PORT_IF_XLAUI == interface) || 2586 (SOC_PORT_IF_LR4 == interface)) { 2587 *is_valid = 1; 2588 } 2589 } else if (num_lanes == 2) { 2590 if ((SOC_PORT_IF_KR2 == interface) || 2591 (SOC_PORT_IF_CR2 == interface) || 2592 (SOC_PORT_IF_SR2 == interface) || 2593 (SOC_PORT_IF_XLAUI2 == interface) || 2594 (SOC_PORT_IF_LR2 == interface)) { 2595 *is_valid = 1; 2596 } 2597 } 2598 } 2599 break; 2600 case 48000: 2601 if (!is_higig && num_lanes == 4) { 2602 if ((SOC_PORT_IF_XLAUI == interface) || 2603 (SOC_PORT_IF_CR4 == interface) || 2604 (SOC_PORT_IF_KR4 == interface)) { 2605 *is_valid = 1; 2606 } 2607 } 2608 break; 2609 case 50000: 2610 case 53000: 2611 if (is_higig) { 2612 if (num_lanes == 2) { 2613 if ((SOC_PORT_IF_KR2 == interface) || 2614 (SOC_PORT_IF_CR2 == interface)) { 2615 *is_valid = 1; 2616 } 2617 } else if (num_lanes == 4) { 2618 if ((SOC_PORT_IF_KR4 == interface) || 2619 (SOC_PORT_IF_CR4 == interface)) { 2620 *is_valid = 1; 2621 } 2622 } else { 2623 LOG_ERROR(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, 2624 "ERROR: u=%d p=%d number of lane %d not supported at speed %d\n"), 2625 unit, port, num_lanes, interface_config->speed)); 2626 return SOC_E_PARAM; 2627 } 2628 } else { 2629 if (num_lanes == 2) { 2630 if ((SOC_PORT_IF_KR2 == interface) || 2631 (SOC_PORT_IF_CR2 == interface) || 2632 (SOC_PORT_IF_SR2 == interface) || 2633 (SOC_PORT_IF_XLAUI2 == interface) || 2634 (SOC_PORT_IF_LR2 == interface)) { 2635 *is_valid = 1; 2636 } 2637 } else if (num_lanes == 4) { 2638 if ((SOC_PORT_IF_KR4 == interface) || 2639 (SOC_PORT_IF_CR4 == interface)) { 2640 *is_valid = 1; 2641 } 2642 } else { 2643 LOG_ERROR(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, 2644 "ERROR: u=%d p=%d number of lane %d not supported at speed %d\n"), 2645 unit, port, num_lanes, interface_config->speed)); 2646 return SOC_E_PARAM; 2647 } 2648 } 2649 break; 2650 case 100000: 2651 case 106000: 2652 if (is_higig) { 2653 if (num_lanes == 4) { 2654 if ((SOC_PORT_IF_KR4 == interface) || 2655 (SOC_PORT_IF_CR4 == interface)) { 2656 *is_valid = 1; 2657 } 2658 } 2659 } else { 2660 if (num_lanes == 4) { 2661 if ((SOC_PORT_IF_KR4 == interface) || 2662 (SOC_PORT_IF_CR4 == interface) || 2663 (SOC_PORT_IF_SR4 == interface) || 2664 (SOC_PORT_IF_CAUI4 == interface) || 2665 (SOC_PORT_IF_CAUI == interface) || 2666 (SOC_PORT_IF_LR4 == interface)) { 2667 *is_valid = 1; 2668 } 2669 } 2670 } 2671 break; 2672 default: 2673 break; 2674 } 2675 2676 exit: 2677 SOC_FUNC_RETURN; 2678 } 2679 2680 STATIC 2681 int _pm4x25_default_interface_get(int unit, int port, 2682 const portmod_port_interface_config_t *interface_config, 2683 soc_port_if_t *interface) 2684 { 2685 int is_higig; 2686 int num_lanes; 2687 2688 *interface = SOC_PORT_IF_NULL; 2689 num_lanes = interface_config->port_num_lanes; 2690 is_higig = ((interface_config->encap_mode == SOC_ENCAP_HIGIG2) || 2691 (interface_config->encap_mode == SOC_ENCAP_HIGIG)) ? 1 : 0; 2692 2693 switch (interface_config->speed) { 2694 case 1000: 2695 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2696 SOC_PORT_IF_GMII: SOC_PORT_IF_SGMII; 2697 break; 2698 case 2500: 2699 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2700 SOC_PORT_IF_GMII: SOC_PORT_IF_SGMII; 2701 break; 2702 case 5000: 2703 *interface = SOC_PORT_IF_KR; 2704 break; 2705 case 10000: 2706 if (is_higig) { 2707 *interface = SOC_PORT_IF_CR; 2708 } else { 2709 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2710 SOC_PORT_IF_SFI : SOC_PORT_IF_XFI; 2711 } 2712 break; 2713 case 11000: 2714 case 12000: 2715 *interface = SOC_PORT_IF_XFI; 2716 break; 2717 case 20000: 2718 case 21000: 2719 if (is_higig) { 2720 if (num_lanes == 2) { 2721 *interface = SOC_PORT_IF_CR2; 2722 } else { 2723 *interface = SOC_PORT_IF_CR; 2724 } 2725 } else { 2726 if (num_lanes == 2) { 2727 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2728 SOC_PORT_IF_SR2 : SOC_PORT_IF_CR2; 2729 } else { 2730 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2731 SOC_PORT_IF_SR : SOC_PORT_IF_CR; 2732 } 2733 } 2734 break; 2735 case 25000: 2736 case 27000: 2737 if (is_higig) { 2738 *interface = SOC_PORT_IF_CR; 2739 } else { 2740 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2741 SOC_PORT_IF_SR : SOC_PORT_IF_CR; 2742 } 2743 break; 2744 case 40000: 2745 case 42000: 2746 if (is_higig) { 2747 if (num_lanes == 4) { 2748 *interface = SOC_PORT_IF_KR4; 2749 } else { 2750 *interface = SOC_PORT_IF_CR2; 2751 } 2752 } else { 2753 if (num_lanes == 4) { 2754 *interface = SOC_PORT_IF_XLAUI; 2755 } else { 2756 *interface = SOC_PORT_IF_XLAUI2; 2757 } 2758 } 2759 break; 2760 case 50000: 2761 case 53000: 2762 if (is_higig) { 2763 if (num_lanes == 4) { 2764 *interface = SOC_PORT_IF_KR4; 2765 } else if (num_lanes == 2){ 2766 *interface = SOC_PORT_IF_CR2; 2767 } else { 2768 LOG_ERROR(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, 2769 "ERROR: u=%d p=%d number of lane %d not supported at speed %d\n"), 2770 unit, port, num_lanes, interface_config->speed)); 2771 return SOC_E_PARAM; 2772 } 2773 } else { 2774 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2775 SOC_PORT_IF_SR2 : SOC_PORT_IF_CR2; 2776 if (num_lanes == 4) { 2777 *interface = SOC_PORT_IF_CR4; 2778 } 2779 } 2780 break; 2781 case 100000: 2782 case 106000: 2783 if (is_higig) { 2784 *interface = SOC_PORT_IF_CR4; 2785 } else { 2786 *interface = SOC_PORT_IF_CAUI4; 2787 } 2788 break; 2789 default: 2790 if (num_lanes == 1) { 2791 if (interface_config->speed >= 10000) { 2792 *interface = SOC_PORT_IF_CR; 2793 } else { 2794 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2795 SOC_PORT_IF_GMII: SOC_PORT_IF_SGMII; 2796 } 2797 } else if (num_lanes == 2) { 2798 *interface = SOC_PORT_IF_CR2; 2799 } else if (num_lanes == 4) { 2800 if (interface_config->speed >= 100000) { 2801 if (is_higig){ 2802 *interface = SOC_PORT_IF_CR4; 2803 } else{ 2804 *interface = SOC_PORT_IF_CAUI4; 2805 } 2806 } else { 2807 *interface = SOC_PORT_IF_CR4; 2808 } 2809 } else { 2810 *interface = SOC_PORT_IF_ILKN; 2811 } 2812 break; 2813 } 2814 2815 return SOC_E_NONE; 2816 } 2817 2818 /* Argument phy_init_flags indicates whether this function is called during the 2819 * port attach process or not. When phy_init_flags == PORTMOD_INIT_F_ALL_PHYS 2820 * it means that this function is being called during the port attach process. 2821 * In this case the default interface type of a pm4x25 port can be changed here. 2822 */ 2823 STATIC 2824 int _pm4x25_line_side_phymod_interface_get(int unit, int port, 2825 pm_info_t pm_info, int phy_init_flags, 2826 const portmod_port_interface_config_t *config, 2827 phymod_interface_t *interface_type) 2828 { 2829 int port_index = 0; 2830 int is_valid = 0, nof_phys = 0; 2831 uint32 bitmap; 2832 soc_port_if_t interface = SOC_PORT_IF_NULL; 2833 phymod_phy_access_t phy_access_arr[1+MAX_PHYN]; 2834 pm_version_t pm_version; 2835 SOC_INIT_FUNC_DEFS; 2836 2837 2838 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, 2839 &bitmap)); 2840 2841 _SOC_IF_ERR_EXIT 2842 (portmod_port_chain_phy_access_get(unit, port, pm_info, 2843 phy_access_arr ,(1+MAX_PHYN), 2844 &nof_phys)); 2845 2846 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(config, &interface)); 2847 2848 /* 5G is 64b/66b encoding in pm4x25 Gen3 */ 2849 /* Change 5G default inteface to SOC_PORT_IF_KR */ 2850 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 2851 if (PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) { 2852 if (config->speed == 5000) { 2853 if (interface == SOC_PORT_IF_GMII) { 2854 interface = SOC_PORT_IF_KR; 2855 } 2856 } 2857 } 2858 2859 if (nof_phys > 1) { 2860 /* EXT PHY interface */ 2861 _SOC_IF_ERR_EXIT 2862 (_pm4x25_ext_phy_interface_check(unit, port, pm_info, &phy_access_arr[nof_phys-1], config, interface, 2863 &is_valid)); 2864 } else { 2865 _SOC_IF_ERR_EXIT 2866 (_pm4x25_interface_check(unit, port, config, interface, &is_valid)); 2867 } 2868 2869 if (!is_valid) { 2870 /* interface check validation for internal sedes failed */ 2871 LOG_ERROR(BSL_LS_BCM_PORT, 2872 (BSL_META_UP(unit, port, 2873 "ERROR: u=%d p=%d interface type %d not supported by internal SERDES for this speed %d \n"), 2874 unit, port, interface, config->speed)); 2875 _SOC_IF_ERR_EXIT(SOC_E_PARAM); 2876 } 2877 2878 2879 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, config->speed, 2880 interface, interface_type)); 2881 2882 2883 exit: 2884 SOC_FUNC_RETURN; 2885 } 2886 2887 int _pm4x25_phymod_interface_mode_set(int unit, int port,pm_info_t pm_info, 2888 const portmod_port_interface_config_t *config, 2889 phymod_phy_inf_config_t *phy_config, 2890 int is_legacy_phy_callback) 2891 { 2892 int port_index = 0; 2893 uint32 bitmap; 2894 soc_port_if_t interface = SOC_PORT_IF_NULL; 2895 SOC_INIT_FUNC_DEFS; 2896 2897 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, 2898 &bitmap)); 2899 _SOC_IF_ERR_EXIT(PM4x25_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index)); 2900 2901 phy_config->interface_modes = config->interface_modes; 2902 2903 /* 2904 * tsce/tscf relies on the interface type and interface mode specified in phy_config 2905 * to determine the exact interface type written into or read from the registers. For 2906 * instance, SR4 and KR4 share the same speed ID (reg value) from TSCE's perspective 2907 * and their difference is the medium type specified in the interface mode. SR4 is 2908 * optical while KR4 is not. Below we prevent updating the medium type in the port 2909 * mode provided to the internal PHY if phy_config is to be provided to the internal 2910 * PHY in the legacy ext PHY callback scenario. Reason is because interface used in 2911 * the function call below is meant for the outmost PHY instead of the internal PHY. 2912 * portmod_port_phychain_interface_config_set() has a similar protection mechanism 2913 * to change the medium type of the port mode based on internal PHY's interface type. 2914 * However, that only works when the config property "serdes_if_type" is specified. 2915 */ 2916 if (!is_legacy_phy_callback) { 2917 _SOC_IF_ERR_EXIT(portmod_media_type_from_port_intf(unit, interface, 2918 phy_config)); 2919 } 2920 exit: 2921 SOC_FUNC_RETURN; 2922 } 2923 2924 STATIC 2925 int _pm4x25_port_timestamp_adjust_wb_get(int unit, int port, pm_info_t pm_info, 2926 int speed, portmod_port_ts_adjust_t *ts_adjust) 2927 { 2928 int rv = 0; 2929 int port_index, adjust_index; 2930 uint32_t bitmap; 2931 portmod_port_ts_adjust_t port_ts_adjust; 2932 2933 SOC_INIT_FUNC_DEFS; 2934 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 2935 &bitmap)); 2936 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM; adjust_index++) { 2937 rv = PM4x25_PORT_TIME_STAMP_ADJUST_GET(unit, pm_info, &port_ts_adjust, adjust_index, port_index); 2938 if ((port_ts_adjust.speed == speed) || 2939 (port_ts_adjust.speed == -1)) { 2940 sal_memcpy(ts_adjust, &port_ts_adjust, sizeof(portmod_port_ts_adjust_t)); 2941 break; 2942 } 2943 } 2944 2945 _SOC_IF_ERR_EXIT(rv); 2946 exit: 2947 SOC_FUNC_RETURN; 2948 } 2949 2950 int pm4x25_port_attach(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 2951 { 2952 int port_index = -1, init_all=0; 2953 int rv = 0, port_i, my_i, found_first_active_lane; 2954 int phy, ii, nof_phys, fec_enable = 0; 2955 int phys_count = 0, first_phy = -1, is_interface_restore; 2956 uint32 pm_is_active = 0; 2957 uint32 pm_is_bypassed = 0, port_dynamic_state; 2958 portmod_pbmp_t port_phys_in_pm; 2959 phymod_phy_init_config_t init_config; 2960 phymod_phy_inf_config_t *phy_config = &init_config.interface; 2961 portmod_access_get_params_t params; 2962 phymod_phy_access_t phy_access[1+MAX_PHYN]; 2963 phymod_phy_access_t phy_access_lane; 2964 portmod_port_ability_t port_ability; 2965 const portmod_port_interface_config_t *config = &add_info->interface_config; 2966 portmod_port_interface_config_t local_config = add_info->interface_config; 2967 phymod_interface_t phymod_interface = phymodInterfaceCount; 2968 soc_port_if_t local_default_interface; 2969 int is_higig, itf_update = 0, usr_cfg_idx, three_ports_mode; 2970 int adjust_index = 0; 2971 pm_version_t pm_version; 2972 uint32 interface_modes; 2973 uint32 vsd_active_group[NUM_VSD_ACTIVE_GROUP_WORD]={0}; 2974 portmod_link_recovery_t link_recovery; 2975 SOC_INIT_FUNC_DEFS; 2976 2977 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &pm_is_bypassed); 2978 _SOC_IF_ERR_EXIT(rv); 2979 2980 2981 /* Get the first phy related to this port */ 2982 if (PM_4x25_INFO(pm_info)->in_pm12x10) { 2983 port_index = 0; 2984 rv = PM4x25_LANE2PORT_SET(unit, pm_info, port_index, port); 2985 _SOC_IF_ERR_EXIT(rv); 2986 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, PM_4x25_INFO(pm_info)->first_phy){break;} /*just get first phy*/ 2987 } else { 2988 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 2989 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x25_INFO(pm_info)->phys); 2990 PORTMOD_PBMP_COUNT(port_phys_in_pm, phys_count); 2991 2992 ii = 0; 2993 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy){ 2994 if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)){ 2995 rv = PM4x25_LANE2PORT_SET(unit, pm_info, ii, port); 2996 _SOC_IF_ERR_EXIT(rv); 2997 first_phy = (first_phy == -1) ? phy : first_phy; 2998 port_index = (port_index == -1 ? ii : port_index); 2999 } 3000 ii++; 3001 } 3002 PM_4x25_INFO(pm_info)->first_phy = first_phy; 3003 } 3004 3005 if(port_index<0 || port_index>=PM4X25_LANES_PER_CORE) { 3006 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 3007 (_SOC_MSG("can't attach port %d. can't find relevant phy"), port)); 3008 } 3009 3010 /* init data for port configuration */ 3011 rv = PM4x25_IS_HG_SET(unit, pm_info, add_info->init_config.is_hg, port_index); 3012 _SOC_IF_ERR_EXIT(rv); 3013 3014 rv = PM4x25_AN_MODE_SET(unit, pm_info, add_info->init_config.an_mode, port_index); 3015 _SOC_IF_ERR_EXIT(rv); 3016 3017 rv = PM4x25_FS_CL72_SET(unit, pm_info, add_info->init_config.fs_cl72, port_index); 3018 _SOC_IF_ERR_EXIT(rv); 3019 3020 rv = PM4x25_CX4_10G_SET(unit, pm_info, add_info->init_config.cx4_10g, port_index); 3021 _SOC_IF_ERR_EXIT(rv); 3022 3023 rv = PM4x25_AN_CL72_SET(unit, pm_info, add_info->init_config.an_cl72, port_index); 3024 _SOC_IF_ERR_EXIT(rv); 3025 3026 rv = PM4x25_AN_FEC_SET(unit, pm_info, add_info->init_config.an_fec, port_index); 3027 _SOC_IF_ERR_EXIT(rv); 3028 3029 rv = PM4x25_AN_MASTER_LANE_SET(unit, pm_info, add_info->init_config.an_master_lane, port_index); 3030 _SOC_IF_ERR_EXIT(rv); 3031 3032 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, add_info->interface_config.max_speed, port_index); 3033 _SOC_IF_ERR_EXIT(rv); 3034 3035 rv = PM4x25_INTERFACE_TYPE_SET(unit, pm_info, add_info->interface_config.interface, port_index); 3036 _SOC_IF_ERR_EXIT(rv); 3037 3038 rv = PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, add_info->interface_config.interface, port_index); 3039 _SOC_IF_ERR_EXIT(rv); 3040 3041 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, add_info->interface_config.interface_modes, port_index); 3042 _SOC_IF_ERR_EXIT(rv); 3043 3044 rv = PM4x25_PORT_PLL_DIVIDER_REQ_SET(unit, pm_info, add_info->init_config.pll_divider_req, port_index); 3045 _SOC_IF_ERR_EXIT(rv); 3046 3047 rv = PM4x25_PORT_1000X_AT_25G_SET(unit, pm_info, add_info->init_config.serdes_1000x_at_25g_vco, port_index); 3048 _SOC_IF_ERR_EXIT(rv); 3049 3050 rv = PM4x25_PORT_10G_AT_25G_SET(unit, pm_info, add_info->init_config.serdes_10g_at_25g_vco, port_index); 3051 _SOC_IF_ERR_EXIT(rv); 3052 3053 rv = PM4x25_CPRI_PORT_VSD_ACTIVE_GROUP_SET(unit, pm_info, vsd_active_group, port_index); 3054 _SOC_IF_ERR_EXIT(rv); 3055 3056 is_interface_restore = (add_info->interface_config.flags & PHYMOD_INTF_F_INTF_PARAM_SET_ONLY) ? 1 : 0 ; 3057 rv = PM4x25_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, port_index); 3058 _SOC_IF_ERR_EXIT(rv); 3059 3060 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM; adjust_index++) { 3061 rv = PM4x25_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, 3062 &add_info->init_config.port_ts_adjust[adjust_index], 3063 adjust_index, port_index); 3064 _SOC_IF_ERR_EXIT(rv); 3065 } 3066 3067 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK; 3068 link_recovery.enabled = TRUE; 3069 link_recovery.tick_cnt = 0; 3070 rv = PM4x25_PORT_LINK_RECOVERY_SET(unit, pm_info, link_recovery, port_index); 3071 _SOC_IF_ERR_EXIT(rv); 3072 3073 if (PM_4x25_INFO(pm_info)->in_pm12x10) { 3074 if (add_info->init_config.fw_load_method_overwrite == 1) { 3075 PM_4x25_INFO(pm_info)->fw_load_method = phymodFirmwareLoadMethodNone; 3076 } 3077 } else { 3078 if (add_info->init_config.polarity_overwrite == 1) { 3079 sal_memcpy(&PM_4x25_INFO(pm_info)->polarity, 3080 &add_info->init_config.polarity[0], sizeof(phymod_polarity_t)); 3081 } 3082 if (add_info->init_config.lane_map_overwrite == 1) { 3083 sal_memcpy(&PM_4x25_INFO(pm_info)->lane_map, 3084 &add_info->init_config.lane_map[0], sizeof(phymod_lane_map_t)); 3085 } 3086 if (add_info->init_config.fw_load_method_overwrite == 1) { 3087 PM_4x25_INFO(pm_info)->fw_load_method = 3088 add_info->init_config.fw_load_method[0]; 3089 } 3090 } 3091 3092 if (add_info->init_config.ref_clk_overwrite == 1) { 3093 PM_4x25_INFO(pm_info)->ref_clk = add_info->init_config.ref_clk; 3094 } 3095 3096 rv = PM4x25_IS_ACTIVE_GET(unit, pm_info, &pm_is_active); 3097 _SOC_IF_ERR_EXIT(rv); 3098 3099 init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) && 3100 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) && 3101 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) ? 1 : 0; 3102 3103 3104 if (!PORTMOD_PORT_ADD_F_AUTONEG_CONFIG_SKIP_GET(add_info)) 3105 { 3106 /* update an information before proceeding further */ 3107 SOC_IF_ERROR_RETURN(_pm4x25_an_mode_update (unit, port, pm_info, port_index, add_info->interface_config.port_num_lanes, add_info->init_config.an_cl73)); 3108 } 3109 3110 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 3111 3112 /* if not active - initalize PM */ 3113 if(!pm_is_active){ 3114 if (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) || (init_all)) { 3115 three_ports_mode = (add_info->init_config.port_mode_aux_info == portmodModeInfoThreePorts) ? 1 : 0; 3116 rv = PM4x25_THREE_PORTS_MODE_SET(unit, pm_info, three_ports_mode); 3117 _SOC_IF_ERR_EXIT(rv); 3118 3119 /*init the PM*/ 3120 rv = _pm4x25_pm_enable(unit, port, pm_info, port_index, add_info, 1); 3121 _SOC_IF_ERR_EXIT(rv); 3122 } 3123 3124 pm_is_active = 1; 3125 3126 if(PORTMOD_PM4x25_IS_GEN3_28nm(pm_version)){ 3127 /* Set tsc and fclk */ 3128 _SOC_IF_ERR_EXIT(_pm4x25_pm_ext_tsc_clk_set(unit, port, pm_info, add_info)); 3129 } 3130 3131 rv = PM4x25_IS_ACTIVE_SET(unit, pm_info, pm_is_active); 3132 _SOC_IF_ERR_EXIT(rv); 3133 } 3134 3135 3136 if ((pm_is_active) && (PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) && 3137 (PM_4x25_INFO(pm_info)->int_core_access.type == phymodDispatchTypeInvalid)){ 3138 _SOC_IF_ERR_EXIT(_pm4x25_pm_ext_tsc_clk_set(unit, port, pm_info, add_info)); 3139 } 3140 3141 /* probe core internal serdes and ext phys if there is any. */ 3142 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] > 0){ 3143 /* only at CORE PROBE phase need probe */ 3144 if (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) || init_all) { 3145 rv = _pm4x25_pm_core_probe(unit, port, pm_info, add_info); 3146 _SOC_IF_ERR_EXIT(rv); 3147 } 3148 } 3149 3150 if (!(PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) && 3151 (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info))) { 3152 return (rv); 3153 } 3154 3155 /* probe core and core config internal serdes and ext phys if there is any. */ 3156 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] > 0 ){ 3157 rv = _pm4x25_pm_core_init(unit, port, pm_info, add_info, 1); 3158 _SOC_IF_ERR_EXIT(rv); 3159 } 3160 3161 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 3162 return (rv); 3163 } 3164 3165 /* initalize port */ 3166 rv = _pm4x25_pm_port_init(unit, port, pm_info, port_index, add_info, 1); 3167 _SOC_IF_ERR_EXIT(rv); 3168 3169 /* initialze phys */ 3170 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] > 0) { 3171 3172 _SOC_IF_ERR_EXIT(phymod_phy_init_config_t_init(&init_config)); 3173 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 3174 3175 params.phyn = 0; 3176 _SOC_IF_ERR_EXIT(pm4x25_port_phy_lane_access_get(unit, port, pm_info, 3177 ¶ms, 1, &phy_access_lane, &nof_phys, NULL)); 3178 3179 init_config.an_en = add_info->autoneg_en; 3180 init_config.cl72_en = add_info->link_training_en; 3181 init_config.op_mode = add_info->interface_config.port_op_mode; 3182 3183 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 3184 phy_access ,(1+MAX_PHYN), 3185 &nof_phys)); 3186 3187 my_i = 0, usr_cfg_idx = 0; 3188 found_first_active_lane = 0; 3189 for(ii=0 ; ii<PM4X25_LANES_PER_CORE ; ii++) { 3190 rv = PM4x25_LANE2PORT_GET(unit, pm_info, ii, &port_i); 3191 _SOC_IF_ERR_EXIT(rv); 3192 3193 if(port_i != port) { 3194 /* There is a difference between XGS and DNX devices. For DNX, a port can consist inconsecutive physical lanes. 3195 * For example, a port can consist lane 1 and 3 of the same core. For XGS, on the other hand, a port always consist 3196 * consecutive physical lanes. Therefore my_i below needs not be incremented for XGS devices. 3197 */ 3198 if(PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy_access[0].device_op_mode) && found_first_active_lane){ 3199 my_i++; 3200 } 3201 continue; 3202 } else{ 3203 found_first_active_lane = 1; 3204 } 3205 3206 if(SHR_BITGET(&(PM_4x25_INFO(pm_info)->polarity.tx_polarity),ii)) { 3207 SHR_BITSET(&init_config.polarity.tx_polarity, my_i); 3208 } 3209 3210 if(SHR_BITGET(&(PM_4x25_INFO(pm_info)->polarity.rx_polarity),ii)) { 3211 SHR_BITSET(&init_config.polarity.rx_polarity, my_i); 3212 } 3213 3214 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access_lane, phymodMediaTypeChipToChip, &init_config.tx[my_i])); 3215 3216 if (PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG_GET(add_info->init_config.tx_params_user_flag[usr_cfg_idx])) { 3217 init_config.tx[my_i].pre = add_info->init_config.tx_params[usr_cfg_idx].pre; 3218 init_config.tx[my_i].main = add_info->init_config.tx_params[usr_cfg_idx].main; 3219 init_config.tx[my_i].post = add_info->init_config.tx_params[usr_cfg_idx].post; 3220 } 3221 3222 if (PORTMOD_USER_SET_TX_AMP_BY_CONFIG_GET(add_info->init_config.tx_params_user_flag[usr_cfg_idx])) { 3223 init_config.tx[my_i].amp = add_info->init_config.tx_params[usr_cfg_idx].amp; 3224 } 3225 3226 if (PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG_GET(add_info->init_config.tx_params_user_flag[usr_cfg_idx]) 3227 || PORTMOD_USER_SET_TX_AMP_BY_CONFIG_GET(add_info->init_config.tx_params_user_flag[usr_cfg_idx])) { 3228 port_dynamic_state = 0; 3229 PORTMOD_PORT_DEFAULT_TX_PARAMS_UPDATED_SET(port_dynamic_state); 3230 3231 PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, port_dynamic_state, port_index); 3232 } 3233 3234 usr_cfg_idx++; 3235 my_i++; 3236 3237 } 3238 3239 phy_config->data_rate = config->speed; 3240 phy_config->pll_divider_req = add_info->init_config.pll_divider_req; 3241 phy_config->ref_clock = PM_4x25_INFO(pm_info)->ref_clk; 3242 3243 _SOC_IF_ERR_EXIT(_pm4x25_line_side_phymod_interface_get(unit, port, pm_info, PORTMOD_INIT_F_ALL_PHYS, config, &phymod_interface)); 3244 phy_config->interface_type = phymod_interface; 3245 _SOC_IF_ERR_EXIT(_pm4x25_phymod_interface_mode_set(unit, port, pm_info, config, phy_config, 0)); 3246 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 3247 _SOC_IF_ERR_EXIT(rv); 3248 if (PHYMOD_INTF_MODES_FIBER_GET(phy_config)) { 3249 interface_modes &= ~(PHYMOD_INTF_MODES_COPPER | PHYMOD_INTF_MODES_BACKPLANE); 3250 interface_modes |= PHYMOD_INTF_MODES_FIBER; 3251 } else if (PHYMOD_INTF_MODES_COPPER_GET(phy_config)){ 3252 interface_modes &= ~(PHYMOD_INTF_MODES_FIBER | PHYMOD_INTF_MODES_BACKPLANE); 3253 interface_modes |= PHYMOD_INTF_MODES_COPPER; 3254 } else if (PHYMOD_INTF_MODES_BACKPLANE_GET(phy_config)){ 3255 interface_modes &= ~(PHYMOD_INTF_MODES_COPPER | PHYMOD_INTF_MODES_FIBER); 3256 interface_modes |= PHYMOD_INTF_MODES_BACKPLANE; 3257 } 3258 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 3259 _SOC_IF_ERR_EXIT(rv); 3260 3261 _SOC_IF_ERR_EXIT(portmod_port_phychain_phy_init(unit, phy_access, nof_phys, 3262 &init_config)); 3263 } 3264 3265 /* enable fec if set, should be done before setting the speed */ 3266 fec_enable = add_info->init_config.serdes_fec_enable; 3267 3268 if (fec_enable) { 3269 int value = 0; 3270 3271 if ((fec_enable != PORTMOD_PORT_FEC_CL91) && 3272 (fec_enable != PORTMOD_PORT_FEC_CL74) && 3273 (fec_enable != PORTMOD_PORT_FEC_CL108)) { 3274 return (SOC_E_PARAM); 3275 } 3276 3277 if (fec_enable == PORTMOD_PORT_FEC_CL91) { 3278 PHYMOD_FEC_CL91_SET(value); 3279 } else if (fec_enable == PORTMOD_PORT_FEC_CL108) { 3280 PHYMOD_FEC_CL108_SET(value); 3281 } 3282 3283 value |= TRUE; 3284 rv = portmod_port_fec_enable_set(unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, value); 3285 _SOC_IF_ERR_EXIT(rv); 3286 } 3287 3288 /* The default interface type given by add_info is filled by soc_esw_portctrl_config_get() 3289 * and should be updated here locally since soc_esw_portctrl_config_get() only gives coarse- 3290 * grained default interface type without considering whether the underlying device is 3291 * pm4x10 or pm4x25, with or without ext PHY, etc. 3292 */ 3293 if (nof_phys == 1) { 3294 if (config->serdes_interface != SOC_PORT_IF_NULL) { 3295 _SOC_IF_ERR_EXIT(_pm4x25_interface_check(unit, port, config, config->serdes_interface, &itf_update)); 3296 if (itf_update) { 3297 local_config.interface = config->serdes_interface; 3298 } 3299 } 3300 3301 is_higig = ((config->encap_mode == SOC_ENCAP_HIGIG2) || 3302 (config->encap_mode == SOC_ENCAP_HIGIG) || 3303 PHYMOD_INTF_MODES_HIGIG_GET(config)) ? 1 : 0; 3304 3305 if ((config->speed == 42000 || config->speed == 40000) && is_higig && !itf_update) { 3306 local_default_interface = SOC_PORT_IF_NULL; 3307 _SOC_IF_ERR_EXIT( 3308 pm4x25_port_default_interface_get(unit, port, pm_info, config, 3309 &local_default_interface)); 3310 if(local_default_interface != SOC_PORT_IF_NULL){ 3311 local_config.interface = local_default_interface; 3312 itf_update = 1; 3313 } 3314 } 3315 3316 if (itf_update) { 3317 _SOC_IF_ERR_EXIT( 3318 PM4x25_INTERFACE_TYPE_SET(unit, pm_info, local_config.interface, port_index)); 3319 _SOC_IF_ERR_EXIT( 3320 PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, local_config.interface, port_index)); 3321 } 3322 } 3323 if (add_info->init_config.cpm_core_mode == portmodCpmMixEthCpri) { 3324 local_config.flags |= PHYMOD_INTF_F_SINGLE_PLL_ONLY; 3325 } 3326 rv = pm4x25_port_interface_config_set(unit, port, pm_info, &local_config, PORTMOD_INIT_F_ALL_PHYS); 3327 _SOC_IF_ERR_EXIT(rv); 3328 3329 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] > 0) { 3330 if(add_info->init_config.fs_cl72) { 3331 /* config port_init_cl72 is used to enable fs cl72 only in the serdes, 3332 * do not enable cl72 on external phys. Set the no of phys argument to 3333 * 1 to avoid setting cl72 enable on ext phys 3334 */ 3335 _SOC_IF_ERR_EXIT(portmod_port_phychain_cl72_set(unit, port, phy_access, 1, 1)); 3336 } 3337 } 3338 3339 if(!(PM_4x25_INFO(pm_info)->in_pm12x10)) { 3340 /* set the default advert ability */ 3341 _SOC_IF_ERR_EXIT 3342 (pm4x25_port_ability_local_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &port_ability)); 3343 _SOC_IF_ERR_EXIT 3344 (pm4x25_port_ability_advert_set(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &port_ability)); 3345 } 3346 3347 if (PORTMOD_PM4x25_IS_GEN3_28nm(pm_version) || PORTMOD_CPM4x25_IS_GEN3_28nm(pm_version)) { 3348 /* Set PMD TXPI mode */ 3349 _SOC_IF_ERR_EXIT(_pm4x25_port_phy_txpi_mode_set(unit, port, pm_info, add_info->init_config.txpi_mode)); 3350 } 3351 3352 /* De-Assert SOFT_RESET */ 3353 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 0)); 3354 3355 3356 exit: 3357 SOC_FUNC_RETURN; 3358 } 3359 3360 int pm4x25_port_detach(int unit, int port, pm_info_t pm_info) 3361 { 3362 int enable; 3363 int invalid_port = -1; 3364 int tmp_port; 3365 int i = 0, flags = 0; 3366 int rv = 0; 3367 int is_last_one = TRUE; 3368 int port_index = -1; 3369 int phytype = 0, nof_phys; 3370 uint32 inactive = 0; 3371 phymod_phy_access_t serdes_acc; 3372 portmod_access_get_params_t params; 3373 phymod_phy_reset_t phy_reset; 3374 SOC_INIT_FUNC_DEFS; 3375 3376 if (PM_4x25_INFO(pm_info)->nof_phys[0] == 0) { 3377 /* There are no phys.., so only mac needs to be checked */ 3378 PORTMOD_PORT_ENABLE_MAC_SET(flags); 3379 } 3380 3381 _SOC_IF_ERR_EXIT(pm4x25_port_enable_get(unit, port, pm_info, flags, &enable)); 3382 if(enable){ 3383 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("can't detach active port %d"), port)); 3384 } 3385 3386 if (!PM_4x25_INFO(pm_info)->in_pm12x10) { 3387 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 3388 params.phyn = 0; 3389 _SOC_IF_ERR_EXIT(pm4x25_port_phy_lane_access_get(unit, port, pm_info, 3390 ¶ms, 1, &serdes_acc, &nof_phys, NULL)); 3391 } 3392 3393 /*remove from array and check if it was the last one*/ 3394 for( i = 0 ; i < MAX_PORTS_PER_PM4X25; i++){ 3395 rv = PM4x25_LANE2PORT_GET(unit, pm_info, i, &tmp_port); 3396 _SOC_IF_ERR_EXIT(rv); 3397 if(tmp_port == port){ 3398 port_index = (port_index == -1 ? i : port_index); 3399 rv = PM4x25_LANE2PORT_SET(unit, pm_info, i, invalid_port); 3400 _SOC_IF_ERR_EXIT(rv); 3401 } else if (tmp_port != -1){ 3402 is_last_one = FALSE; 3403 } 3404 } 3405 3406 if ((PM_4x25_INFO(pm_info)->nof_phys[0]) && (port_index == -1)) { 3407 _SOC_EXIT_WITH_ERR(SOC_E_PORT, (_SOC_MSG("Port %d wasn't found"), port)); 3408 } 3409 3410 rv = _pm4x25_pm_port_init(unit, port, pm_info, port_index, NULL, 0); 3411 _SOC_IF_ERR_EXIT(rv); 3412 3413 if (!PM_4x25_INFO(pm_info)->in_pm12x10 && (PM_4x25_INFO(pm_info)->int_core_access.type == phymodDispatchTypeTscf16)) { 3414 phymod_phy_reset_t_init(&phy_reset); 3415 _SOC_IF_ERR_EXIT(phymod_phy_reset_set(&serdes_acc, &phy_reset)); 3416 } 3417 3418 /*deinit PM in case of last one*/ 3419 if(is_last_one){ 3420 rv = _pm4x25_pm_enable(unit, port, pm_info, port_index, NULL, 0); 3421 _SOC_IF_ERR_EXIT(rv); 3422 3423 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_CLR(PM_4x25_INFO(pm_info)->int_core_access.device_op_mode); 3424 3425 rv = PM4x25_IS_ACTIVE_SET(unit, pm_info, inactive); 3426 _SOC_IF_ERR_EXIT(rv); 3427 3428 rv = PM4x25_IS_INITIALIZED_SET(unit, pm_info, inactive); 3429 _SOC_IF_ERR_EXIT(rv); 3430 3431 rv = PM4x25_IS_BYPASSED_SET(unit, pm_info, inactive); 3432 _SOC_IF_ERR_EXIT(rv); 3433 3434 /* Updating phymod type in pm_info structure and warmboot engine */ 3435 phytype = phymodDispatchTypeInvalid; 3436 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[phy_type], &phytype, 0); 3437 _SOC_IF_ERR_EXIT(rv); 3438 PM_4x25_INFO(pm_info)->int_core_access.type = phymodDispatchTypeInvalid; 3439 3440 } 3441 3442 exit: 3443 SOC_FUNC_RETURN; 3444 } 3445 3446 int pm4x25_port_replace(int unit, int port, pm_info_t pm_info, int new_port) 3447 { 3448 int i, tmp_port; 3449 int rv = 0; 3450 SOC_INIT_FUNC_DEFS; 3451 3452 3453 /* replace old port with new port */ 3454 for(i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 3455 rv = PM4x25_LANE2PORT_GET(unit, pm_info, i, &tmp_port); 3456 _SOC_IF_ERR_EXIT(rv); 3457 if (tmp_port == port) { 3458 rv = PM4x25_LANE2PORT_SET(unit, pm_info, i, new_port); 3459 _SOC_IF_ERR_EXIT(rv); 3460 } 3461 } 3462 3463 exit: 3464 SOC_FUNC_RETURN; 3465 3466 } 3467 3468 int pm4x25_pm_bypass_set(int unit, pm_info_t pm_info, int bypass_enable) 3469 { 3470 int rv = 0, bypass_enable_get; 3471 uint32 pm_is_active = 0; 3472 SOC_INIT_FUNC_DEFS; 3473 3474 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &bypass_enable_get); 3475 _SOC_IF_ERR_EXIT(rv); 3476 3477 if (bypass_enable_get != bypass_enable) { 3478 rv = PM4x25_IS_ACTIVE_GET(unit, pm_info, &pm_is_active); 3479 _SOC_IF_ERR_EXIT(rv); 3480 3481 if(pm_is_active) { 3482 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("can't chenge bypass mode for active pm"))); 3483 } 3484 3485 rv = PM4x25_IS_BYPASSED_SET(unit, pm_info, bypass_enable); 3486 _SOC_IF_ERR_EXIT(rv); 3487 } 3488 3489 exit: 3490 SOC_FUNC_RETURN; 3491 3492 } 3493 3494 int pm4x25_pm_core_info_get(int unit, pm_info_t pm_info, int phyn, portmod_pm_core_info_t* core_info) 3495 { 3496 SOC_INIT_FUNC_DEFS; 3497 3498 if(PM_4x25_INFO(pm_info)->in_pm12x10){ 3499 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("core access get cannot be called for PM4X25 which is part of PM12X10"))); 3500 } 3501 3502 if(phyn >= PM_4x25_INFO(pm_info)->nof_phys[0]){ 3503 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("phyn exceeded. max allowed %d. got %d"), PM_4x25_INFO(pm_info)->nof_phys[0]-1, phyn)); 3504 } 3505 if(phyn < 0) { 3506 phyn = PM_4x25_INFO(pm_info)->nof_phys[0] - 1; /* last one */ 3507 } 3508 core_info->ref_clk = PM_4x25_INFO(pm_info)->ref_clk; 3509 sal_memcpy(&core_info->lane_map, &(PM_4x25_INFO(pm_info)->lane_map), sizeof(phymod_lane_map_t)); 3510 3511 exit: 3512 SOC_FUNC_RETURN; 3513 } 3514 3515 int pm4x25_pm_phys_get(int unit, pm_info_t pm_info, portmod_pbmp_t* phys) 3516 { 3517 SOC_INIT_FUNC_DEFS; 3518 PORTMOD_PBMP_ASSIGN(*phys, PM_4x25_INFO(pm_info)->phys); 3519 SOC_FUNC_RETURN; 3520 } 3521 3522 int pm4x25_port_enable_set(int unit, int port, pm_info_t pm_info, int flags, int enable) 3523 { 3524 3525 uint32 is_bypassed = 0, phychain_flag; 3526 int rv = 0, rst_flags = 0; 3527 int actual_flags = flags; 3528 phymod_phy_access_t phy_access[1+MAX_PHYN]; 3529 phymod_phy_power_t phy_power; 3530 int nof_phys = 0, clmac_flags = 0; 3531 SOC_INIT_FUNC_DEFS; 3532 3533 3534 /* If no RX\TX flags - set both*/ 3535 if((!PORTMOD_PORT_ENABLE_TX_GET(flags)) && (!PORTMOD_PORT_ENABLE_RX_GET(flags))){ 3536 PORTMOD_PORT_ENABLE_RX_SET(actual_flags); 3537 PORTMOD_PORT_ENABLE_TX_SET(actual_flags); 3538 } 3539 3540 /* if no MAC\Phy flags - set both*/ 3541 if((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) && (!PORTMOD_PORT_ENABLE_MAC_GET(flags))){ 3542 PORTMOD_PORT_ENABLE_PHY_SET(actual_flags); 3543 PORTMOD_PORT_ENABLE_MAC_SET(actual_flags); 3544 } 3545 3546 /* if MAC is set and either RX or TX set is invalid combination */ 3547 if( (PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) ) { 3548 if((!PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) || (!PORTMOD_PORT_ENABLE_RX_GET(actual_flags))){ 3549 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("MAC RX and TX can't be enabled separately"))); 3550 } 3551 } 3552 /* phychain_flag is meant to be used if we want only part of the phychin to be affected*/ 3553 phychain_flag = PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_GET(flags) ? 3554 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY : 3555 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY ; 3556 3557 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &is_bypassed); 3558 _SOC_IF_ERR_EXIT(rv); 3559 3560 _SOC_IF_ERR_EXIT(phymod_phy_power_t_init(&phy_power)); 3561 phy_power.rx = phymodPowerNoChange; 3562 phy_power.tx = phymodPowerNoChange; 3563 3564 if(PORTMOD_PORT_ENABLE_RX_GET(actual_flags)){ 3565 phy_power.rx = (enable) ? phymodPowerOn : phymodPowerOff; 3566 clmac_flags |= CLMAC_ENABLE_SET_FLAGS_RX_EN; 3567 } 3568 if(PORTMOD_PORT_ENABLE_TX_GET(actual_flags)){ 3569 phy_power.tx = (enable) ? phymodPowerOn : phymodPowerOff; 3570 clmac_flags |= CLMAC_ENABLE_SET_FLAGS_TX_EN; 3571 } 3572 3573 if(enable){ 3574 if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)){ 3575 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 3576 rst_flags |= CLMAC_ENABLE_SET_FLAGS_SOFT_RESET_DIS; 3577 } 3578 rv = clmac_enable_set(unit, port, rst_flags, 1); 3579 _SOC_IF_ERR_EXIT(rv); 3580 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 3581 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 0)); 3582 } 3583 } 3584 if((PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) && (!(PM_4x25_INFO(pm_info)->in_pm12x10))){ 3585 _SOC_IF_ERR_EXIT 3586 (portmod_port_chain_phy_access_get(unit, port, pm_info, 3587 phy_access ,(1+MAX_PHYN), 3588 &nof_phys)); 3589 3590 _SOC_IF_ERR_EXIT (portmod_port_phychain_power_set(unit, port, phy_access, nof_phys, phychain_flag, &phy_power)); 3591 3592 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 3593 _SOC_IF_ERR_EXIT 3594 (portmod_port_phychain_tx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 3595 phymodTxSquelchOff)); 3596 } 3597 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 3598 _SOC_IF_ERR_EXIT 3599 (portmod_port_phychain_rx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 3600 phymodRxSquelchOff)); 3601 } 3602 } 3603 3604 } 3605 else{ 3606 if((PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) && (!(PM_4x25_INFO(pm_info)->in_pm12x10))){ 3607 3608 _SOC_IF_ERR_EXIT 3609 (portmod_port_chain_phy_access_get(unit, port, pm_info, 3610 phy_access ,(1+MAX_PHYN), 3611 &nof_phys)); 3612 3613 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 3614 _SOC_IF_ERR_EXIT 3615 (portmod_port_phychain_tx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 3616 phymodTxSquelchOn)); 3617 } 3618 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 3619 _SOC_IF_ERR_EXIT 3620 (portmod_port_phychain_rx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 3621 phymodRxSquelchOn)); 3622 } 3623 3624 _SOC_IF_ERR_EXIT (portmod_port_phychain_power_set(unit, port, phy_access, nof_phys, phychain_flag, &phy_power)); 3625 } 3626 if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)){ 3627 rv = clmac_enable_set(unit, port, clmac_flags, 0); 3628 _SOC_IF_ERR_EXIT(rv); 3629 } 3630 } 3631 3632 exit: 3633 SOC_FUNC_RETURN; 3634 3635 } 3636 3637 int pm4x25_port_enable_get(int unit, int port, pm_info_t pm_info, int flags, int* enable) 3638 { 3639 phymod_phy_access_t phy_access[1+MAX_PHYN]; 3640 int nof_phys = 0; 3641 phymod_phy_tx_lane_control_t tx_control = phymodTxSquelchOn; 3642 phymod_phy_rx_lane_control_t rx_control = phymodRxSquelchOn; 3643 int phy_enable = 1, mac_enable = 1; 3644 int mac_rx_enable = 0, mac_tx_enable = 0; 3645 uint32 is_bypassed = 0, phychain_flag; 3646 int rv; 3647 int actual_flags = flags; 3648 SOC_INIT_FUNC_DEFS; 3649 SOC_NULL_CHECK(pm_info); 3650 3651 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &is_bypassed); 3652 _SOC_IF_ERR_EXIT(rv); 3653 3654 /* If no RX\TX flags - set both*/ 3655 if((!PORTMOD_PORT_ENABLE_TX_GET(flags)) && (!PORTMOD_PORT_ENABLE_RX_GET(flags))){ 3656 PORTMOD_PORT_ENABLE_RX_SET(actual_flags); 3657 PORTMOD_PORT_ENABLE_TX_SET(actual_flags); 3658 } 3659 3660 /* if no MAC\Phy flags - set both*/ 3661 if((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) && (!PORTMOD_PORT_ENABLE_MAC_GET(flags))){ 3662 PORTMOD_PORT_ENABLE_PHY_SET(actual_flags); 3663 PORTMOD_PORT_ENABLE_MAC_SET(actual_flags); 3664 } 3665 3666 /* phychain_flag is meant to be used if we want only part of the phychin to be affected*/ 3667 phychain_flag = PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_GET(flags) ? 3668 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY : 3669 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY ; 3670 3671 if (PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) { 3672 3673 _SOC_IF_ERR_EXIT 3674 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access ,(1+MAX_PHYN), &nof_phys)); 3675 3676 _SOC_IF_ERR_EXIT 3677 (portmod_port_phychain_tx_lane_control_get(unit, port, phy_access, nof_phys, phychain_flag, &tx_control)); 3678 _SOC_IF_ERR_EXIT 3679 (portmod_port_phychain_rx_lane_control_get(unit, port, phy_access, nof_phys, phychain_flag, &rx_control)); 3680 3681 phy_enable = 0; 3682 3683 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 3684 phy_enable |= (rx_control == phymodRxSquelchOn) ? 0 : 1; 3685 } 3686 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 3687 phy_enable |= (tx_control == phymodTxSquelchOn) ? 0 : 1; 3688 } 3689 } 3690 3691 if ((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)) { 3692 3693 mac_enable = 0; 3694 3695 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 3696 _SOC_IF_ERR_EXIT(clmac_enable_get(unit, port, CLMAC_ENABLE_SET_FLAGS_RX_EN, &mac_rx_enable)); 3697 mac_enable |= (mac_rx_enable) ? 1 : 0; 3698 } 3699 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 3700 _SOC_IF_ERR_EXIT(clmac_enable_get(unit, port, CLMAC_ENABLE_SET_FLAGS_TX_EN, &mac_tx_enable)); 3701 mac_enable |= (mac_tx_enable) ? 1 : 0; 3702 } 3703 } 3704 3705 *enable = (mac_enable && phy_enable); 3706 3707 exit: 3708 SOC_FUNC_RETURN; 3709 3710 } 3711 3712 int pm4x25_port_interface_check(int unit, int port, pm_info_t pm_info, 3713 const portmod_port_interface_config_t* config, 3714 int is_ext_phy, soc_port_if_t interface, 3715 int* is_valid) 3716 { 3717 int nof_phys = 0; 3718 phymod_phy_access_t phy_access[1+MAX_PHYN]; 3719 SOC_INIT_FUNC_DEFS; 3720 3721 _SOC_IF_ERR_EXIT 3722 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access ,(1+MAX_PHYN), &nof_phys)); 3723 3724 if (is_ext_phy && nof_phys < 2) { 3725 return SOC_E_PARAM; 3726 } 3727 3728 if (is_ext_phy) { 3729 _SOC_IF_ERR_EXIT(_pm4x25_ext_phy_interface_check(unit, port, pm_info, &phy_access[nof_phys-1], 3730 config, interface, is_valid)); 3731 } else { 3732 _SOC_IF_ERR_EXIT(_pm4x25_interface_check(unit, port, config, interface, is_valid)); 3733 } 3734 3735 exit: 3736 SOC_FUNC_RETURN; 3737 } 3738 3739 int pm4x25_port_interface_config_set(int unit, int port, pm_info_t pm_info, 3740 const portmod_port_interface_config_t* config, 3741 int phy_init_flags) 3742 { 3743 uint32 pm_is_bypassed = 0; 3744 phymod_phy_inf_config_t phy_config, cur_phy_config; 3745 phymod_phy_access_t phy_access[1+MAX_PHYN]; 3746 int nof_phys = 0; 3747 int rv = 0, flags = 0; 3748 int port_index=0; 3749 int is_higig = 0; 3750 uint32 bitmap; 3751 uint32 is_interface_restore, interface_modes; 3752 soc_port_if_t interface = SOC_PORT_IF_NULL; 3753 phymod_interface_t phymod_serdes_interface = phymodInterfaceCount; 3754 phymod_interface_t phymod_interface = phymodInterfaceCount; 3755 phymod_tx_t updated_tx_params[PHYMOD_MAX_LANES_PER_CORE]; 3756 int is_legacy_phy_callback = 0, i; 3757 portmod_port_ts_adjust_t ts_adjust; 3758 int pll_divider_req = 0; 3759 int serdes_10g_at_25g_vco = 0; 3760 int serdes_1000x_at_25g_vco = 0; 3761 pm_version_t pm_version; 3762 uint32 port_dynamic_state; 3763 int mac_ts_enable; 3764 SOC_INIT_FUNC_DEFS; 3765 3766 sal_memset(&ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 3767 3768 rv = PM4x25_IS_BYPASSED_GET(unit, pm_info, &pm_is_bypassed); 3769 _SOC_IF_ERR_EXIT(rv); 3770 3771 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 3772 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 3773 _SOC_IF_ERR_EXIT(PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, &port_dynamic_state, port_index)); 3774 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, CLMAC_TS_DISABLEf)) { 3775 _SOC_IF_ERR_EXIT 3776 (pm4x25_port_mac_timestamp_enable_get(unit, port, pm_info, &mac_ts_enable)); 3777 } else { 3778 mac_ts_enable = 1; 3779 } 3780 3781 if (config->flags & PHYMOD_INTF_F_UPDATE_SPEED_LINKUP) { 3782 int serdes_speed = 0, mac_only = 0; 3783 3784 _SOC_IF_ERR_EXIT(portmod_port_speed_get(unit, port, &serdes_speed)); 3785 if (config->speed == serdes_speed) { 3786 mac_only = 1; 3787 } 3788 3789 flags = CLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 3790 _SOC_IF_ERR_EXIT(clmac_speed_set(unit, port, flags, config->speed)); 3791 3792 if (mac_ts_enable) { 3793 /*Set MAC Timestamp Delay*/ 3794 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 3795 _SOC_IF_ERR_EXIT(_pm4x25_port_timestamp_adjust_wb_get(unit, port, pm_info, config->speed, &ts_adjust)); 3796 _SOC_IF_ERR_EXIT(clmac_timestamp_delay_set(unit, port, ts_adjust)); 3797 } 3798 /* PM VERSION and CLMAC BYTE ADJUST aren't valid before TH2 */ 3799 if (!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 3800 _SOC_IF_ERR_EXIT(clmac_timestamp_byte_adjust_set(unit, port, 0, config->speed)); 3801 } 3802 } 3803 if (mac_only) { 3804 /* line side speed and SerDes speed are equal, no need update SerDes configuration */ 3805 SOC_FUNC_RETURN; 3806 } 3807 3808 phy_init_flags = PORTMOD_INIT_F_ALL_PHYS; 3809 } 3810 3811 3812 if(!(PM_4x25_INFO(pm_info)->in_pm12x10)) { 3813 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 3814 &bitmap)); 3815 if ((config->encap_mode == SOC_ENCAP_HIGIG2) || 3816 (config->encap_mode == SOC_ENCAP_HIGIG) || 3817 (PHYMOD_INTF_MODES_HIGIG_GET(config))) { 3818 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 3819 _SOC_IF_ERR_EXIT(rv); 3820 interface_modes |= PHYMOD_INTF_MODES_HIGIG; 3821 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 3822 _SOC_IF_ERR_EXIT(rv); 3823 } else if ((config->encap_mode == SOC_ENCAP_IEEE)) { 3824 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 3825 _SOC_IF_ERR_EXIT(rv); 3826 interface_modes &= ~PHYMOD_INTF_MODES_HIGIG; 3827 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 3828 _SOC_IF_ERR_EXIT(rv); 3829 } 3830 3831 /* Will skip when init, only called when executing command "port xe<n> if=xxxx" */ 3832 if (config->flags & PHYMOD_INTF_F_INTF_PARAM_SET_ONLY) { 3833 /* only flag saved by interface_config->flags */ 3834 interface = config->interface; 3835 3836 /* Update the software state of the interface type. Note that currently 3837 * the legacy ext PHY does not raise the PHYMOD_INTF_F_INTF_PARAM_SET_ONLY 3838 * flag so that the following function call cannot be reached when a legacy 3839 * ext PHY uses the portmod callback function to set the interface type 3840 * of the internal PHY. 3841 */ 3842 rv = PM4x25_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index); 3843 _SOC_IF_ERR_EXIT(rv); 3844 3845 is_interface_restore = 1; 3846 rv = PM4x25_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, port_index); 3847 _SOC_IF_ERR_EXIT(rv); 3848 3849 SOC_FUNC_RETURN; 3850 } 3851 3852 rv = PM4x25_IS_INTERFACE_RESTORE_GET(unit, pm_info, &is_interface_restore, port_index); 3853 _SOC_IF_ERR_EXIT(rv); 3854 _SOC_IF_ERR_EXIT 3855 (portmod_port_chain_phy_access_get(unit, port, pm_info, 3856 phy_access,(1+MAX_PHYN), 3857 &nof_phys)); 3858 /* 3859 * if the interface is already set with PARAM_SET_ONLY 3860 * h/w interface needs to be updated during speed set. 3861 * So load the interface information and clear the flag; 3862 */ 3863 /* After command "port xe<n> if=xxxx; port xe<x> sp=xxx" is issued, the following segment of code will be called 3864 * If ext phy is present, then target interface is retrieved and passed into ext phy interface_set function 3865 * is_legacy_phy_callback is set as 1 when we want ext phy to update interface, which relays on interface_type; 3866 * If ext phy is not present, the target interface is retrieved and passed into internal phy interface_config_set function 3867 * is_legacy_phy_callback is set as 0 when we want internal phy to update interface, which relays on interface_mode 3868 */ 3869 if(is_interface_restore) { 3870 rv = PM4x25_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index); 3871 _SOC_IF_ERR_EXIT(rv); 3872 ((portmod_port_interface_config_t*)config)->interface = interface; 3873 is_interface_restore = 0; 3874 rv = PM4x25_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, port_index); 3875 _SOC_IF_ERR_EXIT(rv); 3876 if ((phy_init_flags == PORTMOD_INIT_F_ALL_PHYS) && (nof_phys > 1)) { 3877 is_legacy_phy_callback = 1; 3878 } else if (nof_phys == 1) { 3879 is_legacy_phy_callback = 0; 3880 } 3881 } else { 3882 /* Speed change only */ 3883 if ((phy_init_flags == PORTMOD_INIT_F_ALL_PHYS) && (nof_phys > 1)) { 3884 is_legacy_phy_callback = 1; 3885 } 3886 /* Internal PHY speed change */ 3887 if (phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) { 3888 is_legacy_phy_callback = 1; 3889 } 3890 } 3891 } 3892 3893 if (!pm_is_bypassed){ 3894 rv = portmod_port_higig2_mode_set(unit, port, PHYMOD_INTF_MODES_HIGIG_GET(config)); 3895 _SOC_IF_ERR_EXIT(rv); 3896 3897 flags = CLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 3898 rv = clmac_speed_set(unit, port, flags, config->speed); 3899 _SOC_IF_ERR_EXIT(rv); 3900 3901 if (mac_ts_enable) { 3902 /*Set MAC Timestamp Delay*/ 3903 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 3904 _SOC_IF_ERR_EXIT(_pm4x25_port_timestamp_adjust_wb_get(unit, port, pm_info, config->speed, &ts_adjust)); 3905 _SOC_IF_ERR_EXIT(clmac_timestamp_delay_set(unit, port, ts_adjust)); 3906 } 3907 if (!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 3908 _SOC_IF_ERR_EXIT(clmac_timestamp_byte_adjust_set(unit, port, 0, config->speed)); 3909 } 3910 } 3911 3912 flags = CLMAC_ENCAP_SET_FLAGS_SOFT_RESET_DIS; 3913 3914 rv = clmac_encap_set(unit, port, 0, PHYMOD_INTF_MODES_HIGIG_GET(config) ? SOC_ENCAP_HIGIG2 : SOC_ENCAP_IEEE); 3915 _SOC_IF_ERR_EXIT(rv); 3916 3917 is_higig = PHYMOD_INTF_MODES_HIGIG_GET(config) ? SOC_ENCAP_HIGIG2 : SOC_ENCAP_IEEE; 3918 rv = clmac_strict_preamble_set(unit, port, (!is_higig && (config->speed >= 10000))); 3919 _SOC_IF_ERR_EXIT(rv); 3920 3921 /* De-Assert SOFT_RESET */ 3922 rv = pm4x25_port_soft_reset(unit, port, pm_info, 0); 3923 _SOC_IF_ERR_EXIT(rv); 3924 } 3925 3926 if(!(PM_4x25_INFO(pm_info)->in_pm12x10)){ 3927 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_config)); 3928 _SOC_IF_ERR_EXIT(_pm4x25_line_side_phymod_interface_get(unit, port, pm_info, phy_init_flags, config, &phymod_interface)); 3929 phy_config.interface_type = phymod_interface; 3930 /* If is_legacy_phy_callback = 0, then interface mode will be set based on inerface type, which is needed for tscf */ 3931 _SOC_IF_ERR_EXIT(_pm4x25_phymod_interface_mode_set(unit, port, pm_info, config, &phy_config, is_legacy_phy_callback)); 3932 3933 /* interface_mode is updated with phy_config->interface_mode */ 3934 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 3935 _SOC_IF_ERR_EXIT(rv); 3936 if (PHYMOD_INTF_MODES_FIBER_GET(&phy_config)) { 3937 interface_modes &= ~(PHYMOD_INTF_MODES_COPPER | PHYMOD_INTF_MODES_BACKPLANE); 3938 interface_modes |= PHYMOD_INTF_MODES_FIBER; 3939 } else if (PHYMOD_INTF_MODES_COPPER_GET(&phy_config)){ 3940 interface_modes &= ~(PHYMOD_INTF_MODES_FIBER | PHYMOD_INTF_MODES_BACKPLANE); 3941 interface_modes |= PHYMOD_INTF_MODES_COPPER; 3942 } else if (PHYMOD_INTF_MODES_BACKPLANE_GET(&phy_config)){ 3943 interface_modes &= ~(PHYMOD_INTF_MODES_COPPER | PHYMOD_INTF_MODES_FIBER); 3944 interface_modes |= PHYMOD_INTF_MODES_BACKPLANE; 3945 } 3946 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 3947 _SOC_IF_ERR_EXIT(rv); 3948 3949 phy_config.data_rate = config->speed; 3950 phy_config.ref_clock = PM_4x25_INFO(pm_info)->ref_clk; 3951 rv = PM4x25_PORT_PLL_DIVIDER_REQ_GET(unit, pm_info, &pll_divider_req, port_index); 3952 _SOC_IF_ERR_EXIT(rv); 3953 rv = PM4x25_PORT_10G_AT_25G_GET(unit, pm_info, &serdes_10g_at_25g_vco, port_index); 3954 _SOC_IF_ERR_EXIT(rv); 3955 rv = PM4x25_PORT_1000X_AT_25G_GET(unit, pm_info, &serdes_1000x_at_25g_vco, port_index); 3956 _SOC_IF_ERR_EXIT(rv); 3957 /*The pll div is set to 165 when 10G working at 25G is supported*/ 3958 if (phy_config.data_rate == 10000) { 3959 if (serdes_10g_at_25g_vco) { 3960 pll_divider_req = 165; 3961 } else { 3962 pll_divider_req = 132; 3963 } 3964 } 3965 if (phy_config.data_rate == 1000) { 3966 if (serdes_1000x_at_25g_vco) { 3967 pll_divider_req = 165; 3968 } else { 3969 pll_divider_req = 132; 3970 } 3971 } 3972 phy_config.pll_divider_req = pll_divider_req; 3973 3974 if (config->serdes_interface != SOC_PORT_IF_NULL) { 3975 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, 3976 config->speed, 3977 config->serdes_interface, 3978 &phymod_serdes_interface)); 3979 } 3980 3981 /* internal phy preemphasis and current */ 3982 if (!(config->flags & (PHYMOD_INTF_F_SET_SPD_TRIGGER | PHYMOD_INTF_F_UPDATE_SPEED_LINKUP))) { 3983 3984 /* if the tx params are updated from non default value read the non dflt value from the HW and update it */ 3985 rv = PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, 3986 &port_dynamic_state, port_index); 3987 _SOC_IF_ERR_EXIT(rv); 3988 3989 if (!PORTMOD_PORT_IS_DEFAULT_TX_PARAMS_UPDATED(port_dynamic_state)) { 3990 _SOC_IF_ERR_EXIT 3991 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 3992 0, PM_4x25_INFO(pm_info)->ref_clk, 3993 &cur_phy_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 3994 if ((phy_config.data_rate != cur_phy_config.data_rate) || 3995 (phy_config.interface_modes != cur_phy_config.interface_modes)) { 3996 for(i=0; i<PHYMOD_MAX_LANES_PER_CORE; i++){ 3997 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access[0], phymodMediaTypeChipToChip, 3998 &(updated_tx_params[i]))); 3999 } 4000 _SOC_IF_ERR_EXIT(portmod_port_phychain_tx_set(unit, phy_access, 1, updated_tx_params)); 4001 } 4002 } 4003 } 4004 4005 _SOC_IF_ERR_EXIT 4006 (portmod_port_phychain_interface_config_set(unit, port, phy_access, nof_phys, 4007 config->flags, 4008 &phy_config, 4009 phymod_serdes_interface, 4010 PM_4x25_INFO(pm_info)->ref_clk, 4011 phy_init_flags)); 4012 4013 /* The interface type software state needs to be stored even if the config flags 4014 * does not include PHYMOD_INTF_F_INTF_PARAM_SET_ONLY. For example, when changing 4015 * the encap, portctrl tries to config the PHY interface type and speed in one 4016 * shot without setting the PHYMOD_INTF_F_INTF_PARAM_SET_ONLY flag. However, 4017 * when the current function is called by the legacy ext PHY through the portmod 4018 * callback function, the interface type software state should not be modified 4019 * since PM4x10_INTERFACE_TYPE_GET() should return the outmost PHY interface type. 4020 */ 4021 if (!(nof_phys > 1 && phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)) { 4022 _SOC_IF_ERR_EXIT 4023 (portmod_intf_from_phymod_intf(unit, phy_config.interface_type, &interface)); 4024 _SOC_IF_ERR_EXIT 4025 (PM4x25_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 4026 _SOC_IF_ERR_EXIT 4027 (PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 4028 } 4029 } 4030 4031 exit: 4032 SOC_FUNC_RETURN; 4033 } 4034 4035 int pm4x25_port_interface_config_get(int unit, int port, pm_info_t pm_info, portmod_port_interface_config_t* config, int phy_init_flags) 4036 { 4037 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4038 soc_port_if_t interface; 4039 phymod_phy_inf_config_t phy_config; 4040 int flags = 0, nof_phys = 0, rv, port_index, max_speed; 4041 uint32_t bitmap; 4042 phymod_interface_t prev_phymod_if; 4043 SOC_INIT_FUNC_DEFS; 4044 4045 if(PM_4x25_INFO(pm_info)->in_pm12x10){ 4046 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("can't get interface config for PM4X25 within PM12X10"))); 4047 } 4048 4049 if (_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)) 4050 return (SOC_E_PARAM); 4051 4052 rv = PM4x25_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index); 4053 _SOC_IF_ERR_EXIT(rv); 4054 rv = PM4x25_OUTMOST_PHY_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index); 4055 _SOC_IF_ERR_EXIT(rv); 4056 4057 _SOC_IF_ERR_EXIT 4058 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4059 phy_access ,(1+MAX_PHYN), 4060 &nof_phys)); 4061 4062 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_config)); 4063 4064 phy_config.data_rate = max_speed; 4065 4066 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, max_speed, interface, &prev_phymod_if)); 4067 4068 _SOC_IF_ERR_EXIT 4069 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 4070 0, PM_4x25_INFO(pm_info)->ref_clk, 4071 &phy_config, phy_init_flags)); 4072 4073 /* It is possible that the underlying phymod interface get API does not 4074 * distinguish among certain interface types. For example, CR4 and KR4 4075 * are treated the same from TSCF's perspective. In these cases portmod 4076 * has to rely on the software state to retrieve the most-recently used 4077 * interface type written into phymod. 4078 */ 4079 if (phy_config.interface_type != prev_phymod_if && 4080 prev_phymod_if != phymodInterfaceCount && 4081 phy_init_flags != PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) { 4082 phy_config.interface_type = prev_phymod_if; 4083 } 4084 4085 config->speed = phy_config.data_rate; 4086 config->interface_modes = phy_config.interface_modes; 4087 config->flags = 0; 4088 4089 rv = portmod_intf_from_phymod_intf(unit, phy_config.interface_type, &(config->interface)); 4090 _SOC_IF_ERR_EXIT(rv); 4091 4092 rv = clmac_encap_get (unit, port, &flags, &config->encap_mode); 4093 _SOC_IF_ERR_EXIT(rv); 4094 4095 /* coverity[Out-of-bounds access:FALSE] */ 4096 SHR_BITCOUNT_RANGE(&bitmap, config->port_num_lanes, 0, PM4X25_LANES_PER_CORE); 4097 rv = PM4x25_MAX_SPEED_GET(unit, pm_info, &config->max_speed, port_index); 4098 _SOC_IF_ERR_EXIT(rv); 4099 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &config->interface_modes, port_index); 4100 _SOC_IF_ERR_EXIT(rv); 4101 4102 4103 exit: 4104 SOC_FUNC_RETURN; 4105 } 4106 4107 int pm4x25_port_default_interface_get(int unit, int port, pm_info_t pm_info, 4108 const portmod_port_interface_config_t* config, 4109 soc_port_if_t* interface) 4110 { 4111 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4112 int nof_phys = 0; 4113 int is_legacy_phy; 4114 int xphy_id; 4115 portmod_port_interface_config_t interface_config; 4116 SOC_INIT_FUNC_DEFS; 4117 4118 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 4119 phy_access ,(1+MAX_PHYN), 4120 &nof_phys)); 4121 4122 if (nof_phys==1) { 4123 _SOC_IF_ERR_EXIT 4124 (_pm4x25_default_interface_get(unit, port, config, interface)); 4125 } else { 4126 xphy_id = phy_access[nof_phys-1].access.addr; 4127 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 4128 4129 if (!is_legacy_phy) { 4130 _SOC_IF_ERR_EXIT 4131 (portmod_port_phymod_xphy_default_interface_get(unit, &(phy_access[nof_phys-1]), 4132 config, interface)); 4133 } else { 4134 interface_config = *config; 4135 _SOC_IF_ERR_EXIT 4136 (portmod_common_default_interface_get(&interface_config)); 4137 *interface = interface_config.interface; 4138 } 4139 } 4140 4141 exit: 4142 SOC_FUNC_RETURN; 4143 } 4144 4145 int pm4x25_port_cl72_set(int unit, int port, pm_info_t pm_info, uint32 enable) 4146 { 4147 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4148 int nof_phys = 0; 4149 4150 SOC_INIT_FUNC_DEFS; 4151 4152 _SOC_IF_ERR_EXIT 4153 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4154 phy_access ,(1+MAX_PHYN), 4155 &nof_phys)); 4156 4157 if (!SAL_BOOT_SIMULATION) { 4158 _SOC_IF_ERR_EXIT 4159 (portmod_port_phychain_cl72_set(unit, port, phy_access, nof_phys, enable)); 4160 } 4161 4162 exit: 4163 SOC_FUNC_RETURN; 4164 } 4165 4166 int pm4x25_port_cl72_get(int unit, int port, pm_info_t pm_info, uint32* enable) 4167 { 4168 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4169 int nof_phys = 0; 4170 4171 SOC_INIT_FUNC_DEFS; 4172 4173 _SOC_IF_ERR_EXIT 4174 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4175 phy_access ,(1+MAX_PHYN), 4176 &nof_phys)); 4177 4178 if (!SAL_BOOT_SIMULATION) { 4179 _SOC_IF_ERR_EXIT 4180 (portmod_port_phychain_cl72_get(unit, phy_access, nof_phys, enable)); 4181 } 4182 4183 exit: 4184 SOC_FUNC_RETURN; 4185 } 4186 4187 int pm4x25_port_cl72_status_get(int unit, int port, pm_info_t pm_info, phymod_cl72_status_t* status) 4188 { 4189 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4190 int nof_phys = 0; 4191 4192 SOC_INIT_FUNC_DEFS; 4193 4194 _SOC_IF_ERR_EXIT 4195 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4196 phy_access ,(1+MAX_PHYN), 4197 &nof_phys)); 4198 4199 if (!SAL_BOOT_SIMULATION) { 4200 _SOC_IF_ERR_EXIT 4201 (portmod_port_phychain_cl72_status_get(unit, phy_access, nof_phys, status)); 4202 } 4203 4204 exit: 4205 SOC_FUNC_RETURN; 4206 } 4207 4208 4209 int pm4x25_port_loopback_get(int unit, int port, pm_info_t pm_info, 4210 portmod_loopback_mode_t loopback_type, int* enable) 4211 { 4212 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4213 int nof_phys; 4214 uint32_t tmp_enable=0; 4215 phymod_loopback_mode_t phymod_lb_type; 4216 int rv = PHYMOD_E_NONE; 4217 int port_index; 4218 uint32 bitmap; 4219 4220 SOC_INIT_FUNC_DEFS; 4221 4222 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 4223 &bitmap)); 4224 4225 switch(loopback_type){ 4226 case portmodLoopbackMacOuter: 4227 _SOC_IF_ERR_EXIT(clmac_loopback_get(unit, port, loopback_type, enable)); 4228 break; 4229 4230 case portmodLoopbackPhyGloopPMD: 4231 case portmodLoopbackPhyRloopPMD: /*slide*/ 4232 case portmodLoopbackPhyGloopPCS: /*slide*/ 4233 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 4234 (*enable) = 0; /* No phy --> no phy loopback*/ 4235 } else { 4236 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, 4237 loopback_type, &phymod_lb_type)); 4238 _SOC_IF_ERR_EXIT 4239 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4240 phy_access ,(1+MAX_PHYN), 4241 &nof_phys)); 4242 4243 rv = portmod_port_phychain_loopback_get(unit, port, phy_access, 4244 nof_phys, 4245 phymod_lb_type, 4246 &tmp_enable); 4247 if (rv == PHYMOD_E_UNAVAIL) { 4248 rv = PHYMOD_E_NONE; 4249 tmp_enable = 0; 4250 } 4251 4252 _SOC_IF_ERR_EXIT(rv); 4253 *enable = tmp_enable; 4254 4255 } 4256 break; 4257 default: 4258 (*enable) = 0; /* not supported --> no loopback */ 4259 break; 4260 } 4261 4262 exit: 4263 SOC_FUNC_RETURN; 4264 } 4265 4266 int pm4x25_port_loopback_set(int unit, int port, pm_info_t pm_info, portmod_loopback_mode_t loopback_type, int enable) 4267 { 4268 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4269 int nof_phys; 4270 int is_clmac_in_soft_reset; 4271 phymod_loopback_mode_t phymod_lb_type; 4272 int port_index; 4273 uint32 bitmap; 4274 portmod_dispatch_type_t pm_type = portmodDispatchTypeCount; 4275 4276 SOC_INIT_FUNC_DEFS; 4277 4278 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 4279 &bitmap)); 4280 4281 /* loopback type validation*/ 4282 switch(loopback_type){ 4283 case portmodLoopbackMacOuter: 4284 4285 /*Get SOFT_RESET status*/ 4286 _SOC_IF_ERR_EXIT(clmac_soft_reset_get(unit, port, &is_clmac_in_soft_reset)); 4287 4288 _SOC_IF_ERR_EXIT(portmod_port_pm_type_get(unit, port, &port, &pm_type)); 4289 4290 /* According to MAC designer - Do MAC SOFT RESET before loopback change */ 4291 if (!is_clmac_in_soft_reset){ 4292 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 4293 /* Since SOFT_RESET sends credits which might cause FIFO overflow, we need to do a procedural pm4x25_port_soft_reset 4294 * (with in_out = 1 to put CLMAC in-to SOFT_RESET) */ 4295 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 1)); 4296 } else { 4297 #ifdef PORTMOD_PM12X10_SUPPORT 4298 if (enable && (pm_type == portmodDispatchTypePm12x10)) { 4299 /* 4300 * CLMAC loopback enable 4301 * CLMAC_CTRL.SOFT_RESET=1 4302 * CLMAC_CTRL.SOFT_RESET=0 4303 * CLMAC_CTRL.LOCAL_LPBK=0 4304 * CLMAC_CTRL.LOCAL_LPBK=1 4305 */ 4306 _SOC_IF_ERR_EXIT(clmac_soft_reset_set(unit, port, 1)); 4307 _SOC_IF_ERR_EXIT(clmac_soft_reset_set(unit, port, 0)); 4308 _SOC_IF_ERR_EXIT(clmac_loopback_set(unit, port, loopback_type, 0)); 4309 } 4310 #endif 4311 } 4312 } 4313 /*Open / close loopback*/ 4314 _SOC_IF_ERR_EXIT(clmac_loopback_set(unit, port, loopback_type, enable)); 4315 4316 4317 if (!is_clmac_in_soft_reset){ 4318 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 4319 /* Get SOFT_RESET out-of-reset, using procedural pm4x25_port_soft_reset with in_out = 0 to get CLMAC out-of SOFT_RESET */ 4320 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 0)); 4321 } else { 4322 #ifdef PORTMOD_PM12X10_SUPPORT 4323 if ((!enable) && (pm_type == portmodDispatchTypePm12x10)) { 4324 /* 4325 * CLMAC loopback disable 4326 * CLMAC_CTRL.LOCAL_LPBK=0 4327 * CLMAC_CTRL.SOFT_RESET=1 4328 * CLMAC_CTRL.SOFT_RESET=0 4329 */ 4330 _SOC_IF_ERR_EXIT(clmac_soft_reset_set(unit, port, 1)); 4331 _SOC_IF_ERR_EXIT(clmac_soft_reset_set(unit, port, 0)); 4332 } 4333 #endif 4334 } 4335 } 4336 break; 4337 4338 case portmodLoopbackPhyRloopPCS: 4339 case portmodLoopbackPhyRloopPMD: /*slide*/ 4340 case portmodLoopbackPhyGloopPMD: 4341 case portmodLoopbackPhyGloopPCS: /*slide*/ 4342 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] != 0) { 4343 if (enable) { 4344 _SOC_IF_ERR_EXIT(clmac_loopback_set(unit, port, portmodLoopbackMacOuter, 0)); 4345 } 4346 4347 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, 4348 loopback_type, &phymod_lb_type)); 4349 4350 _SOC_IF_ERR_EXIT 4351 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4352 phy_access ,(1+MAX_PHYN), 4353 &nof_phys)); 4354 4355 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_set(unit, port, phy_access, 4356 nof_phys, 4357 phymod_lb_type, 4358 enable)); 4359 } 4360 break; 4361 default: 4362 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, ( 4363 _SOC_MSG("unsupported loopback type %d"), loopback_type)); 4364 break; 4365 } 4366 if (enable) 4367 _SOC_IF_ERR_EXIT(PM_DRIVER(pm_info)->f_portmod_port_lag_failover_status_toggle(unit, port, pm_info)); 4368 4369 exit: 4370 SOC_FUNC_RETURN; 4371 } 4372 4373 int pm4x25_port_rx_mac_enable_set(int unit, int port, pm_info_t pm_info, int enable) 4374 { 4375 SOC_INIT_FUNC_DEFS; 4376 4377 _SOC_IF_ERR_EXIT(clmac_rx_enable_set(unit, port, enable)); 4378 exit: 4379 SOC_FUNC_RETURN; 4380 } 4381 4382 int pm4x25_port_rx_mac_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 4383 { 4384 SOC_INIT_FUNC_DEFS; 4385 4386 _SOC_IF_ERR_EXIT(clmac_rx_enable_get(unit, port, enable)); 4387 exit: 4388 SOC_FUNC_RETURN; 4389 } 4390 4391 int pm4x25_port_tx_mac_enable_set(int unit, int port, pm_info_t pm_info, int enable) 4392 { 4393 SOC_INIT_FUNC_DEFS; 4394 4395 _SOC_IF_ERR_EXIT(clmac_tx_enable_set(unit, port, enable)); 4396 4397 exit: 4398 SOC_FUNC_RETURN; 4399 } 4400 4401 int pm4x25_port_tx_mac_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 4402 { 4403 SOC_INIT_FUNC_DEFS; 4404 4405 _SOC_IF_ERR_EXIT(clmac_tx_enable_get(unit, port, enable)); 4406 4407 exit: 4408 SOC_FUNC_RETURN; 4409 } 4410 4411 int pm4x25_port_ability_local_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, portmod_port_ability_t* ability) 4412 { 4413 int rv; 4414 portmod_port_ability_t legacy_phy_ability; 4415 int port_index; 4416 int max_speed = 100000; 4417 int num_of_lanes = 0; 4418 int loopback = SOC_PA_LB_PHY | SOC_PA_LB_MAC; 4419 uint32 bitmap, tmpbit, interface_modes; 4420 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4421 int nof_phys, xphy_id, is_legacy_phy; 4422 4423 SOC_INIT_FUNC_DEFS; 4424 SOC_NULL_CHECK(pm_info); 4425 4426 sal_memset(ability, 0, sizeof(portmod_port_ability_t)); 4427 sal_memset(&legacy_phy_ability, 0, sizeof(portmod_port_ability_t)); 4428 4429 _SOC_IF_ERR_EXIT 4430 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 4431 (1+MAX_PHYN), &nof_phys)); 4432 4433 _SOC_IF_ERR_EXIT 4434 (_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 4435 4436 rv = PM4x25_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index); 4437 _SOC_IF_ERR_EXIT(rv); 4438 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 4439 _SOC_IF_ERR_EXIT(rv); 4440 4441 tmpbit = bitmap; 4442 while(tmpbit) { 4443 num_of_lanes += ((tmpbit&1)?1:0) ; 4444 tmpbit >>= 1 ; 4445 } 4446 4447 4448 if (SAL_BOOT_SIMULATION) { 4449 loopback = SOC_PA_LB_MAC; 4450 } 4451 ability->loopback = loopback; 4452 ability->medium = SOC_PA_MEDIUM_FIBER | SOC_PA_MEDIUM_COPPER | SOC_PA_MEDIUM_BACKPLANE; 4453 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4454 ability->fec = SOC_PA_FEC_NONE | SOC_PA_FEC_CL74 | SOC_PA_FEC_CL91; 4455 ability->flags = SOC_PA_AUTONEG; 4456 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 4457 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | SOC_PA_ENCAP_HIGIG2; 4458 ability->channel = SOC_PA_CHANNEL_LONG | SOC_PA_CHANNEL_SHORT; 4459 4460 if (num_of_lanes == 1) { 4461 if (interface_modes & PHYMOD_INTF_MODES_HIGIG) { 4462 switch(max_speed) { 4463 case 10000: max_speed = 11000 ; break ; 4464 case 20000: max_speed = 21000 ; break ; 4465 case 25000: max_speed = 27000 ; break ; 4466 default: break ; 4467 } 4468 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4469 _SOC_IF_ERR_EXIT(rv); 4470 } else { 4471 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4472 switch(max_speed) { 4473 case 11000: max_speed = 10000 ; break ; 4474 case 21000: max_speed = 20000 ; break ; 4475 case 27000: max_speed = 25000 ; break ; 4476 default: break ; 4477 } 4478 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4479 _SOC_IF_ERR_EXIT(rv); 4480 } 4481 switch(max_speed) { /* must include all the supported speedss */ 4482 case 27000: 4483 case 26500: 4484 ability->speed_full_duplex |= SOC_PA_SPEED_27GB; 4485 case 25000: 4486 ability->speed_full_duplex |= SOC_PA_SPEED_25GB; 4487 case 21000: 4488 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 4489 case 20000: 4490 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 4491 case 11000: 4492 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 4493 case 10000: 4494 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 4495 case 5000: 4496 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 4497 case 2500: 4498 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 4499 default: 4500 break; 4501 } 4502 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4503 ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII; 4504 if (max_speed >= 10000) { 4505 ability->interface |= SOC_PA_INTF_XGMII; 4506 } 4507 ability->loopback = loopback; 4508 ability->flags = SOC_PA_AUTONEG; 4509 } else if (num_of_lanes == 2) { 4510 if (interface_modes & PHYMOD_INTF_MODES_HIGIG) { 4511 switch(max_speed) { 4512 case 20000: max_speed = 21000 ; break ; 4513 case 40000: max_speed = 42000 ; break ; 4514 case 50000: max_speed = 53000 ; break ; 4515 default: break ; 4516 } 4517 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4518 _SOC_IF_ERR_EXIT(rv); 4519 } else { 4520 switch(max_speed) { 4521 case 21000: max_speed = 20000 ; break ; 4522 case 42000: max_speed = 40000 ; break ; 4523 case 53000: max_speed = 50000 ; break ; 4524 default: break ; 4525 } 4526 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4527 _SOC_IF_ERR_EXIT(rv); 4528 } 4529 switch(max_speed) { /* must include all the supported speedss */ 4530 case 53000: 4531 ability->speed_full_duplex |= SOC_PA_SPEED_53GB; 4532 case 50000: 4533 ability->speed_full_duplex |= SOC_PA_SPEED_50GB; 4534 case 42000: 4535 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 4536 case 40000: 4537 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 4538 case 21000: 4539 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 4540 case 20000: 4541 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 4542 default: 4543 break; 4544 } 4545 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4546 ability->interface = SOC_PA_INTF_XGMII; 4547 ability->loopback = loopback; 4548 ability->flags = 0; 4549 } else { 4550 if (interface_modes & PHYMOD_INTF_MODES_HIGIG) { 4551 switch(max_speed) { 4552 case 40000: max_speed = 42000 ; break ; 4553 case 50000: max_speed = 53000 ; break ; 4554 case 100000: max_speed = 106000 ; break ; 4555 case 120000: max_speed = 127000 ; break ; 4556 default: break ; 4557 } 4558 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4559 _SOC_IF_ERR_EXIT(rv); 4560 } else { 4561 switch(max_speed) { 4562 case 42000: max_speed = 40000 ; break ; 4563 case 53000: max_speed = 50000 ; break ; 4564 case 106000: max_speed = 100000 ; break ; 4565 case 127000: max_speed = 120000 ; break ; 4566 default: break ; 4567 } 4568 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 4569 _SOC_IF_ERR_EXIT(rv); 4570 } 4571 switch(max_speed) { 4572 case 127000: 4573 ability->speed_full_duplex |= SOC_PA_SPEED_127GB; 4574 case 120000: 4575 ability->speed_full_duplex |= SOC_PA_SPEED_120GB; 4576 case 106000: 4577 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 4578 case 100000: 4579 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 4580 case 53000: 4581 ability->speed_full_duplex |= SOC_PA_SPEED_53GB; 4582 case 50000: 4583 ability->speed_full_duplex |= SOC_PA_SPEED_50GB; 4584 case 42000: 4585 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 4586 case 40000: 4587 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 4588 default: 4589 break; 4590 } 4591 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4592 ability->interface = SOC_PA_INTF_XGMII; 4593 ability->loopback = loopback; 4594 ability->flags = SOC_PA_AUTONEG; 4595 } 4596 4597 /* If legacy external phy presents, retrieve the local ability from the 4598 * external phy as it has more variants and the ability might vary for each. 4599 * However, if this function is called by the legacy ext PHY driver through 4600 * the PORTMOD callback function portmod_ext_to_int_cmd_get(), the returned 4601 * data should be of the internal SERDES. portmod_ext_to_int_cmd_get() uses 4602 * PORTMOD_USER_ACC_CMD_FOR_PHY_SET() to hint its callees that the target 4603 * of data retrieving is the internal SERDES. 4604 */ 4605 if (nof_phys > 1 && !(phy_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)) { 4606 /* check if the legacy phy present */ 4607 xphy_id = phy_access[nof_phys-1].access.addr; 4608 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 4609 if(is_legacy_phy) { 4610 /* call portmod phy chain function to retrieve the ability */ 4611 _SOC_IF_ERR_EXIT 4612 (portmod_port_phychain_local_ability_get(unit, port, phy_access, 4613 nof_phys, &legacy_phy_ability)); 4614 /* PHY driver returns all the speeds supported by PHY 4615 * Advertise only the speeds supported by both PortMacro and the PHY 4616 */ 4617 legacy_phy_ability.speed_full_duplex &= ability->speed_full_duplex; 4618 /* PHY driver may not return all supported encap modes 4619 * Advertise encap modes supported by both PortMacro and the PHY 4620 */ 4621 legacy_phy_ability.encap |= ability->encap; 4622 *ability = legacy_phy_ability; 4623 } else { 4624 /* We might need to consider calling portmod phy chain for 4625 * non legacy phys as well*/ 4626 } 4627 } 4628 4629 LOG_INFO(BSL_LS_SOC_PHY, 4630 (BSL_META_U(unit, 4631 "phy_tscf_ability_local_get:unit=%d p=%d sp=%08x\n"), 4632 unit, port, ability->speed_full_duplex)); 4633 4634 exit: 4635 SOC_FUNC_RETURN; 4636 } 4637 4638 static int _pm4x25_nof_lanes_get(int unit, int port, pm_info_t pm_info) 4639 { 4640 int port_index, rv; 4641 uint32_t bitmap, bcnt = 0; 4642 4643 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, 4644 &bitmap); 4645 if (rv) return (0); /* bit count is zero will flag error */ 4646 4647 while (bitmap) { 4648 if (bitmap & 0x1) bcnt++; 4649 bitmap >>= 1; 4650 } 4651 return (bcnt); 4652 } 4653 4654 int pm4x25_port_autoneg_set(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 4655 const phymod_autoneg_control_t* an) 4656 { 4657 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4658 int nof_phys, rv; 4659 int port_index, fs_cl72; 4660 uint32_t bitmap, an_done, port_dynamic_state; 4661 phymod_autoneg_control_t *pAn = (phymod_autoneg_control_t*)an; 4662 4663 SOC_INIT_FUNC_DEFS; 4664 4665 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 4666 &bitmap)); 4667 4668 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 4669 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("AN isn't supported"))); 4670 } else { 4671 if (pAn->num_lane_adv == 0) { 4672 pAn->num_lane_adv = _pm4x25_nof_lanes_get(unit, port, pm_info); 4673 } 4674 4675 if (pAn->an_mode == phymod_AN_MODE_NONE) { 4676 rv = PM4x25_AN_MODE_GET(unit, pm_info, &pAn->an_mode, port_index); 4677 _SOC_IF_ERR_EXIT(rv); 4678 } 4679 4680 if (pAn->an_mode == phymod_AN_MODE_NONE) { 4681 pAn->an_mode = phymod_AN_MODE_SGMII; 4682 } 4683 4684 rv = PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, 4685 &port_dynamic_state, port_index); 4686 _SOC_IF_ERR_EXIT(rv); 4687 4688 if (PORTMOD_PORT_IS_AUTONEG_MODE_UPDATED(port_dynamic_state)) { 4689 rv = PM4x25_AN_MODE_GET(unit, pm_info, &pAn->an_mode, port_index); 4690 _SOC_IF_ERR_EXIT(rv); 4691 4692 PORTMOD_PORT_AUTONEG_MODE_UPDATED_CLR(port_dynamic_state); 4693 rv = PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, 4694 port_dynamic_state, port_index); 4695 _SOC_IF_ERR_EXIT(rv); 4696 } 4697 4698 /* next chenck if cl72 force bit is set, if set, don't allow AN to */ 4699 /* change cl72 config */ 4700 rv = PM4x25_FS_CL72_GET(unit, pm_info, &fs_cl72, port_index); 4701 _SOC_IF_ERR_EXIT(rv); 4702 if (fs_cl72) { 4703 PHYMOD_AN_F_ALLOW_CL72_CONFIG_CHANGE_CLR(pAn); 4704 } else { 4705 PHYMOD_AN_F_ALLOW_CL72_CONFIG_CHANGE_SET(pAn); 4706 } 4707 4708 _SOC_IF_ERR_EXIT 4709 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4710 phy_access ,(1+MAX_PHYN), 4711 &nof_phys)); 4712 4713 /* In case of warm boot, get autoneg informaton from hardware */ 4714 if(SOC_WARM_BOOT(unit)) { 4715 if (pAn->an_mode >= phymod_AN_MODE_Count) { 4716 _SOC_IF_ERR_EXIT 4717 (portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, phy_flags, pAn, &an_done)); 4718 } 4719 } 4720 4721 rv = portmod_port_phychain_autoneg_set(unit, port, phy_access, nof_phys, phy_flags, an); 4722 /* Because the returned value PHYMOD_E_UNAVAIL is -12 from tscf phymod driver */ 4723 if (rv == PHYMOD_E_UNAVAIL) { 4724 rv = SOC_E_UNAVAIL; 4725 } 4726 _SOC_IF_ERR_EXIT(rv); 4727 } 4728 4729 exit: 4730 SOC_FUNC_RETURN; 4731 } 4732 4733 int pm4x25_port_autoneg_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, phymod_autoneg_control_t* an) 4734 { 4735 int rv, port_index, nof_phys; 4736 uint32_t bitmap, an_done; 4737 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4738 4739 SOC_INIT_FUNC_DEFS; 4740 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 4741 &bitmap)); 4742 4743 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 4744 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("AN isn't supported"))); 4745 } else { 4746 4747 if (an->num_lane_adv == 0) { 4748 an->num_lane_adv = _pm4x25_nof_lanes_get(unit, port, pm_info); 4749 } 4750 rv = PM4x25_AN_MODE_GET(unit, pm_info, &an->an_mode, port_index); 4751 _SOC_IF_ERR_EXIT(rv); 4752 if (an->an_mode == phymod_AN_MODE_NONE) { 4753 an->an_mode = phymod_AN_MODE_SGMII; 4754 } 4755 4756 _SOC_IF_ERR_EXIT 4757 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4758 phy_access ,(1+MAX_PHYN), 4759 &nof_phys)); 4760 _SOC_IF_ERR_EXIT 4761 (portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, phy_flags, an, &an_done)); 4762 } 4763 4764 exit: 4765 SOC_FUNC_RETURN; 4766 } 4767 4768 int pm4x25_port_autoneg_status_get (int unit, int port, pm_info_t pm_info, 4769 phymod_autoneg_status_t* an_status) 4770 { 4771 int port_index; 4772 uint32 bitmap; 4773 portmod_port_interface_config_t port_intf_config; 4774 phymod_interface_t phy_intf; 4775 4776 SOC_INIT_FUNC_DEFS; 4777 4778 _SOC_IF_ERR_EXIT 4779 (_pm4x25_port_index_get(unit, port, pm_info, &port_index, &bitmap)); 4780 4781 4782 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 4783 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("Invalid number of Phys"))); 4784 } 4785 4786 _SOC_IF_ERR_EXIT 4787 (portmod_phy_port_autoneg_status_get (unit, port, pm_info, an_status)); 4788 4789 _SOC_IF_ERR_EXIT 4790 (pm4x25_port_interface_config_get(unit, port, pm_info, &port_intf_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 4791 4792 _SOC_IF_ERR_EXIT 4793 (portmod_intf_to_phymod_intf(unit, port_intf_config.speed, port_intf_config.interface, &phy_intf)); 4794 4795 if (an_status->enabled && an_status->locked) { 4796 an_status->data_rate = port_intf_config.speed; 4797 an_status->interface = phy_intf; 4798 } else { 4799 /* upper layer should not rely on the 4800 * data rate and interface if the AN is not locked 4801 */ 4802 an_status->data_rate = 0; 4803 an_status->interface = SOC_PORT_IF_NULL; 4804 } 4805 exit: 4806 SOC_FUNC_RETURN; 4807 } 4808 4809 int pm4x25_port_link_get(int unit, int port, pm_info_t pm_info, int flags, int* link) 4810 { 4811 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4812 int nof_phys; 4813 uint32_t cl91_enable = 0, cl108_enable = 0, an_done = 0; 4814 uint32 bitmap; 4815 int port_index=0; 4816 uint32 interface_modes; 4817 phymod_autoneg_control_t an; 4818 portmod_link_recovery_t link_recovery; 4819 int rv_cl91 = 0, rv_cl108 = 0; 4820 uint32_t prbs_enable = 0; 4821 4822 SOC_INIT_FUNC_DEFS; 4823 4824 _SOC_IF_ERR_EXIT 4825 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4826 phy_access ,(1+MAX_PHYN), 4827 &nof_phys)); 4828 4829 _SOC_IF_ERR_EXIT 4830 (portmod_port_phychain_link_status_get(unit, port, phy_access, nof_phys, flags, (uint32_t*) link)); 4831 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 4832 _SOC_IF_ERR_EXIT(PM4x25_PORT_LINK_RECOVERY_GET(unit, pm_info, &link_recovery, port_index)); 4833 4834 if ((nof_phys == 1) && (link_recovery.enabled)) { 4835 /* link recovery for internal serdes only for optical application MLD based */ 4836 uint32_t signal_detect; 4837 4838 /* first get the medium type from internal serdes */ 4839 _SOC_IF_ERR_EXIT(PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index)); 4840 4841 if ((interface_modes & (PHYMOD_INTF_MODES_FIBER | PHYMOD_INTF_MODES_BACKPLANE))) { 4842 /* Get CL91 */ 4843 PHYMOD_FEC_CL91_SET(cl91_enable); 4844 rv_cl91 = phymod_phy_fec_enable_get(&phy_access[0], &cl91_enable); 4845 /* Get CL108 */ 4846 PHYMOD_FEC_CL108_SET(cl108_enable); 4847 rv_cl108 = phymod_phy_fec_enable_get(&phy_access[0], &cl108_enable); 4848 if (((rv_cl91 == PHYMOD_E_NONE) && cl91_enable) || ((rv_cl108 == PHYMOD_E_NONE) && cl108_enable)) { 4849 /* Get AN */ 4850 _SOC_IF_ERR_EXIT 4851 (phymod_phy_autoneg_get(&phy_access[0], &an, &an_done)); 4852 /* Pcs link is impacted once prbs test is enabled. 4853 * The WAR could be triggered to do link recovery to reset PMA/PMD. 4854 * The prbs test may fail in this condition. Make sure this WAR won't be triggered when prbs is enabled. 4855 */ 4856 _SOC_IF_ERR_EXIT 4857 (phymod_phy_prbs_enable_get(&phy_access[0], 0, &prbs_enable)); 4858 if ((!an.enable) && (!prbs_enable)) { 4859 switch (link_recovery.state) { 4860 4861 case PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK: 4862 /* link is good */ 4863 if (*link) { 4864 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD; 4865 } else { 4866 /* no link yet, keep wait for link */ 4867 link_recovery.tick_cnt += 1; 4868 if ((link_recovery.tick_cnt) > PORTMOD_LINK_RECOVERY_LINK_WAIT_CNT_LIMIT) { 4869 /* no link after all the try, reset the rx patha again */ 4870 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_RESET_RX; 4871 } 4872 } 4873 break; 4874 case PORTMOD_LINK_RECOVERY_STATE_RESET_RX: 4875 link_recovery.tick_cnt = 0; 4876 /*first check link status */ 4877 if (*link) { 4878 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD; 4879 } else { 4880 /* first reset the rx path */ 4881 signal_detect = 0; 4882 4883 /* check if there is signal detect */ 4884 _SOC_IF_ERR_EXIT(phymod_phy_rx_signal_detect_get(&phy_access[0], &signal_detect)); 4885 4886 /* only toggle rx reset path only if there is signal on the line */ 4887 if (signal_detect) { 4888 /* first put the rx into reset */ 4889 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxDisable)); 4890 4891 /* add some delay */ 4892 sal_usleep(5000); 4893 4894 /* toggle CDR lock */ 4895 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxSquelchOn)); 4896 /* add some delay */ 4897 sal_usleep(5000); 4898 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxSquelchOff)); 4899 4900 sal_usleep(10000); 4901 /* release the rx reset */ 4902 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxReset)); 4903 4904 sal_usleep(10000); 4905 } 4906 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK; 4907 } 4908 break; 4909 4910 case PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD: 4911 /* no link, need to reset the rx path */ 4912 if (*link == 0) { 4913 link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_RESET_RX; 4914 } 4915 break; 4916 } 4917 _SOC_IF_ERR_EXIT(PM4x25_PORT_LINK_RECOVERY_SET(unit, pm_info, link_recovery, port_index)); 4918 } 4919 } 4920 } 4921 }/* end of link recovery */ 4922 4923 4924 exit: 4925 SOC_FUNC_RETURN; 4926 } 4927 4928 int pm4x25_port_link_latch_down_get(int unit, int port, pm_info_t pm_info, uint32 flags, int* link) 4929 { 4930 int first_index, rv; 4931 uint32 reg32_val, bitmap; 4932 soc_field_t status_field, clear_field; 4933 SOC_INIT_FUNC_DEFS; 4934 4935 *link = 0; 4936 4937 rv = _pm4x25_port_index_get(unit, port, pm_info, &first_index, &bitmap); 4938 _SOC_IF_ERR_EXIT(rv); 4939 4940 switch(first_index) { 4941 case 0: 4942 status_field = PORT0_LINKSTATUSf; 4943 clear_field = PORT0_LINKDOWN_CLEARf; 4944 break; 4945 4946 case 1: 4947 status_field = PORT1_LINKSTATUSf; 4948 clear_field = PORT1_LINKDOWN_CLEARf; 4949 break; 4950 4951 case 2: 4952 status_field = PORT2_LINKSTATUSf; 4953 clear_field = PORT2_LINKDOWN_CLEARf; 4954 break; 4955 4956 case 3: 4957 status_field = PORT3_LINKSTATUSf; 4958 clear_field = PORT3_LINKDOWN_CLEARf; 4959 break; 4960 4961 default: 4962 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 4963 (_SOC_MSG("Port %d, failed to get port index"), port)); 4964 } 4965 4966 rv = READ_CLPORT_LINKSTATUS_DOWNr(unit, port, ®32_val); 4967 _SOC_IF_ERR_EXIT(rv); 4968 4969 (*link) = soc_reg_field_get(unit, CLPORT_LINKSTATUS_DOWNr, 4970 reg32_val, status_field); 4971 4972 if (PORTMOD_PORT_LINK_LATCH_DOWN_F_CLEAR & flags) { 4973 4974 rv = READ_CLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, ®32_val); 4975 _SOC_IF_ERR_EXIT(rv); 4976 4977 soc_reg_field_set(unit, CLPORT_LINKSTATUS_DOWN_CLEARr, 4978 ®32_val, clear_field, 1); 4979 4980 rv = WRITE_CLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, reg32_val); 4981 _SOC_IF_ERR_EXIT(rv); 4982 4983 sal_usleep(10); 4984 4985 soc_reg_field_set(unit, CLPORT_LINKSTATUS_DOWN_CLEARr, 4986 ®32_val, clear_field, 0); 4987 4988 /* reset default register value */ 4989 rv = WRITE_CLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, reg32_val); 4990 _SOC_IF_ERR_EXIT(rv); 4991 4992 } 4993 4994 4995 exit: 4996 SOC_FUNC_RETURN; 4997 } 4998 4999 /* 5000 The field STRICT_PREAMBLE is used to check preamble+SFD strictly. 5001 The preamble will be shrinked when some external PHY works at 1G, 5002 so there are packet errors if STRICT_PREAMBLE is enabled. 5003 */ 5004 int _pm4x25_port_strict_preamble_set(int unit, int port, pm_info_t pm_info) 5005 { 5006 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5007 int nof_phys; 5008 int port_index=0; 5009 uint32 bitmap; 5010 phymod_phy_inf_config_t phy_config; 5011 int is_higig = 0; 5012 uint32 interface_modes; 5013 int strict_preamble_enable=0; 5014 SOC_INIT_FUNC_DEFS; 5015 5016 _SOC_IF_ERR_EXIT 5017 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5018 phy_access ,(1+MAX_PHYN), 5019 &nof_phys)); 5020 5021 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 5022 &bitmap)); 5023 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_config)); 5024 5025 _SOC_IF_ERR_EXIT 5026 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 5027 0, PM_4x25_INFO(pm_info)->ref_clk, 5028 &phy_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 5029 _rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 5030 _SOC_IF_ERR_EXIT(_rv); 5031 is_higig = interface_modes & PHYMOD_INTF_MODES_HIGIG ? 1 : 0; 5032 if (!is_higig && (phy_config.data_rate>= 10000)) { 5033 strict_preamble_enable = 1; 5034 } 5035 _rv = clmac_strict_preamble_set(unit, port, strict_preamble_enable); 5036 _SOC_IF_ERR_EXIT(_rv); 5037 exit: 5038 SOC_FUNC_RETURN; 5039 } 5040 5041 int pm4x25_port_phy_link_up_event(int unit, int port, pm_info_t pm_info) 5042 { 5043 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5044 int nof_phys; 5045 5046 SOC_INIT_FUNC_DEFS; 5047 5048 _SOC_IF_ERR_EXIT 5049 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5050 phy_access ,(1+MAX_PHYN), 5051 &nof_phys)); 5052 _rv = portmod_port_phychain_phy_link_up_event(unit, port, phy_access, nof_phys); 5053 _SOC_IF_ERR_EXIT(_rv); 5054 5055 _SOC_IF_ERR_EXIT(_pm4x25_port_strict_preamble_set(unit, port, pm_info)); 5056 exit: 5057 SOC_FUNC_RETURN; 5058 } 5059 5060 int pm4x25_port_phy_link_down_event(int unit, int port, pm_info_t pm_info) 5061 { 5062 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5063 int nof_phys; 5064 5065 SOC_INIT_FUNC_DEFS; 5066 5067 _SOC_IF_ERR_EXIT 5068 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5069 phy_access ,(1+MAX_PHYN), 5070 &nof_phys)); 5071 5072 _rv = portmod_port_phychain_phy_link_down_event(unit, port, phy_access, nof_phys); 5073 5074 exit: 5075 SOC_FUNC_RETURN; 5076 5077 } 5078 5079 int pm4x25_port_mac_link_get(int unit, int port, pm_info_t pm_info, int* link) 5080 { 5081 uint32 reg_val, bitmap; 5082 int port_index, phy_acc; 5083 SOC_INIT_FUNC_DEFS; 5084 SOC_NULL_CHECK(pm_info); 5085 5086 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 5087 5088 /* coverity[callee_ptr_arith:FALSE] */ 5089 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, (uint32*)(&bitmap))); 5090 5091 switch(port_index) { 5092 case 0: 5093 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_LN0_STATUS0_REGr(unit, phy_acc, ®_val)); 5094 (*link) = soc_reg_field_get(unit, CLPORT_XGXS0_LN0_STATUS0_REGr, reg_val, LINK_STATUSf); 5095 break; 5096 5097 case 1: 5098 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_LN1_STATUS0_REGr(unit, phy_acc, ®_val)); 5099 (*link) = soc_reg_field_get(unit, CLPORT_XGXS0_LN1_STATUS0_REGr, reg_val, LINK_STATUSf); 5100 break; 5101 5102 case 2: 5103 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_LN2_STATUS0_REGr(unit, phy_acc, ®_val)); 5104 (*link) = soc_reg_field_get(unit, CLPORT_XGXS0_LN2_STATUS0_REGr, reg_val, LINK_STATUSf); 5105 break; 5106 5107 case 3: 5108 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_LN3_STATUS0_REGr(unit, phy_acc, ®_val)); 5109 (*link) = soc_reg_field_get(unit, CLPORT_XGXS0_LN3_STATUS0_REGr, reg_val, LINK_STATUSf); 5110 break; 5111 5112 default: 5113 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 5114 (_SOC_MSG("Port %d, failed to get port index"), port)); 5115 } 5116 5117 exit: 5118 SOC_FUNC_RETURN; 5119 } 5120 5121 5122 int pm4x25_port_prbs_config_set(int unit, int port, pm_info_t pm_info, 5123 portmod_prbs_mode_t mode, int flags, 5124 const phymod_prbs_t* config) 5125 { 5126 int port_index, rv; 5127 uint32 bitmap; 5128 5129 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5130 if (SOC_FAILURE(rv)) { 5131 return (rv); 5132 } 5133 5134 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5135 return(SOC_E_UNAVAIL); 5136 } 5137 return (portmod_phy_port_prbs_config_set(unit, port, pm_info, mode, flags, config)); 5138 } 5139 5140 int pm4x25_port_prbs_config_get(int unit, int port, pm_info_t pm_info, 5141 portmod_prbs_mode_t mode, int flags, 5142 phymod_prbs_t* config) 5143 { 5144 int port_index, rv; 5145 uint32 bitmap; 5146 5147 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5148 if (SOC_FAILURE(rv)) { 5149 return (rv); 5150 } 5151 5152 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5153 return(SOC_E_UNAVAIL); 5154 } 5155 5156 return (portmod_phy_port_prbs_config_get(unit, port, pm_info, mode, flags, config)); 5157 } 5158 5159 5160 int pm4x25_port_prbs_enable_set(int unit, int port, pm_info_t pm_info, 5161 portmod_prbs_mode_t mode, int flags, 5162 int enable) 5163 { 5164 int port_index, rv; 5165 uint32 bitmap; 5166 5167 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5168 if (SOC_FAILURE(rv)) { 5169 return (rv); 5170 } 5171 5172 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5173 return(SOC_E_UNAVAIL); 5174 } 5175 return (portmod_phy_port_prbs_enable_set(unit, port, pm_info, mode, flags, enable)); 5176 } 5177 5178 int pm4x25_port_prbs_enable_get(int unit, int port, pm_info_t pm_info, 5179 portmod_prbs_mode_t mode, int flags, 5180 int* enable) 5181 { 5182 int port_index, rv; 5183 uint32 bitmap; 5184 5185 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5186 if (SOC_FAILURE(rv)) { 5187 return (rv); 5188 } 5189 5190 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5191 return(SOC_E_UNAVAIL); 5192 } 5193 return (portmod_phy_port_prbs_enable_get(unit, port, pm_info, mode, flags, enable)); 5194 } 5195 5196 5197 int pm4x25_port_prbs_status_get(int unit, int port, pm_info_t pm_info, 5198 portmod_prbs_mode_t mode, int flags, 5199 phymod_prbs_status_t* status) 5200 { 5201 int port_index, rv; 5202 uint32 bitmap; 5203 5204 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5205 if (SOC_FAILURE(rv)) { 5206 return (rv); 5207 } 5208 5209 if(PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5210 return(SOC_E_UNAVAIL); 5211 } 5212 return (portmod_phy_port_prbs_status_get(unit, port, pm_info, mode, flags, status)); 5213 } 5214 5215 5216 int pm4x25_port_nof_lanes_get(int unit, int port, pm_info_t pm_info, int *nof_lanes) 5217 { 5218 int temp_nof_lanes = 0; 5219 SOC_INIT_FUNC_DEFS; 5220 5221 temp_nof_lanes = _pm4x25_nof_lanes_get(unit, port, pm_info); 5222 if(0 == temp_nof_lanes){ 5223 SOC_EXIT; 5224 } 5225 else{ 5226 *nof_lanes = temp_nof_lanes; 5227 } 5228 5229 exit: 5230 SOC_FUNC_RETURN; 5231 } 5232 5233 5234 int pm4x25_port_firmware_mode_set(int unit, int port, pm_info_t pm_info, 5235 phymod_firmware_mode_t fw_mode) 5236 { 5237 5238 SOC_INIT_FUNC_DEFS; 5239 SOC_NULL_CHECK(pm_info); 5240 5241 /* Place your code here */ 5242 5243 exit: 5244 SOC_FUNC_RETURN; 5245 5246 } 5247 5248 int pm4x25_port_firmware_mode_get(int unit, int port, pm_info_t pm_info, phymod_firmware_mode_t* fw_mode) 5249 { 5250 5251 SOC_INIT_FUNC_DEFS; 5252 SOC_NULL_CHECK(pm_info); 5253 5254 /* Place your code here */ 5255 5256 5257 exit: 5258 SOC_FUNC_RETURN; 5259 5260 } 5261 5262 5263 int pm4x25_port_runt_threshold_set(int unit, int port, pm_info_t pm_info, int value) 5264 { 5265 5266 SOC_INIT_FUNC_DEFS; 5267 SOC_NULL_CHECK(pm_info); 5268 5269 /* Place your code here */ 5270 5271 5272 exit: 5273 SOC_FUNC_RETURN; 5274 5275 } 5276 5277 int pm4x25_port_runt_threshold_get(int unit, int port, pm_info_t pm_info, int* value) 5278 { 5279 5280 SOC_INIT_FUNC_DEFS; 5281 SOC_NULL_CHECK(pm_info); 5282 5283 /* Place your code here */ 5284 5285 5286 exit: 5287 SOC_FUNC_RETURN; 5288 5289 } 5290 5291 5292 int pm4x25_port_max_packet_size_set(int unit, int port, pm_info_t pm_info, int value) 5293 { 5294 5295 SOC_INIT_FUNC_DEFS; 5296 _SOC_IF_ERR_EXIT(clmac_rx_max_size_set(unit, port , value)); 5297 exit: 5298 SOC_FUNC_RETURN; 5299 5300 } 5301 5302 int pm4x25_port_max_packet_size_get(int unit, int port, pm_info_t pm_info, int* value) 5303 { 5304 5305 SOC_INIT_FUNC_DEFS; 5306 _SOC_IF_ERR_EXIT(clmac_rx_max_size_get(unit, port , value)); 5307 exit: 5308 SOC_FUNC_RETURN; 5309 5310 } 5311 5312 5313 int pm4x25_port_pad_size_set(int unit, int port, pm_info_t pm_info, int value) 5314 { 5315 SOC_INIT_FUNC_DEFS; 5316 SOC_NULL_CHECK(pm_info); 5317 5318 _SOC_IF_ERR_EXIT(clmac_pad_size_set(unit, port , value)); 5319 5320 exit: 5321 SOC_FUNC_RETURN; 5322 } 5323 5324 int pm4x25_port_pad_size_get(int unit, int port, pm_info_t pm_info, int* value) 5325 { 5326 SOC_INIT_FUNC_DEFS; 5327 SOC_NULL_CHECK(pm_info); 5328 5329 _SOC_IF_ERR_EXIT(clmac_pad_size_get(unit, port , value)); 5330 5331 exit: 5332 SOC_FUNC_RETURN; 5333 } 5334 5335 5336 int pm4x25_port_tx_drop_on_local_fault_set(int unit, int port, pm_info_t pm_info, int enable) 5337 { 5338 portmod_local_fault_control_t control; 5339 SOC_INIT_FUNC_DEFS; 5340 5341 portmod_local_fault_control_t_init(unit, &control); 5342 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_get(unit, port, pm_info, &control)); 5343 control.drop_tx_on_fault = enable; 5344 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_set(unit, port, pm_info, &control)); 5345 exit: 5346 SOC_FUNC_RETURN; 5347 5348 } 5349 5350 int pm4x25_port_tx_drop_on_local_fault_get(int unit, int port, pm_info_t pm_info, int* enable) 5351 { 5352 portmod_local_fault_control_t control; 5353 SOC_INIT_FUNC_DEFS; 5354 5355 portmod_local_fault_control_t_init(unit, &control); 5356 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_get(unit, port, pm_info, &control)); 5357 *enable = control.drop_tx_on_fault; 5358 exit: 5359 SOC_FUNC_RETURN; 5360 } 5361 5362 5363 int pm4x25_port_tx_drop_on_remote_fault_set(int unit, int port, 5364 pm_info_t pm_info, int enable) 5365 { 5366 portmod_remote_fault_control_t control; 5367 SOC_INIT_FUNC_DEFS; 5368 5369 portmod_remote_fault_control_t_init(unit, &control); 5370 _SOC_IF_ERR_EXIT(pm4x25_port_remote_fault_control_get(unit, port, pm_info, &control)); 5371 control.drop_tx_on_fault = enable; 5372 _SOC_IF_ERR_EXIT(pm4x25_port_remote_fault_control_set(unit, port, pm_info, &control)); 5373 exit: 5374 SOC_FUNC_RETURN; 5375 } 5376 5377 int pm4x25_port_tx_drop_on_remote_fault_get(int unit, int port, pm_info_t pm_info, int* enable) 5378 { 5379 portmod_remote_fault_control_t control; 5380 SOC_INIT_FUNC_DEFS; 5381 5382 portmod_remote_fault_control_t_init(unit, &control); 5383 _SOC_IF_ERR_EXIT(pm4x25_port_remote_fault_control_get(unit, port, pm_info, &control)); 5384 *enable = control.drop_tx_on_fault; 5385 exit: 5386 SOC_FUNC_RETURN; 5387 } 5388 5389 int pm4x25_port_remote_fault_enable_set(int unit, int port, pm_info_t pm_info, int enable) 5390 { 5391 portmod_remote_fault_control_t control; 5392 SOC_INIT_FUNC_DEFS; 5393 5394 portmod_remote_fault_control_t_init(unit, &control); 5395 5396 _SOC_IF_ERR_EXIT(clmac_remote_fault_control_get(unit, port , &control)); 5397 control.enable = enable; 5398 _SOC_IF_ERR_EXIT(clmac_remote_fault_control_set(unit, port , &control)); 5399 exit: 5400 SOC_FUNC_RETURN; 5401 } 5402 5403 int pm4x25_port_remote_fault_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 5404 { 5405 portmod_remote_fault_control_t control; 5406 SOC_INIT_FUNC_DEFS; 5407 5408 portmod_remote_fault_control_t_init(unit, &control); 5409 5410 _SOC_IF_ERR_EXIT(clmac_remote_fault_control_get(unit, port , &control)); 5411 *enable = control.enable; 5412 exit: 5413 SOC_FUNC_RETURN; 5414 5415 } 5416 5417 int pm4x25_port_local_fault_enable_set(int unit, int port, pm_info_t pm_info, int enable) 5418 { 5419 portmod_local_fault_control_t control; 5420 SOC_INIT_FUNC_DEFS; 5421 5422 portmod_local_fault_control_t_init(unit, &control); 5423 5424 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_get(unit, port, pm_info, &control)); 5425 control.enable = enable; 5426 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_set(unit, port, pm_info, &control)); 5427 exit: 5428 SOC_FUNC_RETURN; 5429 } 5430 5431 5432 int pm4x25_port_local_fault_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 5433 { 5434 portmod_local_fault_control_t control; 5435 SOC_INIT_FUNC_DEFS; 5436 5437 portmod_local_fault_control_t_init(unit, &control); 5438 5439 _SOC_IF_ERR_EXIT(pm4x25_port_local_fault_control_get(unit, port, pm_info, &control)); 5440 *enable = control.enable; 5441 5442 exit: 5443 SOC_FUNC_RETURN; 5444 } 5445 5446 int pm4x25_port_local_fault_status_get(int unit, int port, 5447 pm_info_t pm_info, int* value) 5448 { 5449 int rv; 5450 SOC_INIT_FUNC_DEFS; 5451 5452 rv = clmac_local_fault_status_get(unit, port, 0, value); 5453 _SOC_IF_ERR_EXIT(rv); 5454 exit: 5455 SOC_FUNC_RETURN; 5456 } 5457 5458 int pm4x25_port_local_fault_control_set(int unit, int port, pm_info_t pm_info, 5459 const portmod_local_fault_control_t* control) 5460 { 5461 int rv; 5462 SOC_INIT_FUNC_DEFS; 5463 5464 rv = clmac_local_fault_control_set(unit, port, control); 5465 _SOC_IF_ERR_EXIT(rv); 5466 exit: 5467 SOC_FUNC_RETURN; 5468 } 5469 5470 int pm4x25_port_local_fault_control_get(int unit, int port, pm_info_t pm_info, 5471 portmod_local_fault_control_t* control) 5472 { 5473 int rv; 5474 SOC_INIT_FUNC_DEFS; 5475 5476 rv = clmac_local_fault_control_get(unit, port, control); 5477 _SOC_IF_ERR_EXIT(rv); 5478 exit: 5479 SOC_FUNC_RETURN; 5480 } 5481 5482 int pm4x25_port_remote_fault_status_get(int unit, int port, 5483 pm_info_t pm_info, int* value) 5484 { 5485 int rv; 5486 SOC_INIT_FUNC_DEFS; 5487 5488 rv = clmac_remote_fault_status_get(unit, port, 0, value); 5489 _SOC_IF_ERR_EXIT(rv); 5490 exit: 5491 SOC_FUNC_RETURN; 5492 } 5493 5494 int pm4x25_port_remote_fault_control_set(int unit, int port, pm_info_t pm_info, 5495 const portmod_remote_fault_control_t* control) 5496 { 5497 int rv; 5498 SOC_INIT_FUNC_DEFS; 5499 5500 rv = clmac_remote_fault_control_set(unit, port, control); 5501 _SOC_IF_ERR_EXIT(rv); 5502 exit: 5503 SOC_FUNC_RETURN; 5504 } 5505 5506 int pm4x25_port_remote_fault_control_get(int unit, int port, pm_info_t pm_info, 5507 portmod_remote_fault_control_t* control) 5508 { 5509 int rv; 5510 SOC_INIT_FUNC_DEFS; 5511 5512 rv = clmac_remote_fault_control_get(unit, port, control); 5513 _SOC_IF_ERR_EXIT(rv); 5514 exit: 5515 SOC_FUNC_RETURN; 5516 } 5517 5518 int pm4x25_port_pause_control_set(int unit, int port, pm_info_t pm_info, 5519 const portmod_pause_control_t* control) 5520 { 5521 SOC_INIT_FUNC_DEFS; 5522 _SOC_IF_ERR_EXIT(clmac_pause_control_set(unit, port, control)); 5523 exit: 5524 SOC_FUNC_RETURN; 5525 } 5526 5527 int pm4x25_port_pause_control_get(int unit, int port, pm_info_t pm_info, 5528 portmod_pause_control_t* control) 5529 { 5530 SOC_INIT_FUNC_DEFS; 5531 _SOC_IF_ERR_EXIT(clmac_pause_control_get(unit, port, control)); 5532 exit: 5533 SOC_FUNC_RETURN; 5534 } 5535 5536 int pm4x25_port_pfc_control_set(int unit, int port, 5537 pm_info_t pm_info, const portmod_pfc_control_t* control) 5538 { 5539 SOC_INIT_FUNC_DEFS; 5540 _SOC_IF_ERR_EXIT(clmac_pfc_control_set(unit, port, control)); 5541 exit: 5542 SOC_FUNC_RETURN; 5543 } 5544 5545 int pm4x25_port_pfc_control_get(int unit, int port, pm_info_t pm_info, portmod_pfc_control_t* control) 5546 { 5547 SOC_INIT_FUNC_DEFS; 5548 _SOC_IF_ERR_EXIT(clmac_pfc_control_get(unit, port, control)); 5549 exit: 5550 SOC_FUNC_RETURN; 5551 } 5552 5553 5554 int pm4x25_port_llfc_control_set(int unit, int port, 5555 pm_info_t pm_info, const portmod_llfc_control_t* control) 5556 { 5557 SOC_INIT_FUNC_DEFS; 5558 _SOC_IF_ERR_EXIT(clmac_llfc_control_set(unit, port, control)); 5559 exit: 5560 SOC_FUNC_RETURN; 5561 } 5562 5563 int pm4x25_port_llfc_control_get(int unit, int port, 5564 pm_info_t pm_info, portmod_llfc_control_t* control) 5565 { 5566 SOC_INIT_FUNC_DEFS; 5567 _SOC_IF_ERR_EXIT(clmac_llfc_control_get(unit, port, control)); 5568 5569 exit: 5570 SOC_FUNC_RETURN; 5571 } 5572 5573 5574 int pm4x25_port_core_access_get (int unit, int port, 5575 pm_info_t pm_info, int phyn, int max_cores, 5576 phymod_core_access_t* core_access_arr, 5577 int* nof_cores, 5578 int* is_most_ext) 5579 { 5580 int port_index; 5581 uint32 bitmap; 5582 int index; 5583 int done=0; 5584 int i,j, is_legacy_phy; 5585 uint32 xphy_id; 5586 phymod_core_access_t core_access; 5587 5588 SOC_INIT_FUNC_DEFS; 5589 5590 if(PM_4x25_INFO(pm_info)->in_pm12x10){ 5591 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("core access get cannot be called for PM4X25 which is part of PM12X10"))); 5592 } 5593 5594 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 5595 &bitmap)); 5596 5597 if(phyn > PM_4x25_INFO(pm_info)->nof_phys[port_index]){ 5598 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 5599 (_SOC_MSG("phyn exceeded. max allowed %d. got %d"), 5600 PM_4x25_INFO(pm_info)->nof_phys[port_index] - 1, phyn)); 5601 } 5602 5603 if(phyn < 0) 5604 { 5605 phyn = PM_4x25_INFO(pm_info)->nof_phys[port_index] - 1; 5606 } 5607 5608 _SOC_IF_ERR_EXIT(phymod_core_access_t_init(&core_access_arr[0])); 5609 5610 if( phyn == 0 ){ 5611 sal_memcpy(&core_access_arr[0], &(PM_4x25_INFO(pm_info)->int_core_access), 5612 sizeof(phymod_core_access_t)); 5613 *nof_cores = 1; 5614 } else { 5615 index = 0; 5616 done = 0; 5617 for(i=0 ; (i< MAX_PORTS_PER_PM4X25); i++) { 5618 if(bitmap & (0x1U << i)) { 5619 xphy_id = PM_4x25_INFO(pm_info)->lane_conn[phyn-1][i].xphy_id; 5620 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 5621 if(index == 0){ 5622 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 5623 sal_memcpy(&core_access_arr[index], &(core_access), 5624 sizeof(phymod_core_access_t)); 5625 index++; 5626 } else { 5627 for( j = 0 ; (j < index) &&(!done) ; j++) { 5628 if((!sal_memcmp (&core_access_arr[j], &core_access, 5629 sizeof(phymod_core_access_t)))) { /* found a match */ 5630 done = 1; 5631 } 5632 } 5633 if((!done) && (index < max_cores)){ 5634 sal_memcpy(&core_access_arr[index], &(core_access), 5635 sizeof(phymod_core_access_t)); 5636 index++; 5637 } 5638 } 5639 } 5640 } 5641 } 5642 *nof_cores = index; 5643 } 5644 if (is_most_ext) { 5645 if (phyn == PM_4x25_INFO(pm_info)->nof_phys[port_index]-1) { 5646 *is_most_ext = 1; 5647 } else { 5648 *is_most_ext = 0; 5649 } 5650 } 5651 5652 exit: 5653 SOC_FUNC_RETURN; 5654 } 5655 5656 /*! 5657 * pm4x25_port_frame_spacing_stretch_set 5658 * 5659 * @brief Port Mac Control Spacing Stretch 5660 * 5661 * @param [in] unit - unit id 5662 * @param [in] port - logical port 5663 * @param [in] spacing - 5664 */ 5665 int pm4x25_port_frame_spacing_stretch_set (int unit, int port, 5666 pm_info_t pm_info,int spacing) 5667 { 5668 return(clmac_frame_spacing_stretch_set(unit, port, spacing)); 5669 } 5670 5671 /*! 5672 * pm4x25_port_frame_spacing_stretch_get 5673 * 5674 * @brief Port Mac Control Spacing Stretch 5675 * 5676 * @param [in] unit - unit id 5677 * @param [in] port - logical port 5678 * @param [in] spacing - 5679 */ 5680 int pm4x25_port_frame_spacing_stretch_get (int unit, int port, 5681 pm_info_t pm_info, 5682 const int *spacing) 5683 { 5684 return (clmac_frame_spacing_stretch_get(unit, port, (int *)spacing)); 5685 } 5686 5687 /*! 5688 * pm4x25_port_diag_fifo_status_get 5689 * 5690 * @brief get port timestamps in fifo 5691 * 5692 * @param [in] unit - unit id 5693 * @param [in] port - logical port 5694 * @param [in] diag_info - 5695 */ 5696 int pm4x25_port_diag_fifo_status_get (int unit, int port,pm_info_t pm_info, 5697 const portmod_fifo_status_t* diag_info) 5698 { 5699 return(clmac_diag_fifo_status_get(unit, port, diag_info)); 5700 } 5701 5702 int _clport_pfc_config_set(int unit, int port, uint32 value) 5703 { 5704 int rv = SOC_E_UNAVAIL; 5705 uint32 rval32 = 0; 5706 5707 if (SOC_REG_IS_VALID(unit,CLPORT_MAC_RSV_MASKr)) { 5708 rv = READ_CLPORT_MAC_RSV_MASKr(unit, port, &rval32); 5709 if (SOC_SUCCESS(rv)) { 5710 /* CLPORT_MAC_RSV_MASK: Bit 18 PFC frame detected 5711 * Enable PFC Frame : Set 0. Go through 5712 * Disable PFC Frame : Set 1. Purged. 5713 */ 5714 if(value) { 5715 rval32 &= ~(1 << 18); 5716 } else { 5717 rval32 |= (1 << 18); 5718 } 5719 rv = WRITE_CLPORT_MAC_RSV_MASKr(unit, port, rval32); 5720 } 5721 } 5722 5723 return rv; 5724 } 5725 5726 int _clport_pfc_config_get(int unit, int port, uint32* value) 5727 { 5728 int rv = SOC_E_NONE; 5729 uint32 rval32 = 0; 5730 5731 if (SOC_REG_IS_VALID(unit,CLPORT_MAC_RSV_MASKr)) { 5732 rv = READ_CLPORT_MAC_RSV_MASKr(unit, port, &rval32); 5733 if (SOC_SUCCESS(rv)) { 5734 /* CLPORT_MAC_RSV_MASK: Bit 18 PFC frame detected 5735 * Enable PFC Frame : Set 0. Go through 5736 * Disable PFC Frame : Set 1. Purged. 5737 */ 5738 *value = ((rval32 & 0x40000) >> 18) ? 0 : 1; 5739 } 5740 } 5741 5742 return rv; 5743 } 5744 5745 /*! 5746 * pm4x25_port_pfc_config_set 5747 * 5748 * @brief set pass control frames. 5749 * 5750 * @param [in] unit - unit id 5751 * @param [in] port - logical port 5752 * @param [in] pfc_cfg - 5753 */ 5754 int pm4x25_port_pfc_config_set (int unit, int port,pm_info_t pm_info, 5755 const portmod_pfc_config_t* pfc_cfg) 5756 { 5757 SOC_INIT_FUNC_DEFS; 5758 5759 if (pfc_cfg->classes != 8) { 5760 return SOC_E_PARAM; 5761 } 5762 _SOC_IF_ERR_EXIT(clmac_pfc_config_set(unit, port, pfc_cfg)); 5763 _SOC_IF_ERR_EXIT(_clport_pfc_config_set(unit, port, pfc_cfg->rxpass)); 5764 exit: 5765 SOC_FUNC_RETURN; 5766 } 5767 5768 /*! 5769 * pm4x25_port_pfc_config_get 5770 * 5771 * @brief set pass control frames. 5772 * 5773 * @param [in] unit - unit id 5774 * @param [in] port - logical port 5775 * @param [in] pfc_cfg - 5776 */ 5777 int pm4x25_port_pfc_config_get (int unit, int port,pm_info_t pm_info, 5778 portmod_pfc_config_t* pfc_cfg) 5779 { 5780 SOC_INIT_FUNC_DEFS; 5781 5782 pfc_cfg->classes = 8; 5783 _SOC_IF_ERR_EXIT(clmac_pfc_config_get(unit, port, pfc_cfg)); 5784 _SOC_IF_ERR_EXIT(_clport_pfc_config_get(unit, port, &pfc_cfg->rxpass)); 5785 exit: 5786 SOC_FUNC_RETURN; 5787 } 5788 5789 /*! 5790 * pm4x25_port_eee_set 5791 * 5792 * @brief set EEE control and timers 5793 * 5794 * @param [in] unit - unit id 5795 * @param [in] port - logical port 5796 * @param [in] eee - 5797 */ 5798 int pm4x25_port_eee_set(int unit, int port, pm_info_t pm_info,const portmod_eee_t* eee) 5799 { 5800 return (clmac_eee_set(unit, port, eee)); 5801 } 5802 5803 /*! 5804 * pm4x25_port_eee_get 5805 * 5806 * @brief get EEE control and timers 5807 * 5808 * @param [in] unit - unit id 5809 * @param [in] port - logical port 5810 * @param [in] eee - 5811 */ 5812 int pm4x25_port_eee_get(int unit, int port, pm_info_t pm_info,portmod_eee_t* eee) 5813 { 5814 return (clmac_eee_get(unit, port, eee)); 5815 } 5816 5817 /*! 5818 * pm4x25_port_vlan_tag_set 5819 * 5820 * @brief vlan tag set. 5821 * 5822 * @param [in] unit - unit id 5823 * @param [in] port - logical port 5824 * @param [in] vlan_tag - 5825 */ 5826 int pm4x25_port_vlan_tag_set(int unit, int port, pm_info_t pm_info,const portmod_vlan_tag_t* vlan_tag) 5827 { 5828 return (clmac_rx_vlan_tag_set (unit, port, vlan_tag->outer_vlan_tag, 5829 vlan_tag->inner_vlan_tag)); 5830 } 5831 5832 5833 /*! 5834 * pm4x25_port_vlan_tag_get 5835 * 5836 * @brief vlan tag get. 5837 * 5838 * @param [in] unit - unit id 5839 * @param [in] port - logical port 5840 * @param [in] vlan_tag - 5841 */ 5842 int pm4x25_port_vlan_tag_get(int unit, int port, pm_info_t pm_info, portmod_vlan_tag_t* vlan_tag) 5843 { 5844 return (clmac_rx_vlan_tag_get (unit, port, (int*)&vlan_tag->outer_vlan_tag, 5845 (int*)&vlan_tag->inner_vlan_tag)); 5846 } 5847 5848 /*! 5849 * pm4x25_port_duplex_set 5850 * 5851 * @brief duplex set. 5852 * 5853 * @param [in] unit - unit id 5854 * @param [in] port - logical port 5855 * @param [in] enable - 5856 */ 5857 int pm4x25_port_duplex_set(int unit, int port, pm_info_t pm_info,int enable) 5858 { 5859 return (clmac_duplex_set (unit, port, enable)); 5860 } 5861 5862 5863 /*! 5864 * pm4x25_port_duplex_get 5865 * 5866 * @brief duplex get. 5867 * 5868 * @param [in] unit - unit id 5869 * @param [in] port - logical port 5870 * @param [in] vlan_tag - 5871 */ 5872 int pm4x25_port_duplex_get(int unit, int port, pm_info_t pm_info, int* enable) 5873 { 5874 return (clmac_duplex_get (unit, port, enable)); 5875 } 5876 5877 /*! 5878 * pm4x25_port_speed_get 5879 * 5880 * @brief duplex get. 5881 * 5882 * @param [in] unit - unit id 5883 * @param [in] port - logical port 5884 * @param [in] speed - 5885 */ 5886 int pm4x25_port_speed_get(int unit, int port, pm_info_t pm_info, int* speed) 5887 { 5888 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5889 phymod_phy_inf_config_t config; 5890 int nof_phys, rv; 5891 5892 rv = portmod_port_chain_phy_access_get(unit, port, pm_info, 5893 phy_access ,(1+MAX_PHYN), 5894 &nof_phys); 5895 if (rv) return(rv); 5896 5897 rv = phymod_phy_interface_config_get(&phy_access[0], 0,0, &config); 5898 if (rv) return (rv); 5899 5900 *speed = config.data_rate; 5901 return (rv); 5902 } 5903 5904 int pm4x25_port_phy_reg_read(int unit, int port, pm_info_t pm_info, int lane, int flags, int reg_addr, uint32* value) 5905 { 5906 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5907 int nof_phys; 5908 SOC_INIT_FUNC_DEFS; 5909 5910 _SOC_IF_ERR_EXIT 5911 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5912 phy_access ,(1+MAX_PHYN), 5913 &nof_phys)); 5914 _SOC_IF_ERR_EXIT 5915 (portmod_port_phychain_reg_read(unit, port, phy_access, 5916 nof_phys, lane, flags, reg_addr,value)); 5917 exit: 5918 SOC_FUNC_RETURN; 5919 } 5920 5921 int pm4x25_port_phy_reg_write(int unit, int port, pm_info_t pm_info, int lane, int flags, int reg_addr, uint32 value) 5922 { 5923 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5924 int nof_phys; 5925 SOC_INIT_FUNC_DEFS; 5926 5927 _SOC_IF_ERR_EXIT 5928 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5929 phy_access ,(1+MAX_PHYN), 5930 &nof_phys)); 5931 _SOC_IF_ERR_EXIT 5932 (portmod_port_phychain_reg_write(unit, port, phy_access, 5933 nof_phys, lane, flags, reg_addr,value)); 5934 exit: 5935 SOC_FUNC_RETURN; 5936 } 5937 5938 int pm4x25_port_reset_set (int unit, int port, pm_info_t pm_info, 5939 int reset_mode, int opcode, int direction) 5940 { 5941 int port_index, rv; 5942 uint32 bitmap; 5943 5944 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5945 if (SOC_FAILURE(rv)) { 5946 return (rv); 5947 } 5948 5949 if (PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5950 return(SOC_E_UNAVAIL); 5951 } 5952 return(portmod_phy_port_reset_set (unit, port, pm_info, reset_mode, opcode, direction)); 5953 } 5954 5955 int pm4x25_port_reset_get (int unit, int port, pm_info_t pm_info, 5956 int reset_mode, int opcode, int* direction) 5957 { 5958 int port_index, rv; 5959 uint32 bitmap; 5960 5961 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 5962 if (SOC_FAILURE(rv)) { 5963 return (rv); 5964 } 5965 5966 if (PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 5967 return(SOC_E_UNAVAIL); 5968 } 5969 return(portmod_phy_port_reset_get (unit, port, pm_info, reset_mode, opcode, direction)); 5970 } 5971 5972 /*Port remote Adv get*/ 5973 int pm4x25_port_adv_remote_get (int unit, int port, pm_info_t pm_info, 5974 int* ability_mask) 5975 { 5976 return (0); 5977 } 5978 5979 /*get port fec enable*/ 5980 int pm4x25_port_fec_enable_get(int unit, int port, pm_info_t pm_info, 5981 uint32 phy_flags, uint32_t* enable) 5982 { 5983 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5984 int nof_phys = 0; 5985 5986 SOC_INIT_FUNC_DEFS; 5987 5988 _SOC_IF_ERR_EXIT 5989 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5990 phy_access ,(1+MAX_PHYN), 5991 &nof_phys)); 5992 5993 _SOC_IF_ERR_EXIT 5994 (portmod_port_phychain_fec_enable_get(unit, port, phy_access, nof_phys, phy_flags, enable)); 5995 5996 exit: 5997 SOC_FUNC_RETURN; 5998 } 5999 6000 /*set port fec enable*/ 6001 int pm4x25_port_fec_enable_set(int unit, int port, pm_info_t pm_info, 6002 uint32 phy_flags, uint32_t enable) 6003 { 6004 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6005 int nof_phys = 0; 6006 6007 SOC_INIT_FUNC_DEFS; 6008 6009 _SOC_IF_ERR_EXIT 6010 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6011 phy_access ,(1+MAX_PHYN), 6012 &nof_phys)); 6013 6014 _SOC_IF_ERR_EXIT 6015 (portmod_port_phychain_fec_enable_set(unit, port, phy_access, nof_phys, phy_flags, enable)); 6016 6017 exit: 6018 SOC_FUNC_RETURN; 6019 } 6020 6021 /*get port auto negotiation local ability*/ 6022 int pm4x25_port_ability_advert_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 6023 portmod_port_ability_t* ability) 6024 { 6025 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6026 int nof_phys = 0; 6027 phymod_autoneg_ability_t an_ability; 6028 portmod_port_ability_t port_ability; 6029 int phy_index, xphy_id, is_legacy_phy = 0; 6030 6031 SOC_INIT_FUNC_DEFS; 6032 6033 _SOC_IF_ERR_EXIT 6034 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6035 phy_access ,(1+MAX_PHYN), 6036 &nof_phys)); 6037 6038 _SOC_IF_ERR_EXIT 6039 (portmod_port_phychain_autoneg_ability_get(unit, port, phy_access, 6040 nof_phys, phy_flags, &an_ability, 6041 &port_ability)); 6042 phy_index = nof_phys -1; 6043 if (phy_index) { 6044 xphy_id = phy_access[phy_index].access.addr; 6045 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 6046 if (is_legacy_phy) { 6047 sal_memcpy(ability, &port_ability, sizeof(portmod_port_ability_t)); 6048 } 6049 } 6050 if (!is_legacy_phy) { 6051 portmod_common_phy_to_port_ability(&an_ability, ability); 6052 } 6053 6054 exit: 6055 SOC_FUNC_RETURN; 6056 } 6057 6058 /* 6059 * Function: 6060 * _pm4x25_port_to_phy_ability 6061 * Purpose: 6062 * This function will translate the portAbility request, which passed 6063 * from BCM api to anAbility format required by phymod api. 6064 * 6065 * Parameters: 6066 * portAbility -(IN) port an ability request from BCM Api 6067 * anAbility -(OUT) phymod an ability to phymod api. 6068 * port_num_lanes -(IN) number of lane 6069 * line_interface -(IN) line interface 6070 * cx4_10g -(IN) cx4 port 6071 * an_cl72 -(IN) an cl72 configuration 6072 * an_fec -(IN) fec configuration 6073 * an_hg_mode -(IN) hg_mode 6074 * Returns: 6075 * None 6076 */ 6077 void _pm4x25_port_to_phy_ability (portmod_port_ability_t *portAbility, 6078 phymod_autoneg_ability_t *anAbility, 6079 int port_num_lanes, 6080 int line_interface, 6081 int cx4_10g, 6082 int an_cl72, 6083 int an_fec, 6084 int hg_mode, 6085 phymod_an_mode_type_t an_mode) 6086 { 6087 uint32_t an_tech_ability = 0; 6088 uint32_t an_bam37_ability = 0; 6089 uint32_t an_bam73_ability = 0; 6090 _shr_port_mode_t speed_full_duplex = portAbility->speed_full_duplex; 6091 6092 phymod_autoneg_ability_t_init(anAbility); 6093 6094 /* 6095 * an_tech_ability 6096 */ 6097 if (port_num_lanes == 4) { 6098 6099 if (speed_full_duplex & SOC_PA_SPEED_100GB) { 6100 if (portAbility->medium) { 6101 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6102 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 6103 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6104 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 6105 } else { 6106 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 6107 } 6108 } else { 6109 if (line_interface == SOC_PORT_IF_CR4 ) { 6110 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 6111 } else { 6112 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 6113 } 6114 } 6115 } 6116 6117 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 6118 if (portAbility->medium) { 6119 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6120 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 6121 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6122 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 6123 } else { 6124 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 6125 } 6126 } else { 6127 if (line_interface == SOC_PORT_IF_CR4) { 6128 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 6129 } else { 6130 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 6131 } 6132 } 6133 } 6134 6135 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 6136 PHYMOD_AN_CAP_10G_KX4_SET(an_tech_ability); 6137 } 6138 6139 } else if (port_num_lanes == 1) { 6140 /* When in MSA AN mode : We do not want to populate the base page with IEEE mode. 6141 * If we do, then IEEE takes the higher priority. Hence we add the following exception 6142 * block for each 25G case below: if(phymod_AN_MODE_MSA!=an_mode) */ 6143 if ((speed_full_duplex & SOC_PA_SPEED_25GB) && (phymod_AN_MODE_MSA != an_mode)) { 6144 if (portAbility->medium) { 6145 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6146 if (portAbility->channel & SOC_PA_CHANNEL_SHORT) { 6147 PHYMOD_AN_CAP_25G_KRS1_SET(an_tech_ability); 6148 } else { 6149 PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability); 6150 } 6151 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6152 if (portAbility->channel & SOC_PA_CHANNEL_SHORT) { 6153 PHYMOD_AN_CAP_25G_CRS1_SET(an_tech_ability); 6154 } else { 6155 PHYMOD_AN_CAP_25G_CR1_SET(an_tech_ability); 6156 } 6157 } else { 6158 /* 6159 * This is essentially a Fiber mode which is not 6160 * a valid case for normal operation, but port 6161 * but during intialization time, it will 6162 * use fiber mode as it is default. 6163 */ 6164 if (portAbility->channel & SOC_PA_CHANNEL_SHORT) { 6165 PHYMOD_AN_CAP_25G_KRS1_SET(an_tech_ability); 6166 } else { 6167 PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability); 6168 } 6169 } 6170 } else { 6171 if (line_interface == SOC_PORT_IF_CR ) { 6172 if (portAbility->channel & SOC_PA_CHANNEL_SHORT) { 6173 PHYMOD_AN_CAP_25G_CRS1_SET(an_tech_ability); 6174 } else { 6175 PHYMOD_AN_CAP_25G_CR1_SET(an_tech_ability); 6176 } 6177 } else { 6178 if (portAbility->channel & SOC_PA_CHANNEL_SHORT) { 6179 PHYMOD_AN_CAP_25G_KRS1_SET(an_tech_ability); 6180 } else { 6181 PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability); 6182 } 6183 } 6184 } 6185 } 6186 6187 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 6188 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 6189 } 6190 6191 if (speed_full_duplex & SOC_PA_SPEED_1000MB) { 6192 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 6193 } 6194 6195 if (speed_full_duplex & SOC_PA_SPEED_5000MB) { 6196 PHYMOD_AN_CAP_5G_KR1_SET(an_tech_ability); 6197 } 6198 if (speed_full_duplex & SOC_PA_SPEED_2500MB) { 6199 PHYMOD_AN_CAP_2P5G_X_SET(an_tech_ability); 6200 } 6201 } 6202 6203 /* 6204 * an_bam73_ability 6205 */ 6206 if (port_num_lanes == 4) { 6207 if (speed_full_duplex & SOC_PA_SPEED_50GB) { 6208 if (portAbility->medium) { 6209 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6210 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_bam73_ability); 6211 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6212 PHYMOD_BAM_CL73_CAP_50G_CR4_SET(an_bam73_ability); 6213 } else { 6214 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_bam73_ability); 6215 } 6216 } else { 6217 if (line_interface == SOC_PORT_IF_CR4 ) { 6218 PHYMOD_BAM_CL73_CAP_50G_CR4_SET(an_bam73_ability); 6219 } else { 6220 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_bam73_ability); 6221 } 6222 } 6223 } 6224 } else if (port_num_lanes == 2) { 6225 if (speed_full_duplex & SOC_PA_SPEED_20GB) { 6226 if (portAbility->medium) { 6227 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6228 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 6229 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6230 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 6231 } else { 6232 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 6233 } 6234 } else { 6235 if (line_interface == SOC_PORT_IF_CR2) { 6236 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 6237 } else { 6238 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 6239 } 6240 } 6241 } 6242 if (speed_full_duplex & SOC_PA_SPEED_50GB) { 6243 if (portAbility->medium) { 6244 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6245 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability); 6246 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6247 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_bam73_ability); 6248 } else { 6249 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability); 6250 } 6251 } else { 6252 if (line_interface == SOC_PORT_IF_CR2) { 6253 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_bam73_ability); 6254 } else { 6255 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability); 6256 } 6257 } 6258 } 6259 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 6260 if (portAbility->medium) { 6261 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6262 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_bam73_ability); 6263 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6264 PHYMOD_BAM_CL73_CAP_40G_CR2_SET(an_bam73_ability); 6265 } else { 6266 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_bam73_ability); 6267 } 6268 } else { 6269 if (line_interface == SOC_PORT_IF_CR2) { 6270 PHYMOD_BAM_CL73_CAP_40G_CR2_SET(an_bam73_ability); 6271 } else { 6272 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_bam73_ability); 6273 } 6274 } 6275 } 6276 } else { 6277 /* port_num_lanes == 1 */ 6278 if (speed_full_duplex & SOC_PA_SPEED_25GB) { 6279 if (portAbility->medium) { 6280 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 6281 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability); 6282 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 6283 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_bam73_ability); 6284 } else { 6285 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability); 6286 } 6287 } else { 6288 if (line_interface == SOC_PORT_IF_CR) { 6289 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_bam73_ability); 6290 } else { 6291 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability); 6292 } 6293 } 6294 6295 } 6296 } 6297 6298 /* 6299 * an_bam37_ability is not supported in PM4x25 (TSCF) 6300 */ 6301 6302 anAbility->an_cap = an_tech_ability; 6303 anAbility->cl73bam_cap = an_bam73_ability; 6304 anAbility->cl37bam_cap = an_bam37_ability; 6305 6306 switch (portAbility->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 6307 case SOC_PA_PAUSE_TX: 6308 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 6309 break; 6310 case SOC_PA_PAUSE_RX: 6311 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 6312 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 6313 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 6314 break; 6315 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 6316 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 6317 break; 6318 } 6319 6320 if ((speed_full_duplex & SOC_PA_SPEED_10MB) || 6321 (speed_full_duplex & SOC_PA_SPEED_100MB) || 6322 (speed_full_duplex & SOC_PA_SPEED_1000MB)) { 6323 if (portAbility->medium) { 6324 if (!(portAbility->medium & SOC_PA_MEDIUM_FIBER)) { 6325 PHYMOD_AN_CAP_SGMII_SET(anAbility); 6326 } else { 6327 if (portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 6328 PHYMOD_AN_CAP_100M_SET(anAbility->an_cap); 6329 } 6330 } 6331 } else { 6332 if (SOC_PORT_IF_SGMII == line_interface) { 6333 PHYMOD_AN_CAP_SGMII_SET(anAbility); 6334 } else { 6335 if (portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 6336 PHYMOD_AN_CAP_100M_SET(anAbility->an_cap); 6337 } 6338 } 6339 } 6340 } 6341 6342 /* next check if we need to set cl37 attribute */ 6343 if (an_cl72) { 6344 anAbility->an_cl72 = 1; 6345 } 6346 6347 if (hg_mode) { 6348 anAbility->an_hg2 = 1; 6349 } 6350 6351 /* 6352 * check if Cl74 fec is requested from AN BCM api. 6353 * SOC_PA_FEC_NONE mean that FEC be off. If that bit 6354 * is set, it will ignore both FEC_CL74 and FEC_CL91 setting. 6355 */ 6356 if (portAbility->fec & SOC_PA_FEC_NONE) { 6357 PHYMOD_AN_FEC_OFF_SET(anAbility->an_fec); 6358 } else { 6359 if ((an_fec == 1) || (portAbility->fec & SOC_PA_FEC_CL74)) { 6360 /* The 'phy_an_fec=1' and FEC CL74 ability are all the phymod FEC CL74. */ 6361 PHYMOD_AN_FEC_CL74_SET(anAbility->an_fec); 6362 } 6363 6364 if ((an_fec == 2) || (portAbility->fec & SOC_PA_FEC_CL91)) { 6365 /* The 'phy_an_fec=2' and FEC CL91 ability are all the phymod FEC CL74. */ 6366 PHYMOD_AN_FEC_CL91_SET(anAbility->an_fec); 6367 } 6368 } 6369 6370 } 6371 6372 int pm4x25_port_ability_advert_set(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 6373 portmod_port_ability_t* ability) 6374 { 6375 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6376 int nof_phys = 0, port_index = 0, rv = 0; 6377 int port_num_lanes, line_interface, cx4_10g; 6378 int an_cl72, an_fec, hg_mode; 6379 portmod_port_ability_t port_ability; 6380 phymod_autoneg_ability_t an_ability; 6381 uint32_t bitmap = 0, interface_modes; 6382 int line_side; 6383 phymod_an_mode_type_t an_mode; 6384 6385 SOC_INIT_FUNC_DEFS; 6386 6387 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 6388 6389 _SOC_IF_ERR_EXIT 6390 (pm4x25_port_ability_local_get(unit, port, pm_info, phy_flags, &port_ability)); 6391 6392 /* Make sure to advertise only abilities supported by the port */ 6393 port_ability.pause &= ability->pause; 6394 port_ability.interface &= ability->interface; 6395 port_ability.medium &= ability->medium; 6396 port_ability.eee &= ability->eee; 6397 port_ability.loopback &= ability->loopback; 6398 port_ability.flags &= ability->flags; 6399 port_ability.speed_half_duplex &= ability->speed_half_duplex; 6400 port_ability.speed_full_duplex &= ability->speed_full_duplex; 6401 port_ability.fec &= ability->fec; 6402 port_ability.channel &= ability->channel; 6403 6404 /* coverity[Out-of-bounds access:FALSE] */ 6405 SHR_BITCOUNT_RANGE(&bitmap, port_num_lanes, 0, PM4X25_LANES_PER_CORE); 6406 rv = PM4x25_CX4_10G_GET(unit, pm_info, &cx4_10g, port_index); 6407 _SOC_IF_ERR_EXIT(rv); 6408 rv = PM4x25_AN_CL72_GET(unit, pm_info, &an_cl72, port_index); 6409 _SOC_IF_ERR_EXIT(rv); 6410 rv = PM4x25_AN_FEC_GET(unit, pm_info, &an_fec, port_index); 6411 _SOC_IF_ERR_EXIT(rv); 6412 rv = PM4x25_INTERFACE_TYPE_GET(unit, pm_info, &line_interface, port_index); 6413 _SOC_IF_ERR_EXIT(rv); 6414 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 6415 port_index); 6416 _SOC_IF_ERR_EXIT(rv); 6417 rv = PM4x25_AN_MODE_GET(unit,pm_info,&an_mode,port_index); 6418 hg_mode = (interface_modes & PHYMOD_INTF_MODES_HIGIG)? 1: 0; 6419 6420 /* 6421 * Get the number of line side lanes. 6422 */ 6423 6424 line_side = TRUE ; 6425 _SOC_IF_ERR_EXIT 6426 (pm4x25_port_lane_count_get(unit, port, pm_info, 6427 line_side, &port_num_lanes)); 6428 6429 _pm4x25_port_to_phy_ability(&port_ability, &an_ability, 6430 port_num_lanes, line_interface, cx4_10g, 6431 an_cl72, an_fec, hg_mode, an_mode); 6432 6433 _SOC_IF_ERR_EXIT 6434 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6435 phy_access ,(1+MAX_PHYN), 6436 &nof_phys)); 6437 6438 rv = PM4x25_AN_MASTER_LANE_GET(unit, pm_info, &an_ability.an_master_lane, port_index); 6439 _SOC_IF_ERR_EXIT(rv); 6440 6441 _SOC_IF_ERR_EXIT 6442 (portmod_port_phychain_autoneg_ability_set(unit, port, phy_access, 6443 nof_phys, phy_flags, &an_ability, 6444 &port_ability)); 6445 LOG_VERBOSE(BSL_LS_BCM_PORT, 6446 (BSL_META_U(unit, 6447 "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x orig(HD=0x%08x, FD=0x%08x) \n" 6448 "Interface=0x%08x Medium=0x%08x Loopback=0x%08x Flags=0x%08x\n"), 6449 port_ability.speed_half_duplex, 6450 port_ability.speed_full_duplex, 6451 port_ability.pause, 6452 ability->speed_half_duplex, 6453 ability->speed_full_duplex, 6454 port_ability.interface, 6455 port_ability.medium, port_ability.loopback, 6456 port_ability.flags)); 6457 exit: 6458 SOC_FUNC_RETURN; 6459 } 6460 6461 /*Port ability remote Adv get*/ 6462 int pm4x25_port_ability_remote_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 6463 portmod_port_ability_t* ability) 6464 { 6465 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6466 int nof_phys; 6467 phymod_autoneg_ability_t an_ability; 6468 int phy_index, xphy_id, is_legacy_phy = 0; 6469 6470 SOC_INIT_FUNC_DEFS; 6471 6472 _SOC_IF_ERR_EXIT 6473 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6474 phy_access ,(1+MAX_PHYN), 6475 &nof_phys)); 6476 6477 phy_index = nof_phys -1; 6478 if (phy_index) { 6479 xphy_id = phy_access[phy_index].access.addr; 6480 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 6481 } 6482 _SOC_IF_ERR_EXIT 6483 (portmod_port_phychain_autoneg_remote_ability_get(unit, port, 6484 phy_access, nof_phys, phy_flags, &an_ability, ability)); 6485 if (!is_legacy_phy) { 6486 portmod_common_phy_to_port_ability(&an_ability, ability); 6487 } 6488 6489 exit: 6490 SOC_FUNC_RETURN; 6491 } 6492 6493 int _clport_rx_control_set(int unit, int port, int value) 6494 { 6495 int rv = SOC_E_UNAVAIL; 6496 uint32 rval32 = 0; 6497 6498 if (SOC_REG_IS_VALID(unit,CLPORT_MAC_RSV_MASKr)) { 6499 rv = READ_CLPORT_MAC_RSV_MASKr(unit, port, &rval32); 6500 if (SOC_SUCCESS(rv)) { 6501 /* CLPORT_MAC_RSV_MASK: Bit 11 Control Frame recieved 6502 * Enable Control Frame : Set 0. Packet go through 6503 * Disable Control Frame : Set 1. Packet is purged. 6504 */ 6505 if(value) { 6506 rval32 &= ~(1 << 11); 6507 } else { 6508 rval32 |= (1 << 11); 6509 } 6510 rv = WRITE_CLPORT_MAC_RSV_MASKr(unit, port, rval32); 6511 } 6512 } 6513 6514 return rv; 6515 } 6516 6517 int pm4x25_port_rx_control_set (int unit, int port, pm_info_t pm_info, 6518 const portmod_rx_control_t* rx_ctrl) 6519 { 6520 int phy_acc; 6521 uint32 reg_val; 6522 6523 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6524 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_RSV_MASKr(unit, phy_acc, ®_val)); 6525 6526 if (rx_ctrl->flags & PORTMOD_MAC_PASS_CONTROL_FRAME) { 6527 if(rx_ctrl->pass_control_frames){ 6528 reg_val &= ~(1 << 11); 6529 } else{ 6530 reg_val |= (1 << 11); 6531 } 6532 } 6533 6534 if (rx_ctrl->flags & PORTMOD_MAC_PASS_PFC_FRAME) { 6535 if(rx_ctrl->pass_pfc_frames){ 6536 reg_val &= ~(1 << 18); 6537 } else{ 6538 reg_val |= (1 << 18); 6539 } 6540 } 6541 6542 if (rx_ctrl->flags & PORTMOD_MAC_PASS_PAUSE_FRAME) { 6543 if(rx_ctrl->pass_pause_frames){ 6544 reg_val &= ~(1 << 12); 6545 } else{ 6546 reg_val |= (1 << 12); 6547 } 6548 } 6549 6550 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_RSV_MASKr(unit, phy_acc, reg_val)); 6551 6552 return (SOC_E_NONE); 6553 } 6554 6555 int pm4x25_port_rx_control_get (int unit, int port, pm_info_t pm_info, 6556 portmod_rx_control_t* rx_ctrl) 6557 { 6558 int phy_acc; 6559 uint32 reg_val; 6560 6561 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6562 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_RSV_MASKr(unit, phy_acc, ®_val)); 6563 6564 rx_ctrl->pass_control_frames = ((reg_val & 0x800) >> 11) ? 0 : 1; 6565 rx_ctrl->pass_pfc_frames = ((reg_val & 0x40000) >> 18) ? 0 : 1; 6566 rx_ctrl->pass_pause_frames = ((reg_val & 0x1000) >> 12) ? 0 : 1; 6567 6568 return (SOC_E_NONE); 6569 } 6570 6571 int pm4x25_port_tx_average_ipg_set (int unit, int port, pm_info_t pm_info, int value) 6572 { 6573 return (clmac_tx_average_ipg_set(unit, port, value)); 6574 } 6575 6576 int pm4x25_port_tx_average_ipg_get (int unit, int port, pm_info_t pm_info, int* value) 6577 { 6578 return (clmac_tx_average_ipg_get(unit, port, value)); 6579 } 6580 6581 int pm4x25_port_update(int unit, int port, pm_info_t pm_info, const portmod_port_update_control_t* update_control) 6582 { 6583 int link, flags = 0; 6584 int duplex = 0, tx_pause = 0, rx_pause = 0; 6585 phymod_autoneg_status_t autoneg; 6586 portmod_pause_control_t pause_control; 6587 portmod_port_ability_t local_advert, remote_advert; 6588 portmod_port_interface_config_t interface_config; 6589 int port_index, ref_clock, max_speed; 6590 uint32_t bitmap; 6591 phymod_phy_inf_config_t phy_interface_config; 6592 soc_port_if_t interface = SOC_PORT_IF_NULL; 6593 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6594 int nof_phys, is_clmac_en; 6595 portmod_port_ts_adjust_t ts_adjust; 6596 pm_version_t pm_version; 6597 uint32 port_dynamic_state = 0; 6598 int mac_ts_enable; 6599 SOC_INIT_FUNC_DEFS; 6600 6601 _SOC_IF_ERR_EXIT(phymod_autoneg_status_t_init(&autoneg)); 6602 _SOC_IF_ERR_EXIT(portmod_pause_control_t_init(unit, &pause_control)); 6603 sal_memset(&local_advert, 0, sizeof(portmod_port_ability_t)); 6604 sal_memset(&remote_advert, 0, sizeof(portmod_port_ability_t)); 6605 sal_memset(&ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 6606 6607 _SOC_IF_ERR_EXIT 6608 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6609 phy_access ,(1+MAX_PHYN), 6610 &nof_phys)); 6611 6612 if(update_control->link_status == -1) { 6613 _SOC_IF_ERR_EXIT(pm4x25_port_link_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &link)); 6614 } else { 6615 link = update_control->link_status; 6616 } 6617 6618 _SOC_IF_ERR_EXIT(pm4x25_port_autoneg_status_get(unit, port, pm_info, &autoneg)); 6619 6620 /* 6621 * Update the interface type stored in the SW database when the port is in the AN mode 6622 * and link is up. The update has to be done before any possible early return in this 6623 * function or portmod_port_interface_config_get() will get outdated interface type 6624 * causing "BCM.0> ps" to show outdated interface types in the AN mode. 6625 */ 6626 if (link && autoneg.enabled && autoneg.locked) { 6627 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_interface_config)); 6628 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 6629 _SOC_IF_ERR_EXIT(PM4x25_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index)); 6630 6631 ref_clock = PM_4x25_INFO(pm_info)->ref_clk; 6632 phy_interface_config.data_rate = max_speed; 6633 phy_interface_config.ref_clock = ref_clock; 6634 _SOC_IF_ERR_EXIT 6635 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 6636 0, ref_clock, &phy_interface_config, 6637 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 6638 _SOC_IF_ERR_EXIT 6639 (portmod_intf_from_phymod_intf(unit, phy_interface_config.interface_type, &interface)); 6640 _SOC_IF_ERR_EXIT 6641 (PM4x25_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 6642 _SOC_IF_ERR_EXIT 6643 (PM4x25_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 6644 } 6645 6646 if (PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK_GET(update_control)){ 6647 /* 6648 * PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK is set for XGS devices. Since XGS devices 6649 * already update their MAC registers elsewhere, there is an early return below to 6650 * avoid redundant works. 6651 */ 6652 return (SOC_E_NONE); 6653 } 6654 6655 if(!link) { 6656 /* PHY is down. Disable the MAC. */ 6657 if (PORTMOD_PORT_UPDATE_F_DISABLE_MAC_GET(update_control)) { 6658 _SOC_IF_ERR_EXIT(clmac_enable_set(unit, port, 0, 0)); 6659 } 6660 } else { 6661 _SOC_IF_ERR_EXIT(clmac_enable_get(unit, port, 0, &is_clmac_en)); 6662 if (is_clmac_en == 0) { 6663 _SOC_IF_ERR_EXIT(clmac_enable_set(unit, port, 0, 1)); 6664 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 6665 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 0)); 6666 } 6667 } 6668 /* In case of AN - need to update MAC settings*/ 6669 if(autoneg.enabled && autoneg.locked) { 6670 _SOC_IF_ERR_EXIT(pm4x25_port_interface_config_get(unit, port, pm_info, &interface_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 6671 /* update MAC */ 6672 flags = CLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 6673 _SOC_IF_ERR_EXIT(clmac_speed_set(unit, port, flags, interface_config.speed)); 6674 6675 /*Set MAC Timestamp Delay*/ 6676 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, CLMAC_TS_DISABLEf)) { 6677 _SOC_IF_ERR_EXIT 6678 (pm4x25_port_mac_timestamp_enable_get(unit, port, pm_info, &mac_ts_enable)); 6679 } else { 6680 mac_ts_enable = 1; 6681 } 6682 if (mac_ts_enable) { 6683 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, &bitmap)); 6684 _SOC_IF_ERR_EXIT(PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, &port_dynamic_state, port_index)); 6685 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 6686 _SOC_IF_ERR_EXIT(_pm4x25_port_timestamp_adjust_wb_get(unit, port, pm_info, interface_config.speed, &ts_adjust)); 6687 _SOC_IF_ERR_EXIT(clmac_timestamp_delay_set(unit, port, ts_adjust)); 6688 } 6689 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 6690 if (!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 6691 _SOC_IF_ERR_EXIT(clmac_timestamp_byte_adjust_set(unit, port, 0, interface_config.speed)); 6692 } 6693 } 6694 6695 if(PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 6696 _SOC_IF_ERR_EXIT(pm4x25_port_soft_reset(unit, port, pm_info, 0)); 6697 } 6698 /* update pause in MAC on the base of local and remote pause ability*/ 6699 _SOC_IF_ERR_EXIT(pm4x25_port_duplex_get(unit, port, pm_info, &duplex)); 6700 _SOC_IF_ERR_EXIT(pm4x25_port_ability_advert_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_advert)); 6701 _SOC_IF_ERR_EXIT(pm4x25_port_ability_remote_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &remote_advert)); 6702 /* IEEE 802.3 Flow Control Resolution. 6703 * Please see $SDK/doc/pause-resolution.txt for more information. */ 6704 if (duplex) { 6705 tx_pause = \ 6706 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 6707 (local_advert.pause & SOC_PA_PAUSE_RX)) || \ 6708 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 6709 !(remote_advert.pause & SOC_PA_PAUSE_TX) && \ 6710 (local_advert.pause & SOC_PA_PAUSE_TX)); 6711 rx_pause = \ 6712 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 6713 (local_advert.pause & SOC_PA_PAUSE_RX)) || \ 6714 ((local_advert.pause & SOC_PA_PAUSE_RX) && \ 6715 (remote_advert.pause & SOC_PA_PAUSE_TX) && \ 6716 !(local_advert.pause & SOC_PA_PAUSE_TX)); 6717 } 6718 else { 6719 rx_pause = tx_pause = 0; 6720 } 6721 _SOC_IF_ERR_EXIT(pm4x25_port_pause_control_get(unit, port, pm_info, &pause_control)); 6722 if ((pause_control.rx_enable != rx_pause) || (pause_control.tx_enable != tx_pause)) { 6723 pause_control.rx_enable = rx_pause; 6724 pause_control.tx_enable = tx_pause; 6725 _SOC_IF_ERR_EXIT(pm4x25_port_pause_control_set(unit, port, pm_info, &pause_control)); 6726 } 6727 } 6728 _SOC_IF_ERR_EXIT(PM_DRIVER(pm_info)->f_portmod_port_lag_failover_status_toggle(unit, port, pm_info)); 6729 } 6730 6731 exit: 6732 SOC_FUNC_RETURN; 6733 } 6734 6735 int pm4x25_port_drv_name_get (int unit, int port, pm_info_t pm_info, 6736 char* buf, int len) 6737 { 6738 strncpy(buf, "PM4X25 Driver", len); 6739 return (SOC_E_NONE); 6740 } 6741 6742 int pm4x25_port_local_fault_status_clear(int unit, int port, pm_info_t pm_info) 6743 { 6744 int lcl_fault, rmt_fault; 6745 6746 SOC_IF_ERROR_RETURN (pm4x25_port_clear_rx_lss_status_get (unit, port, pm_info, &lcl_fault, &rmt_fault)); 6747 if (lcl_fault) { 6748 SOC_IF_ERROR_RETURN (pm4x25_port_clear_rx_lss_status_set(unit, port, pm_info, 0, rmt_fault)); 6749 } 6750 return (pm4x25_port_clear_rx_lss_status_set (unit, port, pm_info, 1, rmt_fault)); 6751 6752 } 6753 6754 int pm4x25_port_remote_fault_status_clear(int unit, int port, pm_info_t pm_info) 6755 { 6756 int lcl_fault, rmt_fault; 6757 6758 SOC_IF_ERROR_RETURN (pm4x25_port_clear_rx_lss_status_get (unit, port, pm_info, &lcl_fault, &rmt_fault)); 6759 if (rmt_fault) { 6760 SOC_IF_ERROR_RETURN (pm4x25_port_clear_rx_lss_status_set(unit, port, pm_info, lcl_fault, 0)); 6761 } 6762 return (pm4x25_port_clear_rx_lss_status_set (unit, port, pm_info, lcl_fault, 1)); 6763 } 6764 6765 int pm4x25_port_clear_rx_lss_status_set (int unit, soc_port_t port, 6766 pm_info_t pm_info, int lcl_fault, int rmt_fault) 6767 { 6768 return (clmac_clear_rx_lss_status_set (unit, port, lcl_fault, rmt_fault)); 6769 } 6770 6771 int pm4x25_port_clear_rx_lss_status_get (int unit, soc_port_t port, 6772 pm_info_t pm_info, int *lcl_fault, int *rmt_fault) 6773 { 6774 return (clmac_clear_rx_lss_status_get (unit, port, lcl_fault, rmt_fault)); 6775 } 6776 6777 int pm4x25_port_lag_failover_status_toggle (int unit, soc_port_t port, pm_info_t pm_info) 6778 { 6779 int phy_acc; 6780 uint32_t rval; 6781 int link = 0; 6782 soc_timeout_t to; 6783 6784 SOC_INIT_FUNC_DEFS; 6785 6786 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6787 6788 /* Link status to IPIPE is updated by H/W and driven based on both the 6789 * rising edge of CLPORT_LAG_FAILOVER_CONFIG.LINK_STATUS_UP and 6790 * actual link up status from Serdes. 6791 * In some loopback scenarios it may take longer time to see Serdes link up status. 6792 */ 6793 soc_timeout_init(&to, 10000, 0); 6794 6795 do { 6796 _SOC_IF_ERR_EXIT(pm4x25_port_mac_link_get(unit, port, pm_info, &link)); 6797 if (link) { 6798 break; 6799 } 6800 } while(!soc_timeout_check(&to)); 6801 6802 /* Toggle link_status_up bit to notify IPIPE on link up */ 6803 _SOC_IF_ERR_EXIT(READ_CLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, &rval)); 6804 soc_reg_field_set(unit, CLPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 1); 6805 _SOC_IF_ERR_EXIT(WRITE_CLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval)); 6806 soc_reg_field_set(unit, CLPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 0); 6807 _SOC_IF_ERR_EXIT(WRITE_CLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval)); 6808 6809 exit: 6810 SOC_FUNC_RETURN; 6811 } 6812 6813 int pm4x25_port_lag_failover_loopback_set (int unit, soc_port_t port, 6814 pm_info_t pm_info, int value) 6815 { 6816 return (clmac_lag_failover_loopback_set(unit, port, value)); 6817 } 6818 6819 int pm4x25_port_lag_failover_loopback_get (int unit, soc_port_t port, 6820 pm_info_t pm_info, int *value) 6821 { 6822 return(clmac_lag_failover_loopback_get(unit, port, value)); 6823 } 6824 6825 int pm4x25_port_tx_mac_sa_set(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 6826 { 6827 return (clmac_tx_mac_sa_set(unit, port, mac_addr)); 6828 } 6829 6830 int pm4x25_port_tx_mac_sa_get(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 6831 { 6832 return (clmac_tx_mac_sa_get(unit, port, mac_addr)); 6833 } 6834 6835 int pm4x25_port_rx_mac_sa_set(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 6836 { 6837 return (clmac_rx_mac_sa_set(unit, port, mac_addr)); 6838 } 6839 6840 int pm4x25_port_rx_mac_sa_get(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 6841 { 6842 return (clmac_rx_mac_sa_get(unit, port, mac_addr)); 6843 } 6844 6845 int pm4x25_port_mode_get(int unit, soc_port_t port, 6846 pm_info_t pm_info, portmod_port_mode_info_t *mode) 6847 { 6848 int port_index, rv, phy_acc; 6849 uint32 bitmap; 6850 6851 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6852 6853 /* coverity[callee_ptr_arith:FALSE] */ 6854 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 6855 if (rv) return (rv); 6856 6857 return (_clport_mode_get(unit, phy_acc, port_index, &mode->cur_mode, &mode->lanes)); 6858 } 6859 6860 static int _clport_mode_set(int unit, int phy_acc, portmod_core_port_mode_t cur_mode) 6861 { 6862 uint32_t rval; 6863 int mode; 6864 6865 SOC_INIT_FUNC_DEFS; 6866 6867 switch (cur_mode) { 6868 case portmodPortModeQuad: 6869 mode = 0; 6870 break; 6871 6872 case portmodPortModeTri012: 6873 mode = 1; 6874 break; 6875 6876 case portmodPortModeTri023: 6877 mode = 2; 6878 break; 6879 6880 case portmodPortModeDual: 6881 mode = 3; 6882 break; 6883 6884 case portmodPortModeSingle: 6885 mode = 4; 6886 break; 6887 6888 default: 6889 return SOC_E_FAIL; 6890 } 6891 6892 /* Toggle link bit to notify IPIPE on link up */ 6893 _SOC_IF_ERR_EXIT(READ_CLPORT_MODE_REGr(unit, phy_acc, &rval)); 6894 6895 soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf, mode); 6896 soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf, mode); 6897 6898 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MODE_REGr(unit, phy_acc, rval)); 6899 6900 exit: 6901 SOC_FUNC_RETURN; 6902 } 6903 6904 int pm4x25_port_mode_set(int unit, soc_port_t port, 6905 pm_info_t pm_info, const portmod_port_mode_info_t* mode) 6906 { 6907 int phy_acc; 6908 SOC_INIT_FUNC_DEFS; 6909 6910 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6911 6912 _SOC_IF_ERR_EXIT(_clport_mode_set(unit, phy_acc, mode->cur_mode)); 6913 6914 exit: 6915 SOC_FUNC_RETURN; 6916 } 6917 6918 int 6919 pm4x25_port_trunk_hwfailover_config_set(int unit, soc_port_t port, pm_info_t pm_info, int hw_count) 6920 { 6921 int old_failover_en=0, new_failover_en = 0; 6922 int old_link_status_sel=0, new_link_status_sel=0; 6923 int old_reset_flow_control=0, new_reset_flow_control = 0; 6924 int lag_failover_lpbk; 6925 6926 if (hw_count) { 6927 new_failover_en = 1; 6928 new_link_status_sel = 1; 6929 new_reset_flow_control = 1; 6930 } 6931 6932 SOC_IF_ERROR_RETURN (clmac_lag_failover_loopback_get(unit, port, &lag_failover_lpbk)); 6933 if (lag_failover_lpbk) return (SOC_E_NONE); 6934 6935 6936 SOC_IF_ERROR_RETURN (clmac_lag_failover_en_get(unit, port, &old_failover_en)); 6937 SOC_IF_ERROR_RETURN (clmac_sw_link_status_select_get (unit, port, &old_link_status_sel)); 6938 6939 if (old_failover_en != new_failover_en || 6940 old_link_status_sel != new_link_status_sel) { 6941 6942 SOC_IF_ERROR_RETURN (clmac_sw_link_status_select_set (unit, port, new_link_status_sel)); 6943 SOC_IF_ERROR_RETURN (clmac_lag_failover_en_set(unit, port, new_failover_en)); 6944 } 6945 6946 SOC_IF_ERROR_RETURN (clmac_reset_fc_timers_on_link_dn_get(unit, 6947 port, &old_reset_flow_control)); 6948 if (old_reset_flow_control != new_reset_flow_control) { 6949 SOC_IF_ERROR_RETURN (clmac_reset_fc_timers_on_link_dn_set(unit, 6950 port, new_reset_flow_control)); 6951 } 6952 6953 return 0; 6954 } 6955 6956 int 6957 pm4x25_port_trunk_hwfailover_config_get(int unit, soc_port_t port, pm_info_t pm_info, 6958 int *enable) 6959 { 6960 return (clmac_lag_failover_en_get(unit, port, enable)); 6961 } 6962 6963 6964 int 6965 pm4x25_port_trunk_hwfailover_status_get(int unit, soc_port_t port, pm_info_t pm_info, 6966 int *loopback) 6967 { 6968 return (clmac_lag_failover_loopback_get(unit, port, loopback)); 6969 } 6970 6971 int pm4x25_port_diag_ctrl(int unit, soc_port_t port, pm_info_t pm_info, 6972 uint32 inst, int op_type, int op_cmd, const void *arg) 6973 { 6974 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6975 int nof_phys; 6976 portmod_access_get_params_t params; 6977 6978 6979 SOC_IF_ERROR_RETURN(portmod_access_get_params_t_init(unit, ¶ms)); 6980 6981 if( PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_INT ) { 6982 params.phyn = 0 ; 6983 } else { /* most external is default */ 6984 params.phyn = -1 ; 6985 } 6986 6987 if( PHY_DIAG_INST_INTF(inst) == PHY_DIAG_INTF_SYS ) { 6988 params.sys_side = PORTMOD_SIDE_SYSTEM; 6989 } else { /* most external is default */ 6990 params.sys_side = PORTMOD_SIDE_LINE ; 6991 } 6992 6993 SOC_IF_ERROR_RETURN(pm4x25_port_phy_lane_access_get(unit, port, pm_info, 6994 ¶ms, 1, phy_access, &nof_phys, NULL)); 6995 6996 return (portmod_phy_port_diag_ctrl(unit, port, phy_access, nof_phys, inst, op_type, op_cmd, arg)); 6997 } 6998 6999 int 7000 pm4x25_port_ref_clk_get(int unit, soc_port_t port, pm_info_t pm_info, int *ref_clk) 7001 { 7002 *ref_clk = pm_info->pm_data.pm4x25_db->ref_clk; 7003 7004 return (SOC_E_NONE); 7005 } 7006 7007 int pm4x25_port_lag_remove_failover_lpbk_get(int unit, int port, pm_info_t pm_info, int *val) 7008 { 7009 return (clmac_lag_remove_failover_lpbk_get(unit, port, val)); 7010 } 7011 7012 int pm4x25_port_lag_remove_failover_lpbk_set(int unit, int port, pm_info_t pm_info, int val) 7013 { 7014 return (clmac_lag_remove_failover_lpbk_set(unit, port, val)); 7015 } 7016 7017 int pm4x25_port_lag_failover_disable(int unit, int port, pm_info_t pm_info) 7018 { 7019 return (clmac_lag_failover_disable(unit, port)); 7020 } 7021 7022 int pm4x25_port_mac_ctrl_set(int unit, int port, 7023 pm_info_t pm_info, uint64 ctrl) 7024 { 7025 return (clmac_mac_ctrl_set(unit, port, ctrl)); 7026 } 7027 7028 int pm4x25_port_drain_cell_get(int unit, int port, 7029 pm_info_t pm_info, portmod_drain_cells_t *drain_cells) 7030 { 7031 return (clmac_drain_cell_get(unit, port, drain_cells)); 7032 } 7033 7034 int pm4x25_port_drain_cell_stop (int unit, int port, 7035 pm_info_t pm_info, const portmod_drain_cells_t *drain_cells) 7036 { 7037 return (clmac_drain_cell_stop (unit, port, drain_cells)); 7038 7039 } 7040 7041 int pm4x25_port_drain_cell_start(int unit, int port, pm_info_t pm_info) 7042 { 7043 return (clmac_drain_cell_start(unit, port)); 7044 } 7045 7046 int pm4x25_port_txfifo_cell_cnt_get(int unit, int port, 7047 pm_info_t pm_info, uint32* fval) 7048 { 7049 return (clmac_txfifo_cell_cnt_get(unit, port, fval)); 7050 } 7051 7052 int pm4x25_port_egress_queue_drain_get(int unit, int port, 7053 pm_info_t pm_info, uint64 *ctrl, int *rx) 7054 { 7055 return (clmac_egress_queue_drain_get(unit, port, ctrl, rx)); 7056 } 7057 7058 int pm4x25_port_drain_cells_rx_enable(int unit, int port, 7059 pm_info_t pm_info, int rx_en) 7060 { 7061 return (clmac_drain_cells_rx_enable(unit, port, rx_en)); 7062 } 7063 7064 int pm4x25_port_egress_queue_drain_rx_en(int unit, int port, 7065 pm_info_t pm_info, int rx_en) 7066 { 7067 return (clmac_egress_queue_drain_rx_en(unit, port, rx_en)); 7068 } 7069 7070 int pm4x25_port_mac_reset_set(int unit, int port, 7071 pm_info_t pm_info, int val) 7072 { 7073 int rv; 7074 SOC_INIT_FUNC_DEFS; 7075 7076 /* if callback defined, go to local soft reset function */ 7077 rv = (PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) ? pm4x25_port_soft_reset(unit, port, pm_info, val) : clmac_soft_reset_set(unit, port, val); 7078 _SOC_IF_ERR_EXIT(rv); 7079 7080 exit: 7081 SOC_FUNC_RETURN; 7082 } 7083 7084 int pm4x25_port_mac_reset_get(int unit, int port, pm_info_t pm_info, int* val) 7085 { 7086 return (clmac_soft_reset_get(unit, port, val)); 7087 } 7088 7089 int pm4x25_port_mac_reset_check(int unit, int port, pm_info_t pm_info, 7090 int enable, int* reset) 7091 { 7092 return (clmac_reset_check(unit, port, enable, reset)); 7093 } 7094 7095 int pm4x25_port_core_num_get(int unit, int port, pm_info_t pm_info, 7096 int* core_num) 7097 { 7098 *core_num = PM_4x25_INFO(pm_info)->core_num; 7099 return (SOC_E_NONE); 7100 } 7101 7102 /* in_out: 1= in reset, 0= in and out of reset */ 7103 STATIC 7104 int pm4x25_port_soft_reset(int unit, int port, pm_info_t pm_info, int in_out) 7105 { 7106 int rv, rx_enable = 0; 7107 int phy_port, block, bindex, i; 7108 portmod_drain_cells_t drain_cells; 7109 uint32 cell_count; 7110 uint64 mac_ctrl; 7111 soc_timeout_t to; 7112 SOC_INIT_FUNC_DEFS; 7113 7114 /* Callback soft reset function */ 7115 if (PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 7116 rv = PM_4x25_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePre); 7117 _SOC_IF_ERR_EXIT(rv); 7118 } 7119 7120 if (in_out == 0) { 7121 rv = clmac_egress_queue_drain_get(unit, port, &mac_ctrl, &rx_enable); 7122 _SOC_IF_ERR_EXIT(rv); 7123 7124 /* Drain cells */ 7125 rv = clmac_drain_cell_get(unit, port, &drain_cells); 7126 _SOC_IF_ERR_EXIT(rv); 7127 7128 /* Start TX FIFO draining */ 7129 rv = clmac_drain_cell_start(unit, port); 7130 _SOC_IF_ERR_EXIT(rv); 7131 7132 /* De-assert SOFT_RESET to let the drain start */ 7133 rv = clmac_soft_reset_set(unit, port, 0); 7134 _SOC_IF_ERR_EXIT(rv); 7135 7136 /* Wait until TX fifo cell count is 0 */ 7137 soc_timeout_init(&to, 250000, 0); 7138 for (;;) { 7139 rv = clmac_txfifo_cell_cnt_get(unit, port, &cell_count); 7140 _SOC_IF_ERR_EXIT(rv); 7141 if (cell_count == 0) { 7142 break; 7143 } 7144 if (soc_timeout_check(&to)) { 7145 LOG_ERROR(BSL_LS_SOC_PORT,(BSL_META_UP(unit, port, "ERROR: u=%d p=%d timeout draining TX FIFO (%d cells remain)\n"), unit, port, cell_count)); 7146 return SOC_E_INTERNAL; 7147 } 7148 } 7149 7150 /* Stop TX FIFO draining */ 7151 rv = clmac_drain_cell_stop(unit, port, &drain_cells); 7152 _SOC_IF_ERR_EXIT(rv); 7153 7154 /* Reset port FIFO */ 7155 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 7156 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 7157 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 7158 if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT) || 7159 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT)) { 7160 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 7161 _SOC_IF_ERR_EXIT(PM_DRIVER(pm_info)->f_portmod_port_soft_reset_toggle(unit, port, pm_info, bindex)); 7162 break; 7163 } 7164 } 7165 } 7166 7167 /* Put port into SOFT_RESET */ 7168 rv = clmac_soft_reset_set(unit, port, 1); 7169 _SOC_IF_ERR_EXIT(rv); 7170 7171 if(in_out == 0) { 7172 7173 /* Callback soft reset function */ 7174 if (PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 7175 rv = PM_4x25_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypeDuring); 7176 _SOC_IF_ERR_EXIT(rv); 7177 soc_reg64_field32_set (unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); /*make sure restored data wont put mac back in reset*/ 7178 } 7179 7180 /* Enable TX, restore RX, de-assert SOFT_RESET */ 7181 rv = clmac_egress_queue_drain_rx_en(unit, port, rx_enable); 7182 _SOC_IF_ERR_EXIT(rv); 7183 7184 /* Restore clmac_CTRL to original value */ 7185 rv = clmac_mac_ctrl_set(unit, port, mac_ctrl); 7186 _SOC_IF_ERR_EXIT(rv); 7187 } 7188 7189 /* Callback soft reset function */ 7190 if (PM_4x25_INFO(pm_info)->portmod_mac_soft_reset) { 7191 rv = PM_4x25_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePost); 7192 _SOC_IF_ERR_EXIT(rv); 7193 } 7194 7195 exit: 7196 SOC_FUNC_RETURN; 7197 } 7198 7199 /*Port discard set*/ 7200 int pm4x25_port_discard_set(int unit, int port, pm_info_t pm_info, int discard) 7201 { 7202 return(clmac_discard_set(unit, port, discard)); 7203 } 7204 7205 /*Port soft reset set set*/ 7206 int pm4x25_port_soft_reset_set(int unit, int port, pm_info_t pm_info, int idx, 7207 int val, int flags) 7208 { 7209 return (_pm4x25_port_soft_reset_set(unit, port, pm_info, idx, val)); 7210 } 7211 7212 /*Port tx_en=0 and softreset mac*/ 7213 int pm4x25_port_tx_down(int unit, int port, pm_info_t pm_info) 7214 { 7215 SOC_INIT_FUNC_DEFS; 7216 7217 _SOC_IF_ERR_EXIT(clmac_tx_enable_set(unit, port, 0)); 7218 _SOC_IF_ERR_EXIT(clmac_discard_set(unit, port, 0)); 7219 _SOC_IF_ERR_EXIT(clmac_soft_reset_set(unit, port, 1)); 7220 7221 exit: 7222 SOC_FUNC_RETURN; 7223 } 7224 7225 int pm4x25_port_pgw_reconfig (int unit, int port, pm_info_t pm_info, 7226 const portmod_port_mode_info_t *pmode, 7227 int phy_port, int flags) 7228 { 7229 int rv, idx=0, physical_port, i; 7230 int phy_acc, block; 7231 uint32 reg_val; 7232 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 7233 7234 SOC_INIT_FUNC_DEFS; 7235 7236 physical_port = SOC_INFO(unit).port_l2p_mapping[port]; 7237 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 7238 block = SOC_PORT_IDX_BLOCK(unit, physical_port, i); 7239 if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT) || 7240 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT)) { 7241 idx = SOC_PORT_IDX_BINDEX(unit, physical_port, i); 7242 break; 7243 } 7244 } 7245 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7246 7247 /* 1.a st SOFT_RESET field in CLMAC_CTRL for new ports that use XLMAC */ 7248 rv = clmac_soft_reset_set(unit, port, 1); 7249 _SOC_IF_ERR_EXIT(rv); 7250 7251 /* 1.a set PORT[subport] field in CLPORT_SOFT_RESET for all new ports */ 7252 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 7253 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, port_fields[idx], 1); 7254 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 7255 7256 /* Port enable */ 7257 _SOC_IF_ERR_EXIT(READ_CLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 7258 soc_reg_field_set (unit, CLPORT_ENABLE_REGr, ®_val, 7259 port_fields[idx], 1); 7260 _SOC_IF_ERR_EXIT(WRITE_CLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 7261 7262 7263 /* set port mode */ 7264 7265 /* Release CLPORT SOFT RESET */ 7266 _SOC_IF_ERR_EXIT(READ_CLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 7267 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, ®_val, port_fields[idx], 0); 7268 _SOC_IF_ERR_EXIT(WRITE_CLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 7269 7270 /*Release Mac Soft Reset */ 7271 rv = clmac_soft_reset_set(unit, port, 0); 7272 _SOC_IF_ERR_EXIT(rv); 7273 7274 exit: 7275 SOC_FUNC_RETURN; 7276 } 7277 7278 /* get interrupt value. */ 7279 int pm4x25_port_interrupt_enable_get (int unit, int port, pm_info_t pm_info, 7280 int intr_type, uint32 *val) 7281 { 7282 uint32 reg_val; 7283 int phy_acc; 7284 pm_version_t pm_version; 7285 SOC_INIT_FUNC_DEFS; 7286 7287 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7288 _SOC_IF_ERR_EXIT(READ_CLPORT_INTR_ENABLEr(unit, phy_acc, ®_val)); 7289 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 7290 7291 switch(intr_type) { 7292 case portmodIntrTypeMibTxMemErr: 7293 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MIB_TX_MEM_ERRf); 7294 break; 7295 case portmodIntrTypeMibRxMemErr: 7296 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MIB_RX_MEM_ERRf); 7297 break; 7298 case portmodIntrTypeMacTxCdcMemErr: 7299 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7300 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MAC_TX_CDC_MEM_ERRf); 7301 break; 7302 } 7303 else { 7304 return SOC_E_UNAVAIL; 7305 } 7306 case portmodIntrTypeMacRxCdcMemErr: 7307 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7308 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MAC_RX_CDC_MEM_ERRf); 7309 break; 7310 } 7311 else { 7312 return SOC_E_UNAVAIL; 7313 } 7314 case portmodIntrTypeMacRxTsCdcMemErr: 7315 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7316 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MAC_RX_TS_CDC_MEM_ERRf); 7317 break; 7318 } 7319 else { 7320 return SOC_E_UNAVAIL; 7321 } 7322 case portmodIntrTypeTscErr: 7323 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, TSC_ERRf); 7324 break; 7325 case portmodIntrTypePmdErr: 7326 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, PMD_ERRf); 7327 break; 7328 case portmodIntrTypeRxFcReqFull: 7329 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, RX_FLOWCONTROL_REQ_FULLf); 7330 break; 7331 case portmodIntrTypeLinkdown: 7332 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7333 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, LINK_DOWNf); 7334 break; 7335 } 7336 else { 7337 return SOC_E_UNAVAIL; 7338 } 7339 case portmodIntrTypeMacErr: 7340 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7341 *val = soc_reg_field_get(unit, CLPORT_INTR_ENABLEr, reg_val, MAC_ERRf); 7342 break; 7343 } 7344 else { 7345 return SOC_E_UNAVAIL; 7346 } 7347 case portmodIntrTypeTxPktUnderflow : 7348 case portmodIntrTypeTxPktOverflow : 7349 case portmodIntrTypeTxLlfcMsgOverflow : 7350 case portmodIntrTypeTxTSFifoOverflow : 7351 case portmodIntrTypeRxPktOverflow : 7352 case portmodIntrTypeRxMsgOverflow : 7353 case portmodIntrTypeTxCdcSingleBitErr : 7354 case portmodIntrTypeTxCdcDoubleBitErr : 7355 case portmodIntrTypeRxCdcSingleBitErr : 7356 case portmodIntrTypeRxCdcDoubleBitErr : 7357 case portmodIntrTypeRxTsMemSingleBitErr : 7358 case portmodIntrTypeRxTsMemDoubleBitErr : 7359 case portmodIntrTypeLocalFaultStatus : 7360 case portmodIntrTypeRemoteFaultStatus : 7361 case portmodIntrTypeLinkInterruptionStatus : 7362 case portmodIntrTypeTsEntryValid : 7363 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7364 _SOC_IF_ERR_EXIT(clmac_interrupt_enable_get(unit, port, intr_type, val)); 7365 break; 7366 } 7367 else { 7368 return SOC_E_UNAVAIL; 7369 } 7370 default: 7371 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 7372 break; 7373 } 7374 7375 exit: 7376 SOC_FUNC_RETURN; 7377 } 7378 7379 /* set interrupt value. */ 7380 int pm4x25_port_interrupt_enable_set (int unit, int port, pm_info_t pm_info, 7381 int intr_type, uint32 val) 7382 { 7383 uint32 reg_val; 7384 int phy_acc; 7385 pm_version_t pm_version; 7386 SOC_INIT_FUNC_DEFS; 7387 7388 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7389 _SOC_IF_ERR_EXIT(READ_CLPORT_INTR_ENABLEr(unit, phy_acc, ®_val)); 7390 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 7391 7392 switch(intr_type) { 7393 case portmodIntrTypeMibTxMemErr: 7394 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MIB_TX_MEM_ERRf, val); 7395 break; 7396 case portmodIntrTypeMibRxMemErr: 7397 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MIB_RX_MEM_ERRf, val); 7398 break; 7399 case portmodIntrTypeMacTxCdcMemErr: 7400 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7401 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MAC_TX_CDC_MEM_ERRf, val); 7402 break; 7403 } 7404 else { 7405 return SOC_E_UNAVAIL; 7406 } 7407 case portmodIntrTypeMacRxCdcMemErr: 7408 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7409 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MAC_RX_CDC_MEM_ERRf, val); 7410 break; 7411 } 7412 else { 7413 return SOC_E_UNAVAIL; 7414 } 7415 case portmodIntrTypeMacRxTsCdcMemErr: 7416 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7417 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MAC_RX_TS_CDC_MEM_ERRf, val); 7418 break; 7419 } 7420 else { 7421 return SOC_E_UNAVAIL; 7422 } 7423 case portmodIntrTypeTscErr: 7424 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, TSC_ERRf, val); 7425 break; 7426 case portmodIntrTypePmdErr: 7427 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, PMD_ERRf, val); 7428 break; 7429 case portmodIntrTypeRxFcReqFull: 7430 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, RX_FLOWCONTROL_REQ_FULLf, val); 7431 break; 7432 case portmodIntrTypeLinkdown: 7433 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7434 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, LINK_DOWNf, val); 7435 break; 7436 } 7437 else { 7438 return SOC_E_UNAVAIL; 7439 } 7440 case portmodIntrTypeMacErr: 7441 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7442 soc_reg_field_set(unit, CLPORT_INTR_ENABLEr, ®_val, MAC_ERRf, val); 7443 break; 7444 } 7445 else { 7446 return SOC_E_UNAVAIL; 7447 } 7448 case portmodIntrTypeTxPktUnderflow : 7449 case portmodIntrTypeTxPktOverflow : 7450 case portmodIntrTypeTxLlfcMsgOverflow : 7451 case portmodIntrTypeTxTSFifoOverflow : 7452 case portmodIntrTypeRxPktOverflow : 7453 case portmodIntrTypeRxMsgOverflow : 7454 case portmodIntrTypeTxCdcSingleBitErr : 7455 case portmodIntrTypeTxCdcDoubleBitErr : 7456 case portmodIntrTypeRxCdcSingleBitErr : 7457 case portmodIntrTypeRxCdcDoubleBitErr : 7458 case portmodIntrTypeRxTsMemSingleBitErr : 7459 case portmodIntrTypeRxTsMemDoubleBitErr : 7460 case portmodIntrTypeLocalFaultStatus : 7461 case portmodIntrTypeRemoteFaultStatus : 7462 case portmodIntrTypeLinkInterruptionStatus : 7463 case portmodIntrTypeTsEntryValid : 7464 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7465 _SOC_IF_ERR_EXIT(clmac_interrupt_enable_set(unit, port, intr_type, val)); 7466 break; 7467 } 7468 else { 7469 return SOC_E_UNAVAIL; 7470 } 7471 default: 7472 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 7473 break; 7474 } 7475 _SOC_IF_ERR_EXIT(WRITE_CLPORT_INTR_ENABLEr(unit, phy_acc, reg_val)); 7476 7477 exit: 7478 SOC_FUNC_RETURN; 7479 } 7480 7481 /* get interrupt value. */ 7482 int pm4x25_port_interrupt_get (int unit, int port, pm_info_t pm_info, 7483 int intr_type, uint32* val) 7484 { 7485 uint32 reg_val; 7486 int phy_acc; 7487 pm_version_t pm_version; 7488 SOC_INIT_FUNC_DEFS; 7489 7490 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7491 _SOC_IF_ERR_EXIT(READ_CLPORT_INTR_STATUSr(unit, phy_acc, ®_val)); 7492 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 7493 7494 switch(intr_type) { 7495 case portmodIntrTypeMibTxMemErr: 7496 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MIB_TX_MEM_ERRf); 7497 break; 7498 case portmodIntrTypeMibRxMemErr: 7499 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MIB_RX_MEM_ERRf); 7500 break; 7501 case portmodIntrTypeMacTxCdcMemErr: 7502 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7503 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_TX_CDC_MEM_ERRf); 7504 break; 7505 } 7506 else { 7507 return SOC_E_UNAVAIL; 7508 } 7509 case portmodIntrTypeMacRxCdcMemErr: 7510 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7511 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_RX_CDC_MEM_ERRf); 7512 break; 7513 } 7514 else { 7515 return SOC_E_UNAVAIL; 7516 } 7517 case portmodIntrTypeMacRxTsCdcMemErr: 7518 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7519 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_RX_TS_CDC_MEM_ERRf); 7520 break; 7521 } 7522 else { 7523 return SOC_E_UNAVAIL; 7524 } 7525 case portmodIntrTypeTscErr: 7526 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, TSC_ERRf); 7527 break; 7528 case portmodIntrTypePmdErr: 7529 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, PMD_ERRf); 7530 break; 7531 case portmodIntrTypeRxFcReqFull: 7532 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, RX_FLOWCONTROL_REQ_FULLf); 7533 break; 7534 case portmodIntrTypeLinkdown: 7535 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7536 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, LINK_DOWNf); 7537 break; 7538 } 7539 else { 7540 return SOC_E_UNAVAIL; 7541 } 7542 case portmodIntrTypeMacErr: 7543 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7544 *val = soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_ERRf); 7545 break; 7546 } 7547 else { 7548 return SOC_E_UNAVAIL; 7549 } 7550 case portmodIntrTypeTxPktUnderflow : 7551 case portmodIntrTypeTxPktOverflow : 7552 case portmodIntrTypeTxLlfcMsgOverflow : 7553 case portmodIntrTypeTxTSFifoOverflow : 7554 case portmodIntrTypeRxPktOverflow : 7555 case portmodIntrTypeRxMsgOverflow : 7556 case portmodIntrTypeTxCdcSingleBitErr : 7557 case portmodIntrTypeTxCdcDoubleBitErr : 7558 case portmodIntrTypeRxCdcSingleBitErr : 7559 case portmodIntrTypeRxCdcDoubleBitErr : 7560 case portmodIntrTypeRxTsMemSingleBitErr : 7561 case portmodIntrTypeRxTsMemDoubleBitErr : 7562 case portmodIntrTypeLocalFaultStatus : 7563 case portmodIntrTypeRemoteFaultStatus : 7564 case portmodIntrTypeLinkInterruptionStatus : 7565 case portmodIntrTypeTsEntryValid : 7566 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7567 _SOC_IF_ERR_EXIT(clmac_interrupt_status_get(unit, port, intr_type, val)); 7568 break; 7569 } 7570 else { 7571 return SOC_E_UNAVAIL; 7572 } 7573 default: 7574 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 7575 break; 7576 } 7577 exit: 7578 SOC_FUNC_RETURN; 7579 } 7580 7581 int pm4x25_port_interrupts_get (int unit, int port, pm_info_t pm_info, 7582 int arr_max_size, uint32* intr_arr, uint32* size) 7583 { 7584 uint32 reg_val, cnt=0; 7585 int phy_acc; 7586 uint32 mac_intr_cnt = 0; 7587 pm_version_t pm_version; 7588 SOC_INIT_FUNC_DEFS; 7589 7590 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7591 _SOC_IF_ERR_EXIT(READ_CLPORT_INTR_STATUSr(unit, phy_acc, ®_val)); 7592 _SOC_IF_ERR_EXIT(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 7593 7594 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MIB_TX_MEM_ERRf)) { 7595 if (cnt >= arr_max_size) { 7596 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7597 } 7598 intr_arr[cnt++] = portmodIntrTypeMibTxMemErr; 7599 } 7600 7601 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MIB_RX_MEM_ERRf)) { 7602 if (cnt >= arr_max_size) { 7603 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7604 } 7605 intr_arr[cnt++] = portmodIntrTypeMibRxMemErr; 7606 } 7607 7608 if(PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7609 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_TX_CDC_MEM_ERRf)) { 7610 if (cnt >= arr_max_size) { 7611 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7612 } 7613 intr_arr[cnt++] = portmodIntrTypeMacTxCdcMemErr; 7614 } 7615 7616 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_RX_CDC_MEM_ERRf)) { 7617 if (cnt >= arr_max_size) { 7618 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7619 } 7620 intr_arr[cnt++] = portmodIntrTypeMacRxCdcMemErr; 7621 } 7622 7623 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_RX_TS_CDC_MEM_ERRf)) { 7624 if (cnt >= arr_max_size) { 7625 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7626 } 7627 intr_arr[cnt++] = portmodIntrTypeMacRxTsCdcMemErr; 7628 } 7629 } 7630 7631 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, TSC_ERRf)) { 7632 intr_arr[cnt++] = portmodIntrTypeTscErr; 7633 } 7634 7635 if (soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, RX_FLOWCONTROL_REQ_FULLf)) { 7636 if (cnt >= arr_max_size) { 7637 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7638 } 7639 intr_arr[cnt++] = portmodIntrTypeRxFcReqFull; 7640 } 7641 7642 if(!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 7643 if(soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, LINK_DOWNf)) { 7644 if (cnt >= arr_max_size) { 7645 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7646 } 7647 intr_arr[cnt++] = portmodIntrTypeLinkdown; 7648 } 7649 7650 if(soc_reg_field_get(unit, CLPORT_INTR_STATUSr, reg_val, MAC_ERRf)) { 7651 if (cnt >= arr_max_size) { 7652 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 7653 } 7654 intr_arr[cnt++] = portmodIntrTypeMacErr; 7655 } 7656 7657 _SOC_IF_ERR_EXIT(clmac_interrupts_status_get(unit, port, (arr_max_size- cnt), (intr_arr + cnt), &mac_intr_cnt)); 7658 cnt += mac_intr_cnt; 7659 } 7660 7661 *size = cnt; 7662 7663 exit: 7664 SOC_FUNC_RETURN; 7665 } 7666 7667 /*! 7668 * pm4x25_port_eee_clock_set 7669 * 7670 * @brief set EEE Config. 7671 * 7672 * @param [in] unit - unit id 7673 * @param [in] port - logical port 7674 * @param [in] eee - 7675 */ 7676 int pm4x25_port_eee_clock_set(int unit, int port, pm_info_t pm_info, 7677 const portmod_eee_clock_t* eee_clk) 7678 { 7679 int phy_acc; 7680 SOC_INIT_FUNC_DEFS; 7681 7682 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7683 7684 _SOC_IF_ERR_EXIT(WRITE_CLPORT_EEE_CLOCK_GATEr(unit, phy_acc, eee_clk->clock_gate)); 7685 _SOC_IF_ERR_EXIT(WRITE_CLPORT_EEE_CORE0_CLOCK_GATE_COUNTERr(unit, phy_acc, eee_clk->clock_count)); 7686 _SOC_IF_ERR_EXIT(WRITE_CLPORT_EEE_DURATION_TIMER_PULSEr(unit, phy_acc, eee_clk->timer_pulse)); 7687 7688 exit: 7689 SOC_FUNC_RETURN; 7690 } 7691 7692 7693 /*! 7694 * portmod_port_eee_clock_get 7695 * 7696 * @brief set EEE Config. 7697 * 7698 * @param [in] unit - unit id 7699 * @param [in] port - logical port 7700 * @param [out] eee - 7701 */ 7702 int pm4x25_port_eee_clock_get (int unit, int port, pm_info_t pm_info, 7703 portmod_eee_clock_t* eee_clk) 7704 { 7705 int phy_acc; 7706 SOC_INIT_FUNC_DEFS; 7707 7708 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7709 7710 _SOC_IF_ERR_EXIT(READ_CLPORT_EEE_CLOCK_GATEr(unit, phy_acc, &eee_clk->clock_gate)); 7711 _SOC_IF_ERR_EXIT(READ_CLPORT_EEE_CORE0_CLOCK_GATE_COUNTERr(unit, phy_acc, &eee_clk->clock_count)); 7712 _SOC_IF_ERR_EXIT(READ_CLPORT_EEE_DURATION_TIMER_PULSEr(unit, phy_acc, &eee_clk->timer_pulse)); 7713 7714 exit: 7715 SOC_FUNC_RETURN; 7716 } 7717 7718 int pm4x25_port_check_legacy_phy (int unit, int port, pm_info_t pm_info, int *legacy_phy) 7719 { 7720 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7721 int nof_phys, xphy_id, is_legacy_phy; 7722 int port_index; 7723 uint32 bitmap; 7724 7725 SOC_INIT_FUNC_DEFS; 7726 7727 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 7728 &bitmap)); 7729 7730 *legacy_phy = 0; 7731 7732 if (PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 7733 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7734 (_SOC_MSG("phy reset is not supported"))); 7735 } 7736 7737 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 7738 phy_access ,(1+MAX_PHYN), 7739 &nof_phys)); 7740 while (nof_phys > 1) { 7741 --nof_phys; 7742 xphy_id = phy_access[nof_phys].access.addr; 7743 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 7744 if (is_legacy_phy) { 7745 *legacy_phy = 1; 7746 break; 7747 } 7748 } 7749 7750 exit: 7751 SOC_FUNC_RETURN; 7752 } 7753 7754 7755 int pm4x25_port_failover_mode_set(int unit, int port, pm_info_t pm_info, phymod_failover_mode_t failover) 7756 { 7757 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7758 int nof_phys; 7759 int port_index; 7760 uint32 bitmap; 7761 7762 SOC_INIT_FUNC_DEFS; 7763 7764 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 7765 &bitmap)); 7766 7767 if (PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 7768 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7769 (_SOC_MSG("phy failover is not supported"))); 7770 } 7771 7772 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 7773 phy_access ,(1+MAX_PHYN), 7774 &nof_phys)); 7775 7776 SOC_IF_ERROR_RETURN(portmod_port_phychain_failover_mode_set(unit, phy_access, nof_phys, failover)); 7777 7778 exit: 7779 SOC_FUNC_RETURN; 7780 } 7781 7782 int pm4x25_port_failover_mode_get(int unit, int port, pm_info_t pm_info, phymod_failover_mode_t* failover) 7783 { 7784 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7785 int nof_phys; 7786 int port_index; 7787 uint32 bitmap; 7788 7789 SOC_INIT_FUNC_DEFS; 7790 7791 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get (unit, port, pm_info, &port_index, 7792 &bitmap)); 7793 7794 if (PM_4x25_INFO(pm_info)->nof_phys[port_index] == 0) { 7795 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7796 (_SOC_MSG("phy failover is not supported"))); 7797 } 7798 7799 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 7800 phy_access ,(1+MAX_PHYN), 7801 &nof_phys)); 7802 7803 SOC_IF_ERROR_RETURN(portmod_port_phychain_failover_mode_get(unit, phy_access, nof_phys, failover)); 7804 7805 exit: 7806 SOC_FUNC_RETURN; 7807 } 7808 7809 int pm4x25_port_flow_control_set (int unit, int port, pm_info_t pm_info, 7810 int merge_mode_en, int parallel_fc_en) 7811 { 7812 int phy_acc, rv; 7813 uint32 rval; 7814 7815 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7816 7817 rv = READ_CLPORT_FLOW_CONTROL_CONFIGr(unit, phy_acc, &rval); 7818 if (SOC_FAILURE(rv)) return (rv); 7819 7820 soc_reg_field_set(unit, CLPORT_FLOW_CONTROL_CONFIGr, &rval, MERGE_MODE_ENf, merge_mode_en); 7821 soc_reg_field_set(unit, CLPORT_FLOW_CONTROL_CONFIGr, &rval, PARALLEL_FC_ENf, parallel_fc_en); 7822 7823 return(WRITE_CLPORT_FLOW_CONTROL_CONFIGr(unit, phy_acc, rval)); 7824 } 7825 7826 int pm4x25_port_e2ecc_hdr_set (int unit, int port, pm_info_t pm_info, 7827 const portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr) 7828 { 7829 return (clmac_e2ecc_hdr_set (unit, port, (uint32_t *)e2ecc_hdr->words)); 7830 } 7831 7832 7833 int pm4x25_port_e2ecc_hdr_get (int unit, int port, pm_info_t pm_info, 7834 portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr) 7835 { 7836 return (clmac_e2ecc_hdr_get (unit, port, e2ecc_hdr->words)); 7837 } 7838 7839 int pm4x25_port_e2e_enable_set (int unit, int port, pm_info_t pm_info, int enable) 7840 { 7841 return (clmac_e2e_enable_set(unit, port, enable)); 7842 } 7843 7844 7845 int pm4x25_port_e2e_enable_get (int unit, int port, pm_info_t pm_info, int *enable) 7846 { 7847 return (clmac_e2e_enable_get(unit, port, enable)); 7848 } 7849 7850 int pm4x25_port_notify(int unit, int port, pm_info_t pm_info, int link) { 7851 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7852 int nof_phys; 7853 portmod_port_interface_config_t interface_config; 7854 SOC_INIT_FUNC_DEFS; 7855 7856 _SOC_IF_ERR_EXIT 7857 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7858 phy_access ,(1+MAX_PHYN), 7859 &nof_phys)); 7860 /* If nof phys > 1 change the internal phy speed based on the external 7861 link speed if the link is up*/ 7862 if (nof_phys > 1) { 7863 if (link) { 7864 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, 7865 port, 7866 &interface_config, 7867 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 7868 /* Set teh interface config to internal phy */ 7869 _SOC_IF_ERR_EXIT(portmod_port_interface_config_set(unit, 7870 port, 7871 &interface_config, 7872 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 7873 } else { 7874 /*TBD*/ 7875 } 7876 } 7877 exit: 7878 SOC_FUNC_RETURN; 7879 } 7880 7881 int pm4x25_port_mac_rsv_mask_set(int unit, int port, pm_info_t pm_info, uint32 rsv_mask) 7882 { 7883 return(WRITE_CLPORT_MAC_RSV_MASKr(unit, port, rsv_mask)); 7884 } 7885 7886 int pm4x25_port_mib_reset_toggle(int unit, int port, pm_info_t pm_info, int port_index) 7887 { 7888 uint32 reg_val[1]; 7889 int rv = 0, phy_acc; 7890 7891 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7892 7893 rv = READ_CLPORT_MIB_RESETr(unit, phy_acc, reg_val); 7894 if (SOC_FAILURE(rv)) return (rv); 7895 SHR_BITSET(reg_val, port_index); 7896 7897 rv = WRITE_CLPORT_MIB_RESETr(unit, phy_acc, *reg_val); 7898 if (SOC_FAILURE(rv)) return (rv); 7899 SHR_BITCLR(reg_val, port_index); 7900 7901 return(WRITE_CLPORT_MIB_RESETr(unit, phy_acc, *reg_val)); 7902 } 7903 7904 int pm4x25_port_warmboot_db_restore(int unit, int port, pm_info_t pm_info, 7905 const portmod_port_interface_config_t *f_intf_config, 7906 const portmod_port_init_config_t *f_init_config, 7907 const phymod_operation_mode_t phy_op_mode) 7908 { 7909 pm4x25_t pm4x25_data = NULL; 7910 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7911 phymod_phy_inf_config_t phy_intf_config; 7912 portmod_encap_t encap_mode; 7913 phymod_autoneg_control_t an; 7914 soc_port_if_t interface; 7915 int phy, nof_phys, port_index, rv = 0, flags = 0, port_num_lanes = 0, is_interface_restore = 0; 7916 uint32 bitmap, an_done, interface_modes = 0; 7917 7918 /* 7919 * if no warmboot db restore is required return 7920 */ 7921 if(PM_4x25_INFO(pm_info)->warmboot_skip_db_restore){ 7922 return SOC_E_NONE; 7923 } 7924 7925 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 7926 if (SOC_FAILURE(rv)) return (rv); 7927 7928 pm4x25_data = pm_info->pm_data.pm4x25_db; 7929 7930 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy) { 7931 pm4x25_data->first_phy = phy; 7932 break; 7933 } 7934 7935 rv = PM4x25_INTERFACE_TYPE_SET(unit, pm_info, f_intf_config->interface, port_index); 7936 if (SOC_FAILURE(rv)) return (rv); 7937 rv = PM4x25_MAX_SPEED_SET(unit, pm_info, f_intf_config->max_speed, port_index); 7938 if (SOC_FAILURE(rv)) return (rv); 7939 7940 rv = PM4x25_IS_HG_SET(unit, pm_info, f_init_config->is_hg, port_index); 7941 if (SOC_FAILURE(rv)) return (rv); 7942 rv = PM4x25_AN_MODE_SET(unit, pm_info, f_init_config->an_mode, port_index); 7943 if (SOC_FAILURE(rv)) return (rv); 7944 rv = PM4x25_FS_CL72_SET(unit, pm_info, f_init_config->fs_cl72, port_index); 7945 if (SOC_FAILURE(rv)) return (rv); 7946 rv = PM4x25_AN_CL72_SET(unit, pm_info, f_init_config->an_cl72, port_index); 7947 if (SOC_FAILURE(rv)) return (rv); 7948 rv = PM4x25_AN_FEC_SET(unit, pm_info, f_init_config->an_fec, port_index); 7949 if (SOC_FAILURE(rv)) return (rv); 7950 rv = PM4x25_AN_MASTER_LANE_SET(unit, pm_info, f_init_config->an_master_lane, port_index); 7951 if (SOC_FAILURE(rv)) return (rv); 7952 7953 rv = portmod_port_chain_phy_access_get (unit, port, pm_info, phy_access, 7954 (1+MAX_PHYN), &nof_phys); 7955 if (SOC_FAILURE(rv)) return (rv); 7956 7957 rv = portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 7958 0, phymodRefClk156Mhz, &phy_intf_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 7959 if (SOC_FAILURE(rv)) return (rv); 7960 7961 rv = PM4x25_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, port_index); 7962 if (SOC_FAILURE(rv)) return (rv); 7963 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, phy_intf_config.interface_modes, port_index); 7964 if (SOC_FAILURE(rv)) return (rv); 7965 7966 rv = portmod_port_interface_type_get (unit, port, &interface); 7967 if (SOC_FAILURE(rv)) return (rv); 7968 rv = PM4x25_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index); 7969 if (SOC_FAILURE(rv)) return (rv); 7970 7971 clmac_encap_get(unit, port, &flags, &encap_mode); 7972 if ((encap_mode == SOC_ENCAP_HIGIG2) || (encap_mode == SOC_ENCAP_HIGIG)) { 7973 rv = PM4x25_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 7974 if (SOC_FAILURE(rv)) return (rv); 7975 interface_modes |= PHYMOD_INTF_MODES_HIGIG; 7976 rv = PM4x25_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 7977 if (SOC_FAILURE(rv)) return (rv); 7978 } 7979 7980 rv = portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an, &an_done); 7981 if (SOC_FAILURE(rv)) return (rv); 7982 7983 if(an.an_mode != phymod_AN_MODE_NONE) { 7984 rv = PM4x25_AN_MODE_SET(unit, pm_info, an.an_mode, port_index); 7985 if (SOC_FAILURE(rv)) return (rv); 7986 } 7987 else { 7988 /* update an information before proceeding further */ 7989 SOC_IF_ERROR_RETURN(_pm4x25_an_mode_update (unit, port, pm_info, port_index, port_num_lanes, f_init_config->an_cl73)); 7990 } 7991 7992 return (SOC_E_NONE); 7993 } 7994 7995 int pm4x25_port_timesync_config_set(int unit, int port, pm_info_t pm_info, const portmod_phy_timesync_config_t* config) 7996 { 7997 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7998 int nof_phys; 7999 SOC_INIT_FUNC_DEFS; 8000 8001 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8002 phy_access ,(1+MAX_PHYN), 8003 &nof_phys)); 8004 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_config_set(unit, port, phy_access, 8005 nof_phys,config)); 8006 exit: 8007 SOC_FUNC_RETURN; 8008 } 8009 8010 int pm4x25_port_timesync_config_get(int unit, int port, pm_info_t pm_info, portmod_phy_timesync_config_t* config) 8011 { 8012 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8013 int nof_phys; 8014 SOC_INIT_FUNC_DEFS; 8015 8016 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8017 phy_access ,(1+MAX_PHYN), 8018 &nof_phys)); 8019 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_config_get(unit, port, phy_access, 8020 nof_phys,config)); 8021 exit: 8022 SOC_FUNC_RETURN; 8023 } 8024 8025 int pm4x25_port_timesync_enable_set(int unit, int port, pm_info_t pm_info, uint32 enable) 8026 { 8027 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8028 int nof_phys; 8029 SOC_INIT_FUNC_DEFS; 8030 8031 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8032 phy_access ,(1+MAX_PHYN), 8033 &nof_phys)); 8034 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_enable_set(unit, phy_access, 8035 nof_phys,enable)); 8036 exit: 8037 SOC_FUNC_RETURN; 8038 } 8039 8040 int pm4x25_port_timesync_enable_get(int unit, int port, pm_info_t pm_info, uint32* enable) 8041 { 8042 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8043 int nof_phys; 8044 SOC_INIT_FUNC_DEFS; 8045 8046 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8047 phy_access ,(1+MAX_PHYN), 8048 &nof_phys)); 8049 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_enable_get(unit, phy_access, 8050 nof_phys,enable)); 8051 8052 exit: 8053 SOC_FUNC_RETURN; 8054 } 8055 8056 int pm4x25_port_timesync_nco_addend_set(int unit, int port, pm_info_t pm_info, uint32 freq_step) 8057 { 8058 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8059 int nof_phys; 8060 SOC_INIT_FUNC_DEFS; 8061 8062 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8063 phy_access ,(1+MAX_PHYN), 8064 &nof_phys)); 8065 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_nco_addend_set(unit, phy_access, 8066 nof_phys,freq_step)); 8067 exit: 8068 SOC_FUNC_RETURN; 8069 } 8070 8071 int pm4x25_port_timesync_nco_addend_get(int unit, int port, pm_info_t pm_info, uint32* freq_step) 8072 { 8073 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8074 int nof_phys; 8075 SOC_INIT_FUNC_DEFS; 8076 8077 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8078 phy_access ,(1+MAX_PHYN), 8079 &nof_phys)); 8080 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_nco_addend_get(unit, phy_access, 8081 nof_phys,freq_step)); 8082 exit: 8083 SOC_FUNC_RETURN; 8084 } 8085 8086 int pm4x25_port_timesync_framesync_mode_set(int unit, int port, pm_info_t pm_info, 8087 const portmod_timesync_framesync_t* framesync) 8088 { 8089 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8090 int nof_phys; 8091 SOC_INIT_FUNC_DEFS; 8092 8093 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8094 phy_access ,(1+MAX_PHYN), 8095 &nof_phys)); 8096 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_framesync_mode_set(unit, phy_access, 8097 nof_phys,framesync)); 8098 exit: 8099 SOC_FUNC_RETURN; 8100 } 8101 8102 int pm4x25_port_timesync_framesync_mode_get(int unit, int port, pm_info_t pm_info, 8103 portmod_timesync_framesync_t* framesync) 8104 { 8105 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8106 int nof_phys; 8107 SOC_INIT_FUNC_DEFS; 8108 8109 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8110 phy_access ,(1+MAX_PHYN), 8111 &nof_phys)); 8112 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_framesync_mode_get(unit, phy_access, 8113 nof_phys,framesync)); 8114 exit: 8115 SOC_FUNC_RETURN; 8116 } 8117 8118 int pm4x25_port_timesync_local_time_set(int unit, int port, pm_info_t pm_info, const uint64 local_time) 8119 { 8120 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8121 int nof_phys; 8122 SOC_INIT_FUNC_DEFS; 8123 8124 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8125 phy_access ,(1+MAX_PHYN), 8126 &nof_phys)); 8127 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_local_time_set(unit, phy_access, 8128 nof_phys,local_time)); 8129 exit: 8130 SOC_FUNC_RETURN; 8131 } 8132 8133 8134 int pm4x25_port_timesync_local_time_get(int unit, int port, pm_info_t pm_info, uint64* local_time) 8135 { 8136 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8137 int nof_phys; 8138 SOC_INIT_FUNC_DEFS; 8139 8140 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8141 phy_access ,(1+MAX_PHYN), 8142 &nof_phys)); 8143 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_local_time_get(unit, phy_access, nof_phys, 8144 local_time)); 8145 exit: 8146 SOC_FUNC_RETURN; 8147 } 8148 8149 int pm4x25_port_timesync_load_ctrl_set(int unit, int port, pm_info_t pm_info, 8150 uint32 load_once, uint32 load_always) 8151 { 8152 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8153 int nof_phys; 8154 SOC_INIT_FUNC_DEFS; 8155 8156 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8157 phy_access ,(1+MAX_PHYN), 8158 &nof_phys)); 8159 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_load_ctrl_set(unit, phy_access, nof_phys, 8160 load_once, load_always)); 8161 exit: 8162 SOC_FUNC_RETURN; 8163 } 8164 8165 int pm4x25_port_timesync_load_ctrl_get(int unit, int port, pm_info_t pm_info, 8166 uint32* load_once, uint32* load_always) 8167 { 8168 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8169 int nof_phys; 8170 SOC_INIT_FUNC_DEFS; 8171 8172 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8173 phy_access ,(1+MAX_PHYN), 8174 &nof_phys)); 8175 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_load_ctrl_get(unit, phy_access, nof_phys, 8176 load_once, load_always)); 8177 exit: 8178 SOC_FUNC_RETURN; 8179 } 8180 8181 int pm4x25_port_timesync_tx_timestamp_offset_set(int unit, int port, pm_info_t pm_info, uint32 ts_offset) 8182 { 8183 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8184 int nof_phys; 8185 SOC_INIT_FUNC_DEFS; 8186 8187 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8188 phy_access ,(1+MAX_PHYN), 8189 &nof_phys)); 8190 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_tx_timestamp_offset_set(unit, phy_access, nof_phys, 8191 ts_offset)); 8192 exit: 8193 SOC_FUNC_RETURN; 8194 } 8195 8196 int pm4x25_port_timesync_tx_timestamp_offset_get(int unit, int port, pm_info_t pm_info, uint32* ts_offset) 8197 { 8198 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8199 int nof_phys; 8200 SOC_INIT_FUNC_DEFS; 8201 8202 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8203 phy_access ,(1+MAX_PHYN), 8204 &nof_phys)); 8205 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_tx_timestamp_offset_get(unit, phy_access, nof_phys, 8206 ts_offset)); 8207 exit: 8208 SOC_FUNC_RETURN; 8209 } 8210 8211 int pm4x25_port_timesync_rx_timestamp_offset_set(int unit, int port, pm_info_t pm_info, uint32 ts_offset) 8212 { 8213 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8214 int nof_phys; 8215 SOC_INIT_FUNC_DEFS; 8216 8217 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8218 phy_access ,(1+MAX_PHYN), 8219 &nof_phys)); 8220 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_rx_timestamp_offset_set(unit, phy_access, nof_phys, 8221 ts_offset)); 8222 exit: 8223 SOC_FUNC_RETURN; 8224 } 8225 8226 int pm4x25_port_timesync_rx_timestamp_offset_get(int unit, int port, pm_info_t pm_info, uint32* ts_offset) 8227 { 8228 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8229 int nof_phys; 8230 SOC_INIT_FUNC_DEFS; 8231 8232 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8233 phy_access ,(1+MAX_PHYN), 8234 &nof_phys)); 8235 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_rx_timestamp_offset_get(unit, phy_access, nof_phys, 8236 ts_offset)); 8237 exit: 8238 SOC_FUNC_RETURN; 8239 } 8240 8241 /* 8242 *Function: 8243 * pm4x25_port_timestamp_adjust_set 8244 * 8245 *Purpose: 8246 * It sets tsts,osts adjustment into MAC registers. 8247 */ 8248 int 8249 pm4x25_port_timestamp_adjust_set(int unit, int port, pm_info_t pm_info, 8250 const soc_port_timestamp_adjust_t *ts_adjust) 8251 { 8252 int port_index; 8253 uint32_t bitmap, port_dynamic_state; 8254 portmod_port_ts_adjust_t portmod_ts_adjust; 8255 SOC_INIT_FUNC_DEFS; 8256 8257 sal_memset(&portmod_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 8258 portmod_ts_adjust.osts_adjust = ts_adjust->osts_adjust; 8259 portmod_ts_adjust.tsts_adjust = ts_adjust->tsts_adjust; 8260 _SOC_IF_ERR_EXIT(clmac_timestamp_delay_set(unit, port, portmod_ts_adjust)); 8261 8262 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &port_index, &bitmap)); 8263 _SOC_IF_ERR_EXIT(PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, &port_dynamic_state, port_index)); 8264 PORTMOD_PORT_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED_SET(port_dynamic_state); 8265 _SOC_IF_ERR_EXIT(PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, port_dynamic_state, port_index)); 8266 8267 exit: 8268 SOC_FUNC_RETURN; 8269 } 8270 8271 /* 8272 *Function: 8273 * pm4x25_port_timestamp_adjust_get 8274 * 8275 *Purpose: 8276 * Get the tsts,osts adjustment from MAC register for current speed. 8277 */ 8278 int 8279 pm4x25_port_timestamp_adjust_get(int unit, int port, pm_info_t pm_info, 8280 soc_port_timestamp_adjust_t *ts_adjust) 8281 { 8282 portmod_port_ts_adjust_t portmod_ts_adjust; 8283 SOC_INIT_FUNC_DEFS; 8284 8285 sal_memset(&portmod_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 8286 8287 _SOC_IF_ERR_EXIT(clmac_timestamp_delay_get(unit, port, &portmod_ts_adjust)); 8288 ts_adjust->osts_adjust = portmod_ts_adjust.osts_adjust; 8289 ts_adjust->tsts_adjust = portmod_ts_adjust.tsts_adjust; 8290 8291 exit: 8292 SOC_FUNC_RETURN; 8293 } 8294 8295 int pm4x25_port_control_phy_timesync_set(int unit, int port, pm_info_t pm_info, const portmod_port_control_phy_timesync_t config, uint64 value) 8296 { 8297 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8298 int nof_phys; 8299 SOC_INIT_FUNC_DEFS; 8300 8301 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8302 phy_access ,(1+MAX_PHYN), 8303 &nof_phys)); 8304 8305 SOC_IF_ERROR_RETURN(portmod_port_phychain_control_phy_timesync_set(unit, port, phy_access, nof_phys, 8306 config, value)); 8307 8308 exit: 8309 SOC_FUNC_RETURN; 8310 } 8311 8312 int pm4x25_port_control_phy_timesync_get(int unit, int port, pm_info_t pm_info, const portmod_port_control_phy_timesync_t config, uint64* value) 8313 { 8314 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8315 int nof_phys; 8316 SOC_INIT_FUNC_DEFS; 8317 8318 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8319 phy_access ,(1+MAX_PHYN), 8320 &nof_phys)); 8321 8322 SOC_IF_ERROR_RETURN(portmod_port_phychain_control_phy_timesync_get(unit, port, phy_access, nof_phys, 8323 config, value)); 8324 8325 exit: 8326 SOC_FUNC_RETURN; 8327 } 8328 8329 int pm4x25_xphy_lane_attach_to_pm (int unit, pm_info_t pm_info, int iphy, int phyn, const portmod_xphy_lane_connection_t* lane_conn) 8330 { 8331 portmod_xphy_lane_connection_t *candidate_lane_conn = NULL; 8332 int lane_index = 0, phy_index = 0; 8333 int pm_is_active = 0, rv = 0; 8334 uint32 xphy_id; 8335 int lane_mask; 8336 uint32 active_lanes; 8337 SOC_INIT_FUNC_DEFS; 8338 8339 /* Validate parameters */ 8340 _SOC_IF_ERR_EXIT(portmod_xphy_lane_connection_t_validate(unit,lane_conn)); 8341 8342 if (MAX_PHYN <= phyn){ 8343 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid Ext PHY location."))); 8344 } 8345 /* Making sure the port macro is not active */ 8346 rv = PM4x25_IS_ACTIVE_GET(unit, pm_info,&pm_is_active); 8347 _SOC_IF_ERR_EXIT(rv); 8348 8349 /* Attaching the external phy to the phy chain of the port macro */ 8350 8351 /* find lane index corresponding to internal physical port */ 8352 lane_index = 0; 8353 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy_index) { 8354 if (phy_index == iphy) { 8355 break; 8356 } 8357 lane_index++; 8358 } 8359 8360 candidate_lane_conn = &(PM_4x25_INFO(pm_info)->lane_conn[phyn-1][lane_index]); 8361 sal_memcpy(candidate_lane_conn, lane_conn, sizeof(portmod_xphy_lane_connection_t)); 8362 rv = PM4x25_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, candidate_lane_conn, phyn-1, lane_index); 8363 _SOC_IF_ERR_EXIT(rv); 8364 8365 xphy_id = candidate_lane_conn->xphy_id; 8366 lane_mask = candidate_lane_conn->ss_lane_mask; 8367 8368 /* 8369 * Keeping track of the xphy lane usage. If the xphy lane is connected 8370 * it will set the corresponding bit to mark as lane is active. 8371 */ 8372 8373 if ((lane_mask != -1) && (xphy_id != PORTMOD_XPHY_ID_INVALID)) { 8374 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_get(unit, xphy_id, &active_lanes)); 8375 active_lanes |= lane_mask; 8376 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_set(unit,xphy_id, active_lanes)); 8377 } 8378 8379 /* increment the nof_phys for that lane */ 8380 if (PM_4x25_INFO(pm_info)->nof_phys[lane_index] <= phyn){ 8381 PM_4x25_INFO(pm_info)->nof_phys[lane_index] = phyn+1; 8382 rv = PM4x25_PORT_NUM_PHYS_SET(unit, pm_info, PM_4x25_INFO(pm_info)->nof_phys[lane_index], lane_index); 8383 _SOC_IF_ERR_EXIT(rv); 8384 } 8385 8386 exit: 8387 SOC_FUNC_RETURN; 8388 } 8389 8390 int pm4x25_xphy_lane_detach_from_pm (int unit, pm_info_t pm_info, int iphy, int phyn, portmod_xphy_lane_connection_t* lane_conn) 8391 { 8392 8393 portmod_xphy_lane_connection_t *candidate_lane_conn = NULL; 8394 int lane_index = 0, phy_index = 0; 8395 int pm_is_active = 0, rv = 0; 8396 uint32 xphy_id; 8397 int lane_mask; 8398 uint32 active_lanes; 8399 SOC_INIT_FUNC_DEFS; 8400 8401 if (MAX_PHYN <= phyn){ 8402 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid Ext PHY location."))); 8403 } 8404 /* Making sure the port macro is not active */ 8405 rv = PM4x25_IS_ACTIVE_GET(unit, pm_info,&pm_is_active); 8406 _SOC_IF_ERR_EXIT(rv); 8407 8408 /* Attaching the external phy to the phy chain of the port macro */ 8409 8410 /* find lane index corresponding to internal physical port */ 8411 lane_index = 0; 8412 PORTMOD_PBMP_ITER(PM_4x25_INFO(pm_info)->phys, phy_index) { 8413 if (phy_index == iphy) { 8414 break; 8415 } 8416 lane_index++; 8417 } 8418 8419 candidate_lane_conn = &(PM_4x25_INFO(pm_info)->lane_conn[phyn-1][lane_index]); 8420 8421 xphy_id = candidate_lane_conn->xphy_id; 8422 lane_mask = candidate_lane_conn->ss_lane_mask; 8423 8424 /* 8425 * Keeping track of the xphy lane usage. If the xphy lane is disconnected 8426 * it will clear the corresponding bit to mark as lane is not active. 8427 * When none of the lane are active, it clear intialization status, 8428 * phy_type and probe status. When it probe again, it will re-initialize 8429 * this xphy again. 8430 */ 8431 8432 if ((lane_mask != -1) && (xphy_id != PORTMOD_XPHY_ID_INVALID)) { 8433 8434 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_get(unit, xphy_id, &active_lanes)); 8435 active_lanes &= ~lane_mask; 8436 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_set(unit, xphy_id, active_lanes)); 8437 8438 if (active_lanes == 0) { /* none of the lanes are active */ 8439 _SOC_IF_ERR_EXIT(portmod_xphy_core_probed_set(unit, xphy_id, 0)); 8440 _SOC_IF_ERR_EXIT(portmod_xphy_phy_type_set(unit,xphy_id, 8441 phymodDispatchTypeInvalid)); 8442 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_set(unit, xphy_id,0)); 8443 } 8444 } 8445 8446 sal_memcpy( lane_conn, candidate_lane_conn, sizeof(portmod_xphy_lane_connection_t)); 8447 portmod_xphy_lane_connection_t_init(unit, candidate_lane_conn); 8448 rv = PM4x25_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, candidate_lane_conn, phyn-1, lane_index); 8449 _SOC_IF_ERR_EXIT(rv); 8450 8451 /* decrement the nof_phys for that lane */ 8452 if (phyn > 0){ 8453 PM_4x25_INFO(pm_info)->nof_phys[lane_index] = phyn; 8454 rv = PM4x25_PORT_NUM_PHYS_SET(unit, pm_info, PM_4x25_INFO(pm_info)->nof_phys[lane_index], lane_index); 8455 _SOC_IF_ERR_EXIT(rv); 8456 } 8457 8458 exit: 8459 SOC_FUNC_RETURN; 8460 } 8461 8462 int pm4x25_port_update_dynamic_state(int unit, int port, pm_info_t pm_info, uint32_t port_dynamic_state) { 8463 int rv = 0; 8464 int port_index; 8465 uint32_t bitmap; 8466 phymod_an_mode_type_t an_mode; 8467 uint32_t an_updated = FALSE, tmp_state; 8468 SOC_INIT_FUNC_DEFS; 8469 8470 rv = _pm4x25_port_index_get (unit, port, pm_info, &port_index, &bitmap); 8471 if (SOC_FAILURE(rv)) { 8472 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Unable to retrieve the port index"))); 8473 } 8474 8475 if (PORTMOD_PORT_IS_AUTONEG_MODE_UPDATED(port_dynamic_state)) { 8476 rv = PM4x25_PORT_DYNAMIC_STATE_GET(unit, pm_info, &tmp_state, 8477 port_index); 8478 _SOC_IF_ERR_EXIT(rv); 8479 /* we need to change the data base An_mode based on the new value */ 8480 switch (port_dynamic_state >> 16 & 0xffff) { 8481 case SOC_PHY_CONTROL_AUTONEG_MODE_CL37: 8482 an_mode = phymod_AN_MODE_CL37; 8483 an_updated = TRUE; 8484 break; 8485 case SOC_PHY_CONTROL_AUTONEG_MODE_CL37_BAM: 8486 an_mode = phymod_AN_MODE_CL37BAM; 8487 an_updated = TRUE; 8488 break; 8489 case SOC_PHY_CONTROL_AUTONEG_MODE_CL73: 8490 an_mode = phymod_AN_MODE_CL73; 8491 an_updated = TRUE; 8492 break; 8493 case SOC_PHY_CONTROL_AUTONEG_MODE_CL73_BAM: 8494 an_mode = phymod_AN_MODE_CL73BAM; 8495 an_updated = TRUE; 8496 break; 8497 default: 8498 break; 8499 } 8500 } else if (PORTMOD_PORT_IS_DEFAULT_TX_PARAMS_UPDATED(port_dynamic_state)) { 8501 rv = PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, 8502 port_dynamic_state, port_index); 8503 _SOC_IF_ERR_EXIT(rv); 8504 } 8505 if (an_updated == TRUE) { 8506 rv = PM4x25_AN_MODE_SET(unit, pm_info, an_mode, port_index); 8507 _SOC_IF_ERR_EXIT(rv); 8508 PORTMOD_PORT_AUTONEG_MODE_UPDATED_SET(tmp_state); 8509 rv = PM4x25_PORT_DYNAMIC_STATE_SET(unit, pm_info, tmp_state, 8510 port_index); 8511 _SOC_IF_ERR_EXIT(rv); 8512 } 8513 8514 exit: 8515 SOC_FUNC_RETURN; 8516 } 8517 8518 int pm4x25_port_phy_op_mode_get(int unit, int port, pm_info_t pm_info, phymod_operation_mode_t* val) 8519 { 8520 /* there is no opmode config for internal PHYS return 0*/ 8521 *val = 0; 8522 return (SOC_E_NONE); 8523 } 8524 8525 int pm4x25_port_medium_config_set(int unit, int port, pm_info_t pm_info, soc_port_medium_t medium, soc_phy_config_t* config) 8526 { 8527 int rv; 8528 SOC_INIT_FUNC_DEFS; 8529 8530 rv = portmod_port_phychain_medium_config_set(unit, port, medium, config); 8531 if (SOC_FAILURE(rv)) return (rv); 8532 8533 SOC_FUNC_RETURN; 8534 } 8535 8536 int pm4x25_port_medium_config_get(int unit, int port, pm_info_t pm_info, soc_port_medium_t medium, soc_phy_config_t* config) 8537 { 8538 int rv; 8539 SOC_INIT_FUNC_DEFS; 8540 8541 rv = portmod_port_phychain_medium_config_get(unit, port, medium, config); 8542 if (SOC_FAILURE(rv)) return (rv); 8543 8544 SOC_FUNC_RETURN; 8545 } 8546 8547 int pm4x25_port_medium_get(int unit, int port, pm_info_t pm_info, soc_port_medium_t* medium) 8548 { 8549 int rv; 8550 SOC_INIT_FUNC_DEFS; 8551 8552 rv = portmod_port_phychain_medium_get(unit, port, medium); 8553 8554 if (SOC_FAILURE(rv)) return (rv); 8555 8556 SOC_FUNC_RETURN; 8557 } 8558 8559 int pm4x25_port_multi_get(int unit, int port, pm_info_t pm_info, portmod_multi_get_t* multi_get) 8560 { 8561 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8562 int nof_phys; 8563 SOC_INIT_FUNC_DEFS; 8564 8565 _SOC_IF_ERR_EXIT 8566 (portmod_port_chain_phy_access_get(unit, port, pm_info, 8567 phy_access ,(1+MAX_PHYN), 8568 &nof_phys)); 8569 _SOC_IF_ERR_EXIT 8570 (portmod_port_phychain_multi_get(unit, port, phy_access, nof_phys, multi_get)); 8571 8572 exit: 8573 SOC_FUNC_RETURN; 8574 8575 } 8576 8577 int pm4x25_port_lane_map_set(int unit, int port, pm_info_t pm_info, uint32 flags, const phymod_lane_map_t* lane_map) 8578 { 8579 SOC_INIT_FUNC_DEFS; 8580 8581 PM_4x25_INFO(pm_info)->lane_map = *lane_map; 8582 8583 8584 SOC_FUNC_RETURN; 8585 } 8586 8587 int pm4x25_port_lane_map_get(int unit, int port, pm_info_t pm_info, uint32 flags, phymod_lane_map_t* lane_map) 8588 { 8589 SOC_INIT_FUNC_DEFS; 8590 8591 *lane_map = PM_4x25_INFO(pm_info)->lane_map; 8592 8593 8594 SOC_FUNC_RETURN; 8595 } 8596 8597 int pm4x25_port_polarity_set(int unit, int port, pm_info_t pm_info, const phymod_polarity_t* polarity) 8598 { 8599 SOC_INIT_FUNC_DEFS; 8600 8601 PM_4x25_INFO(pm_info)->polarity = *polarity; 8602 8603 8604 SOC_FUNC_RETURN; 8605 } 8606 8607 int pm4x25_port_polarity_get(int unit, int port, pm_info_t pm_info, phymod_polarity_t* polarity) 8608 { 8609 SOC_INIT_FUNC_DEFS; 8610 8611 *polarity = PM_4x25_INFO(pm_info)->polarity; 8612 8613 8614 SOC_FUNC_RETURN; 8615 } 8616 8617 int pm4x25_pm_is_in_pm12x10(int unit, pm_info_t pm_info, int* in_pm12x10) 8618 { 8619 SOC_INIT_FUNC_DEFS; 8620 8621 if (PM_4x25_INFO(pm_info)->in_pm12x10){ 8622 *in_pm12x10 = 1; 8623 } else { 8624 *in_pm12x10 = 0; 8625 } 8626 8627 SOC_FUNC_RETURN; 8628 } 8629 8630 /* 8631 * This function will be called during speed change or flexport. 8632 * This function returns pll_div value by looking up the static table. 8633 * In flexport scenario, this funciton might be called before port is attached. The port number may be invalid(-1). 8634 * So this function can't access registers by logical port number, or access Warmboot DB. 8635 */ 8636 int pm4x25_port_pll_div_get(int unit, int port, pm_info_t pm_info, 8637 const portmod_port_resources_t* port_resource, 8638 uint32_t* pll_div) 8639 { 8640 int higig = SOC_ENCAP_IEEE; 8641 8642 SOC_INIT_FUNC_DEFS; 8643 8644 higig = ((port_resource->encap_mode == SOC_ENCAP_HIGIG2) || 8645 (port_resource->encap_mode == SOC_ENCAP_HIGIG)) ? 1 : 0; 8646 8647 switch (port_resource->speed){ 8648 case 1000: 8649 if (PORTMOD_SERDES_1000X_AT_25G_GET(port_resource->flag)) { 8650 *pll_div = phymod_TSCF_PLL_DIV165; 8651 } else { 8652 *pll_div = phymod_TSCF_PLL_DIV132; 8653 } 8654 break; 8655 case 10000: 8656 if (PORTMOD_SERDES_10G_AT_25G_GET(port_resource->flag)) { 8657 *pll_div = phymod_TSCF_PLL_DIV165; 8658 } else { 8659 *pll_div = phymod_TSCF_PLL_DIV132; 8660 } 8661 break; 8662 case 11000: 8663 *pll_div = phymod_TSCF_PLL_DIV140; 8664 break; 8665 case 12000: 8666 *pll_div = phymod_TSCF_PLL_DIV160; 8667 break; 8668 case 20000: 8669 *pll_div = phymod_TSCF_PLL_DIV132; 8670 break; 8671 case 21000: 8672 case 21200: 8673 *pll_div = phymod_TSCF_PLL_DIV140; 8674 break; 8675 case 25000: 8676 *pll_div = phymod_TSCF_PLL_DIV165; 8677 break; 8678 case 27000: 8679 *pll_div = phymod_TSCF_PLL_DIV175; 8680 break; 8681 case 40000: 8682 *pll_div = phymod_TSCF_PLL_DIV132; 8683 break; 8684 case 42000: 8685 *pll_div = phymod_TSCF_PLL_DIV140; 8686 break; 8687 case 48000: 8688 *pll_div = phymod_TSCF_PLL_DIV160; 8689 break; 8690 case 50000: 8691 *pll_div = phymod_TSCF_PLL_DIV165; 8692 break; 8693 case 53000: 8694 if (port_resource->num_lane == 2) { 8695 *pll_div = phymod_TSCF_PLL_DIV175; 8696 } else { 8697 *pll_div = phymod_TSCF_PLL_DIV165; 8698 } 8699 break; 8700 case 100000: 8701 if (higig){ 8702 *pll_div = phymod_TSCF_PLL_DIV160; 8703 } else { 8704 *pll_div = phymod_TSCF_PLL_DIV165; 8705 } 8706 break; 8707 case 106000: 8708 *pll_div = phymod_TSCF_PLL_DIV175; 8709 break; 8710 default: 8711 *pll_div = phymod_TSCF_PLL_DIV175; 8712 break; 8713 } 8714 8715 SOC_FUNC_RETURN; 8716 } 8717 8718 int pm4x25_port_master_set(int unit, int port, pm_info_t pm_info, int master_mode) 8719 { 8720 SOC_INIT_FUNC_DEFS; 8721 8722 _SOC_IF_ERR_EXIT(portmod_port_phychain_master_set(unit, port, pm_info, master_mode)); 8723 8724 exit: 8725 SOC_FUNC_RETURN; 8726 } 8727 8728 int pm4x25_port_master_get(int unit, int port, pm_info_t pm_info, int* master_mode) 8729 { 8730 SOC_INIT_FUNC_DEFS; 8731 8732 _SOC_IF_ERR_EXIT(portmod_port_phychain_master_get(unit, port, pm_info, master_mode)); 8733 8734 exit: 8735 SOC_FUNC_RETURN; 8736 } 8737 8738 /* 8739 * Function: 8740 * _pm4x25_preemption_rx_frag_size_set 8741 * Purpose: 8742 * This function configures preemption rx fragment size 8743 * of final and non-final fragments. 8744 * 8745 * Parameters: 8746 * unit -(IN) Device unit number 8747 * port -(IN) logical port 8748 * final_frag -(IN) if set indicates final fragment 8749 * value -(IN) value of fragment size 8750 */ 8751 STATIC 8752 int _pm4x25_preemption_rx_frag_size_set(int unit, int port, pm_info_t pm_info, 8753 uint32 frag, uint32 value) 8754 { 8755 int phy_acc; 8756 uint32_t rval; 8757 soc_field_t field; 8758 SOC_INIT_FUNC_DEFS; 8759 8760 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8761 8762 _SOC_IF_ERR_EXIT(READ_CLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, &rval)); 8763 8764 if (frag == PORTMOD_PREEMPTION_FINAL_FRAG) { 8765 field = MIN_FINAL_FRAG_SIZEf; 8766 } else { 8767 field = MIN_NON_FINAL_FRAG_SIZEf; 8768 } 8769 8770 soc_reg_field_set(unit, CLPORT_MIB_MIN_FRAG_SIZEr, &rval, field, value); 8771 _SOC_IF_ERR_EXIT(WRITE_CLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, rval)); 8772 8773 exit: 8774 SOC_FUNC_RETURN; 8775 8776 } 8777 8778 /* 8779 * Function: 8780 * _pm4x25_preemption_rx_frag_size_get 8781 * Purpose: 8782 * This function configures preemption rx fragment size 8783 * of final and non-final fragments. 8784 * 8785 * Parameters: 8786 * unit -(IN) Device unit number 8787 * port -(IN) logical port 8788 * final_frag -(IN) if set indicates final fragment 8789 * value -(OUT) value of fragment size 8790 */ 8791 STATIC 8792 int _pm4x25_preemption_rx_frag_size_get(int unit, int port, pm_info_t pm_info, 8793 uint32 frag, uint32 *value) 8794 { 8795 int phy_acc; 8796 uint32_t rval; 8797 soc_field_t field; 8798 SOC_INIT_FUNC_DEFS; 8799 8800 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8801 8802 _SOC_IF_ERR_EXIT(READ_CLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, &rval)); 8803 8804 if (frag == PORTMOD_PREEMPTION_FINAL_FRAG) { 8805 field = MIN_FINAL_FRAG_SIZEf; 8806 } else { 8807 field = MIN_NON_FINAL_FRAG_SIZEf; 8808 } 8809 8810 *value = soc_reg_field_get(unit, CLPORT_MIB_MIN_FRAG_SIZEr, rval, field); 8811 8812 exit: 8813 SOC_FUNC_RETURN; 8814 8815 } 8816 8817 /* 8818 * Function: 8819 * pm4x25_preemption_control_set 8820 * Purpose: 8821 * This function configures preemption feature parameters 8822 * The application layer has to call this function with 8823 * associated preemption-controls to configure parameters. 8824 * Parameters: 8825 * unit -(IN) Device unit number 8826 * port -(IN) logical port 8827 * type -(IN) preemption parameter to be configured 8828 * value -(IN) value 8829 * Returns: 8830 * Status 8831 */ 8832 int pm4x25_preemption_control_set(int unit, int port, pm_info_t pm_info, 8833 portmod_preemption_control_t type, 8834 uint32 value) 8835 { 8836 SOC_INIT_FUNC_DEFS; 8837 8838 switch(type) { 8839 case portmodPreemptionControlInvalid: 8840 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 8841 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 8842 break; 8843 case portmodPreemptionControlPreemptionSupport: 8844 /* Enable/disable port preemption capability support */ 8845 _SOC_IF_ERR_EXIT(clmac_preemption_mode_set(unit, port, value)); 8846 break; 8847 case portmodPreemptionControlEnableTx: 8848 /* 8849 * Enable/disable port preemption on tx side 8850 * if verify_enable = 1 8851 * this function call blocks until, verify operation is complete 8852 * if verify_enable = 0 8853 * means static preemption, function call returns immediately 8854 * after enabling preemption in the hardware in tx direction 8855 */ 8856 _SOC_IF_ERR_EXIT(clmac_preemption_tx_enable_set(unit, port, value)); 8857 break; 8858 case portmodPreemptionControlVerifyEnable: 8859 /* 8860 * Enable/disable verify operation. 8861 * Before enabling the verify operation on a port, 8862 * the number of attempts for a veriy operation and 8863 * the timeout for each verify operation should be configured 8864 */ 8865 _SOC_IF_ERR_EXIT( 8866 clmac_preemption_verify_enable_set(unit, port, value)); 8867 break; 8868 case portmodPreemptionControlVerifyTime: 8869 /* 8870 * Configuring the verify timeout is valid only when verify 8871 * operation is enabled. 8872 * The timeout here means, if verify operation is not complete 8873 * success/failure/inprogress after the (timeout + 1) millisecs 8874 * the MAC sends another verify message to the link partner 8875 */ 8876 _SOC_IF_ERR_EXIT( 8877 clmac_preemption_verify_time_set(unit, port, value)); 8878 break; 8879 case portmodPreemptionControlVerifyAttempts: 8880 /* 8881 * Configuring the number of verify attempts is valid only when 8882 * verify operation is enabled. 8883 * If verify operation is not complete success/failure/inprogress 8884 * after the (timeout + 1) millisecs the MAC sends another verify 8885 * to the link partner. The MAC tries for (num_verify_attempts + 1) 8886 * to complete the verify operation. 8887 */ 8888 _SOC_IF_ERR_EXIT( 8889 clmac_preemption_verify_attempts_set(unit, port, value)); 8890 break; 8891 case portmodPreemptionControlNonFinalFragSizeRx: 8892 /* configure non-final rx fragment size */ 8893 _SOC_IF_ERR_EXIT( 8894 _pm4x25_preemption_rx_frag_size_set(unit, port, pm_info, 8895 PORTMOD_PREEMPTION_NON_FINAL_FRAG, 8896 value)); 8897 break; 8898 case portmodPreemptionControlFinalFragSizeRx: 8899 /* configure final rx fragment size */ 8900 _SOC_IF_ERR_EXIT( 8901 _pm4x25_preemption_rx_frag_size_set(unit, port, pm_info, 8902 PORTMOD_PREEMPTION_FINAL_FRAG, 8903 value)); 8904 break; 8905 default: 8906 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 8907 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 8908 break; 8909 } 8910 8911 exit: 8912 SOC_FUNC_RETURN; 8913 8914 } 8915 8916 /* 8917 * Function: 8918 * pm4x25_preemption_control_get 8919 * Purpose: 8920 * This function gets the value of preemption parameters 8921 * configured. The application layer has to call this function with 8922 * associated preemption-controls to configure parameters. 8923 * Parameters: 8924 * unit -(IN) Device unit number 8925 * port -(IN) logical port 8926 * type -(IN) preemption parameter to be configured 8927 * value -(OUT) value returned from hardware 8928 * Returns: 8929 * Status 8930 */ 8931 int pm4x25_preemption_control_get(int unit, int port, pm_info_t pm_info, 8932 portmod_preemption_control_t type, 8933 uint32 *value) 8934 { 8935 SOC_INIT_FUNC_DEFS; 8936 8937 switch(type) { 8938 case portmodPreemptionControlInvalid: 8939 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 8940 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 8941 break; 8942 case portmodPreemptionControlPreemptionSupport: 8943 _SOC_IF_ERR_EXIT(clmac_preemption_mode_get(unit, port, value)); 8944 break; 8945 case portmodPreemptionControlEnableTx: 8946 _SOC_IF_ERR_EXIT(clmac_preemption_tx_enable_get(unit, port, value)); 8947 break; 8948 case portmodPreemptionControlVerifyEnable: 8949 _SOC_IF_ERR_EXIT( 8950 clmac_preemption_verify_enable_get(unit, port, value)); 8951 break; 8952 case portmodPreemptionControlVerifyTime: 8953 _SOC_IF_ERR_EXIT( 8954 clmac_preemption_verify_time_get(unit, port, value)); 8955 break; 8956 case portmodPreemptionControlVerifyAttempts: 8957 _SOC_IF_ERR_EXIT( 8958 clmac_preemption_verify_attempts_get(unit, port, value)); 8959 break; 8960 case portmodPreemptionControlNonFinalFragSizeRx: 8961 /* get non-final rx fragment size */ 8962 _SOC_IF_ERR_EXIT( 8963 _pm4x25_preemption_rx_frag_size_get(unit, port, pm_info, 8964 PORTMOD_PREEMPTION_NON_FINAL_FRAG, 8965 value)); 8966 break; 8967 case portmodPreemptionControlFinalFragSizeRx: 8968 /* get final rx fragment size */ 8969 _SOC_IF_ERR_EXIT( 8970 _pm4x25_preemption_rx_frag_size_get(unit, port, pm_info, 8971 PORTMOD_PREEMPTION_FINAL_FRAG, 8972 value)); 8973 break; 8974 default: 8975 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 8976 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 8977 break; 8978 } 8979 8980 exit: 8981 SOC_FUNC_RETURN; 8982 } 8983 8984 /*! 8985 * pm4x25_preemption_tx_status_get 8986 * 8987 * @brief Get the preemption status on the transmit side Indicates if 8988 * preemption on a port is 8989 * Inactive: (Verifiy is enabled but its status is either failed 8990 * or not initiated) or (preemption is not enabled) 8991 * Verify in progress: Preemption is enabled and Verify is 8992 * enabled and its operation is in progress 8993 * Active: Preemption is enabled and ((Verify is enabled and 8994 * succeeded) or (Verify is NOT enabled)) 8995 * 8996 * @param [in] unit - unit id 8997 * @param [in] port - logical port 8998 * @param [out] value - indicates preemption status in tx direction. 8999 */ 9000 int pm4x25_preemption_tx_status_get(int unit, int port, 9001 pm_info_t pm_info, 9002 uint32* value) 9003 { 9004 return (clmac_preemption_tx_status_get(unit, port, 9005 CLMAC_PREEMPTION_TX_STATUS, 9006 value)); 9007 } 9008 9009 /*! 9010 * pm4x25_preemption_verify_status_get 9011 * 9012 * @brief Get the preemption verify status. 9013 * This function gets verify operation status or verify count 9014 * status based on the verify status type argument. 9015 * 9016 * @param [in] unit - unit id 9017 * @param [in] port - logical port 9018 * @param [in] type - portmod_preemption_verify_status_type_t 9019 * @param [out] value - indicates preemption verify op status 9020 */ 9021 int pm4x25_preemption_verify_status_get(int unit, int port, 9022 pm_info_t pm_info, 9023 portmod_preemption_verify_status_type_t type, 9024 uint32* value) 9025 { 9026 SOC_INIT_FUNC_DEFS; 9027 9028 switch (type) { 9029 case portmodPreemptionVerifyStatus: 9030 _SOC_IF_ERR_EXIT(clmac_preemption_tx_status_get(unit, port, 9031 CLMAC_PREEMPTION_VERIFY_STATUS, 9032 value)); 9033 break; 9034 case portmodPreemptionVerifyCountStatus: 9035 _SOC_IF_ERR_EXIT(clmac_preemption_tx_status_get(unit, port, 9036 CLMAC_PREEMPTION_VERIFY_CNT_STATUS, 9037 value)); 9038 break; 9039 default: 9040 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 9041 (_SOC_MSG("Invalid verify status type(%d)"), type)); 9042 break; 9043 } 9044 9045 exit: 9046 SOC_FUNC_RETURN; 9047 } 9048 9049 /*! 9050 * portmod_preemption_force_rx_eop_mode_set 9051 * 9052 * @brief Set preemption forced rx lost eop(end of packet) sequence mode 9053 * setting. The rx lost eop sequence can be either software or hardware 9054 * enforced. 9055 * If HW based rx lost eop is enabled, link down or rx disable even 9056 * forces rx_lost_eop sequence after some internal delay if preempt 9057 * packet EOP was not sent. 9058 * If Sw based rx lost eop is enabled, the application rx eop sequence 9059 * When SW rx lost EOP is enabled(done by application layer), rising 9060 * edge MAC forces rx_lost_eop sequence after some internal delay if 9061 * preempt packet EOP was not sent. 9062 * 9063 * @param [in] unit - unit id 9064 * @param [in] port - logical port 9065 * @param [in] enable - enable/disable 9066 * @param [in] timeout_cnt - timeout in millisecs 9067 */ 9068 int pm4x25_preemption_force_rx_eop_mode_set(int unit, int port, 9069 pm_info_t pm_info, 9070 portmod_preemption_force_rx_eop_mode_t type, 9071 uint32 value) 9072 { 9073 SOC_INIT_FUNC_DEFS; 9074 9075 switch (type) { 9076 case portmodPreemptionForceSwRxEop: 9077 _SOC_IF_ERR_EXIT(clmac_preemption_force_rx_lost_eop_set(unit, port, 9078 CLMAC_PREEMPTION_FORCE_SW_RX_EOP, 9079 value)); 9080 break; 9081 case portmodPreemptionForceAutoHwEop: 9082 _SOC_IF_ERR_EXIT(clmac_preemption_force_rx_lost_eop_set(unit, port, 9083 CLMAC_PREEMPTION_FORCE_AUTO_HW_RX_EOP, 9084 value)); 9085 break; 9086 default: 9087 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 9088 (_SOC_MSG("Invalid Force RX lost EOP type(%d)"), type)); 9089 break; 9090 } 9091 9092 exit: 9093 SOC_FUNC_RETURN; 9094 } 9095 9096 /*! 9097 * pm4x25_preemption_force_rx_eop_mode_get 9098 * 9099 * @brief Get preemption forced rx lost eop(end of packet) sequence mode 9100 * setting. The rx lost eop sequence can be either software or hardware 9101 * enforced. 9102 * This functin returns the rx lost eop setting based on the type 9103 * of lost eop is enforced. 9104 * 9105 * 9106 * @param [in] unit - unit id 9107 * @param [in] port - logical port 9108 * @param [out] type - portmod_preemption_force_rx_eop_mode_t 9109 * @param [out] value - timeout in millisecs 9110 */ 9111 int pm4x25_preemption_force_rx_eop_mode_get(int unit, int port, 9112 pm_info_t pm_info, 9113 portmod_preemption_force_rx_eop_mode_t type, 9114 uint32 *value) 9115 { 9116 SOC_INIT_FUNC_DEFS; 9117 9118 switch (type) { 9119 case portmodPreemptionForceSwRxEop: 9120 _SOC_IF_ERR_EXIT(clmac_preemption_force_rx_lost_eop_get(unit, port, 9121 CLMAC_PREEMPTION_FORCE_SW_RX_EOP, 9122 value)); 9123 break; 9124 case portmodPreemptionForceAutoHwEop: 9125 _SOC_IF_ERR_EXIT(clmac_preemption_force_rx_lost_eop_get(unit, port, 9126 CLMAC_PREEMPTION_FORCE_AUTO_HW_RX_EOP, 9127 value)); 9128 break; 9129 default: 9130 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 9131 (_SOC_MSG("Invalid Force RX lost EOP type(%d)"), type)); 9132 break; 9133 } 9134 9135 exit: 9136 SOC_FUNC_RETURN; 9137 } 9138 int pm4x25_port_lane_count_get (int unit, int port, pm_info_t pm_info, int line_side, int* num_lanes) 9139 { 9140 portmod_access_get_params_t params; 9141 phymod_phy_access_t phy_access; 9142 int nof_phys; 9143 int is_outer_most = 0; 9144 SOC_INIT_FUNC_DEFS; 9145 9146 /* coverity[check_return] */ 9147 portmod_access_get_params_t_init(unit, ¶ms); 9148 9149 if(line_side){ 9150 params.sys_side = PORTMOD_SIDE_LINE; 9151 } else { 9152 params.sys_side = PORTMOD_SIDE_SYSTEM; 9153 } 9154 9155 _SOC_IF_ERR_EXIT(pm4x25_port_phy_lane_access_get(unit, port, pm_info, 9156 ¶ms, 1 , &phy_access, 9157 &nof_phys, &is_outer_most)); 9158 9159 *num_lanes = 0; 9160 PORTMOD_BIT_COUNT(phy_access.access.lane_mask,*num_lanes); 9161 9162 exit: 9163 SOC_FUNC_RETURN; 9164 } 9165 9166 /*! 9167 * pm4x25_preemption_rx_timeout_set 9168 * 9169 * @brief Set specified preemption rx timeout and timeout count. 9170 * This function should only be called during device init. 9171 * There are 2 rx parameters rx timeout enable, rx timeout value in microsec 9172 * that can be configured using this function. 9173 * If set, enables TIMEOUT mechanism for Rx preempt traffic. 9174 * Timeout value in microsec, this configuration indicates link idle 9175 * time(in microsec) after which Rx timeout will force rx_lost_eop sequence 9176 * if preempt packet EOP was not sent. 9177 * 9178 * @param [in] unit - unit id 9179 * @param [in] port - logical port 9180 * @param [in] enable - enables timeout for rx preempt traffic 9181 * @param [in] timeout_cnt - timeout in microsecs 9182 */ 9183 int pm4x25_preemption_rx_timeout_set(int unit, int port, pm_info_t pm_info, 9184 uint32 enable, uint32 timeout_cnt) 9185 { 9186 return (clmac_preemption_rx_timeout_info_set(unit, port, enable, 9187 timeout_cnt)); 9188 } 9189 9190 /*! 9191 * pm4x25_preemption_rx_timeout_set 9192 * 9193 * @brief Get specified preemption rx timeout and timeout count. 9194 * 9195 * @param [in] unit - unit id 9196 * @param [in] port - logical port 9197 * @param [in] enable - enables timeout for rx preempt traffic 9198 * @param [out] timeout_cnt - timeout in millisec 9199 */ 9200 int pm4x25_preemption_rx_timeout_get(int unit, int port, pm_info_t pm_info, 9201 uint32 *enable, uint32 *timeout_cnt) 9202 { 9203 return (clmac_preemption_rx_timeout_info_get(unit, port, enable, 9204 timeout_cnt)); 9205 } 9206 9207 STATIC 9208 int _pm4x25_phy_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info) 9209 { 9210 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9211 int nof_phys; 9212 phymod_ts_fifo_status_t phy_ts_tx_info; 9213 SOC_INIT_FUNC_DEFS; 9214 9215 _SOC_IF_ERR_EXIT(phymod_ts_fifo_status_t_init(&phy_ts_tx_info)); 9216 9217 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9218 phy_access ,(1+MAX_PHYN), 9219 &nof_phys)); 9220 _SOC_IF_ERR_EXIT(portmod_port_phychain_timesync_tx_info_get(unit, port, phy_access, 9221 nof_phys, &phy_ts_tx_info)); 9222 9223 tx_info->timestamps_in_fifo = phy_ts_tx_info.ts_in_fifo_lo; 9224 tx_info->timestamps_in_fifo_hi = phy_ts_tx_info.ts_in_fifo_hi; 9225 tx_info->sequence_id = phy_ts_tx_info.ts_seq_id; 9226 tx_info->timestamp_sub_nanosec = phy_ts_tx_info.ts_sub_nanosec; 9227 9228 exit: 9229 SOC_FUNC_RETURN; 9230 } 9231 9232 /*! 9233 * pm4x10_port_timesync_tx_info_get 9234 * 9235 * @brief get port timestamps in fifo 9236 * 9237 * @param [in] unit - unit id 9238 * @param [in] port - logical port 9239 * @param [inout] tx_info - timestamp and seq id form fifo 9240 */ 9241 9242 int pm4x25_port_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info) 9243 { 9244 int phy_acc, mac_ts_disable; 9245 uint32 reg_val; 9246 SOC_INIT_FUNC_DEFS; 9247 9248 mac_ts_disable = 0; 9249 9250 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9251 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, CLMAC_TS_DISABLEf)) { 9252 _SOC_IF_ERR_EXIT(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 9253 mac_ts_disable = soc_reg_field_get(unit, CLPORT_MAC_CONTROLr, reg_val, CLMAC_TS_DISABLEf); 9254 } 9255 9256 /* 9257 * 1 = disable MAC timestamp, use TSC for timestamp. 9258 * 0 = legacy mode, use MAC for timestamp. 9259 */ 9260 if (mac_ts_disable) { 9261 _SOC_IF_ERR_EXIT(_pm4x25_phy_timesync_tx_info_get(unit, port, pm_info, tx_info)); 9262 } else { 9263 _SOC_IF_ERR_EXIT(clmac_timesync_tx_info_get(unit, port, tx_info)); 9264 } 9265 9266 exit: 9267 SOC_FUNC_RETURN; 9268 } 9269 9270 #ifdef FW_BCAST_DOWNLOAD 9271 STATIC int 9272 _pm4x25_sbus_control_set(int unit, const phymod_core_access_t* core_acc, int bcast_id, int chain_last) 9273 { 9274 portmod_default_user_access_t *user_acc = (portmod_default_user_access_t*)core_acc->access.user_acc; 9275 int reg_acc_idx = user_acc->blk_id | SOC_REG_ADDR_BLOCK_ID_MASK; 9276 soc_reg_t sbus_control_reg = CLPORT_SBUS_CONTROLr; 9277 uint32 reg_val; 9278 9279 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, sbus_control_reg, reg_acc_idx, 0, ®_val)); 9280 soc_reg_field_set(unit, sbus_control_reg, ®_val, 9281 SBUS_BCAST_BLOCK_IDf, bcast_id); 9282 soc_reg_field_set(unit, sbus_control_reg, ®_val, 9283 SBUS_CHAIN_LASTf, chain_last); 9284 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, sbus_control_reg, reg_acc_idx, 0, reg_val)); 9285 9286 return SOC_E_NONE; 9287 } 9288 9289 STATIC int 9290 _pm4x25_tsc_acc_mode_set(int unit, const phymod_core_access_t* core_acc, int acc_mem) 9291 { 9292 portmod_default_user_access_t *user_acc = (portmod_default_user_access_t*)core_acc->access.user_acc;; 9293 int reg_acc_idx = user_acc->blk_id | SOC_REG_ADDR_BLOCK_ID_MASK; 9294 soc_reg_t ucmem_ctrl_reg = CLPORT_WC_UCMEM_CTRLr; 9295 uint64 reg_val; 9296 9297 SOC_IF_ERROR_RETURN(soc_reg_get(unit, ucmem_ctrl_reg, reg_acc_idx, 0, ®_val)); 9298 soc_reg64_field32_set(unit, ucmem_ctrl_reg, ®_val, ACCESS_MODEf, acc_mem); 9299 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ucmem_ctrl_reg, reg_acc_idx, 0, reg_val)); 9300 9301 return SOC_E_NONE; 9302 } 9303 #endif 9304 9305 int pm4x25_fw_bcast(int unit, pm_info_t pm_info, const portmod_sbus_bcast_config_t* config) 9306 { 9307 #ifdef FW_BCAST_DOWNLOAD 9308 phymod_core_access_t* core_access = &PM_4x25_INFO(pm_info)->int_core_access; 9309 phymod_core_init_config_t core_conf; 9310 phymod_core_status_t core_status; 9311 portmod_default_user_access_t* user_acc; 9312 int flag = config->flag; 9313 9314 SOC_IF_ERROR_RETURN(phymod_core_init_config_t_init(&core_conf)); 9315 SOC_IF_ERROR_RETURN(phymod_core_status_t_init(&core_status)); 9316 9317 core_conf.flags = 0; 9318 PHYMOD_CORE_INIT_F_SERDES_FW_BCAST_SET(&core_conf); 9319 if (flag & PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY) { 9320 PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_SET(&core_conf); 9321 flag &= ~PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 9322 } 9323 9324 core_conf.firmware_loader = pm4x25_default_fw_loader; 9325 core_status.pmd_active = 0; 9326 9327 switch (flag) { 9328 case PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD: 9329 PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_SET(&core_conf); 9330 SOC_IF_ERROR_RETURN(phymod_core_init(core_access, &core_conf, &core_status)); 9331 PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_CLR(&core_conf); 9332 break; 9333 9334 case PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD: 9335 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_SET(&core_conf); 9336 SOC_IF_ERROR_RETURN(phymod_core_init(core_access, &core_conf, &core_status)); 9337 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_CLR(&core_conf); 9338 9339 /* program broadcast ID and chain last */ 9340 _pm4x25_sbus_control_set(unit, core_access, config->bcast_id, config->chain_last); 9341 9342 /* access TSC ucode memory */ 9343 _pm4x25_tsc_acc_mode_set(unit, core_access, 1); 9344 break; 9345 9346 case PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD: 9347 /* 9348 * phymod_core_init still need to access register to check whether UC is enabled before download firmware 9349 * TSC access mode will be changed to memory mode finally in fw_loader that will be called in phymod_core_init 9350 */ 9351 _pm4x25_tsc_acc_mode_set(unit, core_access, 0); 9352 9353 user_acc = (portmod_default_user_access_t*)core_access->access.user_acc; 9354 PORTMOD_USER_ACCESS_FW_LOAD_BROADCAST_SET(user_acc); 9355 9356 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_SET(&core_conf); 9357 SOC_IF_ERROR_RETURN(phymod_core_init(core_access, &core_conf, &core_status)); 9358 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_CLR(&core_conf); 9359 9360 PORTMOD_USER_ACCESS_FW_LOAD_BROADCAST_CLR(user_acc); 9361 break; 9362 9363 case PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD: 9364 /* access TSC register */ 9365 _pm4x25_tsc_acc_mode_set(unit, core_access, 0); 9366 9367 /* clear broadcast ID and chain last */ 9368 _pm4x25_sbus_control_set(unit, core_access, 0x7f, 0); 9369 9370 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&core_conf); 9371 SOC_IF_ERROR_RETURN(phymod_core_init(core_access, &core_conf, &core_status)); 9372 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_CLR(&core_conf); 9373 break; 9374 9375 case PHYMOD_CORE_INIT_F_FW_LOAD_END: 9376 PHYMOD_CORE_INIT_F_FW_LOAD_END_SET(&core_conf); 9377 SOC_IF_ERROR_RETURN(phymod_core_init(core_access, &core_conf, &core_status)); 9378 PHYMOD_CORE_INIT_F_FW_LOAD_END_CLR(&core_conf); 9379 break; 9380 9381 default: 9382 break; 9383 } 9384 9385 return SOC_E_NONE; 9386 #else 9387 return SOC_E_UNAVAIL; 9388 #endif 9389 } 9390 9391 9392 STATIC int 9393 _pm4x25_init_plls_get(int unit, int port, pm_info_t pm_info, portmod_vcos_speed_config_t *speed_config, int size, phymod_dual_plls_t *dual_plls) 9394 { 9395 portmod_dual_vcos_t dual_vcos; 9396 9397 portmod_dual_vcos_t_init(unit, &dual_vcos); 9398 size = 1; 9399 pm4x25_port_vcos_get(unit, port, pm_info, speed_config, size, &dual_vcos); 9400 9401 if (speed_config->port_type == portmodCpmPrtEthOfMixedMode) { 9402 /* PLL1 is used for ETH ports */ 9403 dual_plls->pll0_div = 0; 9404 dual_plls->pll1_div = (dual_vcos.vco_1 == portmodVCO20G)? phymod_TSCF_PLL_DIV132 : phymod_TSCF_PLL_DIV165; 9405 } else { 9406 switch (dual_vcos.vco_0) { 9407 case portmodVCO20G: 9408 dual_plls->pll0_div = phymod_TSCF_PLL_DIV132; 9409 break; 9410 case portmodVCO21G: 9411 dual_plls->pll0_div = phymod_TSCF_PLL_DIV140; 9412 break; 9413 case portmodVCO27G: 9414 dual_plls->pll0_div = phymod_TSCF_PLL_DIV175; 9415 break; 9416 default: 9417 dual_plls->pll0_div = phymod_TSCF_PLL_DIV132; 9418 break; 9419 } 9420 /* PLL1 is always 25G */ 9421 dual_plls->pll1_div = phymod_TSCF_PLL_DIV165; 9422 } 9423 9424 return SOC_E_NONE; 9425 } 9426 9427 9428 #define VCO_20G 0x1 9429 #define VCO_21G 0x2 9430 #define VCO_25G 0x4 9431 #define VCO_27G 0x8 9432 #define VCO_20G_25G 0x5 9433 int 9434 pm4x25_port_vcos_get(int unit, int port, pm_info_t pm_info, const portmod_vcos_speed_config_t* speed_config_list, int size, portmod_dual_vcos_t* dual_vco) 9435 { 9436 int index = 0; 9437 int vco_bitmap[4] = {0}; 9438 int vco_bmp = 0; 9439 9440 if (size == 0) return SOC_E_NONE; 9441 for (index = 0; index < size; index++){ 9442 /* Check if eth port is in the quad. If yes, PLL1 vco is either 20G or 25G */ 9443 switch (speed_config_list[index].num_lanes){ 9444 case 1: 9445 if(speed_config_list[index].speed == 1000){ 9446 vco_bitmap[index] = VCO_20G; 9447 }else if (speed_config_list[index].speed == 2500){ 9448 vco_bitmap[index] = VCO_25G; 9449 }else if (speed_config_list[index].speed == 5000){ 9450 vco_bitmap[index] = VCO_20G; 9451 }else if (speed_config_list[index].speed == 10000){ 9452 vco_bitmap[index] = VCO_20G; 9453 }else if (speed_config_list[index].speed == 20000){ 9454 vco_bitmap[index] = VCO_20G; 9455 }else if (speed_config_list[index].speed == 25000){ 9456 vco_bitmap[index] = VCO_25G; 9457 }else if (speed_config_list[index].speed == 11000){ 9458 vco_bitmap[index] = VCO_21G; 9459 } else if (speed_config_list[index].speed == 21000){ 9460 vco_bitmap[index] = VCO_21G; 9461 } else if(speed_config_list[index].speed == 27000){ 9462 vco_bitmap[index] = VCO_27G; 9463 } 9464 break; 9465 case 2: 9466 if(speed_config_list[index].speed == 20000){ 9467 vco_bitmap[index] = VCO_20G; 9468 }else if (speed_config_list[index].speed == 40000){ 9469 vco_bitmap[index] = VCO_25G; 9470 }else if (speed_config_list[index].speed == 50000){ 9471 vco_bitmap[index] = VCO_25G; 9472 }else if (speed_config_list[index].speed == 21000){ 9473 vco_bitmap[index] = VCO_21G; 9474 } else if (speed_config_list[index].speed == 42000){ 9475 vco_bitmap[index] = VCO_21G; 9476 } else if(speed_config_list[index].speed == 53000){ 9477 vco_bitmap[index] = VCO_27G; 9478 } 9479 break; 9480 case 4: 9481 if(speed_config_list[index].speed == 40000){ 9482 vco_bitmap[index] = VCO_20G; 9483 }else if (speed_config_list[index].speed == 50000){ 9484 vco_bitmap[index] = VCO_25G; 9485 }else if (speed_config_list[index].speed == 100000){ 9486 vco_bitmap[index] = VCO_25G; 9487 }else if (speed_config_list[index].speed == 42000){ 9488 vco_bitmap[index] = VCO_21G; 9489 } else if (speed_config_list[index].speed == 53000){ 9490 vco_bitmap[index] = VCO_27G; 9491 } else if(speed_config_list[index].speed == 106000){ 9492 vco_bitmap[index] = VCO_27G; 9493 } 9494 break; 9495 default: 9496 LOG_ERROR(BSL_LS_SOC_PORT, 9497 (BSL_META_U(unit, "fail to get vcos -- no vco matches lane %d speed %d\n"), 9498 speed_config_list[index].num_lanes, speed_config_list[index].speed)); 9499 return SOC_E_PARAM; 9500 } 9501 vco_bmp |= vco_bitmap[index]; 9502 } 9503 if (speed_config_list->port_type == portmodCpmPrtEthOfMixedMode) { 9504 switch (vco_bmp){ 9505 case VCO_20G: 9506 dual_vco->vco_1 = portmodVCO20G; 9507 break; 9508 case VCO_25G: 9509 dual_vco->vco_1 = portmodVCO25G; 9510 break; 9511 default: 9512 LOG_ERROR(BSL_LS_SOC_PORT, 9513 (BSL_META_U(unit, "fail to get vcos -- no vcos matches in ETH vco_bmp 0x%x\n"), vco_bmp)); 9514 return SOC_E_PARAM; 9515 } 9516 } else { 9517 switch (vco_bmp){ 9518 case VCO_20G: 9519 case VCO_25G: 9520 case VCO_20G_25G: 9521 dual_vco->vco_0 = portmodVCO20G; /* IEEE */ 9522 dual_vco->vco_1 = portmodVCO25G; 9523 break; 9524 case VCO_21G: 9525 dual_vco->vco_0 = portmodVCO21G; /* HiGig */ 9526 dual_vco->vco_1 = portmodVCO25G; 9527 break; 9528 case VCO_27G: 9529 dual_vco->vco_0 = portmodVCO27G; /* HiGig */ 9530 dual_vco->vco_1 = portmodVCO25G; 9531 break; 9532 default: 9533 LOG_ERROR(BSL_LS_SOC_PORT, 9534 (BSL_META_U(unit, "fail to get vcos -- no vcos combination vco_bmp 0x%x\n"), vco_bmp)); 9535 return SOC_E_PARAM; 9536 } 9537 } 9538 9539 return SOC_E_NONE; 9540 9541 } 9542 9543 STATIC 9544 int _pm4x25_ext_tsc_clk_set(int unit, int phy_acc, int ext_clk, int pll_vcoclk) 9545 { 9546 uint32 reg_val; 9547 SOC_INIT_FUNC_DEFS; 9548 9549 _SOC_IF_ERR_EXIT(READ_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 9550 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, EXT_TSC_CLK_ENf, ext_clk? 1 : 0); 9551 if (!ext_clk){ 9552 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, ®_val, TSC_CLK_SELf, pll_vcoclk ? 1 : 0); 9553 } 9554 _SOC_IF_ERR_EXIT(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val)); 9555 9556 exit: 9557 SOC_FUNC_RETURN; 9558 9559 } 9560 9561 STATIC 9562 int _pm4x25_pm_ext_tsc_clk_set(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 9563 { 9564 int phy_acc; 9565 int ext_clk = 0; 9566 int pll_vcoclk = 0; 9567 portmod_vcos_speed_config_t speed_config; 9568 phymod_dual_plls_t init_plls; 9569 9570 SOC_INIT_FUNC_DEFS; 9571 portmod_vcos_speed_config_t_init(unit, &speed_config); 9572 speed_config.higig_mode = add_info->init_config.is_hg; 9573 speed_config.speed = add_info->interface_config.speed; 9574 speed_config.num_lanes = add_info->interface_config.port_num_lanes; 9575 if (add_info->init_config.cpm_core_mode == portmodCpmMixEthCpri) { 9576 speed_config.port_type = portmodCpmPrtEthOfMixedMode; 9577 } 9578 _pm4x25_init_plls_get(unit, 0 , pm_info, &speed_config, 1, &init_plls); 9579 9580 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9581 if ((add_info->init_config.cpm_core_mode == portmodCpmAllIEEE) || (add_info->init_config.cpm_core_mode == portmodCpmAllHIGIG) 9582 || (add_info->init_config.cpm_core_mode == portmodCpmMixEthCpri)) { 9583 ext_clk = 1; 9584 9585 } else if (add_info->init_config.cpm_core_mode == portmodCpmAllCpri) { 9586 LOG_ERROR(BSL_LS_SOC_PORT, 9587 (BSL_META_U(unit, " Wrong port _mode from CPM4x25 %d\n"), portmodCpmAllCpri)); 9588 } else { 9589 if(add_info->init_config.is_hg) { 9590 ext_clk = 0; 9591 pll_vcoclk = 0; 9592 /* Check if port is HIGIG mode with IEEE speed */ 9593 if((init_plls.pll0_div == phymod_TSCF_PLL_DIV132) && (init_plls.pll1_div == phymod_TSCF_PLL_DIV165)) { 9594 pll_vcoclk = 1; 9595 } 9596 } else { 9597 ext_clk = 0; 9598 pll_vcoclk = 1; 9599 } 9600 #if 0 9601 if(add_info->init_config.txpi_mode){ 9602 ext_clk = 1; 9603 } 9604 #endif 9605 } 9606 9607 _SOC_IF_ERR_EXIT 9608 (_pm4x25_ext_tsc_clk_set(unit, phy_acc, ext_clk, pll_vcoclk)); 9609 9610 exit: 9611 9612 SOC_FUNC_RETURN; 9613 } 9614 9615 int pm4x25_port_mac_timestamp_enable_set(int unit, int port, pm_info_t pm_info, int enable) 9616 { 9617 int phy_acc; 9618 uint32 reg_val; 9619 pm_version_t pm_version; 9620 9621 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9622 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, CLMAC_TS_DISABLEf)) { 9623 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 9624 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, ®_val, 9625 CLMAC_TS_DISABLEf, (enable) ? 0 : 1); 9626 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 9627 } else { 9628 return SOC_E_UNAVAIL; 9629 } 9630 9631 if (!enable) { 9632 /* Disable XLMAC byte_adjust if MAC timestamp is disabled. 9633 * Otherwise, it will affect timestamp value of TSC timestamping. 9634 */ 9635 SOC_IF_ERROR_RETURN(_pm4x25_pm_version_get(unit, pm_info, &pm_version)); 9636 /* PM VERSION and CLMAC BYTE ADJUST aren't valid before TH2 */ 9637 if (!PORTMOD_PM4x25_IS_GEN1(pm_version)) { 9638 SOC_IF_ERROR_RETURN 9639 (clmac_timestamp_byte_adjust_set(unit, port, CLMAC_TIMESTAMP_BYTE_ADJUST_CLEAR, 0)); 9640 } 9641 9642 } 9643 return (SOC_E_NONE); 9644 } 9645 9646 int pm4x25_port_mac_timestamp_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 9647 { 9648 int phy_acc, tmp; 9649 uint32 reg_val; 9650 9651 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9652 if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, CLMAC_TS_DISABLEf)) { 9653 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 9654 tmp = soc_reg_field_get(unit, CLPORT_MAC_CONTROLr, reg_val, CLMAC_TS_DISABLEf); 9655 } else { 9656 return SOC_E_UNAVAIL; 9657 } 9658 9659 if (tmp) { 9660 *enable = FALSE; 9661 } else { 9662 *enable = TRUE; 9663 } 9664 9665 return (SOC_E_NONE); 9666 } 9667 9668 /* 9669 *Function: 9670 * _pm4x25_txpi_sdm_scheme_set 9671 * 9672 *Purpose: 9673 * Set Portmacro TXPI DSM scheme type 9674 * Default type is portmodTxPiSdmType1StOderWithFloor 9675 * This is a core level API 9676 * SDM scheme can't be changed if the port is active 9677 */ 9678 int _pm4x25_txpi_sdm_scheme_set(int unit, int port, pm_info_t pm_info, portmod_txpi_sdm_type_t type) 9679 { 9680 int phy_acc; 9681 uint32 reg_val; 9682 SOC_INIT_FUNC_DEFS; 9683 9684 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9685 9686 _SOC_IF_ERR_EXIT(READ_CLPORT_TXPI_CSR_CTRL1r(unit, phy_acc, ®_val)); 9687 soc_reg_field_set(unit, CLPORT_TXPI_CSR_CTRL1r, ®_val, TXPI_CSR_CTRL_SDM_TYPEf, type); 9688 _SOC_IF_ERR_EXIT(WRITE_CLPORT_TXPI_CSR_CTRL1r(unit, phy_acc, reg_val)); 9689 9690 exit: 9691 SOC_FUNC_RETURN; 9692 } 9693 9694 /* 9695 *Function: 9696 * pm4x25_txpi_lane_select_set 9697 * 9698 *Purpose: 9699 * Set Portmacro TXPI lane select 9700 * Defaults to using TXPI for it's own lane 9701 * This is a core level API 9702 */ 9703 int _pm4x25_txpi_lane_select_set(int unit, int port, pm_info_t pm_info, uint32_t *lane_select) 9704 { 9705 int phy_acc; 9706 uint32 reg_val = 0; 9707 SOC_INIT_FUNC_DEFS; 9708 9709 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9710 9711 soc_reg_field_set(unit, CLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_0f, lane_select[0]); 9712 soc_reg_field_set(unit, CLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_1f, lane_select[1]); 9713 soc_reg_field_set(unit, CLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_2f, lane_select[2]); 9714 soc_reg_field_set(unit, CLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_3f, lane_select[3]); 9715 _SOC_IF_ERR_EXIT(WRITE_CLPORT_TXPI_LANE_SELECTIONr(unit, phy_acc, reg_val)); 9716 9717 exit: 9718 SOC_FUNC_RETURN; 9719 } 9720 9721 /* 9722 *Function: 9723 * _pm4x25_port_phy_txpi_mode_set 9724 * 9725 *Purpose: 9726 * Set PMD TXPI mode: normal or external PD 9727 * This is a port level API 9728 */ 9729 int _pm4x25_port_phy_txpi_mode_set(int unit, int port, pm_info_t pm_info, uint32 mode) 9730 { 9731 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9732 int nof_phys; 9733 phymod_txpi_config_t config; 9734 SOC_INIT_FUNC_DEFS; 9735 9736 config.enable = mode ? 1 : 0; 9737 config.mode = mode; 9738 9739 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9740 phy_access ,(1+MAX_PHYN), 9741 &nof_phys)); 9742 SOC_IF_ERROR_RETURN(portmod_port_phychain_txpi_config_set(unit, phy_access, nof_phys, &config)); 9743 9744 exit: 9745 SOC_FUNC_RETURN; 9746 } 9747 9748 /* 9749 *Function: 9750 * pm4x25_port_txpi_override_set 9751 * 9752 *Purpose: 9753 * Overwrite Portmacro TXPI SDM value 9754 * Defaults to using value from CMIC 9755 * This is a port level API 9756 */ 9757 int pm4x25_port_txpi_override_set (int unit, int port, pm_info_t pm_info, const portmod_txpi_override_t *override) 9758 { 9759 int phy_acc; 9760 uint32 reg_val_en, bitmap; 9761 int i, first_index; 9762 int64 reg_value; 9763 9764 soc_field_t field[MAX_PORTS_PER_PM4X25] = {TXPI_CSR_OVER_EN_0f, TXPI_CSR_OVER_EN_1f, TXPI_CSR_OVER_EN_2f, TXPI_CSR_OVER_EN_3f}; 9765 soc_reg_t over_reg_low[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_CSR_OVER_VAL_0_LOWr, CLPORT_TXPI_CSR_OVER_VAL_1_LOWr, 9766 CLPORT_TXPI_CSR_OVER_VAL_2_LOWr, CLPORT_TXPI_CSR_OVER_VAL_3_LOWr}; 9767 soc_reg_t over_reg_high[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_CSR_OVER_VAL_0_HIGHr, CLPORT_TXPI_CSR_OVER_VAL_1_HIGHr, 9768 CLPORT_TXPI_CSR_OVER_VAL_2_HIGHr, CLPORT_TXPI_CSR_OVER_VAL_3_HIGHr}; 9769 SOC_INIT_FUNC_DEFS; 9770 9771 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9772 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 9773 9774 /* Enable TXPI DSM override */ 9775 _SOC_IF_ERR_EXIT(READ_CLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, ®_val_en)); 9776 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 9777 if (bitmap & (0x1 << i)) { 9778 soc_reg_field_set(unit, CLPORT_TXPI_CSR_OVER_ENr, ®_val_en, field[i], override->enable ? TRUE : FALSE); 9779 } 9780 } 9781 _SOC_IF_ERR_EXIT(WRITE_CLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, reg_val_en)); 9782 9783 /* Write TXPI DSM override value. Low 32 bits must be wroten before high register 9784 * reg_value = txpi_dsm_value_1ppm * override->value; 9785 */ 9786 COMPILER_64_SET(reg_value, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 9787 COMPILER_64_UMUL_32(reg_value, override->value); 9788 9789 for (i = 0; i < MAX_PORTS_PER_PM4X25; i++) { 9790 if (bitmap & (0x1 << i)) { 9791 soc_reg32_set(unit, over_reg_low[i], phy_acc, 0, override->enable ? COMPILER_64_LO(reg_value) : 0); 9792 soc_reg32_set(unit, over_reg_high[i], phy_acc, 0, override->enable ? (COMPILER_64_HI(reg_value) & 0xffff) : 0); 9793 } 9794 } 9795 9796 exit: 9797 SOC_FUNC_RETURN; 9798 } 9799 9800 /* 9801 *Function: 9802 * pm4x25_port_txpi_override_get 9803 * 9804 *Purpose: 9805 * Get Portmacro TXPI SDM override status and value 9806 * Defaults to using value from CMIC 9807 * This is a port level API 9808 */ 9809 int pm4x25_port_txpi_override_get (int unit, int port, pm_info_t pm_info, portmod_txpi_override_t *override) 9810 { 9811 int phy_acc; 9812 uint32 reg_val_en, bitmap; 9813 int first_index; 9814 uint32 reg_value_lo, reg_value_hi; 9815 int64 tmp_reg_val64, txpi_dsm_value_1ppm; 9816 9817 soc_field_t field[MAX_PORTS_PER_PM4X25] = {TXPI_CSR_OVER_EN_0f, TXPI_CSR_OVER_EN_1f, TXPI_CSR_OVER_EN_2f, TXPI_CSR_OVER_EN_3f}; 9818 soc_reg_t over_reg_low[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_CSR_OVER_VAL_0_LOWr, CLPORT_TXPI_CSR_OVER_VAL_1_LOWr, 9819 CLPORT_TXPI_CSR_OVER_VAL_2_LOWr, CLPORT_TXPI_CSR_OVER_VAL_3_LOWr}; 9820 soc_reg_t over_reg_high[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_CSR_OVER_VAL_0_HIGHr, CLPORT_TXPI_CSR_OVER_VAL_1_HIGHr, 9821 CLPORT_TXPI_CSR_OVER_VAL_2_HIGHr, CLPORT_TXPI_CSR_OVER_VAL_3_HIGHr}; 9822 SOC_INIT_FUNC_DEFS; 9823 9824 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9825 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 9826 9827 /*Get enable status of TXPI DSM override */ 9828 _SOC_IF_ERR_EXIT(READ_CLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, ®_val_en)); 9829 override->enable = soc_reg_field_get(unit, CLPORT_TXPI_CSR_OVER_ENr, reg_val_en, field[first_index]); 9830 9831 /* Get TXPI DSM override value */ 9832 if (override->enable == TRUE) { 9833 /* The LOW register should be read first before reading from the HIGH register. */ 9834 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, over_reg_low[first_index], 9835 phy_acc, 0, ®_value_lo)); 9836 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, over_reg_high[first_index], 9837 phy_acc, 0, ®_value_hi)); 9838 /* 9839 * bit47 : 0 -- positive; 1 -- negative. 9840 * If it is negative, the high 16 bits must be filled with 1. 9841 */ 9842 reg_value_hi = (reg_value_hi & 0x8000) ? (reg_value_hi | 0xffff0000) : (reg_value_hi & 0xffff); 9843 /* 9844 *Use COMPILER_64_XXX macros to put together 64 bit variables txpi_dsm_value_1ppm and tmp_reg_val64 9845 *and then generate the override->value 9846 */ 9847 COMPILER_64_SET(txpi_dsm_value_1ppm, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 9848 COMPILER_64_SET(tmp_reg_val64, reg_value_hi, reg_value_lo); 9849 COMPILER_64_UDIV_64(tmp_reg_val64, txpi_dsm_value_1ppm); 9850 9851 COMPILER_64_TO_32_LO(override->value, tmp_reg_val64); 9852 } else { 9853 override->value = 0; 9854 } 9855 9856 exit: 9857 SOC_FUNC_RETURN; 9858 } 9859 9860 /* 9861 *Function: 9862 * pm4x25_port_txpi_sdm_data_get 9863 * 9864 *Purpose: 9865 * Get Portmacro TXPI SDM value of resolution 9866 * This is a port level API 9867 */ 9868 int pm4x25_port_txpi_sdm_data_get(int unit, int port, pm_info_t pm_info, int *value) 9869 9870 { 9871 int phy_acc; 9872 uint32 bitmap; 9873 int first_index; 9874 uint32 reg_value_lo, reg_value_hi; 9875 int64 tmp_reg_val64, txpi_dsm_value_1ppm; 9876 9877 soc_reg_t data_reg_low[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_DATA_OUT_STS_0_LOWr, CLPORT_TXPI_DATA_OUT_STS_1_LOWr, 9878 CLPORT_TXPI_DATA_OUT_STS_2_LOWr, CLPORT_TXPI_DATA_OUT_STS_3_LOWr}; 9879 soc_reg_t data_reg_high[MAX_PORTS_PER_PM4X25] = {CLPORT_TXPI_DATA_OUT_STS_0_HIGHr, CLPORT_TXPI_DATA_OUT_STS_1_HIGHr, 9880 CLPORT_TXPI_DATA_OUT_STS_2_HIGHr, CLPORT_TXPI_DATA_OUT_STS_3_HIGHr}; 9881 SOC_INIT_FUNC_DEFS; 9882 9883 PM4x25_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9884 _SOC_IF_ERR_EXIT(_pm4x25_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 9885 9886 /* get the first sub-port if the port is dual-lane or quad-lane mode. 9887 * The LOW register should be read first before reading from the HIGH register. 9888 */ 9889 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, data_reg_low[first_index], 9890 phy_acc, 0, ®_value_lo)); 9891 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, data_reg_high[first_index], 9892 phy_acc, 0, ®_value_hi)); 9893 /* 9894 * bit47 : 0 -- positive; 1 -- negative. 9895 * If it is negative, the high 16 bits must be filled with 1. 9896 */ 9897 reg_value_hi = (reg_value_hi & 0x8000) ? (reg_value_hi | 0xffff0000) : (reg_value_hi & 0xffff); 9898 9899 /* 9900 *Use COMPILER_64_XXX macros to put together 64 bit variables txpi_dsm_value_1ppm and tmp_reg_val64 9901 *and then generate the override->value 9902 */ 9903 COMPILER_64_SET(txpi_dsm_value_1ppm, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 9904 COMPILER_64_SET(tmp_reg_val64, reg_value_hi, reg_value_lo); 9905 COMPILER_64_UDIV_64(tmp_reg_val64, txpi_dsm_value_1ppm); 9906 9907 COMPILER_64_TO_32_LO(*value, tmp_reg_val64); 9908 exit: 9909 SOC_FUNC_RETURN; 9910 } 9911 9912 int pm4x25_port_synce_clk_ctrl_set(int unit, int port, pm_info_t pm_info, 9913 const portmod_port_synce_clk_ctrl_t* cfg) 9914 { 9915 phymod_synce_clk_ctrl_t phy_synce_cfg; 9916 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9917 int nof_phys; 9918 SOC_INIT_FUNC_DEFS; 9919 9920 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9921 phy_access ,(1+MAX_PHYN), 9922 &nof_phys)); 9923 9924 phymod_synce_clk_ctrl_t_init(&phy_synce_cfg); 9925 phy_synce_cfg.stg0_mode = cfg->stg0_mode; 9926 phy_synce_cfg.stg1_mode = cfg->stg1_mode; 9927 phy_synce_cfg.sdm_val = cfg->sdm_val; 9928 9929 _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_set(&phy_access[0], 9930 phy_synce_cfg)); 9931 9932 exit: 9933 SOC_FUNC_RETURN; 9934 } 9935 9936 int pm4x25_port_synce_clk_ctrl_get(int unit, int port, pm_info_t pm_info, 9937 portmod_port_synce_clk_ctrl_t* cfg) 9938 { 9939 phymod_synce_clk_ctrl_t phy_synce_cfg; 9940 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9941 int nof_phys; 9942 SOC_INIT_FUNC_DEFS; 9943 9944 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9945 phy_access ,(1+MAX_PHYN), 9946 &nof_phys)); 9947 9948 phymod_synce_clk_ctrl_t_init(&phy_synce_cfg); 9949 9950 _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_get(&phy_access[0], 9951 &phy_synce_cfg)); 9952 9953 cfg->stg0_mode = phy_synce_cfg.stg0_mode; 9954 cfg->stg1_mode = phy_synce_cfg.stg1_mode; 9955 cfg->sdm_val = phy_synce_cfg.sdm_val; 9956 9957 exit: 9958 SOC_FUNC_RETURN; 9959 } 9960 9961 #endif /* PORTMOD_PM4X25_SUPPORT */ 9962 9963 #undef _ERR_MSG_MODULE_NAME