pm4x10.c (438159B)
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_common.h> 17 #include <soc/portmod/portmod_dispatch.h> 18 #include <soc/portmod/portmod_chain.h> 19 #include <soc/portmod/portmod_legacy_phy.h> 20 #include <soc/portmod/portmod_system.h> 21 22 23 #include <soc/portmod/xlmac.h> 24 #include <soc/portmod/pm4x10.h> 25 #include <soc/portmod/pm12x10_internal.h> 26 #include <soc/portmod/pm12x10_xgs_internal.h> 27 28 #ifdef _ERR_MSG_MODULE_NAME 29 #error "_ERR_MSG_MODULE_NAME redefined" 30 #endif 31 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 32 33 #ifdef PORTMOD_PM4X10_SUPPORT 34 35 #if 0 36 #define PORTMOD_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 37 do{\ 38 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 39 (_phy_access)->type = (_core_access)->type; \ 40 }while(0) 41 #endif 42 43 /* 10G mode at 10.3125G and 1G mode at 1.25G */ 44 #define PM4X10_LANES_PER_CORE (4) 45 #define MAX_PORTS_PER_PM4X10 (4) 46 47 #define TXPI_DSM_VALUE_1PPM_HI (uint32) 0x29 /* 1ppm value is 1.80144E+11 (0x29F16B11C7) in register */ 48 #define TXPI_DSM_VALUE_1PPM_LO (uint32) 0xF16B11C7 49 50 #define PM_4x10_INFO(pm_info) ((pm_info)->pm_data.pm4x10_db) 51 52 #define PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc) \ 53 do { \ 54 uint32 is_bypass; \ 55 uint8 in_pm12x10 = PM_4x10_INFO(pm_info)->in_pm12x10; \ 56 phy_acc = 0; \ 57 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &is_bypass); \ 58 phy_acc = (is_bypass && !in_pm12x10 && PM_4x10_INFO(pm_info)->first_phy != -1) ? (PM_4x10_INFO(pm_info)->first_phy | SOC_REG_ADDR_PHY_ACC_MASK) : port; \ 59 } while (0) 60 61 #define PM4x10_WB_BUFFER_VERSION (10) 62 63 #define PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, dynamic_state, \ 64 port_index) \ 65 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 66 pm_info->wb_vars_ids[portDynamicState], \ 67 &dynamic_state, port_index) 68 #define PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, dynamic_state, \ 69 port_index) \ 70 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 71 pm_info->wb_vars_ids[portDynamicState], \ 72 dynamic_state, port_index) 73 #define PM4x10_SPEED_SET(unit, pm_info, speed, port_index) \ 74 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 75 pm_info->wb_vars_ids[dataRate], \ 76 &speed, port_index) 77 #define PM4x10_SPEED_GET(unit, pm_info, speed, port_index) \ 78 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 79 pm_info->wb_vars_ids[dataRate], \ 80 speed, port_index) 81 #define PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index) \ 82 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 83 pm_info->wb_vars_ids[maxSpeed], \ 84 &max_speed, port_index) 85 #define PM4x10_MAX_SPEED_GET(unit, pm_info, max_speed, port_index) \ 86 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 87 pm_info->wb_vars_ids[maxSpeed], \ 88 max_speed, port_index) 89 #define PM4x10_INTERFACE_TYPE_SET(unit, pm_info, interface_type, port_index) \ 90 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 91 pm_info->wb_vars_ids[interfaceType], \ 92 &interface_type, port_index) 93 #define PM4x10_INTERFACE_TYPE_GET(unit, pm_info, interface_type, port_index) \ 94 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 95 pm_info->wb_vars_ids[interfaceType], \ 96 interface_type, port_index) 97 #define PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface_type, port_index) \ 98 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 99 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], \ 100 &interface_type, port_index) 101 #define PM4x10_OUTMOST_PHY_INTERFACE_TYPE_GET(unit, pm_info, interface_type, port_index) \ 102 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 103 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], \ 104 interface_type, port_index) 105 #define PM4x10_SERDES_INTERFACE_TYPE_SET(unit, pm_info, serdes_interface, \ 106 port_index) \ 107 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 108 pm_info->wb_vars_ids[serdesInterfaceType], \ 109 &serdes_interface, port_index) 110 #define PM4x10_SERDES_INTERFACE_TYPE_GET(unit, pm_info, serdes_interface, \ 111 port_index) \ 112 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 113 pm_info->wb_vars_ids[serdesInterfaceType], \ 114 serdes_interface, port_index) 115 #define PM4x10_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index) \ 116 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 117 pm_info->wb_vars_ids[interfaceModes], \ 118 &interface_modes, port_index) 119 #define PM4x10_INTERFACE_MODES_GET(unit, pm_info, interface_modes, port_index) \ 120 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 121 pm_info->wb_vars_ids[interfaceModes], \ 122 interface_modes, port_index) 123 #define PM4x10_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, \ 124 port_index) \ 125 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 126 pm_info->wb_vars_ids[isInterfaceRestore], \ 127 &is_interface_restore, port_index) 128 #define PM4x10_IS_INTERFACE_RESTORE_GET(unit, pm_info, is_interface_restore, \ 129 port_index) \ 130 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 131 pm_info->wb_vars_ids[isInterfaceRestore], \ 132 is_interface_restore, port_index) 133 #define PM4x10_IS_HG_SET(unit, pm_info, is_hg, port_index) \ 134 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 135 pm_info->wb_vars_ids[isHg], &is_hg, port_index) 136 #define PM4x10_IS_HG_GET(unit, pm_info, is_hg, port_index) \ 137 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 138 pm_info->wb_vars_ids[isHg], is_hg, port_index) 139 #define PM4x10_AN_MODE_SET(unit, pm_info, an_mode, port_index) \ 140 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 141 pm_info->wb_vars_ids[anMode], &an_mode, port_index) 142 #define PM4x10_AN_MODE_GET(unit, pm_info, an_mode, port_index) \ 143 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 144 pm_info->wb_vars_ids[anMode], an_mode, port_index) 145 #define PM4x10_FS_CL72_SET(unit, pm_info, fs_cl72, port_index) \ 146 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 147 pm_info->wb_vars_ids[fsCl72], &fs_cl72, port_index) 148 #define PM4x10_FS_CL72_GET(unit, pm_info, fs_cl72, port_index) \ 149 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 150 pm_info->wb_vars_ids[fsCl72], fs_cl72, port_index) 151 #define PM4x10_CX4_10G_SET(unit, pm_info, cx4_10G, port_index) \ 152 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 153 pm_info->wb_vars_ids[cx4In10G], &cx4_10G, port_index) 154 #define PM4x10_CX4_10G_GET(unit, pm_info, cx4_10G, port_index) \ 155 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 156 pm_info->wb_vars_ids[cx4In10G], cx4_10G, port_index) 157 #define PM4x10_AN_CL72_SET(unit, pm_info, an_cl72, port_index) \ 158 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 159 pm_info->wb_vars_ids[anCl72], &an_cl72, port_index) 160 #define PM4x10_AN_CL72_GET(unit, pm_info, an_cl72, port_index) \ 161 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 162 pm_info->wb_vars_ids[anCl72], an_cl72, port_index) 163 #define PM4x10_AN_FEC_SET(unit, pm_info, an_fec, port_index) \ 164 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 165 pm_info->wb_vars_ids[anFec], &an_fec, port_index) 166 #define PM4x10_AN_FEC_GET(unit, pm_info, an_fec, port_index) \ 167 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 168 pm_info->wb_vars_ids[anFec], an_fec, port_index) 169 #define PM4x10_AN_CL37_SET(unit, pm_info, an_cl37, port_index) \ 170 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 171 pm_info->wb_vars_ids[anCl37], &an_cl37, port_index) 172 #define PM4x10_AN_CL37_GET(unit, pm_info, an_cl37, port_index) \ 173 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 174 pm_info->wb_vars_ids[anCl37], an_cl37, port_index) 175 #define PM4x10_AN_MASTER_LANE_SET(unit, pm_info, an_master_lane, port_index) \ 176 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 177 pm_info->wb_vars_ids[anMasterLane], \ 178 &an_master_lane, port_index) 179 #define PM4x10_AN_MASTER_LANE_GET(unit, pm_info, an_master_lane, port_index) \ 180 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 181 pm_info->wb_vars_ids[anMasterLane], \ 182 an_master_lane, port_index) 183 #define PM4x10_CL37_SGMII_CNT_SET(unit, pm_info, cl37_sgmii_cnt, port_index) \ 184 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 185 pm_info->wb_vars_ids[cl37SgmiiCnt], &cl37_sgmii_cnt,\ 186 port_index) 187 #define PM4x10_CL37_SGMII_CNT_GET(unit, pm_info, cl37_sgmii_cnt, port_index) \ 188 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 189 pm_info->wb_vars_ids[cl37SgmiiCnt], cl37_sgmii_cnt, \ 190 port_index) 191 #define PM4x10_CL37_SGMII_RESTART_CNT_SET(unit, pm_info, \ 192 cl37_sgmii_restart_cnt, port_index)\ 193 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 194 pm_info->wb_vars_ids[cl37SgmiiRestartCnt], \ 195 &cl37_sgmii_restart_cnt, port_index) 196 #define PM4x10_CL37_SGMII_RESTART_CNT_GET(unit, pm_info, \ 197 cl37_sgmii_restart_cnt, port_index)\ 198 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 199 pm_info->wb_vars_ids[cl37SgmiiRestartCnt], \ 200 cl37_sgmii_restart_cnt, port_index) 201 #define PM4x10_PORT_OP_MODE_SET(unit, pm_info, port_op_mode, port_index) \ 202 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 203 pm_info->wb_vars_ids[portOpMode], \ 204 &port_op_mode, port_index) 205 #define PM4x10_PORT_OP_MODE_GET(unit, pm_info, port_op_mode, port_index) \ 206 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 207 pm_info->wb_vars_ids[portOpMode], \ 208 port_op_mode, port_index) 209 #define PM4x10_RXAUI_MODE_SET(unit, pm_info, rxaui_mode, port_index) \ 210 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 211 pm_info->wb_vars_ids[rxauiMode], \ 212 &rxaui_mode, port_index) 213 #define PM4x10_RXAUI_MODE_GET(unit, pm_info, rxaui_mode, port_index) \ 214 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 215 pm_info->wb_vars_ids[rxauiMode], \ 216 rxaui_mode, port_index) 217 218 #define PM4x10_TX_PARAMS_USER_FLAG_SET(unit, pm_info, \ 219 tx_params_user_flag, port_index) \ 220 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 221 pm_info->wb_vars_ids[txParamsUserFlag], \ 222 &tx_params_user_flag, port_index) 223 #define PM4x10_TX_PARAMS_USER_FLAG_GET(unit, pm_info, \ 224 tx_params_user_flag, port_index) \ 225 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 226 pm_info->wb_vars_ids[txParamsUserFlag], \ 227 tx_params_user_flag, port_index) 228 229 #define PM4x10_EXT_PHY_TX_PARAMS_USER_FLAG_SET(unit, pm_info, \ 230 ext_phy_tx_params_user_flag, port_index) \ 231 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 232 pm_info->wb_vars_ids[extPhyTxParamsUserFlag], \ 233 &ext_phy_tx_params_user_flag, port_index) 234 #define PM4x10_EXT_PHY_TX_PARAMS_USER_FLAG_GET(unit, pm_info, \ 235 ext_phy_tx_params_user_flag, port_index) \ 236 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 237 pm_info->wb_vars_ids[extPhyTxParamsUserFlag], \ 238 ext_phy_tx_params_user_flag, port_index) 239 240 #define PM4x10_PORT_FALLBACK_LANE_SET(unit, pm_info, fallback_lane, port_index)\ 241 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 242 pm_info->wb_vars_ids[fallbackLane], \ 243 &fallback_lane, port_index) 244 #define PM4x10_PORT_FALLBACK_LANE_GET(unit, pm_info, fallback_lane, port_index)\ 245 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 246 pm_info->wb_vars_ids[fallbackLane], \ 247 fallback_lane, port_index) 248 249 #define PM4x10_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, lane_connection_db, xphy_idx, lane) \ 250 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[laneConnectionDb], \ 251 (uint8 *)lane_connection_db, lane, xphy_idx) 252 #define PM4x10_PORT_LANE_CONNECTION_DB_GET(unit, pm_info, lane_connection_db, xphy_idx, lane) \ 253 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[laneConnectionDb], \ 254 (uint8 *)lane_connection_db, lane, xphy_idx) 255 256 #define PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, nof_phys, lane) \ 257 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[nofPhys], nof_phys, lane) 258 #define PM4x10_PORT_NUM_PHYS_GET(unit, pm_info, nof_phys, lane) \ 259 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[nofPhys], nof_phys, lane) 260 261 #define PM4x10_PORT_PLL_DIVIDER_REQ_SET(unit, pm_info, \ 262 pll_divider_req, \ 263 port_index) \ 264 SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 265 pm_info->wb_vars_ids[pllDividerReq], \ 266 &pll_divider_req, port_index) 267 #define PM4x10_PORT_PLL_DIVIDER_REQ_GET(unit, pm_info, \ 268 pll_divider_req, \ 269 port_index) \ 270 SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 271 pm_info->wb_vars_ids[pllDividerReq], \ 272 pll_divider_req, port_index) 273 274 #define PM4x10_PORT_TIME_STAMP_ADJUST_OLD_SET(unit, pm_info, \ 275 port_ts_adjust, \ 276 adjust_index, \ 277 port_index) \ 278 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 279 pm_info->wb_vars_ids[tsAdjustOld], \ 280 (uint8 *)port_ts_adjust, adjust_index, \ 281 port_index) 282 283 #define PM4x10_PORT_TIME_STAMP_ADJUST_OLD_GET(unit, pm_info, \ 284 port_ts_adjust, \ 285 adjust_index, \ 286 port_index) \ 287 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 288 pm_info->wb_vars_ids[tsAdjustOld], \ 289 (uint8 *)port_ts_adjust, adjust_index, \ 290 port_index) 291 292 #define PM4x10_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, \ 293 port_ts_adjust, \ 294 adjust_index, \ 295 port_index) \ 296 SOC_WB_ENGINE_SET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 297 pm_info->wb_vars_ids[tsAdjust], \ 298 (uint8 *)port_ts_adjust, adjust_index, \ 299 port_index) 300 301 #define PM4x10_PORT_TIME_STAMP_ADJUST_GET(unit, pm_info, \ 302 port_ts_adjust, \ 303 adjust_index, \ 304 port_index) \ 305 SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, \ 306 pm_info->wb_vars_ids[tsAdjust], \ 307 (uint8 *)port_ts_adjust, adjust_index, \ 308 port_index) 309 310 /* Warm Boot Variables to indicate the boot state */ 311 typedef enum pm4x10_fabric_wb_vars{ 312 isInitialized, 313 ports, 314 isActive, 315 isBypassed, 316 threePortsMode, 317 phy_type, 318 interfaceConfig, 319 portInitConfig, 320 phyInitConfig, 321 phyInterfaceConfig, 322 portDynamicState, 323 nofPhys, /* number of phys for the port */ 324 laneConnectionDb, /* represents the physical topology of the serdes and ext phy lanes */ 325 dataRate,/* port speed - phy_intf_config.data_rate */ 326 maxSpeed, /* Max Port Speed Supported */ 327 /* interface type - portmod_port_interface_config_t.interface */ 328 interfaceType, /* interface of type soc_port_if_t */ 329 /* serdes interface - portmod_port_interface_config_t.serdes_interface */ 330 serdesInterfaceType, 331 interfaceModes, /* see PHYMOD_INTF_MODES_ */ 332 isInterfaceRestore, /*indicate whether interface should be restored from DB (otherwise retrieved from HW), replace PHYMOD_INTF_F_INTF_PARAM_SET_ONLY*/ 333 isHg, /* specify wheather the port is higig port */ 334 anMode, /* spn_PHY_AN_MODE - Specify the AN mode */ 335 fsCl72, /* spn_FORCED_INIT_CL72 - if trainig should be enabled in Forced speed mode */ 336 cx4In10G, /* see PHYMOD_BAM_CL37_CAP_10G_CX4 */ 337 anCl72, /* spn_PHY_AN_C72 - Specify if the link training should be enabled */ 338 anFec, /* spn_FORCED_INIT_FEC specify if FEC should be enabled in AN mode */ 339 anCl37, /**< AN CL37 */ 340 anMasterLane, /* spn_PHY_AUTONEG_MASTER_LANE - Specify the AN master lane */ 341 cl37SgmiiCnt, /* store cl37 sgmii count */ 342 cl37SgmiiRestartCnt, /* spn_SERDES_CL37_SGMII_RESTART_COUNT - cl37_sgmii_cnt threshold*/ 343 portOpMode, /* spn_PHY_PCS_REPEATER - phy operation Mode */ 344 rxauiMode, /* portmod_port_init_config_t.rxaui_mode */ 345 /* tx params flag - phy_init_config_t.tx_params_user_flag */ 346 txParamsUserFlag, 347 /* tx params flag - phy_init_config_t.tx */ 348 txParams, 349 /* ext tx params flag - phy_init_config_t.ext_phy_tx_params_user_flag */ 350 extPhyTxParamsUserFlag, 351 /* ext tx params - phy_init_config_t.ext_phy_tx */ 352 extPhyTxParams, 353 /* port fallback lane - portmod_port_init_config_t.port_fallback_lane */ 354 fallbackLane, 355 /* pll_divider_req setting on the port */ 356 pllDividerReq, 357 /* the interface type written into the outmost PHY */ 358 interfaceWrittenIntoOutmostPhy, 359 /* the time stamp adjust setting on MAC ** removed ** */ 360 tsAdjustOld, 361 /* the time stamp adjust setting on MAC */ 362 tsAdjust 363 }pm4x10_wb_vars_t; 364 365 struct pm4x10_s{ 366 portmod_pbmp_t phys; 367 int first_phy; 368 phymod_ref_clk_t ref_clk; 369 phymod_polarity_t polarity; 370 phymod_lane_map_t lane_map; 371 phymod_firmware_load_method_t fw_load_method; 372 phymod_firmware_loader_f external_fw_loader; 373 phymod_core_access_t int_core_access ; /* for internal SerDes only */ 374 int nof_phys[PM4X10_LANES_PER_CORE]; /* internal + External Phys for each lane*/ 375 uint8 in_pm12x10; 376 uint8 default_fw_loader_is_used; 377 uint8 default_bus_is_used; 378 portmod_phy_external_reset_f portmod_phy_external_reset; 379 portmod_mac_soft_reset_f portmod_mac_soft_reset; 380 int core_num; 381 int core_num_int; /* 0, 1, 2 for TSC12 */ 382 portmod_xphy_lane_connection_t lane_conn[MAX_PHYN][PM4X10_LANES_PER_CORE]; 383 int warmboot_skip_db_restore; 384 int rescal; 385 int is_pm4x10q; 386 portmod_port_mode_aux_info_t port_mode_aux_info; 387 portmod_link_recovery_t link_recovery; 388 }; 389 390 #define PM4x10_QUAD_MODE_IF(interface) \ 391 (interface == SOC_PORT_IF_CAUI || \ 392 interface == SOC_PORT_IF_XLAUI || \ 393 interface == SOC_PORT_IF_CR4 || \ 394 interface == SOC_PORT_IF_SR4 || \ 395 interface == SOC_PORT_IF_KR4 || \ 396 interface == SOC_PORT_IF_XGMII || \ 397 interface == SOC_PORT_IF_DNX_XAUI) 398 399 #define PM4x10_DUAL_MODE_IF(interface) \ 400 (interface == SOC_PORT_IF_RXAUI || \ 401 interface == SOC_PORT_IF_SR2 || \ 402 interface == SOC_PORT_IF_KR2 || \ 403 interface == SOC_PORT_IF_CR2) 404 405 /* Legacy phymod_tx_t structure format */ 406 typedef struct pm4x10_phymod_tx_s { 407 int8_t pre; 408 int8_t main; 409 int8_t post; 410 int8_t post2; 411 int8_t post3; 412 int8_t amp; 413 int8_t drivermode; 414 } pm4x10_phymod_tx_t; 415 416 #define PORTMOD_PM4x10_IS_GEN1(pm_version) ((pm_version.type == PM_TYPE_PM4X10) && (pm_version.gen == PM_GEN1)) 417 #define PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) ((pm_version.type == PM_TYPE_PM4X10) && (pm_version.gen == PM_GEN2) && (pm_version.tech_process == PM_TECH_16NM)) 418 #define PORTMOD_PM4x10_IS_GEN2_28nm(pm_version) ((pm_version.type == PM_TYPE_PM4X10) && (pm_version.gen == PM_GEN2) && (pm_version.tech_process == PM_TECH_28NM)) 419 #define PORTMOD_PM4x10_IS_GEN3_16nm(pm_version) ((pm_version.type == PM_TYPE_PM4X10) && (pm_version.gen == PM_GEN3) && (pm_version.tech_process == PM_TECH_16NM)) 420 #define PORTMOD_PM4x10_IS_GEN3_28nm(pm_version) ((pm_version.type == PM_TYPE_PM4X10) && (pm_version.gen == PM_GEN3) && (pm_version.tech_process == PM_TECH_28NM)) 421 #define PORTMOD_PM4x10_IS_REVISION_A0(pm_version) ((pm_version.revision_letter == PM_REVISION_A) && (pm_version.revision_number == PM_REVISION_0)) 422 /* Add other revision check here */ 423 424 STATIC 425 int pm4x10_port_soft_reset(int unit, int port, pm_info_t pm_info, int enable); 426 427 STATIC 428 int _pm4x10_txpi_lane_select_set(int unit, int port, pm_info_t pm_info, uint32_t *lane_select); 429 430 STATIC 431 int _pm4x10_port_phy_txpi_mode_set(int unit, int port, pm_info_t pm_info, uint32 mode); 432 433 STATIC 434 int _pm4x10_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); 435 436 STATIC 437 int _pm4x10_pm_version_get(int unit, pm_info_t pm_info, pm_version_t *version) 438 { 439 uint32 raddr, reg_val, pm_type; 440 int phy_port, block; 441 uint8 access_type; 442 443 SOC_INIT_FUNC_DEFS; 444 445 version->type = PM_TYPE_INVALID; 446 version->gen = PM_GEN_INVALID; 447 version->tech_process = PM_TECH_INVALID; 448 version->revision_number = PM_REVISION_NUM_INVALID; 449 version->revision_letter = PM_REVISION_LETTER_INVALID; 450 451 /* 452 * PM version ID register is not defined in PM GEN1. 453 * PM12x10 only has gen1 now. To be fixed if support PM12X10 gen2. 454 */ 455 if (SOC_REG_IS_VALID(unit, XLPORT_PM_VERSION_IDr) && 456 (!PM_4x10_INFO(pm_info)->in_pm12x10)) { 457 458 /* Get the first physical port of the pm core */ 459 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy_port) { 460 break; 461 } 462 463 raddr = soc_reg_addr_get(unit, XLPORT_PM_VERSION_IDr, phy_port, 0, 464 SOC_REG_ADDR_OPTION_PRESERVE_PORT, &block, &access_type); 465 _SOC_IF_ERR_EXIT(_soc_reg32_get(unit, block, access_type, raddr, ®_val)); 466 467 pm_type = soc_reg_field_get(unit, XLPORT_PM_VERSION_IDr, reg_val, PM_TYPEf); 468 if (pm_type == 0) { 469 version->type = PM_TYPE_PM4X10; 470 version->gen = PM_GEN2; 471 } else if (pm_type == 5){ 472 version->type = PM_TYPE_PM4X10; 473 version->gen = PM_GEN3; 474 } 475 /* The hardware value of techology/revision starts from 0 */ 476 version->tech_process = soc_reg_field_get(unit, XLPORT_PM_VERSION_IDr, reg_val, TECH_PROCESSf) +1; 477 version->revision_number = soc_reg_field_get(unit, XLPORT_PM_VERSION_IDr, reg_val, REV_NUMBERf) + 1; 478 version->revision_letter = soc_reg_field_get(unit, XLPORT_PM_VERSION_IDr, reg_val, REV_LETTERf) + 1; 479 } else { 480 version->type = PM_TYPE_PM4X10; 481 version->gen = PM_GEN1; 482 } 483 484 exit: 485 SOC_FUNC_RETURN; 486 } 487 488 489 /* 490 * Check the PM is a master PLL or not 491 * For GEN1/GEN2, only need to check one PLL 492 * For GEN3, need to check PLL0 and PLL1 493 */ 494 STATIC 495 int _pm4x10_port_tsc_is_master_pll(int unit, int port, pm_info_t pm_info) 496 { 497 int phy_acc; 498 uint32 reg_val; 499 uint32 refclk_out_en_0 = 0, refclk_out_en_1 = 0; 500 pm_version_t pm_version; 501 SOC_INIT_FUNC_DEFS; 502 503 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 504 505 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 506 if (PORTMOD_PM4x10_IS_GEN2_28nm(pm_version)) { 507 /* This function is Valid only for G2 28nm EAGLEPLL, don't care for 16nm */ 508 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 509 refclk_out_en_0 = soc_reg_field_get(unit, XLPORT_XGXS0_CTRL_REGr, reg_val, REFOUT_ENf); 510 } else if (PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 511 /* Valid only for G3 28nm EAGLE2PLL, don't care for 16nm */ 512 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 513 refclk_out_en_0 = soc_reg_field_get(unit, XLPORT_XGXS0_CTRL_REGr, reg_val, PLL0_REFOUT_ENf); 514 refclk_out_en_1 = soc_reg_field_get(unit, XLPORT_XGXS0_CTRL_REGr, reg_val, PLL1_REFOUT_ENf); 515 } else { 516 refclk_out_en_0 = 0; 517 refclk_out_en_1 = 0; 518 } 519 520 if (refclk_out_en_0 || refclk_out_en_1) { 521 return TRUE; 522 } 523 524 return FALSE; 525 526 exit: 527 SOC_FUNC_RETURN; 528 } 529 530 int pm4x10_pm_interface_type_is_supported(int unit, soc_port_if_t interface, 531 int* is_supported) 532 { 533 SOC_INIT_FUNC_DEFS; 534 switch(interface){ 535 case SOC_PORT_IF_SGMII: 536 case SOC_PORT_IF_GMII: 537 case SOC_PORT_IF_KX: 538 case SOC_PORT_IF_KR: 539 case SOC_PORT_IF_DNX_XAUI: 540 case SOC_PORT_IF_XLAUI: 541 case SOC_PORT_IF_RXAUI: 542 case SOC_PORT_IF_KR2: 543 case SOC_PORT_IF_CR2: 544 case SOC_PORT_IF_XFI: 545 case SOC_PORT_IF_SFI: 546 case SOC_PORT_IF_SR4: 547 case SOC_PORT_IF_CR4: 548 case SOC_PORT_IF_KR4: 549 case SOC_PORT_IF_ER4: 550 case SOC_PORT_IF_XGMII: 551 *is_supported = TRUE; 552 break; 553 554 /* these modes pm4x10 should be bypass */ 555 case SOC_PORT_IF_QSGMII: 556 case SOC_PORT_IF_CAUI: 557 *is_supported = TRUE; 558 break; 559 default: 560 *is_supported = FALSE; 561 break; 562 } 563 SOC_FUNC_RETURN; 564 } 565 566 STATIC 567 int _pm4x10_port_index_get(int unit, int port, pm_info_t pm_info, 568 int *first_index, uint32 *bitmap) 569 { 570 int i, rv = 0, tmp_port = 0; 571 572 SOC_INIT_FUNC_DEFS; 573 574 *first_index = -1; 575 *bitmap = 0; 576 577 for( i = 0 ; i < MAX_PORTS_PER_PM4X10; i++) { 578 rv = SOC_WB_ENGINE_GET_ARR (unit, SOC_WB_ENGINE_PORTMOD, 579 pm_info->wb_vars_ids[ports], &tmp_port, i); 580 _SOC_IF_ERR_EXIT(rv); 581 582 if(tmp_port == port){ 583 *first_index = (*first_index == -1 ? i : *first_index); 584 SHR_BITSET(bitmap, i); 585 } 586 } 587 588 if(*first_index == -1) { 589 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 590 (_SOC_MSG("port was not found in internal DB %d"), port)); 591 } 592 593 exit: 594 SOC_FUNC_RETURN; 595 } 596 597 /* 598 * Function: 599 * portmod_pm4x10_wb_upgrade_func 600 * Purpose: 601 * This function will take care of the warmboot variable manipulation 602 * in case of upgrade case, when variable definition got change or 603 * unspoorted varaible from previous version. 604 * Parameters: 605 * unit -(IN) Device unit number . 606 * arg -(IN) Generic pointer for a specific module to be used. 607 * recovered_version -(IN) Warmboot version of the existing data. 608 * new_version -(IN) Warmboot version of new data. 609 * Returns: 610 * Status 611 */ 612 613 int portmod_pm4x10_wb_upgrade_func(int unit, void *arg, int recovered_version, int new_version) 614 { 615 pm_info_t pm_info; 616 int i; 617 int nof_phys, adjust_index; 618 portmod_port_ts_adjust_t port_ts_adjust; 619 soc_port_if_t interface; 620 SOC_INIT_FUNC_DEFS; 621 622 pm_info = arg; 623 624 /* 625 * skip the warmboot db restore, it is only needed for 626 * certain upgrade which will be updated below. 627 */ 628 PM_4x10_INFO(pm_info)->warmboot_skip_db_restore = TRUE; 629 630 if ((recovered_version <= 4) && 631 (new_version >= 5)) { 632 633 /* 634 * Need to do db restore. 635 */ 636 PM_4x10_INFO(pm_info)->warmboot_skip_db_restore = FALSE; 637 } 638 639 if ((recovered_version <= 3) && 640 (new_version >= 4)) { 641 642 /* 643 * in version 3 or earlier, nof_phys was not populated properly. 644 * It need to initialize to 1 to count for internal phy. 1 may not 645 * be proper value as some port may have ext phy. 646 */ 647 nof_phys = 1; 648 for(i = 0 ; i < PM4X10_LANES_PER_CORE ; i++){ 649 _SOC_IF_ERR_EXIT(PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, &nof_phys, i)); 650 PM_4x10_INFO(pm_info)->nof_phys[i] = nof_phys; 651 } 652 } 653 654 if ((recovered_version <= 6) && 655 (new_version >= 7)) { 656 /* interface_written_into_outmost_phy does not exist in version 6 or earlier */ 657 interface = SOC_PORT_IF_COUNT; 658 for (i = 0 ; i < MAX_PORTS_PER_PM4X10 ; i++) { 659 _SOC_IF_ERR_EXIT( 660 PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, i)); 661 } 662 } 663 664 if ((recovered_version <= 7) && 665 (new_version >= 8)) { 666 sal_memset(&port_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 667 for (i = 0; i < MAX_PORTS_PER_PM4X10; i++) { 668 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM_OLD; adjust_index++) { 669 _SOC_IF_ERR_EXIT( 670 PM4x10_PORT_TIME_STAMP_ADJUST_OLD_SET(unit, pm_info, &port_ts_adjust, adjust_index, i)); 671 } 672 } 673 } 674 675 if ((recovered_version <= 9) && 676 (new_version >= 10)) { 677 for (i = 0; i < MAX_PORTS_PER_PM4X10; i++) { 678 /* Copy existing timestamp adjust configs from old WB variable. */ 679 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM_OLD; adjust_index++) { 680 _SOC_IF_ERR_EXIT( 681 PM4x10_PORT_TIME_STAMP_ADJUST_OLD_GET(unit, pm_info, &port_ts_adjust, 682 adjust_index, i)); 683 _SOC_IF_ERR_EXIT( 684 PM4x10_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, &port_ts_adjust, 685 adjust_index, i)); 686 } 687 /* Initialize new timestamp adjust configs as 0. */ 688 while (adjust_index < PORTMOD_TS_ADJUST_NUM) { 689 sal_memset(&port_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 690 _SOC_IF_ERR_EXIT( 691 PM4x10_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, &port_ts_adjust, 692 adjust_index, i)); 693 adjust_index++; 694 } 695 } 696 } 697 exit: 698 SOC_FUNC_RETURN; 699 } 700 /* 701 * Initialize the buffer to support warmboot 702 * The state of warmboot is store in the variables like 703 * isInitialized, isActive, isBypassed, ports.. etc., 704 * All of these variables need to be added to warmboot 705 * any variables added to save the state of warmboot should be 706 * included here. 707 */ 708 STATIC 709 int pm4x10_wb_buffer_init(int unit, int wb_buffer_index, pm_info_t pm_info) 710 { 711 /* Declare the common variables needed for warmboot */ 712 WB_ENGINE_INIT_TABLES_DEFS; 713 int wb_var_id, rv; 714 int buffer_id = wb_buffer_index; /*required by SOC_WB_ENGINE_ADD_ Macros*/ 715 SOC_INIT_FUNC_DEFS; 716 717 COMPILER_REFERENCE(buffer_is_dynamic); 718 719 SOC_WB_ENGINE_ADD_BUFF(SOC_WB_ENGINE_PORTMOD, wb_buffer_index, "pm4x10", 720 portmod_pm4x10_wb_upgrade_func, pm_info, 721 PM4x10_WB_BUFFER_VERSION, 1, SOC_WB_ENGINE_PRE_RELEASE); 722 _SOC_IF_ERR_EXIT(rv); 723 724 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 725 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_initialized", 726 wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 727 _SOC_IF_ERR_EXIT(rv); 728 pm_info->wb_vars_ids[isInitialized] = wb_var_id; 729 730 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 731 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ports", 732 wb_buffer_index, sizeof(int), NULL, 733 MAX_PORTS_PER_PM4X10, VERSION(1)); 734 _SOC_IF_ERR_EXIT(rv); 735 pm_info->wb_vars_ids[ports] = wb_var_id; 736 737 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 738 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_active", 739 wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 740 _SOC_IF_ERR_EXIT(rv); 741 pm_info->wb_vars_ids[isActive] = wb_var_id; 742 743 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 744 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_bypassed", 745 wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 746 _SOC_IF_ERR_EXIT(rv); 747 pm_info->wb_vars_ids[isBypassed] = wb_var_id; 748 749 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 750 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "three_ports_mode", 751 wb_buffer_index, sizeof(uint32), NULL, VERSION(1)); 752 _SOC_IF_ERR_EXIT(rv); 753 pm_info->wb_vars_ids[threePortsMode] = wb_var_id; 754 755 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 756 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "phy_type", 757 wb_buffer_index, sizeof(int), NULL, 758 MAX_PORTS_PER_PM4X10, VERSION(1)); 759 _SOC_IF_ERR_EXIT(rv); 760 pm_info->wb_vars_ids[phy_type] = wb_var_id; 761 762 /* Deleting the below WB structures since most likely to be added in the future in a diffrent format */ 763 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 764 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, 765 "interface_config", wb_buffer_index, 766 sizeof(portmod_port_interface_config_t), 767 NULL, 1, 1, 0xffffffff, 0xffffffff, 768 VERSION(2), VERSION(3), NULL); 769 _SOC_IF_ERR_EXIT(rv); 770 pm_info->wb_vars_ids[interfaceConfig] = wb_var_id; 771 772 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 773 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, 774 "port_init_config", wb_buffer_index, 775 sizeof(portmod_port_init_config_t), 776 NULL, 1, 1, 0xffffffff, 0xffffffff, 777 VERSION(2), VERSION(3), NULL); 778 _SOC_IF_ERR_EXIT(rv); 779 pm_info->wb_vars_ids[portInitConfig] = wb_var_id; 780 781 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 782 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, 783 "phy_init_config", wb_buffer_index, 784 sizeof(phymod_phy_init_config_t), 785 NULL, 1, 1, 0xffffffff, 0xffffffff, 786 VERSION(2), VERSION(3), NULL); 787 _SOC_IF_ERR_EXIT(rv); 788 pm_info->wb_vars_ids[phyInitConfig] = wb_var_id; 789 790 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 791 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, 792 "phy_interface_config", wb_buffer_index, 793 sizeof(phymod_phy_inf_config_t), NULL, 794 1, 1, 0xffffffff, 0xffffffff, VERSION(2), 795 VERSION(3), NULL); 796 _SOC_IF_ERR_EXIT(rv); 797 pm_info->wb_vars_ids[phyInterfaceConfig] = wb_var_id; 798 799 /* 800 * Keeping the below 2 WB var/arr since most likely to be used in the future. 801 */ 802 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 803 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 804 "port_dynamic_state", wb_buffer_index, 805 sizeof(uint32_t), NULL, PM4X10_LANES_PER_CORE, 806 VERSION(2)); 807 _SOC_IF_ERR_EXIT(rv); 808 pm_info->wb_vars_ids[portDynamicState] = wb_var_id; 809 810 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 811 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "nof_phys", 812 wb_buffer_index, sizeof(int), NULL, 813 PM4X10_LANES_PER_CORE, VERSION(2)); 814 _SOC_IF_ERR_EXIT(rv); 815 pm_info->wb_vars_ids[nofPhys] = wb_var_id; 816 817 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 818 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "lane_connection_db", 819 wb_buffer_index, sizeof(portmod_xphy_lane_connection_t), NULL, 820 PM4X10_LANES_PER_CORE, MAX_PHYN, VERSION(4)); 821 _SOC_IF_ERR_EXIT(rv); 822 pm_info->wb_vars_ids[laneConnectionDb] = wb_var_id; 823 824 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 825 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "data_rate", 826 wb_buffer_index, sizeof(int), NULL, 827 MAX_PORTS_PER_PM4X10, VERSION(5)); 828 _SOC_IF_ERR_EXIT(rv); 829 pm_info->wb_vars_ids[dataRate] = wb_var_id; 830 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 831 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "max_speed", 832 wb_buffer_index, sizeof(uint32), NULL, 833 MAX_PORTS_PER_PM4X10, VERSION(5)); 834 _SOC_IF_ERR_EXIT(rv); 835 pm_info->wb_vars_ids[maxSpeed] = wb_var_id; 836 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 837 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_type", 838 wb_buffer_index, sizeof(uint32), NULL, 839 MAX_PORTS_PER_PM4X10, VERSION(5)); 840 _SOC_IF_ERR_EXIT(rv); 841 pm_info->wb_vars_ids[interfaceType] = wb_var_id; 842 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 843 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "serdes_interface", 844 wb_buffer_index, sizeof(uint32), NULL, 845 MAX_PORTS_PER_PM4X10, VERSION(5)); 846 _SOC_IF_ERR_EXIT(rv); 847 pm_info->wb_vars_ids[serdesInterfaceType] = wb_var_id; 848 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 849 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "interface_modes", 850 wb_buffer_index, sizeof(uint32), NULL, 851 MAX_PORTS_PER_PM4X10, VERSION(5)); 852 _SOC_IF_ERR_EXIT(rv); 853 pm_info->wb_vars_ids[interfaceModes] = wb_var_id; 854 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 855 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 856 "is_interface_restore", wb_buffer_index, 857 sizeof(uint32), NULL, PM4X10_LANES_PER_CORE, 858 VERSION(5)); 859 _SOC_IF_ERR_EXIT(rv); 860 pm_info->wb_vars_ids[isInterfaceRestore] = wb_var_id; 861 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 862 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_hg", 863 wb_buffer_index, sizeof(uint32), NULL, 864 PM4X10_LANES_PER_CORE, VERSION(5)); 865 _SOC_IF_ERR_EXIT(rv); 866 pm_info->wb_vars_ids[isHg] = wb_var_id; 867 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 868 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_cl73", 869 wb_buffer_index, sizeof(uint32), NULL, 870 PM4X10_LANES_PER_CORE, VERSION(5)); 871 _SOC_IF_ERR_EXIT(rv); 872 pm_info->wb_vars_ids[anMode] = wb_var_id; 873 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 874 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "fs_cl72", 875 wb_buffer_index, sizeof(uint32), NULL, 876 PM4X10_LANES_PER_CORE, VERSION(5)); 877 _SOC_IF_ERR_EXIT(rv); 878 pm_info->wb_vars_ids[fsCl72] = wb_var_id; 879 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 880 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "cx4_10G", 881 wb_buffer_index, sizeof(uint32), NULL, 882 PM4X10_LANES_PER_CORE, VERSION(5)); 883 _SOC_IF_ERR_EXIT(rv); 884 pm_info->wb_vars_ids[cx4In10G] = wb_var_id; 885 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 886 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_Cl72", 887 wb_buffer_index, sizeof(uint32), NULL, 888 PM4X10_LANES_PER_CORE, VERSION(5)); 889 _SOC_IF_ERR_EXIT(rv); 890 pm_info->wb_vars_ids[anCl72] = wb_var_id; 891 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 892 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_fec", 893 wb_buffer_index, sizeof(uint32), NULL, 894 PM4X10_LANES_PER_CORE, VERSION(5)); 895 _SOC_IF_ERR_EXIT(rv); 896 pm_info->wb_vars_ids[anFec] = wb_var_id; 897 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 898 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_cl37", 899 wb_buffer_index, sizeof(uint32), NULL, 900 PM4X10_LANES_PER_CORE, VERSION(5)); 901 _SOC_IF_ERR_EXIT(rv); 902 pm_info->wb_vars_ids[anCl37] = wb_var_id; 903 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 904 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_master_lane", 905 wb_buffer_index, sizeof(int), NULL, 906 PM4X10_LANES_PER_CORE, VERSION(5)); 907 _SOC_IF_ERR_EXIT(rv); 908 pm_info->wb_vars_ids[anMasterLane] = wb_var_id; 909 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 910 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "cl37_sgmii_count", 911 wb_buffer_index, sizeof(int), NULL, 912 PM4X10_LANES_PER_CORE, VERSION(5)); 913 _SOC_IF_ERR_EXIT(rv); 914 pm_info->wb_vars_ids[cl37SgmiiCnt] = wb_var_id; 915 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 916 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 917 "cl37_sgmii_restart_count", wb_buffer_index, 918 sizeof(int), NULL, PM4X10_LANES_PER_CORE, VERSION(5)); 919 _SOC_IF_ERR_EXIT(rv); 920 pm_info->wb_vars_ids[cl37SgmiiRestartCnt] = wb_var_id; 921 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 922 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "port_op_mode", 923 wb_buffer_index, sizeof(int), NULL, 924 PM4X10_LANES_PER_CORE, VERSION(5)); 925 _SOC_IF_ERR_EXIT(rv); 926 pm_info->wb_vars_ids[portOpMode] = wb_var_id; 927 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 928 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "rxaui_mode", 929 wb_buffer_index, sizeof(int), NULL, 930 PM4X10_LANES_PER_CORE, VERSION(5)); 931 _SOC_IF_ERR_EXIT(rv); 932 pm_info->wb_vars_ids[rxauiMode] = wb_var_id; 933 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 934 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 935 "tx_params_user_flag", 936 wb_buffer_index, sizeof(uint32), NULL, 937 PHYMOD_MAX_LANES_PER_PORT, VERSION(5)); 938 _SOC_IF_ERR_EXIT(rv); 939 pm_info->wb_vars_ids[txParamsUserFlag] = wb_var_id; 940 941 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 942 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, "tx_params", wb_buffer_index, sizeof(pm4x10_phymod_tx_t), NULL, 1, PHYMOD_MAX_LANES_PER_PORT, 0xffffffff, 0xffffffff, VERSION(5), VERSION(9), NULL); 943 _SOC_IF_ERR_EXIT(rv); 944 pm_info->wb_vars_ids[txParams] = wb_var_id; 945 946 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 947 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 948 "ext_phy_tx_params_user_flag", 949 wb_buffer_index, sizeof(uint32), NULL, 950 PHYMOD_MAX_LANES_PER_PORT, VERSION(5)); 951 _SOC_IF_ERR_EXIT(rv); 952 pm_info->wb_vars_ids[extPhyTxParamsUserFlag] = wb_var_id; 953 954 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 955 SOC_WB_ENGINE_ADD_VAR_WITH_FEATURES(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ext_phy_tx_params", wb_buffer_index, sizeof(pm4x10_phymod_tx_t), NULL, 1, PHYMOD_MAX_LANES_PER_PORT, 0xffffffff, 0xffffffff, VERSION(5), VERSION(9), NULL); 956 _SOC_IF_ERR_EXIT(rv); 957 pm_info->wb_vars_ids[extPhyTxParams] = wb_var_id; 958 959 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 960 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "fallback_lane", 961 wb_buffer_index, sizeof(int), NULL, 962 PM4X10_LANES_PER_CORE, VERSION(5)); 963 _SOC_IF_ERR_EXIT(rv); 964 pm_info->wb_vars_ids[fallbackLane] = wb_var_id; 965 966 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 967 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 968 "pll_divider_req", 969 wb_buffer_index, sizeof(int), NULL, 970 PM4X10_LANES_PER_CORE, 971 VERSION(6)); 972 _SOC_IF_ERR_EXIT(rv); 973 pm_info->wb_vars_ids[pllDividerReq] = wb_var_id; 974 975 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 976 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 977 "interface_written_into_outmost_phy", 978 wb_buffer_index, sizeof(uint32), NULL, 979 MAX_PORTS_PER_PM4X10, VERSION(7)); 980 _SOC_IF_ERR_EXIT(rv); 981 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy] = wb_var_id; 982 983 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 984 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 985 "time stamp adjust setting on MAC", 986 wb_buffer_index, sizeof(portmod_port_ts_adjust_t), NULL, 987 PORTMOD_TS_ADJUST_NUM_OLD, 988 MAX_PORTS_PER_PM4X10, VERSION(8)); 989 _SOC_IF_ERR_EXIT(rv); 990 pm_info->wb_vars_ids[tsAdjustOld] = wb_var_id; 991 992 _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id)); 993 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, 994 "new time stamp adjust setting on MAC", 995 wb_buffer_index, sizeof(portmod_port_ts_adjust_t), NULL, 996 PORTMOD_TS_ADJUST_NUM, 997 MAX_PORTS_PER_PM4X10, VERSION(10)); 998 _SOC_IF_ERR_EXIT(rv); 999 pm_info->wb_vars_ids[tsAdjust] = wb_var_id; 1000 1001 _SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD, 1002 wb_buffer_index, FALSE)); 1003 1004 if(!SOC_WARM_BOOT(unit)){ 1005 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1006 pm_info->wb_vars_ids[ports], -1); 1007 _SOC_IF_ERR_EXIT(rv); 1008 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1009 pm_info->wb_vars_ids[dataRate], 0); 1010 _SOC_IF_ERR_EXIT(rv); 1011 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1012 pm_info->wb_vars_ids[maxSpeed], 0); 1013 _SOC_IF_ERR_EXIT(rv); 1014 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1015 pm_info->wb_vars_ids[interfaceType], 1016 _SHR_PORT_IF_COUNT); 1017 _SOC_IF_ERR_EXIT(rv); 1018 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1019 pm_info->wb_vars_ids[serdesInterfaceType], 1020 _SHR_PORT_IF_NULL); 1021 _SOC_IF_ERR_EXIT(rv); 1022 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1023 pm_info->wb_vars_ids[interfaceModes], 0); 1024 _SOC_IF_ERR_EXIT(rv); 1025 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1026 pm_info->wb_vars_ids[nofPhys], 0); 1027 _SOC_IF_ERR_EXIT(rv); 1028 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1029 pm_info->wb_vars_ids[portDynamicState], 0); 1030 _SOC_IF_ERR_EXIT(rv); 1031 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1032 pm_info->wb_vars_ids[isInterfaceRestore], 0); 1033 _SOC_IF_ERR_EXIT(rv); 1034 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1035 pm_info->wb_vars_ids[isHg], _SHR_PORT_IF_COUNT); 1036 _SOC_IF_ERR_EXIT(rv); 1037 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1038 pm_info->wb_vars_ids[anMode], 1039 phymod_AN_MODE_Count); 1040 _SOC_IF_ERR_EXIT(rv); 1041 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1042 pm_info->wb_vars_ids[fsCl72], 0); 1043 _SOC_IF_ERR_EXIT(rv); 1044 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1045 pm_info->wb_vars_ids[cx4In10G], 0); 1046 _SOC_IF_ERR_EXIT(rv); 1047 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1048 pm_info->wb_vars_ids[anCl72], 0); 1049 _SOC_IF_ERR_EXIT(rv); 1050 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1051 pm_info->wb_vars_ids[anFec], 0); 1052 _SOC_IF_ERR_EXIT(rv); 1053 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1054 pm_info->wb_vars_ids[anCl37], 0); 1055 _SOC_IF_ERR_EXIT(rv); 1056 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1057 pm_info->wb_vars_ids[anMasterLane], -1); 1058 _SOC_IF_ERR_EXIT(rv); 1059 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1060 pm_info->wb_vars_ids[rxauiMode], 0); 1061 _SOC_IF_ERR_EXIT(rv); 1062 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1063 pm_info->wb_vars_ids[txParamsUserFlag], 0); 1064 _SOC_IF_ERR_EXIT(rv); 1065 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1066 pm_info->wb_vars_ids[extPhyTxParamsUserFlag], 0); 1067 _SOC_IF_ERR_EXIT(rv); 1068 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1069 pm_info->wb_vars_ids[pllDividerReq], 0); 1070 _SOC_IF_ERR_EXIT(rv); 1071 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1072 pm_info->wb_vars_ids[interfaceWrittenIntoOutmostPhy], _SHR_PORT_IF_COUNT); 1073 _SOC_IF_ERR_EXIT(rv); 1074 } 1075 exit: 1076 SOC_FUNC_RETURN; 1077 } 1078 1079 STATIC portmod_ucode_buf_t pm4x10_ucode_buf[SOC_MAX_NUM_DEVICES] = {{NULL, 0}}; 1080 STATIC portmod_ucode_buf_t pm4x10_ucode_buf_2nd[SOC_MAX_NUM_DEVICES] = {{NULL, 0}}; 1081 1082 1083 int pm4x10_pm_destroy(int unit, pm_info_t pm_info) 1084 { 1085 if(pm_info->pm_data.pm4x10_db != NULL) { 1086 sal_free(pm_info->pm_data.pm4x10_db); 1087 pm_info->pm_data.pm4x10_db = NULL; 1088 } 1089 1090 /* free pm4x10_ucode_buf */ 1091 if(pm4x10_ucode_buf[unit].ucode_dma_buf != NULL){ 1092 portmod_sys_dma_free(unit, pm4x10_ucode_buf[unit].ucode_dma_buf); 1093 pm4x10_ucode_buf[unit].ucode_dma_buf = NULL; 1094 } 1095 pm4x10_ucode_buf[unit].ucode_alloc_size = 0; 1096 1097 if(pm4x10_ucode_buf_2nd[unit].ucode_dma_buf != NULL){ 1098 portmod_sys_dma_free(unit, pm4x10_ucode_buf_2nd[unit].ucode_dma_buf); 1099 pm4x10_ucode_buf_2nd[unit].ucode_dma_buf = NULL; 1100 } 1101 pm4x10_ucode_buf_2nd[unit].ucode_alloc_size = 0; 1102 1103 return SOC_E_NONE; 1104 } 1105 1106 int 1107 pm4x10_default_fw_loader(const phymod_core_access_t* core, uint32_t length, const uint8_t* data) 1108 { 1109 int rv; 1110 portmod_default_user_access_t *user_data; 1111 int unit = ((portmod_default_user_access_t*)core->access.user_acc)->unit; 1112 portmod_ucode_buf_order_t load_order; 1113 SOC_INIT_FUNC_DEFS; 1114 1115 user_data = (portmod_default_user_access_t*)core->access.user_acc; 1116 1117 if (PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_GET(user_data)) { 1118 load_order = portmod_ucode_buf_order_reversed; 1119 } else { 1120 load_order = portmod_ucode_buf_order_straight; 1121 } 1122 1123 rv = portmod_firmware_set(unit, 1124 user_data->blk_id, 1125 data, 1126 length, 1127 load_order, 1128 0, 1129 &(pm4x10_ucode_buf[unit]), 1130 &(pm4x10_ucode_buf_2nd[unit]), 1131 XLPORT_WC_UCMEM_DATAm, 1132 XLPORT_WC_UCMEM_CTRLr); 1133 _SOC_IF_ERR_EXIT(rv); 1134 1135 exit: 1136 SOC_FUNC_RETURN; 1137 } 1138 1139 STATIC 1140 int 1141 pm4x10_default_bus_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 1142 { 1143 return portmod_common_phy_sbus_reg_write(XLPORT_WC_UCMEM_DATAm, user_acc, core_addr, reg_addr, val); 1144 } 1145 1146 STATIC 1147 int 1148 pm4x10_default_bus_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 1149 { 1150 return portmod_common_phy_sbus_reg_read(XLPORT_WC_UCMEM_DATAm, user_acc, core_addr, reg_addr, val); 1151 } 1152 1153 /* 1154 * XLPORT_SOFT_RESET by physical port 1155 * This function expects 2nd argument port is physical port. 1156 */ 1157 STATIC 1158 int _pm4x10_port_soft_reset_set_by_phyport(int unit, int port, pm_info_t pm_info, int idx, int val) 1159 { 1160 int phy_port; 1161 uint32 reg_val, raddr; 1162 int block; 1163 uint8 at; 1164 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 1165 1166 SOC_INIT_FUNC_DEFS; 1167 1168 phy_port = port; 1169 raddr = soc_reg_addr_get(unit, XLPORT_SOFT_RESETr, phy_port, 0, 1170 SOC_REG_ADDR_OPTION_PRESERVE_PORT, 1171 &block, &at); 1172 1173 _SOC_IF_ERR_EXIT 1174 (_soc_reg32_get(unit, block, at, raddr, ®_val)); 1175 1176 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, port_fields[idx], val); 1177 1178 raddr = soc_reg_addr_get(unit, XLPORT_SOFT_RESETr, phy_port, 0, 1179 SOC_REG_ADDR_OPTION_WRITE | SOC_REG_ADDR_OPTION_PRESERVE_PORT, 1180 &block, &at); 1181 _SOC_IF_ERR_EXIT(_soc_reg32_set(unit, block, at, raddr, reg_val)); 1182 1183 exit: 1184 SOC_FUNC_RETURN; 1185 } 1186 1187 STATIC 1188 int _pm4x10_port_soft_reset_set(int unit, int port, pm_info_t pm_info, int idx, int val) 1189 { 1190 int phy_acc; 1191 uint32 reg_val; 1192 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 1193 1194 SOC_INIT_FUNC_DEFS; 1195 1196 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1197 1198 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 1199 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, port_fields[idx], 1200 val); 1201 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 1202 1203 exit: 1204 SOC_FUNC_RETURN; 1205 } 1206 1207 int pm4x10_port_soft_reset_toggle(int unit, int port, pm_info_t pm_info, int idx) 1208 { 1209 int phy_acc; 1210 uint32 reg_val, old_val; 1211 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 1212 1213 SOC_INIT_FUNC_DEFS; 1214 1215 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1216 1217 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 1218 old_val = reg_val; 1219 1220 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, port_fields[idx], 1); 1221 1222 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 1223 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, old_val)); 1224 1225 exit: 1226 SOC_FUNC_RETURN; 1227 } 1228 1229 phymod_bus_t pm4x10_default_bus = { 1230 "PM4x10 Bus", 1231 pm4x10_default_bus_read, 1232 pm4x10_default_bus_write, 1233 NULL, 1234 portmod_common_mutex_take, 1235 portmod_common_mutex_give, 1236 NULL, 1237 NULL, 1238 PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL 1239 }; 1240 1241 int pm4x10_pm_init(int unit, 1242 const portmod_pm_create_info_internal_t* pm_add_info, 1243 int wb_buffer_index, pm_info_t pm_info) 1244 { 1245 const portmod_pm4x10_create_info_t *info; 1246 pm4x10_t pm4x10_data = NULL; 1247 int i,j, pm_is_active, rv, three_ports_mode, nof_phys = 0; 1248 int pm_is_initialized; 1249 int bypass_enable; 1250 int lane, phyn; 1251 portmod_xphy_lane_connection_t lane_conn; 1252 portmod_xphy_lane_connection_t *db_lane_conn; 1253 1254 SOC_INIT_FUNC_DEFS; 1255 1256 info = &pm_add_info->pm_specific_info.pm4x10; 1257 pm4x10_data = sal_alloc(sizeof(struct pm4x10_s), "pm4x10_specific_db"); 1258 SOC_NULL_CHECK(pm4x10_data); 1259 1260 pm_info->type = pm_add_info->type; 1261 pm_info->unit = unit; 1262 pm_info->wb_buffer_id = wb_buffer_index; 1263 pm_info->pm_data.pm4x10_db = pm4x10_data; 1264 pm_info->pm_data.pm4x10_db->link_recovery.enabled = TRUE; 1265 pm_info->pm_data.pm4x10_db->link_recovery.tick_cnt = 0; 1266 pm_info->pm_data.pm4x10_db->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK; 1267 PORTMOD_PBMP_ASSIGN(pm4x10_data->phys, pm_add_info->phys); 1268 pm4x10_data->int_core_access.type = phymodDispatchTypeInvalid; 1269 pm4x10_data->default_bus_is_used = 0; 1270 pm4x10_data->default_fw_loader_is_used = 0; 1271 pm4x10_data->portmod_phy_external_reset = pm_add_info->pm_specific_info.pm4x10.portmod_phy_external_reset; 1272 pm4x10_data->portmod_mac_soft_reset = pm_add_info->pm_specific_info.pm4x10.portmod_mac_soft_reset; 1273 pm4x10_data->first_phy = -1; 1274 pm4x10_data->warmboot_skip_db_restore = TRUE; 1275 pm4x10_data->rescal = pm_add_info->pm_specific_info.pm4x10.rescal; 1276 pm4x10_data->is_pm4x10q = pm_add_info->pm_specific_info.pm4x10.is_pm4x10q; 1277 pm4x10_data->port_mode_aux_info = pm_add_info->pm_specific_info.pm4x10.port_mode_aux_info; 1278 1279 /* initialize num of phys for each lane */ 1280 for(i = 0 ; i < PM4X10_LANES_PER_CORE ; i++){ 1281 pm4x10_data->nof_phys[i] = 0; 1282 } 1283 /* init intertnal SerDes core access */ 1284 phymod_core_access_t_init(&pm4x10_data->int_core_access); 1285 1286 /* initialize lane connections */ 1287 for(i = 0 ; i < MAX_PHYN ; i++){ 1288 for(j = 0 ; j < PM4X10_LANES_PER_CORE ; j++){ 1289 portmod_xphy_lane_connection_t_init(unit, &pm4x10_data->lane_conn[i][j]); 1290 } 1291 } 1292 1293 sal_memcpy(&pm4x10_data->polarity, &info->polarity, 1294 sizeof(phymod_polarity_t)); 1295 sal_memcpy(&(pm4x10_data->int_core_access.access), &info->access, 1296 sizeof(phymod_access_t)); 1297 sal_memcpy(&pm4x10_data->lane_map, &info->lane_map, 1298 sizeof(pm4x10_data->lane_map)); 1299 pm4x10_data->ref_clk = info->ref_clk; 1300 pm4x10_data->fw_load_method = info->fw_load_method; 1301 pm4x10_data->external_fw_loader = info->external_fw_loader; 1302 1303 if(info->access.bus == NULL) { 1304 /* if null - use default */ 1305 pm4x10_data->int_core_access.access.bus = &pm4x10_default_bus; 1306 pm4x10_data->default_bus_is_used = 1; 1307 } 1308 1309 if(pm4x10_data->external_fw_loader == NULL) { 1310 /* if null - use default */ 1311 pm4x10_data->external_fw_loader = pm4x10_default_fw_loader; 1312 pm4x10_data->default_fw_loader_is_used = 1; 1313 } 1314 1315 /* initialize num of phys for each lane */ 1316 for(i = 0 ; i < PM4X10_LANES_PER_CORE ; i++){ 1317 pm4x10_data->nof_phys[i] = 1; 1318 } 1319 1320 pm4x10_data->in_pm12x10 = info->in_pm_12x10; 1321 pm4x10_data->core_num = info->core_num; 1322 pm4x10_data->core_num_int = info->core_num_int; 1323 1324 /*init wb buffer*/ 1325 _SOC_IF_ERR_EXIT(pm4x10_wb_buffer_init(unit, wb_buffer_index, pm_info)); 1326 1327 if(SOC_WARM_BOOT(unit)){ 1328 1329 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1330 pm_info->wb_vars_ids[phy_type], &pm4x10_data->int_core_access.type, 0); 1331 1332 /* restore nof_phys from wb */ 1333 for(i = 0 ; i < PM4X10_LANES_PER_CORE ; i++){ 1334 _SOC_IF_ERR_EXIT(PM4x10_PORT_NUM_PHYS_GET(unit, pm_info, &nof_phys, i)); 1335 pm4x10_data->nof_phys[i] = nof_phys; 1336 } 1337 1338 for(phyn = 0 ; phyn < MAX_PHYN ; phyn++){ 1339 for(lane = 0 ; lane < PM4X10_LANES_PER_CORE ; lane++){ 1340 db_lane_conn = &(PM_4x10_INFO(pm_info)->lane_conn[phyn][lane]); 1341 _SOC_IF_ERR_EXIT(PM4x10_PORT_LANE_CONNECTION_DB_GET(unit, pm_info, 1342 db_lane_conn, phyn, lane)); 1343 } 1344 } 1345 1346 _SOC_IF_ERR_EXIT(rv); 1347 } 1348 1349 if(!SOC_WARM_BOOT(unit)){ 1350 /* Cold Boot */ 1351 1352 for(i = 0 ; i < PM4X10_LANES_PER_CORE ; i++){ 1353 nof_phys = 1; 1354 rv = PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, &nof_phys, i); 1355 _SOC_IF_ERR_EXIT(rv); 1356 } 1357 1358 pm_is_active = 0; 1359 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1360 pm_info->wb_vars_ids[isActive], &pm_is_active); 1361 _SOC_IF_ERR_EXIT(rv); 1362 1363 pm_is_initialized = 0; 1364 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1365 pm_info->wb_vars_ids[isInitialized], &pm_is_initialized); 1366 _SOC_IF_ERR_EXIT(rv); 1367 1368 bypass_enable = 0; 1369 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 1370 pm_info->wb_vars_ids[isBypassed], &bypass_enable); 1371 _SOC_IF_ERR_EXIT(rv); 1372 1373 three_ports_mode = (info->port_mode_aux_info == portmodModeInfoThreePorts) ? 1 : 0; 1374 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 1375 pm_info->wb_vars_ids[threePortsMode], &three_ports_mode); 1376 _SOC_IF_ERR_EXIT(rv); 1377 1378 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1379 pm_info->wb_vars_ids[phy_type], 1380 &PM_4x10_INFO(pm_info)->int_core_access.type, 0); 1381 _SOC_IF_ERR_EXIT(rv); 1382 1383 for(phyn = 0 ; phyn < MAX_PHYN ; phyn++){ 1384 for(lane = 0 ; lane < PM4X10_LANES_PER_CORE ; lane++){ 1385 portmod_xphy_lane_connection_t_init(unit, &lane_conn); 1386 _SOC_IF_ERR_EXIT(PM4x10_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, 1387 &lane_conn, phyn, lane)); 1388 } 1389 } 1390 } 1391 1392 exit: 1393 if(SOC_FUNC_ERROR){ 1394 pm4x10_pm_destroy(unit, pm_info); 1395 } 1396 SOC_FUNC_RETURN; 1397 } 1398 1399 int 1400 pm4x10_default_bus_update(int unit, pm_info_t pm_info, const portmod_bus_update_t* update) 1401 { 1402 portmod_default_user_access_t* user_acc; 1403 soc_error_t rv = SOC_E_NONE; 1404 SOC_INIT_FUNC_DEFS; 1405 1406 if (update == NULL) /*restore to default*/ 1407 { 1408 /* if null - use default */ 1409 PM_4x10_INFO(pm_info)->int_core_access.access.bus = &pm4x10_default_bus; 1410 PM_4x10_INFO(pm_info)->int_core_access.type = phymodDispatchTypeInvalid; 1411 PM_4x10_INFO(pm_info)->default_bus_is_used = 1; 1412 1413 PM_4x10_INFO(pm_info)->external_fw_loader = pm4x10_default_fw_loader; 1414 PM_4x10_INFO(pm_info)->default_fw_loader_is_used = 1; 1415 } 1416 else 1417 { 1418 1419 if(PM_4x10_INFO(pm_info)->default_fw_loader_is_used && update->external_fw_loader != NULL) { 1420 PM_4x10_INFO(pm_info)->external_fw_loader = update->external_fw_loader; 1421 user_acc = (portmod_default_user_access_t*)PM_4x10_INFO(pm_info)->int_core_access.access.user_acc; 1422 user_acc->blk_id = (update->blk_id == -1) ? user_acc->blk_id : update->blk_id; 1423 PM_4x10_INFO(pm_info)->default_fw_loader_is_used = 0; 1424 } 1425 1426 if(PM_4x10_INFO(pm_info)->default_bus_is_used && update->default_bus != NULL) { 1427 PM_4x10_INFO(pm_info)->int_core_access.access.bus = update->default_bus; 1428 user_acc = (portmod_default_user_access_t*)PM_4x10_INFO(pm_info)->int_core_access.access.user_acc; 1429 user_acc->blk_id = (update->blk_id == -1) ? user_acc->blk_id : update->blk_id; 1430 if (PM_4x10_INFO(pm_info)->int_core_access.type >= phymodDispatchTypeCount) { 1431 PM_4x10_INFO(pm_info)->int_core_access.type = phymodDispatchTypeInvalid; 1432 } 1433 PM_4x10_INFO(pm_info)->default_bus_is_used = 0; 1434 } 1435 1436 if (update->user_acc != NULL) { 1437 PM_4x10_INFO(pm_info)->int_core_access.access.user_acc = update->user_acc; 1438 } 1439 1440 } 1441 1442 /*update warmboot engine*/ 1443 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 1444 pm_info->wb_vars_ids[phy_type], 1445 &PM_4x10_INFO(pm_info)->int_core_access.type, 0); 1446 _SOC_IF_ERR_EXIT(rv); 1447 1448 exit: 1449 SOC_FUNC_RETURN; 1450 } 1451 1452 STATIC 1453 int _pm4x10_port_tricore_lane_info_get(int unit, int port, pm_info_t pm_info, 1454 int *start_lane, int* end_lane, 1455 int *line_start_lane, int* line_end_lane, 1456 uint32 *int_core_lane_mask, 1457 const portmod_access_get_params_t* params); 1458 1459 STATIC 1460 int _pm4x10_nof_lanes_get(int unit, int port, pm_info_t pm_info) 1461 { 1462 int port_index, rv; 1463 uint32_t bitmap, bcnt = 0; 1464 1465 rv = _pm4x10_port_index_get (unit, port, pm_info, &port_index, 1466 &bitmap); 1467 if (rv) return (0); /* bit count is zero will flag error */ 1468 1469 while (bitmap) { 1470 if (bitmap & 0x1) bcnt++; 1471 bitmap >>= 1; 1472 } 1473 1474 return (bcnt); 1475 } 1476 1477 STATIC 1478 int _pm4x10_an_mode_update (int unit, int port, pm_info_t pm_info, 1479 int an_cl37, int an_cl73); 1480 1481 int pm4x10_port_warmboot_db_restore(int unit, int port, pm_info_t pm_info, 1482 const portmod_port_interface_config_t *f_intf_config, 1483 const portmod_port_init_config_t *f_init_config, 1484 const phymod_operation_mode_t phy_op_mode) 1485 { 1486 pm4x10_t pm4x10_data = NULL; 1487 phymod_phy_access_t phy_access[1+MAX_PHYN]; 1488 phymod_phy_inf_config_t phy_intf_config; 1489 phymod_autoneg_control_t an; 1490 portmod_encap_t encap_mode; 1491 soc_port_if_t interface; 1492 1493 int phy, nof_phys, port_index, rv = 0, flags = 0; 1494 uint32 bitmap, an_done, interface_modes = 0, is_interface_restore = 0; 1495 1496 /* 1497 * if no warmboot db restore is require, just return here. 1498 */ 1499 if(PM_4x10_INFO(pm_info)->warmboot_skip_db_restore){ 1500 return SOC_E_NONE; 1501 } 1502 1503 rv = _pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap); 1504 if (SOC_FAILURE(rv)) return (rv); 1505 1506 pm4x10_data = pm_info->pm_data.pm4x10_db; 1507 SOC_IF_ERROR_RETURN(phymod_phy_inf_config_t_init(&phy_intf_config)); 1508 1509 rv = PM4x10_IS_HG_SET(unit, pm_info, f_init_config->is_hg, port_index); 1510 if (SOC_FAILURE(rv)) return (rv); 1511 1512 rv = PM4x10_AN_MODE_SET(unit, pm_info, f_init_config->an_mode, port_index); 1513 if (SOC_FAILURE(rv)) return (rv); 1514 1515 rv = PM4x10_FS_CL72_SET(unit, pm_info, f_init_config->fs_cl72, port_index); 1516 if (SOC_FAILURE(rv)) return (rv); 1517 1518 rv = PM4x10_CX4_10G_SET(unit, pm_info, f_init_config->cx4_10g, port_index); 1519 if (SOC_FAILURE(rv)) return (rv); 1520 1521 rv = PM4x10_AN_CL72_SET(unit, pm_info, f_init_config->an_cl72, port_index); 1522 if (SOC_FAILURE(rv)) return (rv); 1523 1524 rv = PM4x10_AN_FEC_SET(unit, pm_info, f_init_config->an_fec, port_index); 1525 if (SOC_FAILURE(rv)) return (rv); 1526 1527 rv = PM4x10_AN_CL37_SET(unit, pm_info, f_init_config->an_cl37, port_index); 1528 if (SOC_FAILURE(rv)) return (rv); 1529 1530 rv = PM4x10_AN_MASTER_LANE_SET(unit, pm_info, 1531 f_init_config->an_master_lane, 1532 port_index); 1533 if (SOC_FAILURE(rv)) return (rv); 1534 1535 rv = PM4x10_PORT_FALLBACK_LANE_SET(unit, pm_info, 1536 f_init_config->port_fallback_lane, 1537 port_index); 1538 if (SOC_FAILURE(rv)) return (rv); 1539 1540 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, f_intf_config->max_speed, 1541 port_index); 1542 if (SOC_FAILURE(rv)) return (rv); 1543 1544 rv = PM4x10_RXAUI_MODE_SET(unit, pm_info, f_init_config->rxaui_mode, 1545 port_index); 1546 if (SOC_FAILURE(rv)) return (rv); 1547 1548 1549 rv = PM4x10_INTERFACE_TYPE_SET(unit, pm_info, 1550 f_intf_config->interface, 1551 port_index); 1552 if (SOC_FAILURE(rv)) return (rv); 1553 1554 rv = PM4x10_SERDES_INTERFACE_TYPE_SET(unit, pm_info, 1555 f_intf_config->serdes_interface, 1556 port_index); 1557 if (SOC_FAILURE(rv)) return (rv); 1558 1559 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) { 1560 pm4x10_data->first_phy = phy; 1561 break; 1562 } 1563 1564 rv = portmod_port_chain_phy_access_get (unit, port, pm_info, phy_access, 1565 (1+MAX_PHYN), &nof_phys); 1566 if (SOC_FAILURE(rv)) return (rv); 1567 1568 rv = portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 1569 0, phymodRefClk156Mhz, &phy_intf_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 1570 if (SOC_FAILURE(rv)) return (rv); 1571 1572 rv = PM4x10_IS_INTERFACE_RESTORE_SET(unit, pm_info, is_interface_restore, 1573 port_index); 1574 if (SOC_FAILURE(rv)) return (rv); 1575 1576 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 1577 port_index); 1578 if (SOC_FAILURE(rv)) return (rv); 1579 1580 interface_modes |= phy_intf_config.interface_modes; 1581 1582 rv = PM4x10_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 1583 if (SOC_FAILURE(rv)) return (rv); 1584 1585 rv = portmod_port_interface_type_get (unit, port, &interface); 1586 if (SOC_FAILURE(rv)) return (rv); 1587 1588 rv = PM4x10_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index); 1589 if (SOC_FAILURE(rv)) return (rv); 1590 1591 rv = PM4x10_SPEED_SET(unit, pm_info, phy_intf_config.data_rate, port_index); 1592 if (SOC_FAILURE(rv)) return (rv); 1593 1594 xlmac_encap_get(unit, port, &flags, &encap_mode); 1595 1596 if ((encap_mode == SOC_ENCAP_HIGIG2) || (encap_mode == SOC_ENCAP_HIGIG)) { 1597 interface_modes |= PHYMOD_INTF_MODES_HIGIG; 1598 rv = PM4x10_INTERFACE_MODES_SET(unit, pm_info, interface_modes, 1599 port_index); 1600 if (SOC_FAILURE(rv)) return (rv); 1601 } 1602 1603 rv = portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an, &an_done); 1604 if (SOC_FAILURE(rv)) return (rv); 1605 1606 rv = PM4x10_AN_MODE_SET(unit, pm_info, an.an_mode, port_index); 1607 if (SOC_FAILURE(rv)) return (rv); 1608 1609 if(an.an_mode == phymod_AN_MODE_NONE){ 1610 _pm4x10_an_mode_update(unit, port, pm_info, f_init_config->an_cl37, 1611 f_init_config->an_cl73); 1612 } 1613 1614 rv = PM4x10_PORT_OP_MODE_SET(unit, pm_info, phy_op_mode, port_index); 1615 if (SOC_FAILURE(rv)) return (rv); 1616 1617 return (SOC_E_NONE); 1618 } 1619 1620 STATIC 1621 int _pm4x10_tsc_reset(int unit, pm_info_t pm_info, int port, int in_reset) 1622 { 1623 int phy_acc; 1624 uint32 reg_val, phy; 1625 SOC_INIT_FUNC_DEFS; 1626 1627 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1628 1629 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) {break;}; 1630 1631 if(PM_4x10_INFO(pm_info)->in_pm12x10) { 1632 #ifdef PORTMOD_PM12X10_SUPPORT 1633 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 1634 1635 if (SOC_IS_APACHE(unit)) { 1636 _SOC_IF_ERR_EXIT(pm12x10_xgs_pm4x10_tsc_reset(unit, port, phy, in_reset)); 1637 } else 1638 #endif 1639 { 1640 _SOC_IF_ERR_EXIT(pm12x10_pm4x10_tsc_reset(unit, port, phy, in_reset)); 1641 } 1642 #endif 1643 } else { 1644 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_CTRL_REGr(unit, phy_acc, ®_val)); 1645 1646 soc_reg_field_set (unit, XLPORT_XGXS0_CTRL_REGr, ®_val, RSTB_HWf, 1647 in_reset ? 0 : 1); 1648 soc_reg_field_set (unit, XLPORT_XGXS0_CTRL_REGr, ®_val, PWRDWNf, 1649 in_reset ? 1 : 0); 1650 soc_reg_field_set (unit, XLPORT_XGXS0_CTRL_REGr, ®_val, IDDQf, 1651 in_reset ? 1 : 0); 1652 1653 _SOC_IF_ERR_EXIT(WRITE_XLPORT_XGXS0_CTRL_REGr(unit, phy_acc, reg_val)); 1654 } 1655 1656 sal_usleep(1100); 1657 1658 exit: 1659 SOC_FUNC_RETURN; 1660 } 1661 1662 static int _xlport_mode_get(int unit, int phy_acc, int bindex, 1663 portmod_core_port_mode_t *core_mode, int *cur_lanes) 1664 { 1665 uint32_t rval; 1666 1667 SOC_INIT_FUNC_DEFS; 1668 1669 /* Toggle link bit to notify IPIPE on link up */ 1670 _SOC_IF_ERR_EXIT(READ_XLPORT_MODE_REGr(unit, phy_acc, &rval)); 1671 1672 *core_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval, XPORT0_CORE_PORT_MODEf); 1673 1674 switch (*core_mode) { 1675 case portmodPortModeQuad: 1676 *cur_lanes = 1; 1677 break; 1678 1679 case portmodPortModeTri012: 1680 *cur_lanes = (bindex == 2 ? 2 : 1); 1681 break; 1682 1683 case portmodPortModeTri023: 1684 *cur_lanes = (bindex == 0 ? 2 : 1); 1685 break; 1686 1687 case portmodPortModeDual: 1688 *cur_lanes = 2; 1689 break; 1690 1691 case portmodPortModeSingle: 1692 *cur_lanes = 4; 1693 break; 1694 1695 default: 1696 return SOC_E_FAIL; 1697 } 1698 1699 exit: 1700 SOC_FUNC_RETURN; 1701 } 1702 1703 static int _xlport_mode_set(int unit, int phy_acc, portmod_core_port_mode_t cur_mode) 1704 { 1705 uint32_t rval; 1706 int mode; 1707 1708 SOC_INIT_FUNC_DEFS; 1709 1710 switch (cur_mode) { 1711 case portmodPortModeQuad: 1712 mode = 0; 1713 break; 1714 1715 case portmodPortModeTri012: 1716 mode = 1; 1717 break; 1718 1719 case portmodPortModeTri023: 1720 mode = 2; 1721 break; 1722 1723 case portmodPortModeDual: 1724 mode = 3; 1725 break; 1726 1727 case portmodPortModeSingle: 1728 mode = 4; 1729 break; 1730 1731 default: 1732 return SOC_E_FAIL; 1733 } 1734 1735 /* Toggle link bit to notify IPIPE on link up */ 1736 _SOC_IF_ERR_EXIT(READ_XLPORT_MODE_REGr(unit, phy_acc, &rval)); 1737 1738 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf, mode); 1739 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf, mode); 1740 1741 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MODE_REGr(unit, phy_acc, rval)); 1742 1743 exit: 1744 SOC_FUNC_RETURN; 1745 } 1746 1747 int pm4x10_port_cntmaxsize_get(int unit, int port, pm_info_t pm_info, int *val) 1748 { 1749 int phy_acc; 1750 1751 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1752 1753 return (READ_XLPORT_CNTMAXSIZEr(unit, phy_acc, (uint32_t *)val)); 1754 } 1755 1756 int pm4x10_port_cntmaxsize_set(int unit, int port, pm_info_t pm_info, int val) 1757 { 1758 uint32 reg_val; 1759 int phy_acc, rv = 0; 1760 1761 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1762 1763 rv = READ_XLPORT_CNTMAXSIZEr(unit, phy_acc, ®_val); 1764 if (SOC_FAILURE(rv)) return (rv); 1765 1766 soc_reg_field_set(unit, XLPORT_CNTMAXSIZEr, ®_val, CNTMAXSIZEf, val); 1767 1768 return(WRITE_XLPORT_CNTMAXSIZEr(unit, phy_acc, reg_val)); 1769 } 1770 1771 int pm4x10_port_mib_reset_toggle(int unit, int port, pm_info_t pm_info, int port_index) 1772 { 1773 uint32 reg_val[1]; 1774 int rv = 0, phy_acc; 1775 1776 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1777 1778 rv = READ_XLPORT_MIB_RESETr(unit, phy_acc, reg_val); 1779 if (SOC_FAILURE(rv)) return (rv); 1780 SHR_BITSET(reg_val, port_index); 1781 1782 rv = WRITE_XLPORT_MIB_RESETr(unit, phy_acc, *reg_val); 1783 if (SOC_FAILURE(rv)) return (rv); 1784 SHR_BITCLR(reg_val, port_index); 1785 1786 return(WRITE_XLPORT_MIB_RESETr(unit, phy_acc, *reg_val)); 1787 } 1788 int pm4x10_port_modid_set (int unit, int port, pm_info_t pm_info, int value) 1789 { 1790 uint32_t rval, modid; 1791 int flen, phy_acc; 1792 SOC_INIT_FUNC_DEFS; 1793 1794 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1795 1796 flen = soc_reg_field_length(unit, XLPORT_CONFIGr, MY_MODIDf)? value : 0; 1797 modid = (value < (1 << flen))? value : 0; 1798 1799 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1800 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, MY_MODIDf, modid); 1801 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, rval)); 1802 1803 exit: 1804 SOC_FUNC_RETURN; 1805 } 1806 1807 int pm4x10_port_higig2_mode_set (int unit, int port, pm_info_t pm_info, int mode) 1808 { 1809 int phy_acc; 1810 uint32_t rval; 1811 SOC_INIT_FUNC_DEFS; 1812 1813 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1814 1815 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1816 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG2_MODEf, mode); 1817 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, rval)); 1818 1819 exit: 1820 SOC_FUNC_RETURN; 1821 } 1822 1823 int pm4x10_port_higig_mode_set (int unit, int port, pm_info_t pm_info, int mode) 1824 { 1825 int phy_acc; 1826 uint32_t rval; 1827 SOC_INIT_FUNC_DEFS; 1828 1829 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1830 1831 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1832 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG_MODEf, mode); 1833 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, rval)); 1834 1835 exit: 1836 SOC_FUNC_RETURN; 1837 } 1838 1839 int pm4x10_port_higig2_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 1840 { 1841 int phy_acc; 1842 uint32_t rval; 1843 SOC_INIT_FUNC_DEFS; 1844 1845 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1846 1847 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1848 *(mode) = soc_reg_field_get(unit, XLPORT_CONFIGr, rval, HIGIG2_MODEf); 1849 1850 exit: 1851 SOC_FUNC_RETURN; 1852 } 1853 1854 int pm4x10_port_higig_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 1855 { 1856 int phy_acc; 1857 uint32_t rval; 1858 SOC_INIT_FUNC_DEFS; 1859 1860 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1861 1862 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1863 *(mode) = soc_reg_field_get(unit, XLPORT_CONFIGr, rval, HIGIG_MODEf); 1864 1865 exit: 1866 SOC_FUNC_RETURN; 1867 } 1868 1869 int pm4x10_port_encap_set (int unit, int port, pm_info_t pm_info, 1870 int flags, portmod_encap_t encap) 1871 { 1872 return (xlmac_encap_set(unit, port, flags, encap)); 1873 1874 } 1875 1876 int pm4x10_port_encap_get (int unit, int port, pm_info_t pm_info, 1877 int *flags, portmod_encap_t *encap) 1878 { 1879 return (xlmac_encap_get(unit, port, flags, encap)); 1880 } 1881 1882 int pm4x10_port_config_port_type_set (int unit, int port, pm_info_t pm_info, int type) 1883 { 1884 int phy_acc; 1885 uint32_t rval; 1886 SOC_INIT_FUNC_DEFS; 1887 1888 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1889 1890 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1891 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, PORT_TYPEf, type); 1892 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, rval)); 1893 1894 exit: 1895 SOC_FUNC_RETURN; 1896 } 1897 1898 int pm4x10_port_config_port_type_get (int unit, int port, pm_info_t pm_info, int *type) 1899 { 1900 int phy_acc; 1901 uint32_t rval; 1902 SOC_INIT_FUNC_DEFS; 1903 1904 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 1905 1906 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, &rval)); 1907 *(type) = soc_reg_field_get(unit, XLPORT_CONFIGr, rval, PORT_TYPEf); 1908 1909 exit: 1910 SOC_FUNC_RETURN; 1911 } 1912 1913 int pm4x10_port_led_chain_config (int unit, int port, pm_info_t pm_info, 1914 int value) 1915 { 1916 SOC_INIT_FUNC_DEFS; 1917 1918 _SOC_IF_ERR_EXIT(WRITE_XLPORT_LED_CHAIN_CONFIGr (unit, port, value)); 1919 1920 exit: 1921 SOC_FUNC_RETURN; 1922 } 1923 1924 typedef enum xlmac_port_mode_e{ 1925 XLMAC_4_LANES_SEPARATE = 0, 1926 XLMAC_3_TRI_0_1_2_2 = 1, 1927 XLMAC_3_TRI_0_0_2_3 = 2, 1928 XLMAC_2_LANES_DUAL = 3, 1929 XLMAC_4_LANES_TOGETHER = 4 1930 } xlmac_port_mode_t; 1931 1932 STATIC 1933 int _pm4x10_port_tricore_lane_info_get(int unit, int port, pm_info_t pm_info, 1934 int *start_lane, int* end_lane, 1935 int *line_start_lane, int* line_end_lane, 1936 uint32 *int_core_lane_mask, 1937 const portmod_access_get_params_t* params) 1938 { 1939 uint32 iphy_lane_mask, interface_modes = 0; 1940 int port_index=0; 1941 int core_num_int; 1942 int data_rate; 1943 int phyn = 0; 1944 uint32 xphy_id = 0; 1945 phymod_core_access_t core_access; 1946 int is_legacy_phy; 1947 SOC_INIT_FUNC_DEFS; 1948 1949 /* get port index and lane mask */ 1950 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &port_index, 1951 &iphy_lane_mask)); 1952 1953 *start_lane = 0; 1954 *end_lane = PM4X10_LANES_PER_CORE-1; 1955 *int_core_lane_mask = 0x0F; 1956 1957 *line_start_lane = 0; 1958 *line_end_lane = PM4X10_LANES_PER_CORE-1; 1959 1960 core_num_int = PM_4x10_INFO(pm_info)->core_num_int; 1961 1962 _SOC_IF_ERR_EXIT(PM4x10_INTERFACE_MODES_GET(unit, pm_info, 1963 &interface_modes, 1964 port_index)); 1965 1966 if(interface_modes & PHYMOD_INTF_MODES_TRIPLE_CORE) { 1967 _SOC_IF_ERR_EXIT(PM4x10_SPEED_GET(unit, pm_info, 1968 &data_rate, 1969 port_index)); 1970 1971 /* first check if 120G or 127G */ 1972 if (data_rate >= 120000) { 1973 if(core_num_int == 0){ 1974 *start_lane = 0; 1975 *end_lane = PM4X10_LANES_PER_CORE-1; 1976 *int_core_lane_mask = 0x0F; 1977 *line_start_lane = -1; 1978 *line_end_lane = -1; 1979 } else if (core_num_int == 1) { 1980 *start_lane = 4; 1981 *end_lane = 7; 1982 *line_start_lane = 0; 1983 *line_end_lane = PM4X10_LANES_PER_CORE-1; 1984 *int_core_lane_mask = 0x0F; 1985 } else if (core_num_int == 2) { 1986 *start_lane = 8; 1987 *end_lane = 11; 1988 *int_core_lane_mask = 0x0F; 1989 *line_start_lane = -1; 1990 *line_end_lane = -1; 1991 } 1992 1993 } else { 1994 if(core_num_int == 0){ 1995 if (interface_modes & PHYMOD_INTF_MODES_TC_244){ 1996 *start_lane = 0 ; 1997 *end_lane = 1 ; 1998 *int_core_lane_mask = 0x03; 1999 } else if (interface_modes & PHYMOD_INTF_MODES_TC_343){ 2000 *start_lane = 0 ; 2001 *end_lane = 2 ; 2002 *int_core_lane_mask = 0x07; 2003 } else if (interface_modes & PHYMOD_INTF_MODES_TC_442){ 2004 *start_lane = 0; 2005 *end_lane = PM4X10_LANES_PER_CORE-1; 2006 *int_core_lane_mask = 0x0F; 2007 } 2008 *line_start_lane = -1; 2009 *line_end_lane = -1; 2010 2011 } else if (core_num_int == 1) { 2012 if (interface_modes & PHYMOD_INTF_MODES_TC_244){ 2013 *start_lane = 2 ; 2014 *end_lane = 5 ; 2015 } else if (interface_modes & PHYMOD_INTF_MODES_TC_343){ 2016 *start_lane = 3 ; 2017 *end_lane = 6 ; 2018 } else if (interface_modes & PHYMOD_INTF_MODES_TC_442){ 2019 *start_lane = 4; 2020 *end_lane = 7; 2021 } 2022 *line_start_lane = 0; 2023 *line_end_lane = PM4X10_LANES_PER_CORE-1; 2024 *int_core_lane_mask = 0x0F; 2025 } else if (core_num_int == 2) { 2026 if (interface_modes & PHYMOD_INTF_MODES_TC_244){ 2027 *start_lane = 6 ; 2028 *end_lane = 9 ; 2029 *int_core_lane_mask = 0x0F; 2030 } else if (interface_modes & PHYMOD_INTF_MODES_TC_343){ 2031 *start_lane = 7 ; 2032 *end_lane = 9 ; 2033 *int_core_lane_mask = 0x07; 2034 } else if (interface_modes & PHYMOD_INTF_MODES_TC_442){ 2035 *start_lane = 8; 2036 *end_lane = 9; 2037 *int_core_lane_mask = 0x03; 2038 } 2039 *line_start_lane = -1; 2040 *line_end_lane = -1; 2041 } 2042 if ( params != NULL ) { 2043 phyn = params->phyn; 2044 2045 /* if phyn is -1, it is looking for outer most phy. 2046 assumption is that all lane has same phy depth. */ 2047 if(phyn < 0) { 2048 phyn = PM_4x10_INFO(pm_info)->nof_phys[port_index] - 1; 2049 } 2050 2051 if (phyn > 0) { 2052 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[phyn-1][0].xphy_id; 2053 _SOC_IF_ERR_EXIT ( portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 2054 if (core_access.device_op_mode != PHYMOD_INTF_CONFIG_PHY_GEARBOX_ENABLE) { 2055 *line_start_lane = *start_lane; 2056 *line_end_lane = *end_lane; 2057 } 2058 } 2059 } 2060 } 2061 } 2062 exit: 2063 SOC_FUNC_RETURN; 2064 } 2065 2066 int pm4x10_port_phy_lane_access_get(int unit, int port, pm_info_t pm_info, 2067 const portmod_access_get_params_t* params, 2068 int max_phys, 2069 phymod_phy_access_t* phy_access, 2070 int* nof_phys, int* is_most_ext) 2071 { 2072 int phyn = 0, rv; 2073 uint32 iphy_lane_mask; 2074 int port_index=0; 2075 int serdes_lane=-1; 2076 int xphy_lane_mask=0; 2077 uint32 xphy_id = 0; 2078 uint32 lane_mask[MAX_NUM_CORES]; 2079 phymod_port_loc_t port_loc[MAX_NUM_CORES]; 2080 int i, is_legacy_phy; 2081 uint32 xphy_idx; 2082 uint32 pm_is_bypassed = 0; 2083 int num_of_phys; 2084 int done; 2085 int sys_start_lane=0; 2086 int sys_end_lane=0; 2087 int line_start_lane=0; 2088 int line_end_lane=0; 2089 int start_lane = 0; 2090 int end_lane = 0; 2091 uint32 int_lane_mask = 0xf; 2092 phymod_core_access_t core_access; 2093 2094 2095 SOC_INIT_FUNC_DEFS; 2096 2097 start_lane = 0; 2098 end_lane = PM4X10_LANES_PER_CORE-1; 2099 2100 if(max_phys > MAX_NUM_CORES) 2101 { 2102 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2103 (_SOC_MSG("max_phys parameter exceeded the MAX value. max_phys=%d, max allowed %d."), 2104 max_phys, MAX_NUM_CORES)); 2105 } 2106 2107 /* get port index and lane mask */ 2108 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &port_index, 2109 &iphy_lane_mask)); 2110 2111 _SOC_IF_ERR_EXIT(_pm4x10_port_tricore_lane_info_get(unit, port, pm_info, 2112 &sys_start_lane, &sys_end_lane, 2113 &line_start_lane, &line_end_lane, 2114 &int_lane_mask, params)); 2115 2116 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &pm_is_bypassed); 2117 _SOC_IF_ERR_EXIT(rv); 2118 2119 if(!params->apply_lane_mask){ 2120 int_lane_mask = 0xF; 2121 } 2122 2123 if(params->phyn >= PM_4x10_INFO(pm_info)->nof_phys[port_index]){ 2124 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2125 (_SOC_MSG("phyn exceeded. max allowed %d. got %d"), 2126 PM_4x10_INFO(pm_info)->nof_phys[port_index] - 1, params->phyn)); 2127 } 2128 2129 2130 for( i = 0 ; i < max_phys; i++) { 2131 lane_mask[i] = 0; 2132 _SOC_IF_ERR_EXIT(phymod_phy_access_t_init(&phy_access[i])); 2133 } 2134 2135 phyn = params->phyn; 2136 2137 /* if phyn is -1, it is looking for outer most phy. 2138 assumption is that all lane has same phy depth. */ 2139 if(phyn < 0) { 2140 phyn = PM_4x10_INFO(pm_info)->nof_phys[port_index] - 1; 2141 } 2142 2143 if( phyn == 0 ) { 2144 /* internal core */ 2145 sal_memcpy (&phy_access[0], &(PM_4x10_INFO(pm_info)->int_core_access), 2146 sizeof(phymod_phy_access_t)); 2147 phy_access[0].access.lane_mask = iphy_lane_mask; 2148 if (params->lane != -1) { 2149 2150 start_lane = sys_start_lane; 2151 end_lane = sys_end_lane; 2152 2153 if((params->lane >= start_lane) && (params->lane <= end_lane)) { 2154 serdes_lane = port_index + params->lane-start_lane; 2155 phy_access[0].access.lane_mask &= (0x1 << serdes_lane ); 2156 *nof_phys = 1; 2157 } else { 2158 phy_access[0].access.lane_mask &= 0; 2159 *nof_phys = 0; 2160 } 2161 } else { 2162 *nof_phys = 1; 2163 phy_access[0].access.lane_mask &= int_lane_mask; 2164 } 2165 phy_access[0].port_loc = phymodPortLocLine; /* only line is availabe for internal. */ 2166 2167 /* PCS bypass flag is set when the underlying device is DNX */ 2168 if ((pm_is_bypassed) && (!PM_4x10_INFO(pm_info)->in_pm12x10)) { 2169 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(phy_access[0].device_op_mode); 2170 } 2171 2172 /* if it is warm boot, get probed information from wb db instead of re-probing. */ 2173 if(SOC_WARM_BOOT(unit)) { 2174 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[phy_type], &(phy_access[0].type)); 2175 _SOC_IF_ERR_EXIT(rv); 2176 } 2177 } else { 2178 2179 /* external phy */ 2180 num_of_phys = 0; 2181 2182 /* xphy idx is 1 less than phyn since internal core does not count */ 2183 xphy_idx = phyn-1; 2184 2185 if (params->lane != -1){ /* specific lane */ 2186 2187 if(params->sys_side == PORTMOD_SIDE_SYSTEM){ 2188 start_lane = sys_start_lane; 2189 end_lane = sys_end_lane; 2190 } else { /* PORTMOD_SIDE_LINE */ 2191 start_lane = line_start_lane; 2192 end_lane = line_end_lane; 2193 } 2194 2195 if((params->lane >= start_lane) && (params->lane <= end_lane)) { 2196 serdes_lane = port_index + params->lane-start_lane; 2197 } else { 2198 serdes_lane = -1; /* no matching lane in this core. */ 2199 *nof_phys = 0; 2200 } 2201 if( serdes_lane != -1){ 2202 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].xphy_id; 2203 2204 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 2205 _SOC_IF_ERR_EXIT ( portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 2206 sal_memcpy (&phy_access[num_of_phys], &core_access, 2207 sizeof(phymod_phy_access_t)); 2208 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 2209 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 2210 if( xphy_lane_mask != -1 ){ 2211 phy_access[0].access.lane_mask = xphy_lane_mask; 2212 } 2213 phy_access[0].port_loc = ( params->sys_side == PORTMOD_SIDE_SYSTEM) ? 2214 phymodPortLocSys : phymodPortLocLine; 2215 *nof_phys = 1; 2216 } 2217 } 2218 } else { /* all lanes */ 2219 /* go thru all the lanes related to this port. */ 2220 serdes_lane = 0; 2221 2222 for (serdes_lane = 0; serdes_lane < MAX_PORTS_PER_PM4X10; serdes_lane++) { 2223 if (iphy_lane_mask & (1U<<serdes_lane)) { 2224 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].xphy_id; 2225 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 2226 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 2227 if(num_of_phys == 0 ) {/* first one */ 2228 sal_memcpy (&phy_access[num_of_phys], &core_access, 2229 sizeof(phymod_phy_access_t)); 2230 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 2231 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 2232 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 2233 if( xphy_lane_mask != -1) { 2234 lane_mask[num_of_phys] |= xphy_lane_mask; 2235 } 2236 port_loc[num_of_phys] = ( params->sys_side == PORTMOD_SIDE_SYSTEM) ? 2237 phymodPortLocSys : phymodPortLocLine; 2238 num_of_phys++; 2239 } else { 2240 /* if not the first one, see if this one sharing core with other 2241 lanes. */ 2242 done = 0; 2243 2244 /* Skip if the lane is used by an inactive port marked with :i in the config 2245 * * property. 2246 */ 2247 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port+serdes_lane)){ 2248 continue; 2249 } 2250 2251 for( i = 0 ; (i < num_of_phys) &&(!done) ; i++) { 2252 if((!sal_memcmp (&phy_access[i], &core_access, 2253 sizeof(phymod_phy_access_t)))) { /* found a match */ 2254 /* update lane */ 2255 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 2256 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 2257 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 2258 if( xphy_lane_mask != -1) { 2259 lane_mask[i] |= xphy_lane_mask; 2260 } 2261 done = 1; 2262 } 2263 } 2264 if((!done) && (num_of_phys < max_phys)){ 2265 sal_memcpy (&phy_access[num_of_phys], &core_access, 2266 sizeof(phymod_phy_access_t)); 2267 xphy_lane_mask = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 2268 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ss_lane_mask: 2269 PM_4x10_INFO(pm_info)->lane_conn[xphy_idx][serdes_lane].ls_lane_mask; 2270 if( xphy_lane_mask != -1) { 2271 lane_mask[num_of_phys] = xphy_lane_mask; 2272 } 2273 port_loc[num_of_phys] = ( params->sys_side == PORTMOD_SIDE_SYSTEM)? 2274 phymodPortLocSys : phymodPortLocLine ; 2275 num_of_phys++; 2276 } 2277 } 2278 } 2279 } 2280 } 2281 *nof_phys = num_of_phys; 2282 for( i = 0 ; (i < *nof_phys) ; i++) { 2283 phy_access[i].access.lane_mask = lane_mask[i]; 2284 phy_access[i].port_loc = port_loc[i]; 2285 } 2286 } 2287 } /* ext phys */ 2288 2289 /* assumption is that all logical port have same phy depths, that 2290 will not true when simplex introduced , until then we can keep 2291 this code. */ 2292 if (is_most_ext) { 2293 if (phyn == PM_4x10_INFO(pm_info)->nof_phys[port_index]-1) { 2294 *is_most_ext = 1; 2295 } else { 2296 *is_most_ext = 0; 2297 } 2298 } 2299 2300 exit: 2301 SOC_FUNC_RETURN; 2302 } 2303 2304 int pm4x10_port_mac_rsv_mask_set(int unit, int port, pm_info_t pm_info, uint32 rsv_mask) 2305 { 2306 return(WRITE_XLPORT_MAC_RSV_MASKr(unit, port, rsv_mask)); 2307 } 2308 2309 STATIC 2310 int _pm4x10_pm_port_init(int unit, int port, int phy_acc, int internal_port, 2311 const portmod_port_add_info_t* add_info, int enable, pm_info_t pm_info) 2312 { 2313 int rv; 2314 uint32 reg_val, flags; 2315 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 2316 uint32 rsv_mask; 2317 SOC_INIT_FUNC_DEFS; 2318 2319 if(enable) { 2320 /* RSV Mask */ 2321 rsv_mask = 0; 2322 SHR_BITSET(&rsv_mask, 3); /* Receive terminate/code error */ 2323 SHR_BITSET(&rsv_mask, 4); /* CRC error */ 2324 SHR_BITSET(&rsv_mask, 6); /* PGW_MACTruncated/Frame out of Range */ 2325 SHR_BITSET(&rsv_mask, 17); /* RUNT detected*/ 2326 2327 rv = __portmod__dispatch__[pm_info->type]->f_portmod_port_mac_rsv_mask_set(unit, port, pm_info, rsv_mask); 2328 _SOC_IF_ERR_EXIT(rv); 2329 2330 2331 /* Soft reset */ 2332 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 2333 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, 2334 port_fields[internal_port], 1); 2335 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2336 2337 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, 2338 port_fields[internal_port], 0); 2339 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2340 2341 2342 /* Port enable */ 2343 _SOC_IF_ERR_EXIT(READ_XLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 2344 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, ®_val, 2345 port_fields[internal_port], 1); 2346 _SOC_IF_ERR_EXIT(WRITE_XLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 2347 2348 /* Init MAC */ 2349 flags = 0; 2350 if(PORTMOD_PORT_ADD_F_RX_SRIP_CRC_GET(add_info)) { 2351 flags |= XLMAC_INIT_F_RX_STRIP_CRC; 2352 } 2353 2354 if(PORTMOD_PORT_ADD_F_TX_APPEND_CRC_GET(add_info)) { 2355 flags |= XLMAC_INIT_F_TX_APPEND_CRC; 2356 } 2357 2358 if(PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_GET(add_info)) { 2359 flags |= XLMAC_INIT_F_TX_REPLACE_CRC; 2360 } 2361 2362 if(PORTMOD_PORT_ADD_F_TX_PASS_THROUGH_CRC_GET(add_info)) { 2363 flags |= XLMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE; 2364 } 2365 2366 if (IS_HG_PORT(unit,port)){ 2367 flags |= XLMAC_INIT_F_IPG_CHECK_DISABLE; 2368 } else { 2369 flags &= ~XLMAC_INIT_F_IPG_CHECK_DISABLE; 2370 } 2371 2372 if(PHYMOD_INTF_MODES_HIGIG_GET(&(add_info->interface_config))) { 2373 flags |= XLMAC_INIT_F_IS_HIGIG; 2374 } 2375 rv = xlmac_init(unit, port, flags); 2376 _SOC_IF_ERR_EXIT(rv); 2377 2378 /* LSS */ 2379 _SOC_IF_ERR_EXIT(READ_XLPORT_FAULT_LINK_STATUSr(unit, phy_acc, ®_val)); 2380 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, ®_val, 2381 REMOTE_FAULTf, 1); 2382 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, ®_val, 2383 LOCAL_FAULTf, 1); 2384 _SOC_IF_ERR_EXIT(WRITE_XLPORT_FAULT_LINK_STATUSr(unit, phy_acc, reg_val)); 2385 2386 /* Counter MAX size */ 2387 rv = __portmod__dispatch__[pm_info->type]->f_portmod_port_cntmaxsize_set(unit, port, pm_info, 1518); 2388 _SOC_IF_ERR_EXIT(rv); 2389 2390 /* Reset MIB counters */ 2391 rv = __portmod__dispatch__[pm_info->type]->f_portmod_port_mib_reset_toggle(unit, port, pm_info, internal_port); 2392 _SOC_IF_ERR_EXIT(rv); 2393 2394 } else { 2395 /* Port disable */ 2396 _SOC_IF_ERR_EXIT(READ_XLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 2397 soc_reg_field_set (unit, XLPORT_ENABLE_REGr, ®_val, 2398 port_fields[internal_port], 0); 2399 _SOC_IF_ERR_EXIT(WRITE_XLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 2400 2401 /* Soft reset */ 2402 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 2403 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, 2404 port_fields[internal_port], 1); 2405 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 2406 } 2407 2408 exit: 2409 SOC_FUNC_RETURN; 2410 } 2411 2412 STATIC 2413 int _pm4x10_ext_phy_interface_check(int unit, int port, phymod_phy_access_t *phy_acc, 2414 const portmod_port_interface_config_t *interface_config, 2415 soc_port_if_t interface, int *is_valid) 2416 { 2417 int rv = 0; 2418 int num_lanes = 0, data_rate = 0; 2419 uint32_t interface_mode = 0; 2420 phymod_interface_t phymod_intf; 2421 int is_legacy_phy = 0, xphy_id; 2422 SOC_INIT_FUNC_DEFS; 2423 2424 num_lanes = interface_config->port_num_lanes; 2425 interface_mode = interface_config->interface_modes; 2426 data_rate = interface_config->speed; 2427 2428 xphy_id = phy_acc->access.addr; 2429 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 2430 2431 if (is_legacy_phy) { 2432 /* if its a legacy PHY let the PHY driver decide the valid interface types */ 2433 *is_valid = 1; 2434 rv = SOC_E_NONE; 2435 SOC_EXIT; 2436 } 2437 2438 /* convert portmod interface to phymod interface */ 2439 rv = portmod_intf_to_phymod_intf(unit, data_rate, interface, &phymod_intf); 2440 _SOC_IF_ERR_EXIT(rv); 2441 2442 rv = portmod_port_line_interface_is_valid(unit, phy_acc, port, data_rate, phymod_intf, 2443 num_lanes, interface_mode, is_valid); 2444 _SOC_IF_ERR_EXIT(rv); 2445 2446 if (!*is_valid) { 2447 LOG_ERROR(BSL_LS_BCM_PORT, 2448 (BSL_META_UP(unit, port, 2449 "ERROR: u=%d p=%d interface type %d not supported by external PHY for this speed %d \n"), 2450 unit, port, interface, data_rate)); 2451 rv = SOC_E_PARAM; 2452 _SOC_IF_ERR_EXIT(rv); 2453 } 2454 2455 exit: 2456 SOC_FUNC_RETURN; 2457 } 2458 2459 STATIC 2460 int _pm4x10_interface_check(int unit, int port, pm_info_t pm_info, 2461 const portmod_port_interface_config_t *interface_config, 2462 soc_port_if_t interface, int *is_valid) 2463 { 2464 int is_higig; 2465 int num_lanes; 2466 2467 *is_valid = 0; 2468 num_lanes = interface_config->port_num_lanes; 2469 is_higig = ((interface_config->encap_mode == SOC_ENCAP_HIGIG2) || 2470 (interface_config->encap_mode == SOC_ENCAP_HIGIG) || 2471 PHYMOD_INTF_MODES_HIGIG_GET(interface_config)) ? 1 : 0; 2472 2473 if (SOC_PORT_IF_ILKN == interface) { 2474 *is_valid = 1; 2475 return SOC_E_NONE; 2476 } 2477 2478 switch (interface_config->speed) { 2479 case 0: 2480 /* When AN=1 the input speed to portmod may be 0. At 2481 * this moment the speed is still undecided so there 2482 * is no reason to invalidate the interface type. 2483 */ 2484 *is_valid = 1; 2485 break; 2486 case 10: 2487 if (num_lanes == 1) { 2488 if ((SOC_PORT_IF_SGMII == interface) || 2489 (SOC_PORT_IF_GMII == interface)) { 2490 *is_valid = 1; 2491 } 2492 } 2493 break; 2494 case 100: 2495 if (num_lanes == 1) { 2496 if ((SOC_PORT_IF_SGMII == interface) || 2497 (SOC_PORT_IF_GMII == interface)) { 2498 *is_valid = 1; 2499 } 2500 } 2501 break; 2502 case 1000: 2503 if (num_lanes == 1) { 2504 if ((SOC_PORT_IF_SGMII == interface) || 2505 (SOC_PORT_IF_GMII == interface) || 2506 (SOC_PORT_IF_KX == interface) || 2507 (SOC_PORT_IF_CX == interface) || 2508 ((SOC_PORT_IF_QSGMII == interface) && 2509 (PM_4x10_INFO(pm_info)->is_pm4x10q))) { 2510 *is_valid = 1; 2511 } 2512 } 2513 break; 2514 case 2500: 2515 if (num_lanes == 1) { 2516 if ((SOC_PORT_IF_SGMII == interface) || 2517 (SOC_PORT_IF_GMII == interface)) { 2518 *is_valid = 1; 2519 } 2520 } 2521 break; 2522 case 5000: 2523 if (num_lanes == 1) { 2524 if ((SOC_PORT_IF_XFI == interface) || 2525 (SOC_PORT_IF_KR == interface) || 2526 (SOC_PORT_IF_GMII == interface)) { 2527 *is_valid = 1; 2528 } 2529 } else if (num_lanes == 2) { 2530 if (SOC_PORT_IF_RXAUI == interface) { 2531 *is_valid = 1; 2532 } 2533 } 2534 break; 2535 case 10000: 2536 case 11000: 2537 if (is_higig) { 2538 if (num_lanes == 1) { 2539 if ((SOC_PORT_IF_XFI == interface) || 2540 (SOC_PORT_IF_SFI == interface) || 2541 (SOC_PORT_IF_KR == interface) || 2542 (SOC_PORT_IF_CR == interface) || 2543 (SOC_PORT_IF_SR == interface)) { 2544 *is_valid = 1; 2545 } 2546 } else if (num_lanes == 2) { 2547 if (SOC_PORT_IF_RXAUI == interface) { 2548 *is_valid = 1; 2549 } 2550 } else if (num_lanes == 4) { 2551 if ((SOC_PORT_IF_XGMII == interface) || 2552 (SOC_PORT_IF_XLAUI == interface)) { 2553 *is_valid = 1; 2554 } 2555 } 2556 } else { 2557 if (num_lanes == 1) { 2558 if ((SOC_PORT_IF_SFI == interface) || 2559 (SOC_PORT_IF_XFI == interface) || 2560 (SOC_PORT_IF_KR == interface) || 2561 (SOC_PORT_IF_CR == interface) || 2562 (SOC_PORT_IF_SR == interface) || 2563 (SOC_PORT_IF_LR == interface) || 2564 (SOC_PORT_IF_ER == interface) || 2565 (SOC_PORT_IF_CX == interface) || 2566 (SOC_PORT_IF_LRM == interface)) { 2567 *is_valid = 1; 2568 } 2569 } else if (num_lanes == 2) { 2570 if (SOC_PORT_IF_RXAUI == interface) { 2571 *is_valid = 1; 2572 } 2573 } else if (num_lanes == 4) { 2574 if ((SOC_PORT_IF_XGMII == interface) || 2575 (SOC_PORT_IF_XLAUI == interface) || 2576 (SOC_PORT_IF_DNX_XAUI == interface) || 2577 (SOC_PORT_IF_XAUI == interface) || 2578 (SOC_PORT_IF_SFI == interface) || 2579 (SOC_PORT_IF_XFI == interface) || 2580 (SOC_PORT_IF_QSGMII == interface)) { 2581 *is_valid = 1; 2582 } 2583 } 2584 } 2585 break; 2586 case 3125: 2587 case 5750: 2588 case 6250: 2589 case 8125: 2590 case 8500: 2591 case 10312: 2592 case 10937: 2593 case 11250: 2594 if (SOC_PORT_IF_ILKN == interface) { 2595 /* 2596 * COVERITY 2597 * It is kept intentionally as a defensive check. 2598 */ 2599 /* coverity[dead_error_line] */ 2600 *is_valid = 1; 2601 } 2602 break; 2603 case 10500: 2604 case 12500: 2605 break; 2606 case 11500: 2607 if (num_lanes == 1) { 2608 if (SOC_PORT_IF_XFI == interface) { 2609 *is_valid = 1; 2610 } 2611 } 2612 break; 2613 case 12000: 2614 if ((num_lanes == 4) && 2615 (SOC_PORT_IF_XGMII == interface)) { 2616 *is_valid = 1; 2617 } else if ((num_lanes == 2) && 2618 (SOC_PORT_IF_RXAUI == interface)) { 2619 *is_valid = 1; 2620 } else if ((num_lanes == 1) && 2621 ((SOC_PORT_IF_XFI == interface) || 2622 (SOC_PORT_IF_SFI == interface) || 2623 (SOC_PORT_IF_SR == interface) || 2624 (SOC_PORT_IF_LR == interface) || 2625 (SOC_PORT_IF_CR == interface) || 2626 (SOC_PORT_IF_KR == interface))) { 2627 *is_valid = 1; 2628 } 2629 break; 2630 case 12773: /* 12733Mbps */ 2631 if (num_lanes == 2) { 2632 if (SOC_PORT_IF_RXAUI == interface) { 2633 *is_valid = 1; 2634 } 2635 } 2636 break; 2637 case 13000: 2638 if ((num_lanes == 4) && 2639 (SOC_PORT_IF_XGMII == interface)) { 2640 *is_valid = 1; 2641 } else if ((num_lanes == 2) && 2642 (SOC_PORT_IF_RXAUI == interface)) { 2643 *is_valid = 1; 2644 } 2645 break; 2646 case 15000: 2647 if ((num_lanes == 4) && 2648 (SOC_PORT_IF_XGMII == interface)) { 2649 *is_valid = 1; 2650 } else if ((num_lanes == 2) && 2651 (SOC_PORT_IF_RXAUI == interface)) { 2652 *is_valid = 1; 2653 } 2654 break; 2655 case 15750: 2656 case 16000: /* setting RX66_CONTROL_CC_EN/CC_DATA_SEL failed this 16000 HI_DXGXS mode */ 2657 if ((num_lanes == 4) && 2658 (SOC_PORT_IF_XGMII == interface)) { 2659 *is_valid = 1; 2660 } else if ((num_lanes == 2) && 2661 (SOC_PORT_IF_RXAUI == interface)) { 2662 *is_valid = 1; 2663 } 2664 break; 2665 case 20000: 2666 case 21000: 2667 if (is_higig) { 2668 if (num_lanes == 2) { 2669 if ((SOC_PORT_IF_KR2 == interface) || 2670 (SOC_PORT_IF_CR2 == interface) || 2671 (SOC_PORT_IF_RXAUI == interface)) { 2672 *is_valid = 1; 2673 } 2674 } else if (num_lanes == 4) { 2675 if (SOC_PORT_IF_XGMII == interface) { 2676 *is_valid = 1; 2677 } 2678 } 2679 } else { 2680 if (num_lanes == 2) { 2681 if ((SOC_PORT_IF_KR2 == interface) || 2682 (SOC_PORT_IF_CR2 == interface) || 2683 (SOC_PORT_IF_RXAUI == interface)) { 2684 *is_valid = 1; 2685 } 2686 } else if (num_lanes == 4) { 2687 if ((SOC_PORT_IF_XGMII == interface) || 2688 (SOC_PORT_IF_SR4 == interface) || 2689 (SOC_PORT_IF_CR4 == interface) || 2690 (SOC_PORT_IF_KR4 == interface) || 2691 (SOC_PORT_IF_DNX_XAUI == interface)) { 2692 *is_valid = 1; 2693 } 2694 } 2695 } 2696 break; 2697 case 23000: 2698 if (num_lanes == 2) { 2699 if (SOC_PORT_IF_RXAUI == interface) { 2700 *is_valid = 1; 2701 } 2702 } 2703 break; 2704 case 25000: 2705 case 25450: 2706 case 25455: 2707 case 30000: 2708 case 31500: 2709 if (num_lanes == 4) { 2710 if ((SOC_PORT_IF_XGMII == interface) || 2711 (SOC_PORT_IF_KR4 == interface)) { 2712 *is_valid = 1; 2713 } 2714 } else if (num_lanes == 2) { 2715 if (SOC_PORT_IF_KR2 == interface) { 2716 *is_valid = 1; 2717 } 2718 } else { 2719 if (SOC_PORT_IF_KR == interface) { 2720 *is_valid = 1; 2721 } 2722 } 2723 break; 2724 case 40000: 2725 if (is_higig) { 2726 if (num_lanes == 4) { 2727 if ((SOC_PORT_IF_KR4 == interface) || 2728 (SOC_PORT_IF_CR4 == interface) || 2729 (SOC_PORT_IF_SR4 == interface) || 2730 (SOC_PORT_IF_LR4 == interface) || 2731 (SOC_PORT_IF_ER4 == interface) || 2732 (SOC_PORT_IF_XGMII == interface)) { 2733 *is_valid = 1; 2734 } 2735 } 2736 } else { 2737 if (num_lanes == 4) { 2738 if ((SOC_PORT_IF_KR4 == interface) || 2739 (SOC_PORT_IF_CR4 == interface) || 2740 (SOC_PORT_IF_SR4 == interface) || 2741 (SOC_PORT_IF_LR4 == interface) || 2742 (SOC_PORT_IF_ER4 == interface) || 2743 (SOC_PORT_IF_XLAUI == interface) || 2744 (SOC_PORT_IF_XLPPI == interface)) { 2745 *is_valid = 1; 2746 } 2747 } 2748 } 2749 break; 2750 case 42000: 2751 if (is_higig) { 2752 if (num_lanes == 4) { 2753 if ((SOC_PORT_IF_KR4 == interface) || 2754 (SOC_PORT_IF_CR4 == interface) || 2755 (SOC_PORT_IF_XLAUI == interface) || 2756 (SOC_PORT_IF_SR4 == interface) || 2757 (SOC_PORT_IF_XGMII == interface)) { 2758 *is_valid = 1; 2759 } 2760 } 2761 } else { 2762 if (num_lanes == 4) { 2763 if ((SOC_PORT_IF_KR4 == interface) || 2764 (SOC_PORT_IF_XLAUI == interface)) { 2765 *is_valid = 1; 2766 } 2767 } 2768 } 2769 break; 2770 case 48000: 2771 if (!is_higig && num_lanes == 4) { 2772 if (SOC_PORT_IF_XLAUI == interface) { 2773 *is_valid = 1; 2774 } 2775 } 2776 break; 2777 case 100000: 2778 if ((num_lanes == 10) || (num_lanes == 12)) { 2779 if ((SOC_PORT_IF_CR10 == interface) || 2780 (SOC_PORT_IF_KR10 == interface) || 2781 (SOC_PORT_IF_LR10 == interface) || 2782 (SOC_PORT_IF_SR10 == interface) || 2783 (SOC_PORT_IF_CAUI == interface)) { 2784 *is_valid = 1; 2785 } 2786 } 2787 break; 2788 case 106000: 2789 if ((num_lanes == 10) || (num_lanes == 12)) { 2790 if ((SOC_PORT_IF_CR10 == interface) || 2791 (SOC_PORT_IF_KR10 == interface) || 2792 (SOC_PORT_IF_CAUI == interface)) { 2793 *is_valid = 1; 2794 } 2795 } 2796 break; 2797 case 120000: 2798 if (num_lanes == 12) { 2799 if (SOC_PORT_IF_CAUI == interface) { 2800 *is_valid = 1; 2801 } 2802 } 2803 break; 2804 case 127000: 2805 if (num_lanes == 12) { 2806 if (SOC_PORT_IF_CAUI == interface) { 2807 *is_valid = 1; 2808 } 2809 } 2810 break; 2811 default: 2812 break; 2813 } 2814 2815 return SOC_E_NONE; 2816 } 2817 2818 STATIC 2819 int _pm4x10_default_interface_get(int unit, int port, 2820 const portmod_port_interface_config_t *interface_config, 2821 soc_port_if_t *interface) 2822 { 2823 int is_higig; 2824 int num_lanes; 2825 soc_port_if_t interface_tmp = SOC_PORT_IF_NULL; 2826 SOC_INIT_FUNC_DEFS; 2827 2828 *interface = SOC_PORT_IF_NULL; 2829 num_lanes = interface_config->port_num_lanes; 2830 is_higig = ((interface_config->encap_mode == SOC_ENCAP_HIGIG2) || 2831 (interface_config->encap_mode == SOC_ENCAP_HIGIG)) ? 1 : 0; 2832 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(interface_config, &interface_tmp)); 2833 2834 switch (interface_config->speed) { 2835 case 10: 2836 *interface = SOC_PORT_IF_SGMII; 2837 break; 2838 case 100: 2839 *interface = SOC_PORT_IF_SGMII; 2840 break; 2841 case 1000: 2842 if (PHYMOD_INTF_MODES_FIBER_GET(interface_config)) { 2843 *interface = SOC_PORT_IF_GMII; 2844 } else if(interface_tmp == SOC_PORT_IF_KX) { 2845 *interface = SOC_PORT_IF_KX; 2846 } else { 2847 *interface = SOC_PORT_IF_SGMII; 2848 } 2849 break; 2850 case 2500: 2851 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2852 SOC_PORT_IF_GMII: SOC_PORT_IF_SGMII; 2853 break; 2854 case 5000: 2855 if (num_lanes == 1) { 2856 *interface = SOC_PORT_IF_XFI; 2857 } else if (num_lanes == 2) { 2858 *interface = SOC_PORT_IF_RXAUI; 2859 } else { 2860 *interface = SOC_PORT_IF_XFI; 2861 } 2862 break; 2863 case 10000: 2864 case 11000: 2865 if (num_lanes == 2) { 2866 *interface = SOC_PORT_IF_RXAUI; 2867 } else if (num_lanes == 4) { 2868 *interface = SOC_PORT_IF_XGMII; 2869 } else { 2870 *interface = PHYMOD_INTF_MODES_FIBER_GET(interface_config)? 2871 SOC_PORT_IF_SFI : SOC_PORT_IF_XFI; 2872 } 2873 break; 2874 case 3125: 2875 case 5750: 2876 case 6250: 2877 case 8125: 2878 case 8500: 2879 case 10312: 2880 case 10937: 2881 case 11250: 2882 *interface = SOC_PORT_IF_ILKN; 2883 break; 2884 case 10500: 2885 case 12500: 2886 break; 2887 case 20000: 2888 case 21000: 2889 if (num_lanes == 4) { 2890 *interface = SOC_PORT_IF_XGMII; 2891 } else { 2892 *interface = SOC_PORT_IF_RXAUI; 2893 } 2894 break; 2895 case 23000: 2896 *interface = SOC_PORT_IF_RXAUI; 2897 break; 2898 case 25000: 2899 case 25450: 2900 case 25455: 2901 case 30000: 2902 case 31500: 2903 if (num_lanes == 4) { 2904 *interface = SOC_PORT_IF_KR4; 2905 } else if (num_lanes == 2) { 2906 *interface = SOC_PORT_IF_KR2; 2907 } else { 2908 *interface = SOC_PORT_IF_KR; 2909 } 2910 break; 2911 case 40000: 2912 if (is_higig) { 2913 *interface = SOC_PORT_IF_XGMII; 2914 } else { 2915 *interface = SOC_PORT_IF_XLAUI; 2916 } 2917 break; 2918 case 42000: 2919 if (is_higig) { 2920 *interface = SOC_PORT_IF_XGMII; 2921 } else { 2922 *interface = SOC_PORT_IF_KR4; 2923 } 2924 break; 2925 case 100000: 2926 *interface = SOC_PORT_IF_CAUI; 2927 break; 2928 case 106000: 2929 *interface = SOC_PORT_IF_CAUI; 2930 break; 2931 case 120000: 2932 *interface = SOC_PORT_IF_CAUI; 2933 break; 2934 case 127000: 2935 *interface = SOC_PORT_IF_CAUI; 2936 break; 2937 default: 2938 if (num_lanes == 1) { 2939 if (interface_config->speed >= 10000) { 2940 *interface = SOC_PORT_IF_CR; 2941 } else { 2942 *interface = SOC_PORT_IF_SGMII; 2943 } 2944 } else if (num_lanes == 2) { 2945 if (is_higig) { 2946 *interface = SOC_PORT_IF_RXAUI; 2947 } else { 2948 *interface = SOC_PORT_IF_CR2; 2949 } 2950 } else if (num_lanes == 4) { 2951 if (interface_config->speed >= 40000) { 2952 if (is_higig){ 2953 *interface = SOC_PORT_IF_CR4; 2954 } else{ 2955 *interface = SOC_PORT_IF_XLAUI; 2956 } 2957 } else { 2958 *interface = SOC_PORT_IF_XGMII; 2959 } 2960 } else if (num_lanes == 10) { 2961 *interface = SOC_PORT_IF_CAUI; 2962 } else if (num_lanes == 12) { 2963 *interface = SOC_PORT_IF_CAUI; 2964 } else { 2965 *interface = SOC_PORT_IF_ILKN; 2966 } 2967 break; 2968 } 2969 2970 exit: 2971 SOC_FUNC_RETURN; 2972 } 2973 2974 STATIC 2975 int _pm4x10_line_side_phymod_interface_get(int unit, int port, 2976 pm_info_t pm_info, int rxaui_mode, 2977 const portmod_port_interface_config_t *config, 2978 phymod_interface_t *interface_type) 2979 { 2980 int port_index = 0; 2981 int is_valid = 0, nof_phys = 0; 2982 uint32 bitmap; 2983 soc_port_if_t interface = SOC_PORT_IF_NULL; 2984 phymod_phy_access_t phy_access_arr[1+MAX_PHYN]; 2985 SOC_INIT_FUNC_DEFS; 2986 2987 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &port_index, 2988 &bitmap)); 2989 2990 _SOC_IF_ERR_EXIT 2991 (portmod_port_chain_phy_access_get(unit, port, pm_info, 2992 phy_access_arr ,(1+MAX_PHYN), 2993 &nof_phys)); 2994 2995 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(config, &interface)); 2996 2997 if (nof_phys > 1) { 2998 /* EXT PHY interface */ 2999 _SOC_IF_ERR_EXIT 3000 (_pm4x10_ext_phy_interface_check(unit, port, &phy_access_arr[nof_phys-1], config, interface, 3001 &is_valid)); 3002 } else if (nof_phys == 1) { 3003 _SOC_IF_ERR_EXIT(_pm4x10_interface_check(unit, port, pm_info, config, interface, &is_valid)); 3004 } 3005 3006 if (!is_valid) { 3007 /* interface check validation for internal sedes failed */ 3008 LOG_ERROR(BSL_LS_BCM_PORT, 3009 (BSL_META_UP(unit, port, 3010 "ERROR: u=%d p=%d interface type %d not supported by internal SERDES for this speed %d \n"), 3011 unit, port, interface, config->speed)); 3012 _SOC_IF_ERR_EXIT(SOC_E_PARAM); 3013 } 3014 3015 3016 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, config->speed, 3017 interface, interface_type)); 3018 if ((config->speed == 10000) && (config->port_num_lanes == 2)) { 3019 if (rxaui_mode == 0x2) { 3020 *interface_type = phymodInterfaceRXAUI; 3021 } 3022 else if (rxaui_mode) { 3023 *interface_type = phymodInterfaceX2; 3024 } else { 3025 *interface_type = phymodInterfaceRXAUI; 3026 } 3027 } 3028 3029 exit: 3030 SOC_FUNC_RETURN; 3031 } 3032 3033 int _pm4x10_phymod_interface_mode_set(int unit, int port,pm_info_t pm_info, 3034 const portmod_port_interface_config_t *config, 3035 phymod_phy_inf_config_t *phy_config, 3036 int is_legacy_phy_callback) 3037 { 3038 int port_index = 0; 3039 uint32 bitmap; 3040 soc_port_if_t interface = SOC_PORT_IF_NULL; 3041 SOC_INIT_FUNC_DEFS; 3042 3043 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &port_index, 3044 &bitmap)); 3045 3046 _SOC_IF_ERR_EXIT(PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &interface, 3047 port_index)); 3048 phy_config->interface_modes = config->interface_modes; 3049 3050 switch (config->speed) { 3051 case 6250: 3052 if (PHYMOD_INTF_MODES_OS2_GET(config)) {/* for dual rate OS2 is required */ 3053 PHYMOD_INTF_MODES_OS2_SET(phy_config); 3054 } 3055 break; 3056 case 10000: 3057 if (config->port_num_lanes == 2) { 3058 if (PHYMOD_INTF_MODES_SCR_GET(config)) { 3059 PHYMOD_INTF_MODES_SCR_SET(phy_config); 3060 } 3061 } 3062 break; 3063 case 20000: 3064 if (config->port_num_lanes == 4) { 3065 if (PHYMOD_INTF_MODES_SCR_GET(config)) { 3066 PHYMOD_INTF_MODES_SCR_SET(phy_config); 3067 } 3068 } 3069 break; 3070 case 100000: 3071 case 106000: 3072 case 107000: 3073 case 120000: 3074 case 127000: 3075 if ((phy_config->interface_type == phymodInterfaceSR10) || 3076 (phy_config->interface_type == phymodInterfaceLR10)) { 3077 PHYMOD_INTF_MODES_FIBER_SET(phy_config); 3078 } 3079 break; 3080 default: 3081 break; 3082 } 3083 3084 /* 3085 * tsce/tscf relies on the interface type and interface mode specified in phy_config 3086 * to determine the exact interface type written into or read from the registers. For 3087 * instance, SR4 and KR4 share the same speed ID (reg value) from TSCE's perspective 3088 * and their difference is the medium type specified in the interface mode. SR4 is 3089 * optical while KR4 is not. Below we prevent updating the medium type in the port 3090 * mode provided to the internal PHY if phy_config is to be provided to the internal 3091 * PHY in the legacy ext PHY callback scenario. Reason is because interface used in 3092 * the function call below is meant for the outmost PHY instead of the internal PHY. 3093 * portmod_port_phychain_interface_config_set() has a similar protection mechanism 3094 * to change the medium type of the port mode based on internal PHY's interface type. 3095 * However, that only works when the config property "serdes_if_type" is specified. 3096 */ 3097 if (!is_legacy_phy_callback) { 3098 _SOC_IF_ERR_EXIT(portmod_media_type_from_port_intf(unit, interface, 3099 phy_config)); 3100 } 3101 exit: 3102 SOC_FUNC_RETURN; 3103 } 3104 3105 /* 3106 * overwrite default tx params from config file. 3107 * set phy_init_config in PM. 3108 */ 3109 STATIC 3110 int _pm4x10_port_tx_config_init_set(int unit, pm_info_t pm_info, 3111 int lane_mask, 3112 int core_start_lane, 3113 int core_end_lane, 3114 phymod_tx_t *tx_params_default, 3115 const phymod_tx_t user_tx_params[], 3116 const int *config_flag, 3117 phymod_tx_t phy_tx_params[], 3118 int *tx_params_update) 3119 { 3120 int lane_index, user_cfg_index, phy_param_index, start_cfg_index = core_start_lane, find_first_active_lane = 0; 3121 3122 if(core_start_lane==-1){ 3123 start_cfg_index = 0; 3124 } 3125 3126 /* 3127 * Read user configuration into the parameter array which will be passed to Phymod driver. 3128 * For consecutive physical lanes, Phymod driver expect each item in the parameter array 3129 * indicate the value for every active lane. 3130 * For inconsecutive physical lanes, it's a little different. 3131 * For exampe, there are two active lane: lane 0 and lane 2, Phymod driver expect the first 3132 * item indicate lane 0 and the third item indicate lane 2. 3133 */ 3134 *tx_params_update = 0; 3135 for (lane_index = 0, user_cfg_index = start_cfg_index, phy_param_index = 0; lane_index < PHYMOD_MAX_LANES_PER_PORT; lane_index++) { 3136 if (lane_mask & (0x1<<lane_index)) { 3137 phy_tx_params[phy_param_index].pre = tx_params_default->pre; 3138 phy_tx_params[phy_param_index].main = tx_params_default->main; 3139 phy_tx_params[phy_param_index].post = tx_params_default->post; 3140 phy_tx_params[phy_param_index].post2 = tx_params_default->post2; 3141 phy_tx_params[phy_param_index].post3 = tx_params_default->post3; 3142 phy_tx_params[phy_param_index].amp = tx_params_default->amp; 3143 phy_tx_params[phy_param_index].drivermode = tx_params_default->drivermode; 3144 3145 if (config_flag[user_cfg_index] & PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG) { 3146 phy_tx_params[phy_param_index].pre = user_tx_params[user_cfg_index].pre; 3147 phy_tx_params[phy_param_index].main = user_tx_params[user_cfg_index].main; 3148 phy_tx_params[phy_param_index].post = user_tx_params[user_cfg_index].post; 3149 } 3150 3151 if (config_flag[user_cfg_index] & PORTMOD_USER_SET_TX_AMP_BY_CONFIG) { 3152 phy_tx_params[phy_param_index].amp = user_tx_params[user_cfg_index].amp; 3153 } 3154 3155 3156 if ((config_flag[user_cfg_index] & PORTMOD_USER_SET_TX_PREEMPHASIS_BY_CONFIG) 3157 || (config_flag[user_cfg_index] & PORTMOD_USER_SET_TX_AMP_BY_CONFIG)){ 3158 *tx_params_update = 1; 3159 } 3160 3161 user_cfg_index++; 3162 3163 if (!find_first_active_lane) { 3164 find_first_active_lane = 1; 3165 } 3166 } 3167 3168 if (find_first_active_lane) { 3169 phy_param_index++; 3170 } 3171 } 3172 3173 return SOC_E_NONE; 3174 } 3175 3176 STATIC 3177 int _pm4x10_port_timestamp_adjust_wb_get(int unit, int port, pm_info_t pm_info, 3178 int speed, portmod_port_ts_adjust_t *ts_adjust) 3179 { 3180 int rv = 0; 3181 int port_index, adjust_index; 3182 uint32_t bitmap; 3183 portmod_port_ts_adjust_t port_ts_adjust; 3184 3185 SOC_INIT_FUNC_DEFS; 3186 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 3187 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM; adjust_index++) { 3188 rv = PM4x10_PORT_TIME_STAMP_ADJUST_GET(unit, pm_info, &port_ts_adjust, adjust_index, port_index); 3189 if ((port_ts_adjust.speed == speed) || 3190 (port_ts_adjust.speed == -1)) { 3191 sal_memcpy(ts_adjust, &port_ts_adjust, sizeof(portmod_port_ts_adjust_t)); 3192 break; 3193 } 3194 } 3195 3196 _SOC_IF_ERR_EXIT(rv); 3197 exit: 3198 SOC_FUNC_RETURN; 3199 } 3200 3201 /* 3202 * clear pm_info's phy_interface_config, and set few members of phy_interface_config 3203 * initialize phy_init_config tx params and set registers 3204 */ 3205 int _pm4x10_port_interface_config_init_set(int unit, int port, 3206 pm_info_t pm_info, 3207 const portmod_port_interface_config_t* config, 3208 const portmod_port_init_config_t* init_config, 3209 phymod_tx_t serdes_tx_params[], 3210 phymod_tx_t ext_phy_tx_params[]) 3211 { 3212 uint32 reg_val, pm_is_bypassed = 0; 3213 int nof_phys = 0, rv = 0, phy_acc, flags = 0; 3214 int tx_params_update = 0, mac_ts_enable; 3215 int core_start_lane=-1, core_end_lane=-1, line_start_lane=-1, line_end_lane=-1; 3216 uint32 int_lane_mask=0xf, port_dynamic_state = 0; 3217 phymod_phy_access_t phy_access[1 + MAX_PHYN]; 3218 phymod_phy_inf_config_t phy_interface_config; 3219 phymod_tx_t phymod_tx; 3220 int port_index, is_legacy_phy = 0; 3221 int is_higig, rxaui_mode, xphy_id; 3222 uint32_t bitmap; 3223 phymod_interface_t phymod_interface = phymodInterfaceCount; 3224 portmod_port_ts_adjust_t ts_adjust; 3225 3226 SOC_INIT_FUNC_DEFS; 3227 3228 sal_memset(&ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 3229 3230 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 3231 3232 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 3233 &bitmap)); 3234 3235 _SOC_IF_ERR_EXIT(phymod_tx_t_init(&phymod_tx)); 3236 3237 is_higig = ((config->encap_mode == SOC_ENCAP_HIGIG2) || 3238 (config->encap_mode == SOC_ENCAP_HIGIG) || 3239 PHYMOD_INTF_MODES_HIGIG_GET(config)) ? 1 : 0; 3240 3241 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 3242 pm_info->wb_vars_ids[isBypassed], 3243 &pm_is_bypassed); 3244 _SOC_IF_ERR_EXIT(rv); 3245 3246 if(!pm_is_bypassed){ 3247 /* set HiG mode */ 3248 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, ®_val)); 3249 soc_reg_field_set (unit, XLPORT_CONFIGr, ®_val, HIGIG2_MODEf, is_higig); 3250 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, reg_val)); 3251 3252 /* set port speed */ 3253 flags = XLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 3254 _SOC_IF_ERR_EXIT(xlmac_speed_set(unit, port, flags, config->speed)); 3255 3256 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 3257 _SOC_IF_ERR_EXIT 3258 (pm4x10_port_mac_timestamp_enable_get(unit, port, pm_info, &mac_ts_enable)); 3259 } else { 3260 mac_ts_enable = 1; 3261 } 3262 _SOC_IF_ERR_EXIT(PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, 3263 &port_dynamic_state, port_index)); 3264 if (mac_ts_enable) { 3265 /*Set MAC Timestamp Delay*/ 3266 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 3267 _SOC_IF_ERR_EXIT(_pm4x10_port_timestamp_adjust_wb_get(unit, port, pm_info, config->speed, &ts_adjust)); 3268 _SOC_IF_ERR_EXIT(xlmac_timestamp_delay_set(unit, port, ts_adjust, config->speed)); 3269 } 3270 _SOC_IF_ERR_EXIT(xlmac_timestamp_byte_adjust_set(unit, port, 0, config->speed)); 3271 } 3272 3273 /* set encapsulation */ 3274 flags = XLMAC_ENCAP_SET_FLAGS_SOFT_RESET_DIS; 3275 rv = xlmac_encap_set (unit, port, flags, is_higig ? SOC_ENCAP_HIGIG2 : 3276 SOC_ENCAP_IEEE); 3277 _SOC_IF_ERR_EXIT(rv); 3278 3279 rv = xlmac_strict_preamble_set(unit, port, (!is_higig && (config->speed >= 10000))); 3280 3281 _SOC_IF_ERR_EXIT(rv); 3282 3283 } 3284 3285 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 3286 phy_access ,(1+MAX_PHYN), 3287 &nof_phys)); 3288 3289 _SOC_IF_ERR_EXIT(PM4x10_RXAUI_MODE_GET(unit, pm_info, 3290 &rxaui_mode, port_index)); 3291 3292 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init (&phy_interface_config)); 3293 _SOC_IF_ERR_EXIT(_pm4x10_line_side_phymod_interface_get(unit, port, 3294 pm_info, rxaui_mode, 3295 config, 3296 &phymod_interface)); 3297 phy_interface_config.interface_type = phymod_interface; 3298 _SOC_IF_ERR_EXIT(_pm4x10_phymod_interface_mode_set(unit, port, 3299 pm_info, config, 3300 &phy_interface_config, 3301 0)); 3302 3303 phy_interface_config.data_rate = config->speed; 3304 phy_interface_config.pll_divider_req = config->pll_divider_req; 3305 phy_interface_config.ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 3306 3307 _SOC_IF_ERR_EXIT(PM4x10_SPEED_SET(unit, pm_info, 3308 config->speed, port_index)); 3309 3310 3311 /* find the start_lane and end_lane of the current core */ 3312 _SOC_IF_ERR_EXIT(_pm4x10_port_tricore_lane_info_get(unit, port, pm_info, 3313 &core_start_lane, &core_end_lane, 3314 &line_start_lane, &line_end_lane, 3315 &int_lane_mask, NULL)); 3316 3317 if(nof_phys > 1) 3318 { /* external phy. */ 3319 /* get most external phy default tx params */ 3320 xphy_id = phy_access[nof_phys-1].access.addr; 3321 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 3322 if (!is_legacy_phy) { 3323 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access[nof_phys-1], phymodMediaTypeChipToChip, &phymod_tx)); 3324 } 3325 3326 /* overlap most external phy preemphasis and amp from config */ 3327 tx_params_update = 0; 3328 _SOC_IF_ERR_EXIT( 3329 _pm4x10_port_tx_config_init_set(unit, pm_info, 3330 phy_access[nof_phys-1].access.lane_mask, 3331 core_start_lane, 3332 core_end_lane, &phymod_tx, 3333 init_config->ext_phy_tx_params, 3334 init_config->ext_phy_tx_params_user_flag, 3335 ext_phy_tx_params, 3336 &tx_params_update)); 3337 if (tx_params_update) { 3338 PORTMOD_PORT_DEFAULT_EXT_PHY_TX_PARAMS_UPDATED_SET(port_dynamic_state); 3339 PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, port_dynamic_state, port_index); 3340 } 3341 } 3342 3343 /* get serdes default tx params */ 3344 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(phy_access, phymodMediaTypeChipToChip, &phymod_tx)); 3345 3346 /* overlap serdes preemphasis and amp from config */ 3347 tx_params_update = 0; 3348 _SOC_IF_ERR_EXIT( 3349 _pm4x10_port_tx_config_init_set(unit, pm_info, 3350 phy_access[0].access.lane_mask, 3351 core_start_lane, 3352 core_end_lane, &phymod_tx, 3353 init_config->tx_params, 3354 init_config->tx_params_user_flag, 3355 serdes_tx_params, 3356 &tx_params_update)); 3357 if (tx_params_update) { 3358 PORTMOD_PORT_DEFAULT_TX_PARAMS_UPDATED_SET(port_dynamic_state); 3359 PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, port_dynamic_state, port_index); 3360 } 3361 3362 /* set the outmost external PHY tx. internal and intermediary phy will be modified in portmod_port_phychain_phy_init*/ 3363 if (nof_phys > 1){ 3364 SOC_IF_ERROR_RETURN( 3365 portmod_port_phychain_tx_set(unit, phy_access, nof_phys, 3366 ext_phy_tx_params)); 3367 } 3368 3369 /* update the interface type in the scache buffer */ 3370 _SOC_IF_ERR_EXIT(PM4x10_PORT_OP_MODE_SET(unit, pm_info, 3371 config->port_op_mode, 3372 port_index)); 3373 3374 exit: 3375 SOC_FUNC_RETURN; 3376 } 3377 3378 3379 STATIC 3380 int _pm4x10_pm_disable (int unit, int port, pm_info_t pm_info, int phy_acc) 3381 { 3382 uint32 reg_val; 3383 int rv = 0; 3384 3385 /* put MAC in reset */ 3386 rv = READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val); 3387 if (rv) return (rv); 3388 3389 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 1); 3390 rv = WRITE_XLPORT_MAC_CONTROLr(unit, phy_acc, reg_val); 3391 if (rv) return (rv); 3392 3393 /* Put Serdes in reset*/ 3394 if(PM_4x10_INFO(pm_info)->portmod_phy_external_reset) { 3395 rv = PM_4x10_INFO(pm_info)->portmod_phy_external_reset(unit, port, 1); 3396 } else { 3397 if ( _pm4x10_port_tsc_is_master_pll(unit, port, pm_info) != TRUE) { /* Not master PLL PM, reset it */ 3398 rv = _pm4x10_tsc_reset(unit, pm_info, port, 1); 3399 } 3400 } 3401 3402 return (rv); 3403 } 3404 3405 STATIC 3406 int _pm4x10_pm_xlport_init (int unit, int port, pm_info_t pm_info, 3407 int port_index, int phy_acc, const portmod_port_add_info_t* add_info) 3408 { 3409 uint32 reg_val, port_mode; 3410 int three_ports_mode, rv; 3411 pm_version_t pm_version; 3412 int interface = add_info->interface_config.interface; 3413 int timestamp_mode = add_info->flags & PORTMOD_PORT_ADD_F_EGR_1588_TIMESTAMP_MODE_48BIT ? 1 : 0; 3414 uint32 *txpi_lane_select = (uint32 *)add_info->init_config.lane_map[0].lane_map_tx; 3415 SOC_INIT_FUNC_DEFS; 3416 3417 /* Power Save */ 3418 _SOC_IF_ERR_EXIT(READ_XLPORT_POWER_SAVEr(unit, phy_acc, ®_val)); 3419 soc_reg_field_set(unit, XLPORT_POWER_SAVEr, ®_val, XPORT_CORE0f, 0); 3420 _SOC_IF_ERR_EXIT(WRITE_XLPORT_POWER_SAVEr(unit, phy_acc, reg_val)); 3421 3422 /* Port configuration */ 3423 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 3424 pm_info->wb_vars_ids[threePortsMode], &three_ports_mode); 3425 _SOC_IF_ERR_EXIT(rv); 3426 3427 if(PM4x10_QUAD_MODE_IF(interface)) { 3428 /* This is WAR for shim issue on Merlin16 MGMT port, XLPORT_MODE_REG is 3429 * set as dual-port mode for XAUI mode 3430 */ 3431 if (PM_4x10_INFO(pm_info)->port_mode_aux_info == portmodModeInfoTwoDualModePorts) { 3432 port_mode = XLMAC_2_LANES_DUAL; 3433 } else { 3434 port_mode = XLMAC_4_LANES_TOGETHER; 3435 } 3436 } else if(PM4x10_DUAL_MODE_IF(interface)){ 3437 port_mode = (!three_ports_mode) ? XLMAC_2_LANES_DUAL : 3438 ((port_index < 2) ? XLMAC_3_TRI_0_0_2_3 : 3439 XLMAC_3_TRI_0_1_2_2); 3440 } else { /*single mode*/ 3441 if (PM_4x10_INFO(pm_info)->port_mode_aux_info == portmodModeInfoTwoDualModePorts) { 3442 port_mode = XLMAC_2_LANES_DUAL; 3443 } else { 3444 port_mode = (!three_ports_mode) ? XLMAC_4_LANES_SEPARATE : 3445 ((port_index < 2) ? XLMAC_3_TRI_0_1_2_2 : 3446 XLMAC_3_TRI_0_0_2_3); 3447 } 3448 } 3449 3450 _SOC_IF_ERR_EXIT(READ_XLPORT_MODE_REGr(unit, phy_acc, ®_val)); 3451 soc_reg_field_set (unit, XLPORT_MODE_REGr, ®_val, XPORT0_CORE_PORT_MODEf, port_mode); 3452 soc_reg_field_set (unit, XLPORT_MODE_REGr, ®_val, XPORT0_PHY_PORT_MODEf, port_mode); 3453 soc_reg_field_set (unit, XLPORT_MODE_REGr, ®_val, EGR_1588_TIMESTAMPING_MODEf, timestamp_mode); 3454 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MODE_REGr(unit, phy_acc, reg_val)); 3455 3456 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 3457 if (PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 3458 /* Set txpi lane select */ 3459 _SOC_IF_ERR_EXIT(_pm4x10_txpi_lane_select_set(unit, port, pm_info, txpi_lane_select)); 3460 } 3461 3462 /* Get Serdes OOR */ 3463 if(PM_4x10_INFO(pm_info)->portmod_phy_external_reset) { 3464 if(!((interface == SOC_PORT_IF_CAUI)&&(PM_4x10_INFO(pm_info)->core_num_int))) { 3465 _SOC_IF_ERR_EXIT(PM_4x10_INFO(pm_info)->portmod_phy_external_reset(unit, port, 1)); 3466 _SOC_IF_ERR_EXIT(PM_4x10_INFO(pm_info)->portmod_phy_external_reset(unit, port, 0)); 3467 } 3468 } else { 3469 if ( _pm4x10_port_tsc_is_master_pll(unit, port, pm_info) != TRUE) { /* Not master PLL PM, reset it */ 3470 _SOC_IF_ERR_EXIT(_pm4x10_tsc_reset(unit, pm_info, port, 1)); 3471 _SOC_IF_ERR_EXIT(_pm4x10_tsc_reset(unit, pm_info, port, 0)); 3472 } 3473 } 3474 3475 /* Bring MAC OOR */ 3476 _SOC_IF_ERR_EXIT(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 3477 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 0); 3478 /* Disable MAC timestamp by default */ 3479 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 3480 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, XLMAC_TS_DISABLEf, 1); 3481 } 3482 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 3483 3484 exit: 3485 SOC_FUNC_RETURN; 3486 } 3487 3488 static phymod_dispatch_type_t pm4x10_serdes_list[] = 3489 { 3490 phymodDispatchTypeTsce, 3491 phymodDispatchTypeTsce16, 3492 phymodDispatchTypeTsce_dpll, 3493 phymodDispatchTypeQsgmiie, 3494 phymodDispatchTypeInvalid 3495 }; 3496 3497 STATIC 3498 int _pm4x10_pm_core_probe (int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 3499 { 3500 int rv = SOC_E_NONE; 3501 int temp, phy; 3502 portmod_pbmp_t port_phys_in_pm; 3503 int probe =0; 3504 uint32 xphy_id; 3505 uint32 nof_ext_phys =0; 3506 int i, is_legacy_phy; 3507 int core_probed; 3508 phymod_core_access_t core_access; 3509 phymod_firmware_load_method_t fw_load_method; 3510 SOC_INIT_FUNC_DEFS; 3511 3512 /* probe phys (both internal and external cores. */ 3513 3514 /* Get the first phy related to this port */ 3515 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 3516 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x10_INFO(pm_info)->phys); 3517 3518 /* if internal core is not probe, probe it. Currently checking to type to see 3519 phymodDispatchTypeInvalid, later need to move to WB. */ 3520 _SOC_IF_ERR_EXIT(portmod_common_serdes_probe(pm4x10_serdes_list, &PM_4x10_INFO(pm_info)->int_core_access, &probe)); 3521 3522 /* save probed phy type to wb. */ 3523 if(probe) { 3524 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 3525 pm_info->wb_vars_ids[phy_type], 3526 &PM_4x10_INFO(pm_info)->int_core_access.type); 3527 _SOC_IF_ERR_EXIT(rv); 3528 } 3529 3530 /* probe ext core related to this logical port. */ 3531 temp = 0; 3532 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) { 3533 if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) { 3534 if( PM_4x10_INFO(pm_info)->nof_phys[temp] >= 2 ){ 3535 nof_ext_phys = PM_4x10_INFO(pm_info)->nof_phys[temp]-1; 3536 for(i=0 ; i<nof_ext_phys ; i++) { 3537 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[i][temp].xphy_id; 3538 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 3539 _SOC_IF_ERR_EXIT(portmod_xphy_core_probed_get(unit, xphy_id, &core_probed)); 3540 _SOC_IF_ERR_EXIT(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 3541 if( !core_probed ){ 3542 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 3543 probe = 0; 3544 if(SOC_E_NONE != (portmod_common_ext_phy_probe(unit, port, &core_access, &probe))) { 3545 /* 3546 * Remove un-probed external PHY from phy number count. 3547 * Also save it to warmboot memory. 3548 */ 3549 PM_4x10_INFO(pm_info)->nof_phys[temp] = i + 1; 3550 rv = PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, &(PM_4x10_INFO(pm_info)->nof_phys[temp]), temp); 3551 _SOC_IF_ERR_EXIT(rv); 3552 /* Set firmware download method to phymodFirmwareLoadMethodNone to avoid image download for unprobed XPHY */ 3553 fw_load_method = phymodFirmwareLoadMethodNone; 3554 } else { 3555 if (!probe) { 3556 /* 3557 * case where port_phy_addr is specified and phy is not connetced. 3558 * Remove un-probed external PHY from phy number count. 3559 * Also save it to warmboot memory. 3560 */ 3561 PM_4x10_INFO(pm_info)->nof_phys[temp] = i + 1; 3562 rv = PM4x10_PORT_NUM_PHYS_SET(unit, pm_info,&(PM_4x10_INFO(pm_info)->nof_phys[temp]), temp); 3563 _SOC_IF_ERR_EXIT(rv); 3564 /* Set firmware download method to phymodFirmwareLoadMethodNone to avoid image download for unprobed XPHY */ 3565 fw_load_method = phymodFirmwareLoadMethodNone; 3566 } else { 3567 core_probed = 1; 3568 } 3569 } 3570 _SOC_IF_ERR_EXIT(portmod_xphy_core_probed_set(unit, xphy_id, core_probed)); 3571 _SOC_IF_ERR_EXIT(portmod_xphy_fw_load_method_set(unit, xphy_id, fw_load_method)); 3572 /* Check if after the probe the ext phy is legacy, so we dont overrun the current value */ 3573 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 3574 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_set(unit, xphy_id, &core_access, is_legacy_phy)); 3575 } 3576 } 3577 } 3578 } 3579 } 3580 temp++; 3581 } 3582 3583 /*update warmboot engine*/ 3584 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 3585 pm_info->wb_vars_ids[phy_type], 3586 &PM_4x10_INFO(pm_info)->int_core_access.type, 0); 3587 _SOC_IF_ERR_EXIT(rv); 3588 3589 exit: 3590 SOC_FUNC_RETURN; 3591 } 3592 3593 STATIC 3594 int _pm4x10_pm_serdes_core_init(int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 3595 { 3596 int rv; 3597 phymod_core_init_config_t core_conf; 3598 phymod_core_status_t core_status; 3599 const portmod_port_interface_config_t* config; 3600 uint32 core_is_initialized; 3601 uint32 init_flags, is_bypass; 3602 soc_port_if_t interface = SOC_PORT_IF_NULL; 3603 pm_version_t pm_version; 3604 SOC_INIT_FUNC_DEFS; 3605 3606 config = &(add_info->interface_config); 3607 3608 _SOC_IF_ERR_EXIT(phymod_core_init_config_t_init(&core_conf)); 3609 3610 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &is_bypass); 3611 _SOC_IF_ERR_EXIT(rv); 3612 /* set internal setting. */ 3613 3614 core_conf.firmware_load_method = PM_4x10_INFO(pm_info)->fw_load_method; 3615 core_conf.firmware_loader = PM_4x10_INFO(pm_info)->external_fw_loader; 3616 if (PM_4x10_INFO(pm_info)->is_pm4x10q) { 3617 core_conf.lane_map = add_info->init_config.lane_map[0]; 3618 } else { 3619 core_conf.lane_map = PM_4x10_INFO(pm_info)->lane_map; 3620 } 3621 3622 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&core_conf.interface)); 3623 _SOC_IF_ERR_EXIT(portmod_line_intf_from_config_get(config, &interface)); 3624 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, config->speed, 3625 interface, &core_conf.interface.interface_type)); 3626 core_conf.interface.data_rate = config->speed; 3627 core_conf.interface.interface_modes = config->interface_modes; 3628 core_conf.interface.ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 3629 core_conf.interface.pll_divider_req = add_info->init_config.pll_divider_req; 3630 3631 _SOC_IF_ERR_EXIT(phymod_core_status_t_init(&core_status)); 3632 3633 if(PORTMOD_PORT_ADD_F_FIRMWARE_LOAD_VERIFY_GET(add_info)) { 3634 PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_SET(&core_conf); 3635 } 3636 3637 init_flags = PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) | PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info); 3638 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 3639 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_SET(&core_conf); 3640 } 3641 3642 if(PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 3643 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_SET(&core_conf); 3644 } 3645 3646 core_conf.op_datapath = add_info->phy_op_datapath; 3647 3648 /* deal witn internal serdes first */ 3649 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 3650 pm_info->wb_vars_ids[isInitialized], 3651 &core_is_initialized); 3652 _SOC_IF_ERR_EXIT(rv); 3653 3654 if (!PORTMOD_CORE_INIT_FLAG_INITIALZIED_GET(core_is_initialized)) { 3655 /* firmware load will happen after init_pass1 */ 3656 if (!PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_GET(core_is_initialized) || 3657 PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 3658 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 3659 3660 if (PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 3661 portmod_vcos_speed_config_t speed_config; 3662 phymod_dual_plls_t init_plls; 3663 3664 init_plls.pll0_div = phymod_TSCE_PLL_DIV66; 3665 init_plls.pll1_div = phymod_TSCE_PLL_DIV40; 3666 3667 portmod_vcos_speed_config_t_init(unit, &speed_config); 3668 speed_config.higig_mode = add_info->init_config.is_hg; 3669 speed_config.speed = add_info->interface_config.speed; 3670 speed_config.num_lanes = add_info->interface_config.port_num_lanes; 3671 3672 _SOC_IF_ERR_EXIT(_pm4x10_init_plls_get(unit, port, pm_info, &speed_config, 1, &init_plls)); 3673 core_conf.pll0_div_init_value = init_plls.pll0_div; 3674 core_conf.pll1_div_init_value = init_plls.pll1_div; 3675 } 3676 3677 if ((is_bypass) && (!PM_4x10_INFO(pm_info)->in_pm12x10)) { 3678 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_SET(PM_4x10_INFO(pm_info)->int_core_access.device_op_mode); 3679 } 3680 _SOC_IF_ERR_EXIT(phymod_core_init(&PM_4x10_INFO(pm_info)->int_core_access, 3681 &core_conf, 3682 &core_status)); 3683 3684 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_flags == 0) { 3685 PORTMOD_CORE_INIT_FLAG_FIRMWARE_LOADED_SET(core_is_initialized); 3686 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 3687 pm_info->wb_vars_ids[isInitialized], 3688 &core_is_initialized); 3689 _SOC_IF_ERR_EXIT(rv); 3690 } 3691 if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info) || init_flags == 0) { 3692 PORTMOD_CORE_INIT_FLAG_INITIALZIED_SET(core_is_initialized); 3693 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 3694 pm_info->wb_vars_ids[isInitialized], 3695 &core_is_initialized); 3696 _SOC_IF_ERR_EXIT(rv); 3697 } 3698 } 3699 } 3700 3701 /*update warmboot engine*/ 3702 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 3703 pm_info->wb_vars_ids[phy_type], 3704 &PM_4x10_INFO(pm_info)->int_core_access.type, 0); 3705 _SOC_IF_ERR_EXIT(rv); 3706 3707 exit: 3708 SOC_FUNC_RETURN; 3709 } 3710 3711 STATIC 3712 int _pm4x10_pm_ext_phy_core_init(int unit, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 3713 { 3714 int temp, phy; 3715 phymod_core_init_config_t core_conf; 3716 phymod_core_status_t core_status; 3717 portmod_pbmp_t port_phys_in_pm; 3718 uint32 xphy_id; 3719 uint32 nof_ext_phys =0; 3720 int i; 3721 int is_initialized; 3722 int lane; 3723 int init_all; 3724 phymod_firmware_load_method_t fw_load_method; 3725 int force_fw_load; 3726 phymod_lane_map_t lane_map; 3727 phymod_core_access_t core_access; 3728 uint32 primary_core_num; 3729 int is_legacy_phy; 3730 SOC_INIT_FUNC_DEFS; 3731 3732 init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) && 3733 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) && 3734 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) ? 1 : 0; 3735 3736 /* Get the first phy related to this port */ 3737 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 3738 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x10_INFO(pm_info)->phys); 3739 3740 /* core init (both internal and external cores. */ 3741 3742 _SOC_IF_ERR_EXIT(phymod_core_init_config_t_init(&core_conf)); 3743 3744 core_conf.interface.pll_divider_req = 3745 add_info->init_config.pll_divider_req; 3746 3747 _SOC_IF_ERR_EXIT(phymod_core_status_t_init(&core_status)); 3748 3749 3750 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 3751 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_SET(&core_conf); 3752 } 3753 3754 if(PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 3755 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_SET(&core_conf); 3756 } 3757 3758 core_conf.op_datapath = add_info->phy_op_datapath; 3759 3760 /* deal with ext phys now ... */ 3761 if(PORTMOD_PORT_ADD_F_PORT_ATTACH_EXT_PHY_SKIP_GET(add_info)) { 3762 return(SOC_E_NONE); 3763 } 3764 3765 /* adjust config setup for external phys. */ 3766 3767 /* for external phys, FW load method is default to Internal 3768 unless it is force to NONE. */ 3769 3770 3771 core_conf.firmware_load_method = (PM_4x10_INFO(pm_info)->fw_load_method == 3772 phymodFirmwareLoadMethodNone) ? 3773 phymodFirmwareLoadMethodNone : 3774 phymodFirmwareLoadMethodInternal; 3775 core_conf.firmware_loader = NULL; 3776 3777 /* config "no swap" for external phys.set later using APIs*/ 3778 for(lane=0 ; lane < (core_conf.lane_map.num_of_lanes); lane++) { 3779 core_conf.lane_map.lane_map_rx[lane] = lane; 3780 core_conf.lane_map.lane_map_tx[lane] = lane; 3781 } 3782 3783 3784 temp = 0; 3785 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) { 3786 if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) { 3787 if( PM_4x10_INFO(pm_info)->nof_phys[temp] >= 2 ){ 3788 nof_ext_phys = PM_4x10_INFO(pm_info)->nof_phys[temp]-1; 3789 for(i=0 ; i<nof_ext_phys ; i++) { 3790 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[i][temp].xphy_id; 3791 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 3792 3793 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 3794 _SOC_IF_ERR_EXIT(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 3795 _SOC_IF_ERR_EXIT(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 3796 _SOC_IF_ERR_EXIT(portmod_xphy_lane_map_get(unit, xphy_id, &lane_map)); 3797 _SOC_IF_ERR_EXIT(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 3798 3799 /* for external phys, FW load method is default to Internal 3800 unless it is force to NONE. */ 3801 core_conf.firmware_load_method = fw_load_method; 3802 core_conf.firmware_loader = NULL; 3803 3804 if (force_fw_load == phymodFirmwareLoadForce) { 3805 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_conf); 3806 } 3807 else if (force_fw_load == phymodFirmwareLoadAuto) { 3808 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_conf); 3809 } 3810 3811 /* config "no swap" for external phys.set later using APIs*/ 3812 for(lane=0 ; lane < lane_map.num_of_lanes; lane++) { 3813 core_conf.lane_map.lane_map_rx[lane] = lane_map.lane_map_rx[lane]; 3814 core_conf.lane_map.lane_map_tx[lane] = lane_map.lane_map_tx[lane]; 3815 } 3816 if (xphy_id == primary_core_num) { 3817 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 3818 /* Very first time this function gets called, honor the call and 3819 * ignore the flags */ 3820 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 3821 if (PM_4x10_INFO(pm_info)->first_phy == phy) { 3822 _SOC_IF_ERR_EXIT(portmod_xphy_core_config_set(unit, xphy_id, &core_conf)); 3823 } 3824 } 3825 } else { 3826 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_get(unit, primary_core_num, &is_initialized)); 3827 } 3828 3829 3830 if ((PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || init_all) && 3831 (is_initialized & PHYMOD_CORE_INIT_F_EXECUTE_PASS1)) 3832 continue; 3833 3834 if ((PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info) || init_all) && 3835 (is_initialized & PHYMOD_CORE_INIT_F_EXECUTE_PASS2)) { 3836 continue; 3837 } 3838 3839 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 3840 if (is_legacy_phy) { 3841 /* Dont do a core init for legacy Phys.*/ 3842 } else { 3843 _SOC_IF_ERR_EXIT(phymod_core_init(&core_access, &core_conf, &core_status)); 3844 } 3845 3846 if (init_all) { 3847 is_initialized = (PHYMOD_CORE_INIT_F_EXECUTE_PASS2 | PHYMOD_CORE_INIT_F_EXECUTE_PASS1); 3848 } 3849 else if (PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) { 3850 is_initialized |= PHYMOD_CORE_INIT_F_EXECUTE_PASS2; 3851 } else { 3852 is_initialized = PHYMOD_CORE_INIT_F_EXECUTE_PASS1; 3853 } 3854 3855 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 3856 3857 if (xphy_id != primary_core_num) { 3858 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_set(unit, primary_core_num, is_initialized)); 3859 } 3860 } 3861 } 3862 } 3863 } 3864 temp++; 3865 } 3866 3867 exit: 3868 SOC_FUNC_RETURN; 3869 } 3870 3871 3872 3873 STATIC 3874 int _pm4x10_pm_core_init (int unit, int port, pm_info_t pm_info, const portmod_port_add_info_t* add_info) 3875 { 3876 SOC_INIT_FUNC_DEFS; 3877 _SOC_IF_ERR_EXIT(_pm4x10_pm_serdes_core_init(unit, port, pm_info, add_info)); 3878 _SOC_IF_ERR_EXIT(_pm4x10_pm_ext_phy_core_init(unit,pm_info,add_info)); 3879 3880 exit: 3881 SOC_FUNC_RETURN; 3882 } 3883 3884 3885 STATIC 3886 int _pm4x10_port_attach_core_probe (int unit, int port, pm_info_t pm_info, 3887 const portmod_port_add_info_t* add_info) 3888 { 3889 int port_index = -1, rv = 0, phy, i, phys_count = 0; 3890 uint32 pm_is_active = 0; 3891 portmod_pbmp_t port_phys_in_pm; 3892 int first_phy = -1, phy_acc; 3893 int prev_phy = -1; 3894 int adjust_index = 0, three_ports_mode; 3895 SOC_INIT_FUNC_DEFS; 3896 3897 /* Get the first phy related to this port */ 3898 PORTMOD_PBMP_ASSIGN(port_phys_in_pm, add_info->phys); 3899 PORTMOD_PBMP_AND(port_phys_in_pm, PM_4x10_INFO(pm_info)->phys); 3900 PORTMOD_PBMP_COUNT(port_phys_in_pm, phys_count); 3901 3902 /* if first phy is initialized and use it, default is -1 anyways */ 3903 first_phy = PM_4x10_INFO(pm_info)->first_phy; 3904 3905 i = 0; 3906 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) { 3907 if (prev_phy != -1) { 3908 i += phy - prev_phy; 3909 } 3910 3911 if(PORTMOD_PBMP_MEMBER(port_phys_in_pm, phy)) { 3912 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 3913 pm_info->wb_vars_ids[ports], &port, i); 3914 port_index = (port_index == -1 ? i : port_index); 3915 _SOC_IF_ERR_EXIT(rv); 3916 first_phy = (first_phy == -1) ? phy : first_phy; 3917 } 3918 prev_phy = phy; 3919 } 3920 3921 3922 PM_4x10_INFO(pm_info)->first_phy = first_phy; 3923 3924 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 3925 3926 if(port_index<0 || port_index>=PM4X10_LANES_PER_CORE) { 3927 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 3928 (_SOC_MSG("can't attach port %d. can't find relevant phy"), port)); 3929 } 3930 3931 rv = PM4x10_IS_HG_SET(unit, pm_info, add_info->init_config.is_hg, 3932 port_index); 3933 _SOC_IF_ERR_EXIT(rv); 3934 rv = PM4x10_AN_MODE_SET(unit, pm_info, add_info->init_config.an_mode, 3935 port_index); 3936 _SOC_IF_ERR_EXIT(rv); 3937 rv = PM4x10_FS_CL72_SET(unit, pm_info, add_info->init_config.fs_cl72, 3938 port_index); 3939 _SOC_IF_ERR_EXIT(rv); 3940 rv = PM4x10_CX4_10G_SET(unit, pm_info, add_info->init_config.cx4_10g, 3941 port_index); 3942 _SOC_IF_ERR_EXIT(rv); 3943 rv = PM4x10_AN_CL72_SET(unit, pm_info, add_info->init_config.an_cl72, 3944 port_index); 3945 _SOC_IF_ERR_EXIT(rv); 3946 rv = PM4x10_AN_FEC_SET(unit, pm_info, add_info->init_config.an_fec, 3947 port_index); 3948 _SOC_IF_ERR_EXIT(rv); 3949 rv = PM4x10_AN_CL37_SET(unit, pm_info, add_info->init_config.an_cl37, 3950 port_index); 3951 _SOC_IF_ERR_EXIT(rv); 3952 rv = PM4x10_AN_MASTER_LANE_SET(unit, pm_info, 3953 add_info->init_config.an_master_lane, 3954 port_index); 3955 _SOC_IF_ERR_EXIT(rv); 3956 rv = PM4x10_CL37_SGMII_CNT_SET(unit, pm_info, 3957 add_info->init_config.cl37_sgmii_cnt, 3958 port_index); 3959 _SOC_IF_ERR_EXIT(rv); 3960 rv = PM4x10_CL37_SGMII_RESTART_CNT_SET(unit, pm_info, 3961 add_info->init_config.cl37_sgmii_RESTART_CNT, 3962 port_index); 3963 _SOC_IF_ERR_EXIT(rv); 3964 rv = PM4x10_PORT_FALLBACK_LANE_SET(unit, pm_info, 3965 add_info->init_config.port_fallback_lane, 3966 port_index); 3967 _SOC_IF_ERR_EXIT(rv); 3968 rv = PM4x10_RXAUI_MODE_SET(unit, pm_info, 3969 add_info->init_config.rxaui_mode, 3970 port_index); 3971 _SOC_IF_ERR_EXIT(rv); 3972 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, 3973 add_info->interface_config.max_speed, port_index); 3974 _SOC_IF_ERR_EXIT(rv); 3975 rv = PM4x10_INTERFACE_TYPE_SET(unit, pm_info, 3976 add_info->interface_config.interface, 3977 port_index); 3978 _SOC_IF_ERR_EXIT(rv); 3979 rv = PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, 3980 add_info->interface_config.interface, 3981 port_index); 3982 _SOC_IF_ERR_EXIT(rv); 3983 rv = PM4x10_SERDES_INTERFACE_TYPE_SET(unit, pm_info, 3984 add_info->interface_config.serdes_interface, 3985 port_index); 3986 _SOC_IF_ERR_EXIT(rv); 3987 rv = PM4x10_INTERFACE_MODES_SET(unit, pm_info, 3988 add_info->interface_config.interface_modes, 3989 port_index); 3990 _SOC_IF_ERR_EXIT(rv); 3991 rv = PM4x10_PORT_OP_MODE_SET(unit, pm_info, 3992 add_info->interface_config.port_op_mode, 3993 port_index); 3994 _SOC_IF_ERR_EXIT(rv); 3995 3996 rv = PM4x10_PORT_PLL_DIVIDER_REQ_SET(unit, pm_info, 3997 add_info->init_config.pll_divider_req, 3998 port_index); 3999 _SOC_IF_ERR_EXIT(rv); 4000 4001 for (adjust_index = 0; adjust_index < PORTMOD_TS_ADJUST_NUM; adjust_index++) { 4002 rv = PM4x10_PORT_TIME_STAMP_ADJUST_SET(unit, pm_info, 4003 &add_info->init_config.port_ts_adjust[adjust_index], 4004 adjust_index, port_index); 4005 _SOC_IF_ERR_EXIT(rv); 4006 } 4007 4008 if (add_info->init_config.polarity_overwrite == 1) { 4009 sal_memcpy(&PM_4x10_INFO(pm_info)->polarity, 4010 &add_info->init_config.polarity[PM_4x10_INFO(pm_info)->core_num_int], 4011 sizeof(phymod_polarity_t)); 4012 } 4013 if (add_info->init_config.lane_map_overwrite == 1) { 4014 sal_memcpy(&PM_4x10_INFO(pm_info)->lane_map, 4015 &add_info->init_config.lane_map[PM_4x10_INFO(pm_info)->core_num_int], 4016 sizeof(phymod_lane_map_t)); 4017 } 4018 if (add_info->init_config.ref_clk_overwrite == 1) { 4019 PM_4x10_INFO(pm_info)->ref_clk = add_info->init_config.ref_clk; 4020 } 4021 if (add_info->init_config.fw_load_method_overwrite == 1) { 4022 PM_4x10_INFO(pm_info)->fw_load_method = 4023 add_info->init_config.fw_load_method[PM_4x10_INFO(pm_info)->core_num_int]; 4024 } 4025 if (add_info->interface_config.interface == SOC_PORT_IF_QSGMII) { 4026 PM_4x10_INFO(pm_info)->is_pm4x10q = 1; 4027 } 4028 /* port_index is 0, 1, 2, or 3 */ 4029 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 4030 pm_info->wb_vars_ids[isActive], &pm_is_active); 4031 _SOC_IF_ERR_EXIT(rv); 4032 4033 /* if not active - initalize PM */ 4034 if(!pm_is_active){ 4035 #ifdef PORTMOD_PM12X10_SUPPORT 4036 if(PM_4x10_INFO(pm_info)->in_pm12x10) { 4037 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) {break;} 4038 /* this will be redirected to pm12x10 */ 4039 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 4040 4041 if (SOC_IS_APACHE(unit)) { 4042 rv = pm12x10_xgs_pm4x10_enable(unit, port, phy, 1); 4043 _SOC_IF_ERR_EXIT(rv); 4044 } else 4045 #endif 4046 { 4047 rv = pm12x10_pm4x10_enable(unit, port, phy, 1); 4048 _SOC_IF_ERR_EXIT(rv); 4049 } 4050 } 4051 #endif /* PORTMOD_PM12X10_SUPPORT */ 4052 three_ports_mode = (add_info->init_config.port_mode_aux_info == portmodModeInfoThreePorts) ? 1 : 0; 4053 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4054 pm_info->wb_vars_ids[threePortsMode], &three_ports_mode); 4055 _SOC_IF_ERR_EXIT(rv); 4056 4057 rv = _pm4x10_pm_xlport_init (unit, port, pm_info, port_index, 4058 phy_acc, add_info); 4059 _SOC_IF_ERR_EXIT(rv); 4060 4061 pm_is_active = 1; 4062 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4063 pm_info->wb_vars_ids[isActive], &pm_is_active); 4064 _SOC_IF_ERR_EXIT(rv); 4065 } 4066 4067 /*probe the core*/ 4068 rv = _pm4x10_pm_core_probe(unit, port, pm_info, add_info); 4069 _SOC_IF_ERR_EXIT(rv); 4070 4071 exit: 4072 SOC_FUNC_RETURN; 4073 } 4074 4075 STATIC 4076 int _pm4x10_port_attach_resume_fw_load (int unit, int port, pm_info_t pm_info, 4077 const portmod_port_add_info_t* add_info) 4078 { 4079 int port_index = -1, rv = 0, i, nof_phys, port_i; 4080 uint32 bitmap; 4081 int my_i, phy_acc, is_bypass, found_first_active_lane, itf_update = 0; 4082 int fec_enable = 0; 4083 phymod_interface_t phymod_serdes_interface = phymodInterfaceCount; 4084 phymod_phy_init_config_t phy_init_config; 4085 phymod_phy_inf_config_t *phy_interface_config = &phy_init_config.interface; 4086 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4087 phymod_phy_access_t phy_access_lane; 4088 portmod_port_ability_t port_ability; 4089 portmod_access_get_params_t params; 4090 soc_port_if_t interface = SOC_PORT_IF_NULL; 4091 pm_version_t pm_version; 4092 SOC_INIT_FUNC_DEFS; 4093 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 4094 4095 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &is_bypass); 4096 _SOC_IF_ERR_EXIT(rv); 4097 4098 /* initialze phys */ 4099 4100 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 4101 &bitmap)); 4102 4103 /* clean up polarity and tx of phy_init_config */ 4104 _SOC_IF_ERR_EXIT(phymod_phy_init_config_t_init(&phy_init_config)); 4105 4106 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 4107 _SOC_IF_ERR_EXIT(pm4x10_port_phy_lane_access_get(unit, port, pm_info, 4108 ¶ms, 1, &phy_access_lane, &nof_phys, NULL)); 4109 4110 /*init the core*/ 4111 rv = _pm4x10_pm_core_init(unit, port, pm_info, add_info); 4112 _SOC_IF_ERR_EXIT(rv); 4113 4114 /* initalize port */ 4115 rv = _pm4x10_pm_port_init(unit, port, phy_acc, port_index, add_info, 1, pm_info); 4116 _SOC_IF_ERR_EXIT(rv); 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 my_i = 0; 4122 found_first_active_lane = 0; 4123 for(i=0 ; i<PM4X10_LANES_PER_CORE ; i++) { 4124 4125 rv = SOC_WB_ENGINE_GET_ARR (unit, SOC_WB_ENGINE_PORTMOD, 4126 pm_info->wb_vars_ids[ports], &port_i, i); 4127 _SOC_IF_ERR_EXIT(rv); 4128 4129 if(port_i != port) { 4130 /* There is a difference between XGS and DNX devices. For DNX, a port can consist inconsecutive physical lanes. 4131 * For example, a port can consist lane 1 and 3 of the same core. For XGS, on the other hand, a port always consist 4132 * consecutive physical lanes. Therefore my_i below needs not be incremented for XGS devices. 4133 */ 4134 if(PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(PM_4x10_INFO(pm_info)->int_core_access.device_op_mode) && found_first_active_lane){ 4135 my_i++; 4136 } 4137 continue; 4138 } else { 4139 found_first_active_lane = 1; 4140 } 4141 4142 if(SHR_BITGET(&PM_4x10_INFO(pm_info)->polarity.tx_polarity,i)) { 4143 SHR_BITSET(&phy_init_config.polarity.tx_polarity, my_i); 4144 } 4145 4146 if(SHR_BITGET(&PM_4x10_INFO(pm_info)->polarity.rx_polarity,i)) { 4147 SHR_BITSET(&phy_init_config.polarity.rx_polarity, my_i); 4148 } 4149 my_i++; 4150 } 4151 4152 _SOC_IF_ERR_EXIT(PM4x10_PORT_OP_MODE_SET(unit, pm_info, 4153 add_info->phy_op_mode, 4154 port_index)); 4155 4156 4157 _SOC_IF_ERR_EXIT(_pm4x10_port_interface_config_init_set(unit, port, pm_info, 4158 &add_info->interface_config, 4159 &add_info->init_config, 4160 phy_init_config.tx, 4161 phy_init_config.ext_phy_tx)); 4162 4163 /* get phy interface config details */ 4164 4165 _SOC_IF_ERR_EXIT(PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &interface, 4166 port_index)); 4167 _SOC_IF_ERR_EXIT( 4168 PM4x10_INTERFACE_MODES_GET(unit, pm_info, 4169 &phy_interface_config->interface_modes, 4170 port_index)); 4171 4172 /* add_info->interface_config->interface comes from soc_esw_portctrl_config_get() 4173 * and is a very general value based on the port speed, number of lanes, and 4174 * encap regardless of the underlying PM type and whether there is an ext PHY 4175 * on the port. Here pm4x10 may change the default interface type under certain 4176 * situations during system init according to the more fine-grained conditions. 4177 */ 4178 if (nof_phys == 1) { 4179 if ((add_info->interface_config.interface != add_info->interface_config.serdes_interface) 4180 && (add_info->interface_config.serdes_interface != SOC_PORT_IF_NULL)) { 4181 _SOC_IF_ERR_EXIT(_pm4x10_interface_check(unit, port, pm_info, &add_info->interface_config, 4182 add_info->interface_config.serdes_interface, &itf_update)); 4183 if (itf_update) { 4184 interface = add_info->interface_config.serdes_interface; 4185 } 4186 } 4187 4188 if ((add_info->interface_config.speed == 42000 || 4189 add_info->interface_config.speed == 40000 ) && 4190 (phy_interface_config->interface_modes & PHYMOD_INTF_MODES_HIGIG) && !itf_update) { 4191 _SOC_IF_ERR_EXIT(_pm4x10_default_interface_get(unit, port, 4192 &(add_info->interface_config), &interface)); 4193 itf_update = 1; 4194 } 4195 4196 /* Since the interface type written into the outmost PHY has changed, 4197 * the software state also needs to be updated so that "ps" will show 4198 * the correct interface type. 4199 */ 4200 if (itf_update) { 4201 _SOC_IF_ERR_EXIT 4202 (PM4x10_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 4203 _SOC_IF_ERR_EXIT 4204 (PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 4205 } 4206 } 4207 4208 _SOC_IF_ERR_EXIT(PM4x10_PORT_OP_MODE_GET(unit, pm_info, 4209 &phy_init_config.op_mode, 4210 port_index)); 4211 4212 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, 4213 add_info->interface_config.speed, 4214 interface, 4215 &phy_interface_config->interface_type)); 4216 phy_interface_config->data_rate = add_info->interface_config.speed; 4217 phy_interface_config->pll_divider_req = 4218 add_info->init_config.pll_divider_req; 4219 phy_interface_config->ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 4220 4221 _SOC_IF_ERR_EXIT(portmod_port_phychain_phy_init(unit, phy_access, nof_phys, 4222 &phy_init_config)); 4223 4224 /* enable fec if set, should be done before setting the speed */ 4225 fec_enable = add_info->init_config.serdes_fec_enable; 4226 4227 if (fec_enable) { 4228 int value = 0; 4229 4230 /* FEC CL91 not supported on TSCE */ 4231 if (fec_enable != PORTMOD_PORT_FEC_CL74) { 4232 _SOC_IF_ERR_EXIT(SOC_E_PARAM); 4233 } 4234 4235 value |= TRUE; 4236 rv = pm4x10_port_fec_enable_set(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, value); 4237 _SOC_IF_ERR_EXIT(rv); 4238 } 4239 4240 if (add_info->interface_config.serdes_interface != SOC_PORT_IF_NULL) { 4241 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, 4242 add_info->interface_config.speed, 4243 add_info->interface_config.serdes_interface, 4244 &phymod_serdes_interface)); 4245 } 4246 4247 /* store the speed in PM database */ 4248 _SOC_IF_ERR_EXIT(PM4x10_SPEED_SET(unit, pm_info, 4249 add_info->interface_config.speed, 4250 port_index)); 4251 4252 4253 /* Apply to ALL PHY with same interface config */ 4254 _SOC_IF_ERR_EXIT( 4255 portmod_port_phychain_interface_config_set(unit, port, phy_access, nof_phys, 4256 add_info->interface_config.flags , 4257 phy_interface_config, 4258 phymod_serdes_interface, 4259 PM_4x10_INFO(pm_info)->ref_clk, 4260 PORTMOD_INIT_F_ALL_PHYS)); 4261 4262 4263 if(add_info->init_config.fs_cl72) { 4264 /* config port_init_cl72 is used to enable fs cl72 only in the serdes, 4265 do not enable cl72 on external phys. Set the no of phys argument to 1 to avoid setting cl72 enable 4266 on ext phys */ 4267 /* need to check if multi core and not pcs by pass mode */ 4268 if ((phy_interface_config->data_rate >= 100000) && 4269 (phy_interface_config->interface_type != phymodInterfaceBypass)) { 4270 uint32_t temp_flag = add_info->interface_config.flags; 4271 if (temp_flag == PHYMOD_INTF_F_SET_SPD_NO_TRIGGER) { 4272 _SOC_IF_ERR_EXIT(portmod_port_phychain_cl72_set(unit, port, phy_access, 1, 1)); 4273 } 4274 } else { 4275 _SOC_IF_ERR_EXIT(portmod_port_phychain_cl72_set(unit, port, phy_access, 1, 1)); 4276 } 4277 } 4278 /* set the default advert ability */ 4279 _SOC_IF_ERR_EXIT 4280 (pm4x10_port_ability_local_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &port_ability)); 4281 _SOC_IF_ERR_EXIT 4282 (pm4x10_port_ability_advert_set(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &port_ability)); 4283 4284 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 4285 if (PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 4286 /* Set PMD TXPI mode */ 4287 _SOC_IF_ERR_EXIT(_pm4x10_port_phy_txpi_mode_set(unit, port, pm_info, add_info->init_config.txpi_mode)); 4288 } 4289 4290 /* De-Assert SOFT_RESET */ 4291 _SOC_IF_ERR_EXIT(pm4x10_port_soft_reset(unit, port, pm_info, 0)); 4292 4293 exit: 4294 SOC_FUNC_RETURN; 4295 4296 } 4297 4298 STATIC 4299 int _pm4x10_an_mode_update (int unit, int port, pm_info_t pm_info, 4300 int an_cl37, int an_cl73) 4301 { 4302 int is_hg, rv; 4303 phymod_an_mode_type_t an_mode; 4304 int port_index; 4305 uint32_t bitmap; 4306 4307 SOC_INIT_FUNC_DEFS; 4308 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 4309 &bitmap)); 4310 4311 rv = PM4x10_IS_HG_GET(unit, pm_info, &is_hg, port_index); 4312 _SOC_IF_ERR_EXIT(rv); 4313 rv = PM4x10_AN_MODE_GET(unit, pm_info, &an_mode, port_index); 4314 _SOC_IF_ERR_EXIT(rv); 4315 if(is_hg) { 4316 an_mode = phymod_AN_MODE_CL37BAM ; 4317 if (an_cl37 == PORTMOD_CL37_W_BAM_HG) { 4318 an_mode = phymod_AN_MODE_CL37BAM_10P9375G_VCO; 4319 } 4320 } else { 4321 if (an_cl73) { 4322 switch (an_cl73) { 4323 case PORTMOD_CL73_W_BAM: 4324 an_mode = phymod_AN_MODE_CL73BAM; 4325 break; 4326 /* case PORTMOD_CL73_WO_BAM: 4327 * an_mode = phymod_AN_MODE_CL73; 4328 * break; 4329 */ 4330 default: 4331 an_mode = phymod_AN_MODE_CL73; 4332 break; 4333 } 4334 } else { 4335 switch (an_cl37) { 4336 case PORTMOD_CL37_SGMII_COMBO: 4337 an_mode = phymod_AN_MODE_CL37_SGMII; 4338 break; 4339 case PORTMOD_CL37_W_BAM: 4340 an_mode = phymod_AN_MODE_CL37BAM; 4341 break; 4342 case PORTMOD_CL37_WO_BAM: 4343 an_mode = phymod_AN_MODE_CL37; 4344 break; 4345 default: 4346 an_mode = phymod_AN_MODE_CL37; 4347 break; 4348 } 4349 } 4350 } 4351 4352 rv = PM4x10_AN_MODE_SET(unit, pm_info, an_mode, port_index); 4353 _SOC_IF_ERR_EXIT(rv); 4354 exit: 4355 SOC_FUNC_RETURN; 4356 } 4357 4358 4359 int pm4x10_port_attach (int unit, int port, pm_info_t pm_info, 4360 const portmod_port_add_info_t* add_info) 4361 { 4362 phymod_phy_access_t serdes_access; 4363 4364 int init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) && 4365 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) && 4366 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(add_info)) ? 1 : 0; 4367 4368 if (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) || (init_all)) { 4369 SOC_IF_ERROR_RETURN(_pm4x10_port_attach_core_probe (unit, port, pm_info, add_info)); 4370 } 4371 4372 if (PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(add_info) && 4373 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 4374 return (SOC_E_NONE); 4375 } 4376 4377 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info) || (init_all)) { 4378 4379 if (!PORTMOD_PORT_ADD_F_AUTONEG_CONFIG_SKIP_GET(add_info)) 4380 { 4381 SOC_IF_ERROR_RETURN(_pm4x10_an_mode_update (unit, port, pm_info, 4382 add_info->init_config.an_cl37, 4383 add_info->init_config.an_cl73)); 4384 } 4385 4386 if (PM_4x10_INFO(pm_info)->rescal != -1) { 4387 sal_memcpy(&serdes_access, &(PM_4x10_INFO(pm_info)->int_core_access), sizeof(phymod_phy_access_t)); 4388 phymod_phy_rescal_set(&serdes_access, 1, PM_4x10_INFO(pm_info)->rescal); 4389 } 4390 4391 SOC_IF_ERROR_RETURN(_pm4x10_pm_core_init(unit, port, pm_info, add_info)); 4392 } 4393 4394 if (PORTMOD_PORT_ADD_F_INIT_PASS1_GET(add_info)) { 4395 return (SOC_E_NONE); 4396 } 4397 4398 SOC_IF_ERROR_RETURN(_pm4x10_port_attach_resume_fw_load (unit, port, pm_info, add_info)); 4399 4400 return (SOC_E_NONE); 4401 } 4402 4403 4404 int pm4x10_port_detach(int unit, int port, pm_info_t pm_info) 4405 { 4406 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4407 phymod_phy_inf_config_t phy_interface_config; 4408 4409 int tmp_port, i=0, rv=0, port_index = -1, nof_phys; 4410 int invalid_port = -1, is_last_one = TRUE, phy_acc; 4411 int phytype; 4412 uint32 inactive = 0; 4413 4414 SOC_INIT_FUNC_DEFS; 4415 4416 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 4417 4418 /* in case of 100G disable the speed for the port */ 4419 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access,(1+MAX_PHYN), &nof_phys)); 4420 4421 if( (nof_phys > 1) && (phy_access[nof_phys-1].access.lane_mask == 0) ) { 4422 nof_phys = 1; 4423 } 4424 4425 _SOC_IF_ERR_EXIT(portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 4426 0, PM_4x10_INFO(pm_info)->ref_clk, &phy_interface_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 4427 4428 if ( phy_interface_config.data_rate >= 100000 ) { 4429 _SOC_IF_ERR_EXIT(portmod_port_phychain_interface_config_set(unit, port, phy_access, nof_phys, 4430 PHYMOD_INTF_F_SET_SPD_DISABLE, 4431 &phy_interface_config, phy_interface_config.interface_type, 4432 PM_4x10_INFO(pm_info)->ref_clk, 4433 PORTMOD_INIT_F_ALL_PHYS )); 4434 _SOC_IF_ERR_EXIT(portmod_port_phychain_interface_config_set(unit, port, phy_access, nof_phys, 4435 PHYMOD_INTF_F_SPEED_CONFIG_CLEAR, 4436 &phy_interface_config, phy_interface_config.interface_type, 4437 PM_4x10_INFO(pm_info)->ref_clk, 4438 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 4439 } 4440 4441 4442 /*remove from array and check if it was the last one*/ 4443 for( i = 0 ; i < MAX_PORTS_PER_PM4X10; i++) { 4444 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 4445 pm_info->wb_vars_ids[ports], &tmp_port, i); 4446 _SOC_IF_ERR_EXIT(rv); 4447 4448 if(tmp_port == port){ 4449 port_index = (port_index == -1 ? i : port_index); 4450 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 4451 pm_info->wb_vars_ids[ports], &invalid_port, i); 4452 _SOC_IF_ERR_EXIT(rv); 4453 } else if (tmp_port != -1) { 4454 is_last_one = FALSE; 4455 } 4456 } 4457 4458 if(port_index == -1) { 4459 _SOC_EXIT_WITH_ERR(SOC_E_PORT,(_SOC_MSG("Port %d wasn't found"),port)); 4460 } 4461 4462 rv = _pm4x10_pm_port_init(unit, port, phy_acc, port_index, NULL, 0, pm_info); 4463 _SOC_IF_ERR_EXIT(rv); 4464 4465 /*deinit PM in case of last one*/ 4466 if (is_last_one) { 4467 rv = _pm4x10_pm_disable(unit, port, pm_info, phy_acc); 4468 _SOC_IF_ERR_EXIT(rv); 4469 4470 PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_CLR(PM_4x10_INFO(pm_info)->int_core_access.device_op_mode); 4471 4472 #ifdef PORTMOD_PM12X10_SUPPORT 4473 if(PM_4x10_INFO(pm_info)->in_pm12x10) { 4474 uint32 phy; 4475 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy) {break;}; 4476 /* this will be redirected to pm12x10 */ 4477 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 4478 4479 if (SOC_IS_APACHE(unit)) { 4480 rv = pm12x10_xgs_pm4x10_enable(unit, port, phy, 1); 4481 _SOC_IF_ERR_EXIT(rv); 4482 } else 4483 #endif 4484 { 4485 rv = pm12x10_pm4x10_enable(unit, port, phy, 0); 4486 _SOC_IF_ERR_EXIT(rv); 4487 } 4488 } 4489 #endif /* PORTMOD_PM12X10_SUPPORT */ 4490 4491 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4492 pm_info->wb_vars_ids[isActive], &inactive); 4493 _SOC_IF_ERR_EXIT(rv); 4494 4495 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4496 pm_info->wb_vars_ids[isInitialized], 4497 &inactive); 4498 _SOC_IF_ERR_EXIT(rv); 4499 4500 rv = SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4501 pm_info->wb_vars_ids[isBypassed], &inactive); 4502 _SOC_IF_ERR_EXIT(rv); 4503 /* Updating phymod type in pm_info structure and warmboot engine */ 4504 phytype = phymodDispatchTypeInvalid; 4505 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[phy_type], &phytype, 0); 4506 _SOC_IF_ERR_EXIT(rv); 4507 PM_4x10_INFO(pm_info)->int_core_access.type = phymodDispatchTypeInvalid; 4508 PM_4x10_INFO(pm_info)->is_pm4x10q = 0; 4509 } 4510 4511 exit: 4512 SOC_FUNC_RETURN; 4513 } 4514 4515 int pm4x10_port_replace(int unit, int port, pm_info_t pm_info, int new_port) 4516 { 4517 int i, tmp_port; 4518 int rv = 0; 4519 SOC_INIT_FUNC_DEFS; 4520 4521 /* replace old port with new port */ 4522 for (i = 0; i < MAX_PORTS_PER_PM4X10; i++) { 4523 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 4524 pm_info->wb_vars_ids[ports], &tmp_port, i); 4525 _SOC_IF_ERR_EXIT(rv); 4526 4527 if (tmp_port == port){ 4528 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, 4529 pm_info->wb_vars_ids[ports], &new_port, i); 4530 _SOC_IF_ERR_EXIT(rv); 4531 } 4532 } 4533 4534 exit: 4535 SOC_FUNC_RETURN; 4536 4537 } 4538 4539 int pm4x10_pm_bypass_set(int unit, pm_info_t pm_info, int bypass_enable) 4540 { 4541 int rv = 0; 4542 uint32 pm_is_active = 0; 4543 uint32 is_bypass; 4544 4545 SOC_INIT_FUNC_DEFS; 4546 4547 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &is_bypass); 4548 _SOC_IF_ERR_EXIT(rv); 4549 4550 if (bypass_enable != is_bypass) { 4551 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isActive], &pm_is_active); 4552 _SOC_IF_ERR_EXIT(rv); 4553 4554 if(pm_is_active) { 4555 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("can't chenge bypass mode for active pm"))); 4556 } 4557 4558 rv = SOC_WB_ENGINE_SET_VAR (unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isBypassed], &bypass_enable); 4559 _SOC_IF_ERR_EXIT(rv); 4560 4561 } 4562 4563 4564 exit: 4565 SOC_FUNC_RETURN; 4566 } 4567 4568 int pm4x10_pm_core_info_get(int unit, pm_info_t pm_info, int phyn, portmod_pm_core_info_t* core_info) 4569 { 4570 core_info->ref_clk = PM_4x10_INFO(pm_info)->ref_clk; 4571 return SOC_E_NONE; 4572 } 4573 4574 int pm4x10_pm_phys_get(int unit, pm_info_t pm_info, portmod_pbmp_t* phys) 4575 { 4576 SOC_INIT_FUNC_DEFS; 4577 PORTMOD_PBMP_ASSIGN(*phys, PM_4x10_INFO(pm_info)->phys); 4578 SOC_FUNC_RETURN; 4579 } 4580 4581 int pm4x10_port_enable_set (int unit, int port, pm_info_t pm_info, 4582 int flags, int enable) 4583 { 4584 uint32 is_bypassed = 0, phychain_flag; 4585 int rv = 0, rst_flags = 0; 4586 int actual_flags = flags, nof_phys = 0, xlmac_flags = 0; 4587 phymod_phy_power_t phy_power; 4588 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4589 4590 SOC_INIT_FUNC_DEFS; 4591 4592 /* If no Rx/Tx flags - set both */ 4593 if ((!PORTMOD_PORT_ENABLE_TX_GET(flags)) && 4594 (!PORTMOD_PORT_ENABLE_RX_GET(flags))) 4595 { 4596 PORTMOD_PORT_ENABLE_RX_SET(actual_flags); 4597 PORTMOD_PORT_ENABLE_TX_SET(actual_flags); 4598 } 4599 4600 /* If no Mac/Phy flags - set both */ 4601 if ((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) && 4602 (!PORTMOD_PORT_ENABLE_MAC_GET(flags))) 4603 { 4604 PORTMOD_PORT_ENABLE_PHY_SET(actual_flags); 4605 PORTMOD_PORT_ENABLE_MAC_SET(actual_flags); 4606 } 4607 4608 /* if MAC is set and either RX or TX set is invalid combination */ 4609 if( (PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) ) { 4610 if((!PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) || (!PORTMOD_PORT_ENABLE_RX_GET(actual_flags))){ 4611 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("MAC RX and TX can't be enabled separately"))); 4612 } 4613 } 4614 4615 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4616 pm_info->wb_vars_ids[isBypassed], &is_bypassed); 4617 _SOC_IF_ERR_EXIT(rv); 4618 4619 _SOC_IF_ERR_EXIT(phymod_phy_power_t_init(&phy_power)); 4620 phy_power.rx = phymodPowerNoChange; 4621 phy_power.tx = phymodPowerNoChange; 4622 4623 if(PORTMOD_PORT_ENABLE_RX_GET(actual_flags)){ 4624 phy_power.rx = (enable) ? phymodPowerOn : phymodPowerOff; 4625 xlmac_flags |= XLMAC_ENABLE_SET_FLAGS_RX_EN; 4626 } 4627 if(PORTMOD_PORT_ENABLE_TX_GET(actual_flags)){ 4628 phy_power.tx = (enable) ? phymodPowerOn : phymodPowerOff; 4629 xlmac_flags |= XLMAC_ENABLE_SET_FLAGS_TX_EN; 4630 } 4631 4632 /* phychain_flag is meant to be used if we want only part of the phychin to be affected*/ 4633 phychain_flag = PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_GET(flags) ? 4634 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY : 4635 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY ; 4636 4637 if(enable){ 4638 if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)){ 4639 if(PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 4640 rst_flags |= XLMAC_ENABLE_SET_FLAGS_SOFT_RESET_DIS; 4641 } 4642 rv = xlmac_enable_set(unit, port, rst_flags, 1); 4643 _SOC_IF_ERR_EXIT(rv); 4644 if(PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 4645 _SOC_IF_ERR_EXIT(pm4x10_port_soft_reset(unit, port, pm_info, 0)); 4646 } 4647 } 4648 4649 if(PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) 4650 { 4651 _SOC_IF_ERR_EXIT 4652 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4653 phy_access ,(1+MAX_PHYN), 4654 &nof_phys)); 4655 4656 _SOC_IF_ERR_EXIT 4657 (portmod_port_phychain_power_set(unit, port, phy_access, nof_phys, phychain_flag, &phy_power)); 4658 4659 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 4660 _SOC_IF_ERR_EXIT 4661 (portmod_port_phychain_tx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 4662 phymodTxSquelchOff)); 4663 } 4664 4665 if(PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 4666 _SOC_IF_ERR_EXIT 4667 (portmod_port_phychain_rx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 4668 phymodRxSquelchOff)); 4669 } 4670 4671 } 4672 } else { 4673 if (PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) { 4674 _SOC_IF_ERR_EXIT 4675 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4676 phy_access ,(1+MAX_PHYN), 4677 &nof_phys)); 4678 4679 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 4680 _SOC_IF_ERR_EXIT 4681 (portmod_port_phychain_tx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 4682 phymodTxSquelchOn)); 4683 } 4684 4685 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 4686 _SOC_IF_ERR_EXIT 4687 (portmod_port_phychain_rx_lane_control_set(unit, port, phy_access, nof_phys, phychain_flag, 4688 phymodRxSquelchOn)); 4689 } 4690 4691 _SOC_IF_ERR_EXIT 4692 (portmod_port_phychain_power_set(unit, port, phy_access, nof_phys, phychain_flag, &phy_power)); 4693 } 4694 4695 /* if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)){ */ 4696 /* Not checking is_bypassed as if clmac was enable before bypass was set */ 4697 if((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) ){ 4698 rv = xlmac_enable_set(unit, port, xlmac_flags, 0); 4699 _SOC_IF_ERR_EXIT(rv); 4700 } 4701 } 4702 4703 exit: 4704 SOC_FUNC_RETURN; 4705 } 4706 4707 int pm4x10_port_enable_get (int unit, int port, pm_info_t pm_info, int flags, 4708 int* enable) 4709 { 4710 uint32 is_bypassed = 0, phychain_flag; 4711 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4712 int nof_phys = 0; 4713 phymod_phy_tx_lane_control_t tx_control = phymodTxSquelchOn; 4714 phymod_phy_rx_lane_control_t rx_control = phymodRxSquelchOn; 4715 int phy_enable = 1, mac_enable = 1; 4716 int mac_rx_enable = 0, mac_tx_enable = 0; 4717 int actual_flags = flags; 4718 SOC_INIT_FUNC_DEFS; 4719 SOC_NULL_CHECK(pm_info); 4720 4721 /* If no RX\TX flags - set both*/ 4722 if((!PORTMOD_PORT_ENABLE_TX_GET(flags)) && (!PORTMOD_PORT_ENABLE_RX_GET(flags))){ 4723 PORTMOD_PORT_ENABLE_RX_SET(actual_flags); 4724 PORTMOD_PORT_ENABLE_TX_SET(actual_flags); 4725 } 4726 4727 /* if no MAC\Phy flags - set both*/ 4728 if((!PORTMOD_PORT_ENABLE_PHY_GET(flags)) && (!PORTMOD_PORT_ENABLE_MAC_GET(flags))){ 4729 PORTMOD_PORT_ENABLE_PHY_SET(actual_flags); 4730 PORTMOD_PORT_ENABLE_MAC_SET(actual_flags); 4731 } 4732 4733 /* phychain_flag is meant to be used if we want only part of the phychin to be affected*/ 4734 phychain_flag = PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_GET(flags) ? 4735 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY : 4736 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY ; 4737 4738 if (PORTMOD_PORT_ENABLE_PHY_GET(actual_flags)) { 4739 4740 _SOC_IF_ERR_EXIT 4741 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access ,(1+MAX_PHYN), &nof_phys)); 4742 4743 _SOC_IF_ERR_EXIT 4744 (portmod_port_phychain_tx_lane_control_get(unit, port, phy_access, nof_phys, phychain_flag, &tx_control)); 4745 _SOC_IF_ERR_EXIT 4746 (portmod_port_phychain_rx_lane_control_get(unit, port, phy_access, nof_phys, phychain_flag, &rx_control)); 4747 4748 phy_enable = 0; 4749 4750 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 4751 phy_enable |= (rx_control == phymodRxSquelchOn) ? 0 : 1; 4752 } 4753 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 4754 phy_enable |= (tx_control == phymodTxSquelchOn) ? 0 : 1; 4755 } 4756 } 4757 4758 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, 4759 pm_info->wb_vars_ids[isBypassed], &is_bypassed)); 4760 4761 if ((PORTMOD_PORT_ENABLE_MAC_GET(actual_flags)) && (!is_bypassed)) { 4762 4763 mac_enable = 0; 4764 4765 if (PORTMOD_PORT_ENABLE_RX_GET(actual_flags)) { 4766 _SOC_IF_ERR_EXIT(xlmac_enable_get(unit, port, XLMAC_ENABLE_SET_FLAGS_RX_EN, &mac_rx_enable)); 4767 mac_enable |= (mac_rx_enable) ? 1 : 0; 4768 } 4769 if (PORTMOD_PORT_ENABLE_TX_GET(actual_flags)) { 4770 _SOC_IF_ERR_EXIT(xlmac_enable_get(unit, port, XLMAC_ENABLE_SET_FLAGS_TX_EN, &mac_tx_enable)); 4771 mac_enable |= (mac_tx_enable) ? 1 : 0; 4772 } 4773 } 4774 4775 *enable = (mac_enable && phy_enable); 4776 4777 exit: 4778 SOC_FUNC_RETURN; 4779 } 4780 4781 int pm4x10_port_interface_check(int unit, int port, pm_info_t pm_info, 4782 const portmod_port_interface_config_t* config, 4783 int is_ext_phy, soc_port_if_t interface, 4784 int* is_valid) 4785 { 4786 int nof_phys = 0; 4787 phymod_phy_access_t phy_access[1+MAX_PHYN]; 4788 SOC_INIT_FUNC_DEFS; 4789 4790 _SOC_IF_ERR_EXIT 4791 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access ,(1+MAX_PHYN), &nof_phys)); 4792 4793 if (is_ext_phy && nof_phys < 2) { 4794 return SOC_E_PARAM; 4795 } 4796 4797 if (is_ext_phy) { 4798 _SOC_IF_ERR_EXIT(_pm4x10_ext_phy_interface_check(unit, port, &phy_access[nof_phys-1], config, 4799 interface, is_valid)); 4800 } else { 4801 _SOC_IF_ERR_EXIT(_pm4x10_interface_check(unit, port, pm_info, config, interface, is_valid)); 4802 } 4803 4804 exit: 4805 SOC_FUNC_RETURN; 4806 } 4807 4808 int pm4x10_port_interface_config_set(int unit, int port, 4809 pm_info_t pm_info, 4810 const portmod_port_interface_config_t* config, 4811 int phy_init_flags) 4812 { 4813 uint32 reg_val; 4814 uint32 pm_is_bypassed = 0, pm_is_initialized = 0; 4815 int nof_phys = 0, rv = 0, phy_acc, flags = 0; 4816 phymod_phy_access_t phy_access_arr[1+MAX_PHYN]; 4817 phymod_phy_access_t phy_access; 4818 phymod_phy_inf_config_t phy_interface_config, cur_phy_if_config; 4819 portmod_access_get_params_t params; 4820 int port_index; 4821 uint32_t bitmap; 4822 portmod_port_interface_config_t config_temp ; 4823 phymod_interface_t phymod_interface; 4824 phymod_interface_t phymod_serdes_interface = phymodInterfaceCount; 4825 phymod_tx_t tx_params[PHYMOD_MAX_LANES_PER_CORE]; 4826 phymod_tx_t ext_phy_tx_params[PHYMOD_MAX_LANES_PER_CORE]; 4827 soc_port_if_t interface = SOC_PORT_IF_NULL; 4828 int is_legacy_phy = 0; 4829 int i, xphy_id; 4830 int is_higig, rxaui_mode, fs_cl72; 4831 uint32 is_interface_restore, interface_modes, port_dynamic_state; 4832 int is_legacy_phy_callback = 0; 4833 portmod_port_ts_adjust_t ts_adjust; 4834 int mac_ts_enable; 4835 #ifdef PORTMOD_PM12X10_SUPPORT 4836 soc_100g_lane_config_t lane_config=0; 4837 #endif 4838 SOC_INIT_FUNC_DEFS; 4839 4840 sal_memset(&ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 4841 4842 /* 4843 * Ignore the call to interface config set if the pm is not iniialized. 4844 * This happens if the legacy external phy does a call back prior to initializing 4845 * and probing internal phys 4846 */ 4847 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 4848 pm_info->wb_vars_ids[isInitialized], 4849 &pm_is_initialized); 4850 _SOC_IF_ERR_EXIT(rv); 4851 if (!pm_is_initialized) return (SOC_E_NONE); 4852 4853 4854 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 4855 4856 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 4857 &bitmap)); 4858 _SOC_IF_ERR_EXIT(PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, 4859 &port_dynamic_state, port_index)); 4860 4861 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 4862 _SOC_IF_ERR_EXIT(pm4x10_port_mac_timestamp_enable_get(unit, port, pm_info, 4863 &mac_ts_enable)); 4864 } else { 4865 mac_ts_enable = 1; 4866 } 4867 4868 is_higig = ((config->encap_mode == SOC_ENCAP_HIGIG2) || 4869 (config->encap_mode == SOC_ENCAP_HIGIG) || 4870 PHYMOD_INTF_MODES_HIGIG_GET(config)) ? 1 : 0; 4871 4872 if (config->flags & PHYMOD_INTF_F_UPDATE_SPEED_LINKUP) { 4873 int mac_speed = 0, serdes_speed = 0, mac_only = 0; 4874 int nof_lanes = SOC_INFO(unit).port_num_lanes[port]; 4875 4876 _SOC_IF_ERR_EXIT(portmod_port_speed_get(unit, port, &serdes_speed)); 4877 if (config->speed == serdes_speed) { 4878 xlmac_speed_get(unit, port, &mac_speed); 4879 mac_speed *= nof_lanes; 4880 if (config->speed == mac_speed) { 4881 SOC_FUNC_RETURN; 4882 } 4883 4884 mac_only = 1; 4885 } 4886 4887 flags = XLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 4888 _SOC_IF_ERR_EXIT(xlmac_speed_set(unit, port, flags, config->speed)); 4889 4890 if (mac_ts_enable) { 4891 /*Set MAC Timestamp Delay*/ 4892 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 4893 _SOC_IF_ERR_EXIT(_pm4x10_port_timestamp_adjust_wb_get(unit, port, pm_info, config->speed, &ts_adjust)); 4894 _SOC_IF_ERR_EXIT(xlmac_timestamp_delay_set(unit, port, ts_adjust, config->speed)); 4895 } 4896 _SOC_IF_ERR_EXIT(xlmac_timestamp_byte_adjust_set(unit, port, 0, config->speed)); 4897 } 4898 4899 if (mac_only) { 4900 /* line side speed and SerDes speed are equal, no need update SerDes configuration */ 4901 SOC_FUNC_RETURN; 4902 } 4903 4904 phy_init_flags = PORTMOD_INIT_F_ALL_PHYS; 4905 } 4906 4907 if ((config->encap_mode == SOC_ENCAP_HIGIG2) || 4908 (config->encap_mode == SOC_ENCAP_HIGIG) || 4909 (PHYMOD_INTF_MODES_HIGIG_GET(config))) { 4910 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 4911 port_index); 4912 _SOC_IF_ERR_EXIT(rv); 4913 interface_modes |= PHYMOD_INTF_MODES_HIGIG; 4914 rv = PM4x10_INTERFACE_MODES_SET(unit, pm_info, interface_modes, 4915 port_index); 4916 _SOC_IF_ERR_EXIT(rv); 4917 } else if ((config->encap_mode == SOC_ENCAP_IEEE)) { 4918 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 4919 _SOC_IF_ERR_EXIT(rv); 4920 interface_modes &= ~PHYMOD_INTF_MODES_HIGIG; 4921 rv = PM4x10_INTERFACE_MODES_SET(unit, pm_info, interface_modes, port_index); 4922 _SOC_IF_ERR_EXIT(rv); 4923 } 4924 4925 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 4926 params.phyn = 0; 4927 params.lane = -1; 4928 params.sys_side = PORTMOD_SIDE_LINE; 4929 4930 _SOC_IF_ERR_EXIT(pm4x10_port_phy_lane_access_get(unit, port, pm_info, 4931 ¶ms, 1, &phy_access, &nof_phys, NULL)); 4932 4933 _SOC_IF_ERR_EXIT 4934 (portmod_port_chain_phy_access_get(unit, port, pm_info, 4935 phy_access_arr ,(1+MAX_PHYN), &nof_phys)); 4936 4937 rv = SOC_WB_ENGINE_GET_VAR (unit, SOC_WB_ENGINE_PORTMOD, 4938 pm_info->wb_vars_ids[isBypassed], 4939 &pm_is_bypassed); 4940 _SOC_IF_ERR_EXIT(rv); 4941 4942 if(config->flags & PHYMOD_INTF_F_INTF_PARAM_SET_ONLY) { 4943 /* Update the software state of the interface type. Note that currently 4944 * the legacy ext PHY does not raise the PHYMOD_INTF_F_INTF_PARAM_SET_ONLY 4945 * flag so that the following function call cannot be reached when a legacy 4946 * ext PHY uses the portmod callback function to set the interface type 4947 * of the internal PHY. 4948 */ 4949 rv = PM4x10_INTERFACE_TYPE_SET(unit, pm_info, config->interface, 4950 port_index); 4951 _SOC_IF_ERR_EXIT(rv); 4952 4953 is_interface_restore = 1; 4954 rv = PM4x10_IS_INTERFACE_RESTORE_SET(unit, pm_info, 4955 is_interface_restore, port_index); 4956 _SOC_IF_ERR_EXIT(rv); 4957 4958 SOC_FUNC_RETURN; 4959 } 4960 4961 rv = PM4x10_IS_INTERFACE_RESTORE_GET(unit, pm_info, &is_interface_restore, 4962 port_index); 4963 _SOC_IF_ERR_EXIT(rv); 4964 /* 4965 * if the interface is already set with PARAM_SET_ONLY 4966 * h/w interface needs to be updated during speed set. 4967 * So load the interface information and clear the flag; 4968 */ 4969 if(is_interface_restore) { 4970 rv = PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index); 4971 _SOC_IF_ERR_EXIT(rv); 4972 ((portmod_port_interface_config_t*)config)->interface = interface; 4973 4974 is_interface_restore = 0; 4975 rv = PM4x10_IS_INTERFACE_RESTORE_SET(unit, pm_info, 4976 is_interface_restore, port_index); 4977 _SOC_IF_ERR_EXIT(rv); 4978 } 4979 4980 if (!(config->flags & (PHYMOD_INTF_F_SET_SPD_TRIGGER | PHYMOD_INTF_F_UPDATE_SPEED_LINKUP)) && (!pm_is_bypassed)){ 4981 4982 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 4983 port_index); 4984 _SOC_IF_ERR_EXIT(rv); 4985 /* set HiG mode */ 4986 _SOC_IF_ERR_EXIT(READ_XLPORT_CONFIGr(unit, phy_acc, ®_val)); 4987 soc_reg_field_set (unit, XLPORT_CONFIGr, ®_val, HIGIG2_MODEf, 4988 (interface_modes & PHYMOD_INTF_MODES_HIGIG)? 1: 0); 4989 _SOC_IF_ERR_EXIT(WRITE_XLPORT_CONFIGr(unit, phy_acc, reg_val)); 4990 4991 /* set port speed */ 4992 flags = XLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 4993 rv = xlmac_speed_set(unit, port, flags, config->speed); 4994 _SOC_IF_ERR_EXIT(rv); 4995 4996 /*Set Timestamp Mac Delays*/ 4997 if (mac_ts_enable) { 4998 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 4999 _SOC_IF_ERR_EXIT 5000 (_pm4x10_port_timestamp_adjust_wb_get(unit, 5001 port, 5002 pm_info, 5003 config->speed, 5004 &ts_adjust)); 5005 _SOC_IF_ERR_EXIT(xlmac_timestamp_delay_set(unit, 5006 port, 5007 ts_adjust, 5008 config->speed)); 5009 } 5010 _SOC_IF_ERR_EXIT(xlmac_timestamp_byte_adjust_set(unit, port, 0, config->speed)); 5011 } 5012 5013 /* set encapsulation */ 5014 flags = XLMAC_ENCAP_SET_FLAGS_SOFT_RESET_DIS; 5015 rv = xlmac_encap_set (unit, port, flags, config->encap_mode); 5016 _SOC_IF_ERR_EXIT(rv); 5017 5018 rv = xlmac_strict_preamble_set(unit, port, (!is_higig && (config->speed >= 10000))); 5019 _SOC_IF_ERR_EXIT(rv); 5020 5021 /* De-Assert SOFT_RESET */ 5022 rv = pm4x10_port_soft_reset(unit, port, pm_info, 0); 5023 _SOC_IF_ERR_EXIT(rv); 5024 } 5025 5026 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init (&phy_interface_config)); 5027 5028 _SOC_IF_ERR_EXIT(PM4x10_RXAUI_MODE_GET(unit, pm_info, 5029 &rxaui_mode, port_index)); 5030 5031 _SOC_IF_ERR_EXIT(_pm4x10_line_side_phymod_interface_get(unit, port, 5032 pm_info, rxaui_mode, 5033 config, 5034 &phymod_interface)); 5035 phy_interface_config.interface_type = phymod_interface; 5036 5037 if (phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY && nof_phys > 1) { 5038 is_legacy_phy_callback = 1; 5039 } 5040 5041 _SOC_IF_ERR_EXIT(_pm4x10_phymod_interface_mode_set(unit, port, pm_info, config, 5042 &phy_interface_config, 5043 is_legacy_phy_callback)); 5044 _SOC_IF_ERR_EXIT(PM4x10_SPEED_SET(unit, pm_info, 5045 config->speed, port_index)); 5046 5047 phy_interface_config.data_rate = config->speed; 5048 phy_interface_config.pll_divider_req = config->pll_divider_req; 5049 phy_interface_config.ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 5050 5051 /* 5052 * copy const *config to config_temp cause 5053 * config.interface may come from storage 5054 */ 5055 _SOC_IF_ERR_EXIT(portmod_port_interface_config_t_init(unit, &config_temp)); 5056 sal_memcpy(&config_temp, config, sizeof(portmod_port_interface_config_t)); 5057 5058 rv = PM4x10_IS_INTERFACE_RESTORE_GET(unit, pm_info, 5059 &is_interface_restore, port_index); 5060 _SOC_IF_ERR_EXIT(rv); 5061 5062 if(is_interface_restore) { 5063 /* overwrite config->interface form storage */ 5064 rv = PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index); 5065 _SOC_IF_ERR_EXIT(rv); 5066 config_temp.interface = interface ; 5067 is_interface_restore = 0; 5068 rv = PM4x10_IS_INTERFACE_RESTORE_SET(unit, pm_info, 5069 is_interface_restore, port_index); 5070 _SOC_IF_ERR_EXIT(rv); 5071 } 5072 5073 _SOC_IF_ERR_EXIT(PM4x10_FS_CL72_GET(unit, pm_info, &fs_cl72, port_index)); 5074 if(fs_cl72) { 5075 /* 5076 * PHYMOD_INTF_F_CL72_REQUESTED_BY_CNFG config is only honoured 5077 * by tsce. incase if the external phys start using this flag, 5078 * cl72 should not be set for the external phys. Because port_init_cl72 5079 * should enable cl72 only on the serdes. 5080 */ 5081 config_temp.flags |= PHYMOD_INTF_F_CL72_REQUESTED_BY_CNFG ; 5082 } 5083 5084 rv = PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, 5085 &port_dynamic_state, port_index); 5086 _SOC_IF_ERR_EXIT(rv); 5087 5088 if( nof_phys > 1 ){ 5089 /* external phy preemphasis and current */ 5090 if (!(config->flags & (PHYMOD_INTF_F_SET_SPD_TRIGGER | PHYMOD_INTF_F_UPDATE_SPEED_LINKUP))) { 5091 xphy_id = phy_access_arr[nof_phys-1].access.addr; 5092 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 5093 if (!is_legacy_phy && !PORTMOD_PORT_IS_DEFAULT_EXT_PHY_TX_PARAMS_UPDATED(port_dynamic_state)) { 5094 for(i=0; i < PHYMOD_MAX_LANES_PER_CORE; i++){ 5095 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access_arr[nof_phys-1], phymodMediaTypeChipToChip, 5096 &(ext_phy_tx_params[i]))); 5097 } 5098 _SOC_IF_ERR_EXIT( 5099 portmod_port_phychain_tx_set(unit, &phy_access_arr[nof_phys-1], 5100 1, ext_phy_tx_params)); 5101 } 5102 } 5103 } 5104 5105 #ifdef PORTMOD_PM12X10_SUPPORT 5106 if ((nof_phys > 1) && (config->interface_modes & PHYMOD_INTF_MODES_TRIPLE_CORE)) { 5107 /* external phy TRI-CORE MODE */ 5108 xphy_id = phy_access_arr[nof_phys-1].access.addr; 5109 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 5110 if((SOC_INFO(unit).port_speed_max[port] >= 100000) && !is_legacy_phy) { 5111 /* read the portmap config to get the map info */ 5112 lane_config = SOC_INFO(unit).port_100g_lane_config[port]; 5113 /* convert SOC level lane config to interface mode setting */ 5114 switch(lane_config) { 5115 case SOC_LANE_CONFIG_100G_4_4_2: 5116 phy_interface_config.interface_modes |= PHYMOD_INTF_MODES_TC_442; 5117 break; 5118 case SOC_LANE_CONFIG_100G_3_4_3: 5119 phy_interface_config.interface_modes |= PHYMOD_INTF_MODES_TC_343; 5120 break; 5121 case SOC_LANE_CONFIG_100G_2_4_4: 5122 phy_interface_config.interface_modes |= PHYMOD_INTF_MODES_TC_244; 5123 default: 5124 break; 5125 } 5126 } 5127 } 5128 #endif 5129 5130 /* internal phy preemphasis and current */ 5131 if (!(config->flags & (PHYMOD_INTF_F_SET_SPD_TRIGGER | PHYMOD_INTF_F_UPDATE_SPEED_LINKUP))) { 5132 if (!PORTMOD_PORT_IS_DEFAULT_TX_PARAMS_UPDATED(port_dynamic_state)) { 5133 _SOC_IF_ERR_EXIT 5134 (portmod_port_phychain_interface_config_get(unit, port, phy_access_arr, nof_phys, 5135 0, PM_4x10_INFO(pm_info)->ref_clk, 5136 &cur_phy_if_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 5137 if ((phy_interface_config.data_rate != cur_phy_if_config.data_rate) || 5138 (phy_interface_config.interface_modes != cur_phy_if_config.interface_modes)) { 5139 for(i=0; i<PHYMOD_MAX_LANES_PER_CORE; i++){ 5140 _SOC_IF_ERR_EXIT(phymod_phy_media_type_tx_get(&phy_access_arr[0], phymodMediaTypeChipToChip, 5141 &(tx_params[i]))); 5142 } 5143 _SOC_IF_ERR_EXIT( 5144 portmod_port_phychain_tx_set(unit, phy_access_arr, 1, tx_params)); 5145 } 5146 } 5147 } 5148 5149 if (config->serdes_interface != SOC_PORT_IF_NULL) { 5150 _SOC_IF_ERR_EXIT(portmod_intf_to_phymod_intf(unit, 5151 config->speed, 5152 config->serdes_interface, 5153 &phymod_serdes_interface)); 5154 _SOC_IF_ERR_EXIT(PM4x10_SERDES_INTERFACE_TYPE_SET(unit, pm_info, 5155 config->serdes_interface, 5156 port_index)); 5157 } 5158 _SOC_IF_ERR_EXIT 5159 (portmod_port_phychain_interface_config_set(unit, port, phy_access_arr, nof_phys, 5160 config_temp.flags, 5161 &phy_interface_config, 5162 phymod_serdes_interface, 5163 PM_4x10_INFO(pm_info)->ref_clk, 5164 phy_init_flags)); 5165 5166 /* The interface type software state needs to be stored even if the config flags 5167 * does not include PHYMOD_INTF_F_INTF_PARAM_SET_ONLY. For example, when changing 5168 * the encap, portctrl tries to config the PHY interface type and speed in one 5169 * shot without setting the PHYMOD_INTF_F_INTF_PARAM_SET_ONLY flag. However, 5170 * when the current function is called by the legacy ext PHY through the portmod 5171 * callback function, the interface type software state should not be modified 5172 * since PM4x10_INTERFACE_TYPE_GET() should return the outmost PHY interface type. 5173 */ 5174 if (!(nof_phys > 1 && phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)) { 5175 _SOC_IF_ERR_EXIT 5176 (portmod_intf_from_phymod_intf(unit, phy_interface_config.interface_type, &interface)); 5177 _SOC_IF_ERR_EXIT 5178 (PM4x10_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 5179 _SOC_IF_ERR_EXIT 5180 (PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 5181 } 5182 5183 exit: 5184 SOC_FUNC_RETURN; 5185 } 5186 5187 int pm4x10_port_interface_config_get (int unit, int port, pm_info_t pm_info, 5188 portmod_port_interface_config_t* config, int phy_init_flags) 5189 { 5190 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5191 phymod_phy_inf_config_t phy_interface_config; 5192 int port_index, pll_divider_req; 5193 uint32_t bitmap; 5194 int flags=0, nof_phys = 0, rv = 0, ref_clock, max_speed; 5195 phymod_interface_t prev_phymod_if; 5196 soc_port_if_t interface = SOC_PORT_IF_NULL; 5197 phymod_autoneg_status_t an_status; 5198 5199 SOC_INIT_FUNC_DEFS; 5200 5201 ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 5202 5203 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5204 &bitmap)); 5205 5206 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_interface_config)); 5207 5208 _SOC_IF_ERR_EXIT 5209 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5210 phy_access ,(1+MAX_PHYN), 5211 &nof_phys)); 5212 5213 rv = PM4x10_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index); 5214 _SOC_IF_ERR_EXIT(rv); 5215 5216 rv = PM4x10_OUTMOST_PHY_INTERFACE_TYPE_GET(unit, pm_info, &interface, port_index); 5217 _SOC_IF_ERR_EXIT(rv); 5218 5219 phy_interface_config.data_rate = max_speed; 5220 phy_interface_config.ref_clock = ref_clock; 5221 5222 _SOC_IF_ERR_EXIT( portmod_intf_to_phymod_intf(unit, max_speed, interface, 5223 &prev_phymod_if)); 5224 _SOC_IF_ERR_EXIT 5225 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 5226 0, ref_clock, 5227 &phy_interface_config, phy_init_flags)); 5228 _SOC_IF_ERR_EXIT 5229 (portmod_phy_port_autoneg_status_get(unit, port, pm_info, &an_status)); 5230 /* It is possible that the underlying phymod interface get API does not 5231 * distinguish among certain interface types. For example, CR2 and KR2 5232 * are treated the same from TSCE's perspective. In these cases portmod 5233 * has to rely on the software state to retrieve the most-recently used 5234 * interface type written into phymod. 5235 */ 5236 if (phy_interface_config.interface_type != prev_phymod_if && 5237 prev_phymod_if != phymodInterfaceCount && 5238 !(nof_phys >1 && phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)) { 5239 if (!(an_status.enabled && an_status.locked)) { 5240 /*If an is enabled and locked, use the interface getting from phymod*/ 5241 phy_interface_config.interface_type = prev_phymod_if; 5242 } 5243 } 5244 5245 config->speed = phy_interface_config.data_rate; 5246 config->interface_modes = phy_interface_config.interface_modes; 5247 config->flags = 0; 5248 config->interface = interface; 5249 5250 rv = PM4x10_PORT_PLL_DIVIDER_REQ_GET(unit, pm_info, 5251 &pll_divider_req, 5252 port_index); 5253 5254 config->pll_divider_req = pll_divider_req; 5255 5256 _SOC_IF_ERR_EXIT( 5257 PM4x10_SERDES_INTERFACE_TYPE_GET(unit, pm_info, 5258 &config->serdes_interface, 5259 port_index)); 5260 5261 #if 1 5262 rv = portmod_intf_from_phymod_intf (unit, 5263 phy_interface_config.interface_type, &(config->interface)); 5264 _SOC_IF_ERR_EXIT(rv); 5265 #endif 5266 5267 rv = xlmac_encap_get (unit, port, &flags, &config->encap_mode); 5268 _SOC_IF_ERR_EXIT(rv); 5269 5270 rv = PM4x10_PORT_OP_MODE_GET(unit, pm_info, &config->port_op_mode, 5271 port_index); 5272 _SOC_IF_ERR_EXIT(rv); 5273 5274 config->port_num_lanes = SOC_INFO(unit).port_num_lanes[port]; 5275 5276 rv = PM4x10_MAX_SPEED_GET(unit, pm_info, &config->max_speed, port_index); 5277 _SOC_IF_ERR_EXIT(rv); 5278 5279 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &config->interface_modes, 5280 port_index); 5281 _SOC_IF_ERR_EXIT(rv); 5282 5283 5284 5285 exit: 5286 SOC_FUNC_RETURN; 5287 } 5288 5289 int pm4x10_port_default_interface_get(int unit, int port, pm_info_t pm_info, 5290 const portmod_port_interface_config_t* config, 5291 soc_port_if_t* interface) 5292 { 5293 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5294 int nof_phys = 0; 5295 int is_legacy_present, xphy_id; 5296 portmod_port_interface_config_t interface_config; 5297 SOC_INIT_FUNC_DEFS; 5298 5299 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 5300 phy_access ,(1+MAX_PHYN), 5301 &nof_phys)); 5302 if (nof_phys==1) { 5303 _SOC_IF_ERR_EXIT 5304 (_pm4x10_default_interface_get(unit, port, config, interface)); 5305 } else { 5306 xphy_id = phy_access[nof_phys - 1].access.addr; 5307 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_present)); 5308 5309 if (!is_legacy_present) { 5310 _SOC_IF_ERR_EXIT 5311 (portmod_port_phymod_xphy_default_interface_get(unit, &(phy_access[nof_phys-1]), 5312 config, interface)); 5313 } else { 5314 interface_config = *config; 5315 _SOC_IF_ERR_EXIT 5316 (portmod_common_default_interface_get(&interface_config)); 5317 5318 /* A TD2P+G28 40G/42G HG2 port is of XLAUI interface type on the 5319 * line side historically. On the system side, the int PHY should 5320 * be of BRCM mode (XGMII) and this is taken care by 5321 * portmod_port_line_to_sys_intf_map(). 5322 */ 5323 if ((config->encap_mode == SOC_ENCAP_HIGIG || 5324 config->encap_mode == SOC_ENCAP_HIGIG2) && 5325 (config->speed == 40000 || 5326 config->speed == 42000)) { 5327 interface_config.interface = SOC_PORT_IF_XLAUI; 5328 } 5329 5330 *interface = interface_config.interface; 5331 } 5332 } 5333 5334 exit: 5335 SOC_FUNC_RETURN; 5336 } 5337 5338 int pm4x10_port_cl72_set(int unit, int port, pm_info_t pm_info, uint32 enable) 5339 { 5340 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5341 int nof_phys = 0; 5342 5343 SOC_INIT_FUNC_DEFS; 5344 5345 _SOC_IF_ERR_EXIT 5346 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5347 phy_access ,(1+MAX_PHYN), 5348 &nof_phys)); 5349 5350 _SOC_IF_ERR_EXIT 5351 (portmod_port_phychain_cl72_set(unit, port, phy_access, nof_phys, enable)); 5352 5353 exit: 5354 SOC_FUNC_RETURN; 5355 } 5356 int pm4x10_port_cl72_get(int unit, int port, pm_info_t pm_info, uint32* enable) 5357 { 5358 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5359 int nof_phys = 0; 5360 5361 SOC_INIT_FUNC_DEFS; 5362 5363 _SOC_IF_ERR_EXIT 5364 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5365 phy_access ,(1+MAX_PHYN), 5366 &nof_phys)); 5367 5368 _SOC_IF_ERR_EXIT 5369 (portmod_port_phychain_cl72_get(unit, phy_access, nof_phys, enable)); 5370 5371 exit: 5372 SOC_FUNC_RETURN; 5373 } 5374 5375 int pm4x10_port_cl72_status_get(int unit, int port, pm_info_t pm_info, phymod_cl72_status_t* status) 5376 { 5377 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5378 int nof_phys = 0; 5379 5380 SOC_INIT_FUNC_DEFS; 5381 5382 _SOC_IF_ERR_EXIT 5383 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5384 phy_access ,(1+MAX_PHYN), 5385 &nof_phys)); 5386 5387 _SOC_IF_ERR_EXIT 5388 (portmod_port_phychain_cl72_status_get(unit, phy_access, nof_phys, status)); 5389 5390 exit: 5391 SOC_FUNC_RETURN; 5392 } 5393 5394 5395 int pm4x10_port_loopback_get(int unit, int port, pm_info_t pm_info, 5396 portmod_loopback_mode_t loopback_type, int* enable) 5397 { 5398 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5399 int nof_phys; 5400 uint32_t tmp_enable=0; 5401 phymod_loopback_mode_t phymod_lb_type; 5402 int rv = PHYMOD_E_NONE; 5403 int port_index; 5404 uint32 bitmap; 5405 5406 SOC_INIT_FUNC_DEFS; 5407 5408 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5409 &bitmap)); 5410 5411 switch(loopback_type){ 5412 case portmodLoopbackMacOuter: 5413 _SOC_IF_ERR_EXIT(xlmac_loopback_get(unit, port, enable)); 5414 break; 5415 5416 case portmodLoopbackPhyRloopPCS: 5417 case portmodLoopbackPhyGloopPMD: 5418 case portmodLoopbackPhyRloopPMD: /*slide*/ 5419 case portmodLoopbackPhyGloopPCS: /*slide*/ 5420 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 5421 (*enable) = 0; /* No phy --> no phy loopback*/ 5422 } else { 5423 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, 5424 loopback_type, &phymod_lb_type)); 5425 _SOC_IF_ERR_EXIT 5426 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5427 phy_access ,(1+MAX_PHYN), 5428 &nof_phys)); 5429 5430 rv = portmod_port_phychain_loopback_get(unit, port, phy_access, 5431 nof_phys, 5432 phymod_lb_type, 5433 &tmp_enable); 5434 if (rv == PHYMOD_E_UNAVAIL) { 5435 rv = PHYMOD_E_NONE; 5436 tmp_enable = 0; 5437 } 5438 5439 _SOC_IF_ERR_EXIT(rv); 5440 *enable = tmp_enable; 5441 5442 } 5443 break; 5444 default: 5445 (*enable) = 0; /* not supported --> no loopback */ 5446 break; 5447 } 5448 5449 exit: 5450 SOC_FUNC_RETURN; 5451 } 5452 5453 int pm4x10_port_loopback_set (int unit, int port, pm_info_t pm_info, 5454 portmod_loopback_mode_t loopback_type, int enable) 5455 { 5456 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5457 int nof_phys; 5458 phymod_loopback_mode_t phymod_lb_type; 5459 int port_index; 5460 uint32 bitmap; 5461 5462 SOC_INIT_FUNC_DEFS; 5463 5464 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5465 &bitmap)); 5466 5467 /* loopback type validation*/ 5468 switch(loopback_type){ 5469 case portmodLoopbackMacOuter: 5470 _SOC_IF_ERR_EXIT(xlmac_loopback_set(unit, port, enable)); 5471 break; 5472 5473 case portmodLoopbackPhyRloopPCS: 5474 case portmodLoopbackPhyRloopPMD: /*slide*/ 5475 case portmodLoopbackPhyGloopPMD: 5476 case portmodLoopbackPhyGloopPCS: /*slide*/ 5477 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] != 0) { 5478 if (enable) { 5479 _SOC_IF_ERR_EXIT(xlmac_loopback_set(unit, port, 0)); 5480 } 5481 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, 5482 loopback_type, &phymod_lb_type)); 5483 5484 _SOC_IF_ERR_EXIT 5485 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5486 phy_access ,(1+MAX_PHYN), 5487 &nof_phys)); 5488 5489 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_set(unit, port, phy_access, 5490 nof_phys, 5491 phymod_lb_type, 5492 enable)); 5493 } 5494 break; 5495 default: 5496 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, ( 5497 _SOC_MSG("unsupported loopback type %d"), loopback_type)); 5498 break; 5499 } 5500 if (enable) 5501 _SOC_IF_ERR_EXIT(PM_DRIVER(pm_info)->f_portmod_port_lag_failover_status_toggle(unit, port, pm_info)); 5502 5503 exit: 5504 SOC_FUNC_RETURN; 5505 } 5506 5507 int pm4x10_port_rx_mac_enable_set(int unit, int port, pm_info_t pm_info, int enable) 5508 { 5509 SOC_INIT_FUNC_DEFS; 5510 5511 _SOC_IF_ERR_EXIT(xlmac_rx_enable_set(unit, port, enable)); 5512 5513 exit: 5514 SOC_FUNC_RETURN; 5515 5516 } 5517 5518 int pm4x10_port_rx_mac_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 5519 { 5520 SOC_INIT_FUNC_DEFS; 5521 5522 _SOC_IF_ERR_EXIT(xlmac_rx_enable_get(unit, port, enable)); 5523 5524 exit: 5525 SOC_FUNC_RETURN; 5526 5527 } 5528 5529 int pm4x10_port_tx_mac_enable_set(int unit, int port, pm_info_t pm_info, int enable) 5530 { 5531 SOC_INIT_FUNC_DEFS; 5532 5533 _SOC_IF_ERR_EXIT(xlmac_tx_enable_set(unit, port, enable)); 5534 5535 exit: 5536 SOC_FUNC_RETURN; 5537 5538 } 5539 5540 int pm4x10_port_tx_mac_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 5541 { 5542 SOC_INIT_FUNC_DEFS; 5543 5544 _SOC_IF_ERR_EXIT(xlmac_tx_enable_get(unit, port, enable)); 5545 5546 exit: 5547 SOC_FUNC_RETURN; 5548 5549 } 5550 5551 int pm4x10_port_ability_local_get (int unit, int port, pm_info_t pm_info, uint32 phy_flags, 5552 portmod_port_ability_t* ability) 5553 { 5554 portmod_port_ability_t legacy_phy_ability; 5555 int fiber_pref, port_index; 5556 int max_speed = 11000; 5557 int num_of_lanes = 0; 5558 uint32 bitmap, tmpbit, interface_modes; 5559 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5560 int nof_phys, xphy_id, is_legacy_phy, rv = SOC_E_NONE; 5561 pm_version_t pm_version; 5562 5563 SOC_INIT_FUNC_DEFS; 5564 5565 sal_memset(ability, 0, sizeof(portmod_port_ability_t)); 5566 sal_memset(&legacy_phy_ability, 0, sizeof(portmod_port_ability_t)); 5567 5568 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 5569 5570 _SOC_IF_ERR_EXIT 5571 (portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 5572 (1+MAX_PHYN), &nof_phys)); 5573 5574 _SOC_IF_ERR_EXIT 5575 (_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 5576 5577 rv = PM4x10_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index); 5578 _SOC_IF_ERR_EXIT(rv); 5579 5580 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 5581 port_index); 5582 _SOC_IF_ERR_EXIT(rv); 5583 5584 fiber_pref = (interface_modes & PHYMOD_INTF_MODES_FIBER)? 1 : 0; 5585 5586 tmpbit = bitmap ; 5587 while(tmpbit) { 5588 num_of_lanes += ((tmpbit&1)?1:0) ; 5589 tmpbit >>= 1 ; 5590 } 5591 5592 ability->loopback = SOC_PA_LB_PHY | SOC_PA_LB_MAC; 5593 ability->medium = SOC_PA_MEDIUM_FIBER | SOC_PA_MEDIUM_COPPER | SOC_PA_MEDIUM_BACKPLANE; 5594 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5595 ability->fec = SOC_PA_FEC_NONE | SOC_PA_FEC_CL74; 5596 ability->flags = SOC_PA_AUTONEG; 5597 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 5598 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | SOC_PA_ENCAP_HIGIG2; 5599 ability->channel = SOC_PA_CHANNEL_LONG; 5600 5601 if (num_of_lanes == 1) { 5602 if (interface_modes & PHYMOD_INTF_MODES_HIGIG) { 5603 switch(max_speed) { 5604 case 10000: max_speed = 11000 ; break ; 5605 default: break; 5606 } 5607 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5608 _SOC_IF_ERR_EXIT(rv); 5609 } else { 5610 /* 10M, 100M, 1G, 2.5G, 5G don't have equivalent HiGig speeds 5611 Should only be supported on a non-HiGig port 5612 */ 5613 if (!fiber_pref) { 5614 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 5615 } 5616 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 5617 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 5618 5619 switch(max_speed) { 5620 case 11000: max_speed = 10000; break; 5621 default: break; 5622 } 5623 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5624 _SOC_IF_ERR_EXIT(rv); 5625 5626 /* Must include all supported speeds */ 5627 switch(max_speed) { 5628 case 12000: 5629 case 11000: 5630 case 10000: 5631 case 5000: 5632 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 5633 case 2500: 5634 /* Need to revisit: 2500MB for copper mode */ 5635 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 5636 default: break; 5637 } 5638 } 5639 switch(max_speed) { /* Must include all the supported speeds */ 5640 case 12000: 5641 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 5642 case 11000: 5643 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 5644 case 10000: 5645 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 5646 default: 5647 break; 5648 } 5649 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5650 ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII; 5651 if (max_speed >= 10000) { 5652 ability->interface |= SOC_PA_INTF_XGMII; 5653 } 5654 5655 /* single lane port */ 5656 ability->flags = SOC_PA_AUTONEG; 5657 } else if (num_of_lanes == 2) { 5658 if(interface_modes & PHYMOD_INTF_MODES_HIGIG) { 5659 switch(max_speed) { 5660 case 10000: max_speed = 11000 ; break ; 5661 case 20000: max_speed = 21000 ; break ; 5662 default: break ; 5663 } 5664 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5665 _SOC_IF_ERR_EXIT(rv); 5666 } else { 5667 switch(max_speed) { 5668 case 11000: max_speed = 10000 ; break ; 5669 case 21000: max_speed = 20000 ; break ; 5670 default: break ; 5671 } 5672 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5673 _SOC_IF_ERR_EXIT(rv); 5674 } 5675 switch(max_speed) { /* must include all the supported speedss */ 5676 case 21000: 5677 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 5678 case 20000: 5679 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 5680 case 16000: 5681 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5682 ability->speed_full_duplex |= SOC_PA_SPEED_16GB; 5683 } 5684 case 15000: 5685 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5686 ability->speed_full_duplex |= SOC_PA_SPEED_15GB; 5687 } 5688 case 13000: 5689 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5690 ability->speed_full_duplex |= SOC_PA_SPEED_13GB; 5691 } 5692 case 12000: 5693 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5694 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 5695 } 5696 case 11000: 5697 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5698 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 5699 } 5700 case 10000: 5701 if (!PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 5702 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 5703 } 5704 default: 5705 break; 5706 } 5707 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5708 ability->interface = SOC_PA_INTF_XGMII; 5709 ability->flags = 0; 5710 } else { 5711 if(interface_modes & PHYMOD_INTF_MODES_HIGIG) { 5712 switch(max_speed) { 5713 case 10000: max_speed = 11000 ; break ; 5714 case 20000: max_speed = 21000 ; break ; 5715 case 40000: max_speed = 42000 ; break ; 5716 case 100000: max_speed = 106000 ; break ; 5717 case 120000: max_speed = 127000 ; break ; 5718 default: break ; 5719 } 5720 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5721 _SOC_IF_ERR_EXIT(rv); 5722 } else { 5723 switch(max_speed) { 5724 case 11000: max_speed = 10000 ; break ; 5725 case 21000: max_speed = 20000 ; break ; 5726 case 42000: max_speed = 40000 ; break ; 5727 case 106000: max_speed = 100000 ; break ; 5728 case 127000: max_speed = 120000 ; break ; 5729 default: break ; 5730 } 5731 rv = PM4x10_MAX_SPEED_SET(unit, pm_info, max_speed, port_index); 5732 _SOC_IF_ERR_EXIT(rv); 5733 } 5734 switch(max_speed) { 5735 case 127000: 5736 ability->speed_full_duplex |= SOC_PA_SPEED_127GB; 5737 case 120000: 5738 ability->speed_full_duplex |= SOC_PA_SPEED_120GB; 5739 case 106000: 5740 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 5741 case 100000: 5742 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 5743 break; /* PM12x10 with lanes >=10 only supports above speeds */ 5744 case 42000: 5745 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 5746 case 40000: 5747 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 5748 case 30000: 5749 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5750 ability->speed_full_duplex |= SOC_PA_SPEED_30GB; 5751 } 5752 case 25000: 5753 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5754 ability->speed_full_duplex |= SOC_PA_SPEED_25GB; 5755 } 5756 case 21000: 5757 if (!PORTMOD_PM4x10_IS_GEN2_16nm(pm_version)) { 5758 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 5759 } 5760 case 20000: 5761 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 5762 case 16000: 5763 if (!PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 5764 ability->speed_full_duplex |= SOC_PA_SPEED_16GB; 5765 } 5766 case 15000: 5767 if (!PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 5768 ability->speed_full_duplex |= SOC_PA_SPEED_15GB; 5769 } 5770 case 13000: 5771 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5772 ability->speed_full_duplex |= SOC_PA_SPEED_13GB; 5773 } 5774 case 12000: 5775 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5776 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 5777 } 5778 case 11000: 5779 if (!(PORTMOD_PM4x10_IS_GEN2_16nm(pm_version) || PORTMOD_PM4x10_IS_GEN3_28nm(pm_version))) { 5780 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 5781 } 5782 case 10000: 5783 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 5784 default: 5785 break; 5786 } 5787 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5788 ability->interface = SOC_PA_INTF_XGMII; 5789 ability->flags = SOC_PA_AUTONEG; 5790 } 5791 5792 /* If legacy external phy presents, retrieve the local ability from the 5793 * external phy as it has more variants and the ability might vary for each. 5794 * However, if this function is called by the legacy ext PHY driver through 5795 * the PORTMOD callback function portmod_ext_to_int_cmd_get(), the returned 5796 * data should be of the internal SERDES. portmod_ext_to_int_cmd_get() uses 5797 * PORTMOD_USER_ACC_CMD_FOR_PHY_SET() to hint its callees that the target 5798 * of data retrieving is the internal SERDES. 5799 */ 5800 if (nof_phys > 1 && !(phy_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)) { 5801 /* check if the legacy phy present */ 5802 xphy_id = phy_access[nof_phys-1].access.addr; 5803 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 5804 if(is_legacy_phy) { 5805 /* call portmod phy chain function to retrieve the ability */ 5806 _SOC_IF_ERR_EXIT 5807 (portmod_port_phychain_local_ability_get(unit, port, phy_access, 5808 nof_phys, &legacy_phy_ability)); 5809 /* PHY driver returns all the speeds supported by PHY 5810 * Advertise only the speeds supported by both PortMacro and the PHY 5811 */ 5812 legacy_phy_ability.speed_full_duplex &= ability->speed_full_duplex; 5813 /* PHY driver may not return all supported encap modes 5814 * Advertise encap modes supported by both PortMacro and the PHY 5815 */ 5816 legacy_phy_ability.encap |= ability->encap; 5817 *ability = legacy_phy_ability; 5818 } else { 5819 /* We might need to consider calling portmod phy chain for 5820 * non legacy phys as well*/ 5821 } 5822 } 5823 5824 LOG_INFO(BSL_LS_SOC_PHY, 5825 (BSL_META_U(unit, 5826 "%-22s:unit=%d p=%d sp=%08x bitmap=%x\n"), 5827 __FUNCTION__, unit, port, ability->speed_full_duplex, bitmap)); 5828 5829 exit: 5830 SOC_FUNC_RETURN; 5831 5832 } 5833 5834 int pm4x10_port_autoneg_set (int unit, int port, pm_info_t pm_info, uint32 phy_flags, 5835 const phymod_autoneg_control_t* an) 5836 { 5837 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5838 int nof_phys, rv; 5839 int port_index, an_cl37, cl37_sgmii_cnt; 5840 uint32_t bitmap, an_done, port_dynamic_state; 5841 phymod_autoneg_control_t *pAn = (phymod_autoneg_control_t*)an; 5842 phymod_firmware_lane_config_t fw_config; 5843 phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer; 5844 SOC_INIT_FUNC_DEFS; 5845 5846 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5847 &bitmap)); 5848 5849 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 5850 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("AN isn't supported"))); 5851 } else { 5852 if (pAn->num_lane_adv == 0) { 5853 pAn->num_lane_adv = _pm4x10_nof_lanes_get(unit, port, pm_info); 5854 } 5855 5856 if (pAn->an_mode == phymod_AN_MODE_NONE) { 5857 rv = PM4x10_AN_MODE_GET(unit, pm_info, &pAn->an_mode, port_index); 5858 _SOC_IF_ERR_EXIT(rv); 5859 } 5860 5861 if (pAn->an_mode == phymod_AN_MODE_NONE) { 5862 pAn->an_mode = phymod_AN_MODE_SGMII; 5863 } 5864 5865 rv = PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, 5866 &port_dynamic_state, port_index); 5867 _SOC_IF_ERR_EXIT(rv); 5868 if (PORTMOD_PORT_IS_AUTONEG_MODE_UPDATED(port_dynamic_state)) { 5869 rv = PM4x10_AN_MODE_GET(unit, pm_info, &pAn->an_mode, port_index); 5870 _SOC_IF_ERR_EXIT(rv); 5871 PORTMOD_PORT_AUTONEG_MODE_UPDATED_CLR(port_dynamic_state); 5872 rv = PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, 5873 port_dynamic_state, port_index); 5874 _SOC_IF_ERR_EXIT(rv); 5875 } 5876 5877 _SOC_IF_ERR_EXIT 5878 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5879 phy_access ,(1+MAX_PHYN), 5880 &nof_phys)); 5881 5882 rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, nof_phys, &phy_op_mode); 5883 5884 /* Setting SerDes SGMII AN mode*/ 5885 if ((nof_phys <= 1) || 5886 ((phy_op_mode == phymodOperationModePassthru) && (rv == PHYMOD_E_NONE))) { 5887 SOC_IF_ERROR_RETURN 5888 (portmod_port_phychain_firmware_lane_config_get(unit, phy_access, nof_phys, &fw_config)); 5889 if (pAn->an_mode == phymod_AN_MODE_CL37) { 5890 if (!(fw_config.MediaType & phymodFirmwareMediaTypeOptics)) { 5891 pAn->an_mode = phymod_AN_MODE_SGMII; 5892 } 5893 } 5894 } 5895 5896 /* In case of warm boot, get autoneg informaton from hardware */ 5897 if(SOC_WARM_BOOT(unit)) { 5898 if (pAn->an_mode >= phymod_AN_MODE_Count) { 5899 _SOC_IF_ERR_EXIT 5900 (portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, phy_flags, pAn, &an_done)); 5901 } 5902 } 5903 5904 rv = PM4x10_AN_CL37_GET(unit, pm_info, &an_cl37, port_index); 5905 _SOC_IF_ERR_EXIT(rv); 5906 if(an_cl37 == PORTMOD_CL37_SGMII_COMBO){ 5907 if(pAn->enable){ 5908 cl37_sgmii_cnt = 0; 5909 _SOC_IF_ERR_EXIT(PM4x10_CL37_SGMII_CNT_SET(unit, pm_info, 5910 cl37_sgmii_cnt, 5911 port_index)); 5912 } 5913 } 5914 5915 _SOC_IF_ERR_EXIT 5916 (portmod_port_phychain_autoneg_set(unit, port, phy_access, nof_phys, phy_flags, an)); 5917 } 5918 5919 exit: 5920 SOC_FUNC_RETURN; 5921 5922 } 5923 5924 int pm4x10_port_autoneg_get (int unit, int port, pm_info_t pm_info, uint32 phy_flags, 5925 phymod_autoneg_control_t* an) 5926 { 5927 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5928 int nof_phys; 5929 uint32 an_done; 5930 int port_index, rv; 5931 uint32_t bitmap; 5932 5933 SOC_INIT_FUNC_DEFS; 5934 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5935 &bitmap)); 5936 5937 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 5938 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("AN isn't supported"))); 5939 } else { 5940 5941 if (an->num_lane_adv == 0) { 5942 an->num_lane_adv = _pm4x10_nof_lanes_get(unit, port, pm_info); 5943 } 5944 rv = PM4x10_AN_MODE_GET(unit, pm_info, &an->an_mode, port_index); 5945 _SOC_IF_ERR_EXIT(rv); 5946 5947 if (an->an_mode == phymod_AN_MODE_NONE) { 5948 an->an_mode = phymod_AN_MODE_SGMII; 5949 } 5950 5951 _SOC_IF_ERR_EXIT 5952 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5953 phy_access ,(1+MAX_PHYN), 5954 &nof_phys)); 5955 _SOC_IF_ERR_EXIT 5956 (portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, phy_flags, an, &an_done)); 5957 } 5958 5959 exit: 5960 SOC_FUNC_RETURN; 5961 5962 } 5963 5964 int pm4x10_port_autoneg_status_get (int unit, int port, pm_info_t pm_info, 5965 phymod_autoneg_status_t* an_status) 5966 { 5967 phymod_phy_access_t phy_access[1+MAX_PHYN]; 5968 int nof_phys; 5969 int port_index; 5970 uint32 bitmap; 5971 portmod_port_interface_config_t port_intf_config; 5972 phymod_interface_t phy_intf; 5973 5974 SOC_INIT_FUNC_DEFS; 5975 5976 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 5977 &bitmap)); 5978 5979 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 5980 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 5981 (_SOC_MSG("Invalid number of Phys"))); 5982 } 5983 5984 5985 _SOC_IF_ERR_EXIT 5986 (portmod_port_chain_phy_access_get(unit, port, pm_info, 5987 phy_access ,(1+MAX_PHYN), 5988 &nof_phys)); 5989 _SOC_IF_ERR_EXIT 5990 (portmod_port_phychain_autoneg_status_get(unit, port, phy_access, nof_phys, an_status)); 5991 5992 /* Even if AN is enabled the data rate and interface should be retrieved through 5993 * interface_config_get function 5994 */ 5995 _SOC_IF_ERR_EXIT 5996 (pm4x10_port_interface_config_get(unit, port, pm_info, &port_intf_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 5997 _SOC_IF_ERR_EXIT 5998 (portmod_intf_to_phymod_intf(unit, port_intf_config.speed, port_intf_config.interface, &phy_intf)); 5999 6000 if (an_status->enabled && an_status->locked) { 6001 an_status->data_rate = port_intf_config.speed; 6002 an_status->interface = phy_intf; 6003 } else { 6004 /* upper layer should not rely on the 6005 * data rate and interface if the AN is not locked 6006 */ 6007 an_status->data_rate = 0; 6008 an_status->interface = SOC_PORT_IF_NULL; 6009 } 6010 6011 exit: 6012 SOC_FUNC_RETURN; 6013 6014 } 6015 6016 int pm4x10_port_link_get(int unit, int port, pm_info_t pm_info, int flags, int* link) 6017 { 6018 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6019 int nof_phys; 6020 int sys_start_lane=-1; 6021 int sys_end_lane=-1; 6022 int line_start_lane=-1; 6023 int line_end_lane=-1; 6024 uint32 int_lane_mask=0xf; 6025 uint32 bitmap, an_done; 6026 int port_index, an_cl37, cl37_sgmii_war = 0; 6027 int cl37_sgmii_cnt, cl37_sgmii_restart_cnt; 6028 phymod_autoneg_control_t an; 6029 SOC_INIT_FUNC_DEFS; 6030 6031 _SOC_IF_ERR_EXIT 6032 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6033 phy_access ,(1+MAX_PHYN), 6034 &nof_phys)); 6035 6036 _SOC_IF_ERR_EXIT(_pm4x10_port_tricore_lane_info_get(unit, port, pm_info, 6037 &sys_start_lane, &sys_end_lane, 6038 &line_start_lane, &line_end_lane, 6039 &int_lane_mask, NULL)); 6040 /* only look at the lanes that are used. */ 6041 phy_access[0].access.lane_mask &= int_lane_mask; 6042 6043 _SOC_IF_ERR_EXIT 6044 (portmod_port_phychain_link_status_get(unit, port, phy_access, nof_phys, flags, (uint32_t*) link)); 6045 6046 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6047 &bitmap)); 6048 6049 _SOC_IF_ERR_EXIT(PM4x10_AN_CL37_GET(unit, pm_info, &an_cl37, port_index)); 6050 if(an_cl37 == PORTMOD_CL37_SGMII_COMBO) { 6051 _SOC_IF_ERR_EXIT(portmod_port_phychain_autoneg_get(unit, port, phy_access, 6052 nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 6053 &an, &an_done)); 6054 if (an.enable) { 6055 cl37_sgmii_war = 1; 6056 } 6057 } 6058 6059 if(*link == 0){ 6060 if(cl37_sgmii_war){ 6061 _SOC_IF_ERR_EXIT(PM4x10_CL37_SGMII_CNT_GET(unit, pm_info, 6062 &cl37_sgmii_cnt, 6063 port_index)); 6064 _SOC_IF_ERR_EXIT(PM4x10_CL37_SGMII_RESTART_CNT_GET(unit, pm_info, 6065 &cl37_sgmii_restart_cnt, 6066 port_index)); 6067 if(++cl37_sgmii_cnt >= cl37_sgmii_restart_cnt){ 6068 cl37_sgmii_cnt = 0; 6069 _SOC_IF_ERR_EXIT(PM4x10_CL37_SGMII_CNT_SET(unit, pm_info, 6070 cl37_sgmii_cnt, 6071 port_index)); 6072 _SOC_IF_ERR_EXIT 6073 (portmod_port_phychain_autoneg_restart_set(unit, phy_access,nof_phys)); 6074 } 6075 } 6076 } 6077 6078 if ((nof_phys == 1) && (PM_4x10_INFO(pm_info)->link_recovery.enabled)) { 6079 /* link recovery for internal serdes only for optical application MLD based */ 6080 uint32_t signal_detect; 6081 phymod_firmware_lane_config_t firmware_lane_config; 6082 6083 /* first get the medium type from internal serdes */ 6084 _SOC_IF_ERR_EXIT(phymod_phy_firmware_lane_config_get(&phy_access[0], &firmware_lane_config)); 6085 6086 if ((firmware_lane_config.MediaType == phymodFirmwareMediaTypeOptics) && 6087 (phy_access[0].access.lane_mask == 0xf)) { 6088 switch (PM_4x10_INFO(pm_info)->link_recovery.state) { 6089 6090 case PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK: 6091 /* link is good */ 6092 if (*link) { 6093 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt = 0; 6094 PM_4x10_INFO(pm_info)->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD; 6095 } else if ((PM_4x10_INFO(pm_info)->link_recovery.tick_cnt) > PORTMOD_LINK_RECOVERY_LINK_WAIT_CNT_LIMIT) { 6096 /* no link after all the try, reset the rx patha again */ 6097 PM_4x10_INFO(pm_info)->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_RESET_RX; 6098 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt = 0; 6099 } else { 6100 /* no link yet, keep wait for link */ 6101 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt += 1; 6102 } 6103 break; 6104 case PORTMOD_LINK_RECOVERY_STATE_RESET_RX: 6105 /*first check link status */ 6106 if (*link) { 6107 PM_4x10_INFO(pm_info)->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD; 6108 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt = 0; 6109 } else { 6110 /* first reset the rx path */ 6111 signal_detect = 0; 6112 6113 /* check if there is signal detect */ 6114 _SOC_IF_ERR_EXIT(phymod_phy_rx_signal_detect_get(&phy_access[0], &signal_detect)); 6115 6116 /* only toggle rx reset path only if there is signal on the line */ 6117 if (signal_detect) { 6118 /* first put the rx into reset */ 6119 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxDisable)); 6120 6121 /* add some delay */ 6122 sal_usleep(5000); 6123 6124 /* toggle CDR lock */ 6125 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxSquelchOn)); 6126 /* add some delay */ 6127 sal_usleep(5000); 6128 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxSquelchOff)); 6129 6130 sal_usleep(10000); 6131 /* release the rx reset */ 6132 _SOC_IF_ERR_EXIT(phymod_phy_rx_lane_control_set(&phy_access[0], phymodRxReset)); 6133 6134 sal_usleep(10000); 6135 } 6136 PM_4x10_INFO(pm_info)->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_WAIT_FOR_LINK; 6137 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt = 0; 6138 } 6139 break; 6140 6141 case PORTMOD_LINK_RECOVERY_STATE_LINK_GOOD: 6142 /* no link, need to reset the rx path */ 6143 if (*link == 0) { 6144 PM_4x10_INFO(pm_info)->link_recovery.state = PORTMOD_LINK_RECOVERY_STATE_RESET_RX; 6145 PM_4x10_INFO(pm_info)->link_recovery.tick_cnt = 0; 6146 } 6147 break; 6148 } 6149 } /* end of fiber_pref link recovery */ 6150 } 6151 6152 exit: 6153 SOC_FUNC_RETURN; 6154 } 6155 6156 int pm4x10_port_link_latch_down_get(int unit, int port, pm_info_t pm_info, uint32 flags, int* link) 6157 { 6158 int first_index, rv; 6159 uint32 reg32_val, bitmap; 6160 soc_field_t status_field, clear_field; 6161 SOC_INIT_FUNC_DEFS; 6162 6163 *link = 0; 6164 6165 rv = _pm4x10_port_index_get(unit, port, pm_info, &first_index, &bitmap); 6166 _SOC_IF_ERR_EXIT(rv); 6167 6168 switch(first_index) { 6169 case 0: 6170 status_field = PORT0_LINKSTATUSf; 6171 clear_field = PORT0_LINKDOWN_CLEARf; 6172 break; 6173 6174 case 1: 6175 status_field = PORT1_LINKSTATUSf; 6176 clear_field = PORT1_LINKDOWN_CLEARf; 6177 break; 6178 6179 case 2: 6180 status_field = PORT2_LINKSTATUSf; 6181 clear_field = PORT2_LINKDOWN_CLEARf; 6182 break; 6183 6184 case 3: 6185 status_field = PORT3_LINKSTATUSf; 6186 clear_field = PORT3_LINKDOWN_CLEARf; 6187 break; 6188 6189 default: 6190 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 6191 (_SOC_MSG("Port %d, failed to get port index"), port)); 6192 } 6193 6194 rv = READ_XLPORT_LINKSTATUS_DOWNr(unit, port, ®32_val); 6195 _SOC_IF_ERR_EXIT(rv); 6196 6197 (*link) = soc_reg_field_get(unit, XLPORT_LINKSTATUS_DOWNr, 6198 reg32_val, status_field); 6199 6200 if (PORTMOD_PORT_LINK_LATCH_DOWN_F_CLEAR & flags) { 6201 6202 rv = READ_XLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, ®32_val); 6203 _SOC_IF_ERR_EXIT(rv); 6204 6205 soc_reg_field_set(unit, XLPORT_LINKSTATUS_DOWN_CLEARr, 6206 ®32_val, clear_field, 1); 6207 6208 rv = WRITE_XLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, reg32_val); 6209 _SOC_IF_ERR_EXIT(rv); 6210 6211 sal_usleep(10); 6212 6213 soc_reg_field_set(unit, XLPORT_LINKSTATUS_DOWN_CLEARr, 6214 ®32_val, clear_field, 0); 6215 6216 /* reset default register value */ 6217 rv = WRITE_XLPORT_LINKSTATUS_DOWN_CLEARr(unit, port, reg32_val); 6218 _SOC_IF_ERR_EXIT(rv); 6219 6220 } 6221 6222 6223 exit: 6224 SOC_FUNC_RETURN; 6225 } 6226 6227 /* 6228 The field STRICT_PREAMBLE is used to check preamble+SFD strictly. 6229 The preamble will be shrinked when some external PHY works at 1G, 6230 so there are packet errors if STRICT_PREAMBLE is enabled. 6231 */ 6232 int _pm4x10_port_strict_preamble_set(int unit, int port, pm_info_t pm_info) 6233 { 6234 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6235 int nof_phys; 6236 int port_index=0; 6237 uint32 bitmap; 6238 phymod_phy_inf_config_t phy_config; 6239 int is_higig = 0; 6240 uint32 interface_modes; 6241 int strict_preamble_enable=0; 6242 SOC_INIT_FUNC_DEFS; 6243 6244 _SOC_IF_ERR_EXIT 6245 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6246 phy_access ,(1+MAX_PHYN), 6247 &nof_phys)); 6248 6249 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6250 &bitmap)); 6251 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_config)); 6252 6253 _SOC_IF_ERR_EXIT 6254 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 6255 0, PM_4x10_INFO(pm_info)->ref_clk, 6256 &phy_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 6257 _rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, port_index); 6258 _SOC_IF_ERR_EXIT(_rv); 6259 is_higig = interface_modes & PHYMOD_INTF_MODES_HIGIG ? 1 : 0; 6260 if (!is_higig && (phy_config.data_rate>= 10000)) { 6261 strict_preamble_enable = 1; 6262 } 6263 _rv = xlmac_strict_preamble_set(unit, port, strict_preamble_enable); 6264 _SOC_IF_ERR_EXIT(_rv); 6265 exit: 6266 SOC_FUNC_RETURN; 6267 } 6268 6269 int pm4x10_port_phy_link_up_event(int unit, int port, pm_info_t pm_info) 6270 { 6271 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6272 int nof_phys; 6273 6274 SOC_INIT_FUNC_DEFS; 6275 6276 _SOC_IF_ERR_EXIT 6277 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6278 phy_access ,(1+MAX_PHYN), 6279 &nof_phys)); 6280 _rv = portmod_port_phychain_phy_link_up_event(unit, port, phy_access, nof_phys); 6281 _SOC_IF_ERR_EXIT(_rv); 6282 6283 _SOC_IF_ERR_EXIT(_pm4x10_port_strict_preamble_set(unit, port, pm_info)); 6284 exit: 6285 SOC_FUNC_RETURN; 6286 } 6287 6288 int pm4x10_port_phy_link_down_event(int unit, int port, pm_info_t pm_info) 6289 { 6290 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6291 int nof_phys; 6292 6293 SOC_INIT_FUNC_DEFS; 6294 6295 _SOC_IF_ERR_EXIT 6296 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6297 phy_access ,(1+MAX_PHYN), 6298 &nof_phys)); 6299 6300 _rv = portmod_port_phychain_phy_link_down_event(unit, port, phy_access, nof_phys); 6301 6302 exit: 6303 SOC_FUNC_RETURN; 6304 6305 } 6306 6307 int pm4x10_port_mac_link_get(int unit, int port, pm_info_t pm_info, int* link) 6308 { 6309 uint32 reg_val, bitmap; 6310 int port_index, phy_acc; 6311 SOC_INIT_FUNC_DEFS; 6312 SOC_NULL_CHECK(pm_info); 6313 6314 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 6315 6316 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6317 &bitmap)); 6318 6319 switch(port_index) { 6320 case 0: 6321 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_LN0_STATUS0_REGr(unit, phy_acc, 6322 ®_val)); 6323 (*link) = soc_reg_field_get(unit, XLPORT_XGXS0_LN0_STATUS0_REGr, 6324 reg_val, LINK_STATUSf); 6325 break; 6326 6327 case 1: 6328 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_LN1_STATUS0_REGr(unit, phy_acc, 6329 ®_val)); 6330 (*link) = soc_reg_field_get(unit, XLPORT_XGXS0_LN1_STATUS0_REGr, 6331 reg_val, LINK_STATUSf); 6332 break; 6333 6334 case 2: 6335 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_LN2_STATUS0_REGr(unit, phy_acc, 6336 ®_val)); 6337 (*link) = soc_reg_field_get(unit, XLPORT_XGXS0_LN2_STATUS0_REGr, 6338 reg_val, LINK_STATUSf); 6339 break; 6340 6341 case 3: 6342 _SOC_IF_ERR_EXIT(READ_XLPORT_XGXS0_LN3_STATUS0_REGr(unit, phy_acc, 6343 ®_val)); 6344 (*link) = soc_reg_field_get(unit, XLPORT_XGXS0_LN3_STATUS0_REGr, 6345 reg_val, LINK_STATUSf); 6346 break; 6347 6348 default: 6349 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, 6350 (_SOC_MSG("Port %d, failed to get port index"), port)); 6351 } 6352 6353 exit: 6354 SOC_FUNC_RETURN; 6355 } 6356 6357 6358 int pm4x10_port_prbs_config_set(int unit, int port, pm_info_t pm_info, 6359 portmod_prbs_mode_t mode, int flags, const phymod_prbs_t* config) 6360 { 6361 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6362 int nof_phys; 6363 int port_index; 6364 uint32 bitmap; 6365 6366 SOC_INIT_FUNC_DEFS; 6367 6368 if(mode == 1 /*MAC*/) { 6369 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 6370 (_SOC_MSG("MAC PRBS is not supported for PM4x10"))); 6371 } 6372 6373 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6374 &bitmap)); 6375 6376 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 6377 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 6378 (_SOC_MSG("phy PRBS isn't supported"))); 6379 } 6380 6381 _SOC_IF_ERR_EXIT 6382 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6383 phy_access ,(1+MAX_PHYN), 6384 &nof_phys)); 6385 _SOC_IF_ERR_EXIT 6386 (portmod_port_phychain_prbs_config_set(unit, phy_access, nof_phys, flags, config)); 6387 6388 exit: 6389 SOC_FUNC_RETURN; 6390 } 6391 6392 int pm4x10_port_prbs_config_get (int unit, int port, pm_info_t pm_info, 6393 portmod_prbs_mode_t mode, int flags, phymod_prbs_t* config) 6394 { 6395 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6396 int nof_phys; 6397 int port_index; 6398 uint32 bitmap; 6399 6400 SOC_INIT_FUNC_DEFS; 6401 6402 if(mode == 1 /*MAC*/) { 6403 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 6404 (_SOC_MSG("MAC PRBS is not supported for PM4x10"))); 6405 } 6406 6407 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6408 &bitmap)); 6409 6410 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 6411 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 6412 (_SOC_MSG("phy PRBS isn't supported"))); 6413 } 6414 6415 _SOC_IF_ERR_EXIT 6416 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6417 phy_access ,(1+MAX_PHYN), 6418 &nof_phys)); 6419 _SOC_IF_ERR_EXIT 6420 (portmod_port_phychain_prbs_config_get(unit, phy_access, nof_phys, flags, config)); 6421 6422 exit: 6423 SOC_FUNC_RETURN; 6424 } 6425 6426 6427 int pm4x10_port_prbs_enable_set (int unit, int port, pm_info_t pm_info, 6428 portmod_prbs_mode_t mode, int flags, int enable) 6429 { 6430 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6431 int nof_phys; 6432 int port_index; 6433 uint32 bitmap; 6434 6435 SOC_INIT_FUNC_DEFS; 6436 6437 if(mode == 1 /*MAC*/) { 6438 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ( 6439 _SOC_MSG("MAC PRBS is not supported for PM4x10"))); 6440 } 6441 6442 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6443 &bitmap)); 6444 6445 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 6446 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, ( 6447 _SOC_MSG("phy PRBS isn't supported"))); 6448 } 6449 6450 _SOC_IF_ERR_EXIT 6451 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6452 phy_access ,(1+MAX_PHYN), 6453 &nof_phys)); 6454 _SOC_IF_ERR_EXIT 6455 (portmod_port_phychain_prbs_enable_set(unit, phy_access, nof_phys, flags, enable)); 6456 6457 exit: 6458 SOC_FUNC_RETURN; 6459 } 6460 6461 int pm4x10_port_prbs_enable_get (int unit, int port, pm_info_t pm_info, 6462 portmod_prbs_mode_t mode, int flags, int* enable) 6463 { 6464 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6465 uint32 is_enabled; 6466 int nof_phys; 6467 int port_index; 6468 uint32 bitmap; 6469 6470 SOC_INIT_FUNC_DEFS; 6471 6472 if(mode == 1 /*MAC*/) { 6473 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 6474 (_SOC_MSG("MAC PRBS is not supported for PM4x10"))); 6475 } 6476 6477 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6478 &bitmap)); 6479 6480 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 6481 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 6482 (_SOC_MSG("phy PRBS isn't supported"))); 6483 } 6484 6485 _SOC_IF_ERR_EXIT 6486 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6487 phy_access ,(1+MAX_PHYN), 6488 &nof_phys)); 6489 6490 _SOC_IF_ERR_EXIT 6491 (portmod_port_phychain_prbs_enable_get(unit, phy_access, nof_phys, flags, &is_enabled)); 6492 6493 (*enable) = (is_enabled ? 1 : 0); 6494 6495 exit: 6496 SOC_FUNC_RETURN; 6497 } 6498 6499 6500 int pm4x10_port_prbs_status_get(int unit, int port, pm_info_t pm_info, 6501 portmod_prbs_mode_t mode, int flags, phymod_prbs_status_t* status) 6502 { 6503 phymod_phy_access_t phy_access[1+MAX_PHYN]; 6504 int nof_phys; 6505 int port_index; 6506 uint32 bitmap; 6507 6508 SOC_INIT_FUNC_DEFS; 6509 6510 if(mode == 1 /*MAC*/) { 6511 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 6512 (_SOC_MSG("MAC PRBS is not supported for PM4x10"))); 6513 } 6514 6515 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6516 &bitmap)); 6517 6518 if(PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 6519 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 6520 (_SOC_MSG("phy PRBS isn't supported"))); 6521 } 6522 6523 _SOC_IF_ERR_EXIT 6524 (portmod_port_chain_phy_access_get(unit, port, pm_info, 6525 phy_access ,(1+MAX_PHYN), 6526 &nof_phys)); 6527 _SOC_IF_ERR_EXIT 6528 (portmod_port_phychain_prbs_status_get(unit, phy_access, nof_phys, flags, status)); 6529 6530 exit: 6531 SOC_FUNC_RETURN; 6532 6533 } 6534 6535 int pm4x10_port_nof_lanes_get(int unit, int port, pm_info_t pm_info, int *nof_lanes) 6536 { 6537 int temp_nof_lanes = 0; 6538 SOC_INIT_FUNC_DEFS; 6539 6540 temp_nof_lanes = _pm4x10_nof_lanes_get(unit, port, pm_info); 6541 if(0 == temp_nof_lanes){ 6542 SOC_EXIT; 6543 } 6544 else{ 6545 *nof_lanes = temp_nof_lanes; 6546 } 6547 6548 exit: 6549 SOC_FUNC_RETURN; 6550 } 6551 6552 6553 int pm4x10_port_firmware_mode_set (int unit, int port, pm_info_t pm_info, 6554 phymod_firmware_mode_t fw_mode) 6555 { 6556 6557 SOC_INIT_FUNC_DEFS; 6558 SOC_NULL_CHECK(pm_info); 6559 6560 /* Place your code here */ 6561 6562 6563 exit: 6564 SOC_FUNC_RETURN; 6565 6566 } 6567 6568 int pm4x10_port_firmware_mode_get (int unit, int port, pm_info_t pm_info, 6569 phymod_firmware_mode_t* fw_mode) 6570 { 6571 6572 SOC_INIT_FUNC_DEFS; 6573 SOC_NULL_CHECK(pm_info); 6574 6575 /* Place your code here */ 6576 6577 6578 exit: 6579 SOC_FUNC_RETURN; 6580 6581 } 6582 6583 6584 int pm4x10_port_runt_threshold_set (int unit, int port, 6585 pm_info_t pm_info, int value) 6586 { 6587 6588 SOC_INIT_FUNC_DEFS; 6589 SOC_NULL_CHECK(pm_info); 6590 6591 /* Place your code here */ 6592 6593 exit: 6594 SOC_FUNC_RETURN; 6595 6596 } 6597 6598 int pm4x10_port_runt_threshold_get(int unit, int port, pm_info_t pm_info, int* value) 6599 { 6600 6601 SOC_INIT_FUNC_DEFS; 6602 SOC_NULL_CHECK(pm_info); 6603 6604 /* Place your code here */ 6605 6606 6607 exit: 6608 SOC_FUNC_RETURN; 6609 6610 } 6611 6612 6613 int pm4x10_port_max_packet_size_set (int unit, int port, 6614 pm_info_t pm_info, int value) 6615 { 6616 SOC_INIT_FUNC_DEFS; 6617 6618 _SOC_IF_ERR_EXIT(xlmac_rx_max_size_set(unit, port, value)); 6619 6620 exit: 6621 SOC_FUNC_RETURN; 6622 } 6623 6624 int pm4x10_port_max_packet_size_get (int unit, int port, 6625 pm_info_t pm_info, int* value) 6626 { 6627 SOC_INIT_FUNC_DEFS; 6628 _SOC_IF_ERR_EXIT(xlmac_rx_max_size_get(unit, port, value)); 6629 6630 exit: 6631 SOC_FUNC_RETURN; 6632 } 6633 6634 6635 int pm4x10_port_pad_size_set(int unit, int port, pm_info_t pm_info, int value) 6636 { 6637 SOC_INIT_FUNC_DEFS; 6638 SOC_NULL_CHECK(pm_info); 6639 6640 _SOC_IF_ERR_EXIT(xlmac_pad_size_set(unit, port , value)); 6641 6642 exit: 6643 SOC_FUNC_RETURN; 6644 6645 } 6646 6647 int pm4x10_port_pad_size_get(int unit, int port, pm_info_t pm_info, int* value) 6648 { 6649 SOC_INIT_FUNC_DEFS; 6650 SOC_NULL_CHECK(pm_info); 6651 6652 _SOC_IF_ERR_EXIT(xlmac_pad_size_get(unit, port , value)); 6653 6654 exit: 6655 SOC_FUNC_RETURN; 6656 } 6657 6658 6659 int pm4x10_port_tx_drop_on_local_fault_set (int unit, int port, 6660 pm_info_t pm_info, int enable) 6661 { 6662 portmod_local_fault_control_t control; 6663 SOC_INIT_FUNC_DEFS; 6664 6665 portmod_local_fault_control_t_init(unit, &control); 6666 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_get(unit, port, pm_info, &control)); 6667 6668 control.drop_tx_on_fault = enable; 6669 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_set(unit, port, pm_info, &control)); 6670 6671 exit: 6672 SOC_FUNC_RETURN; 6673 } 6674 6675 int pm4x10_port_tx_drop_on_local_fault_get (int unit, int port, 6676 pm_info_t pm_info, int* enable) 6677 { 6678 portmod_local_fault_control_t control; 6679 SOC_INIT_FUNC_DEFS; 6680 6681 portmod_local_fault_control_t_init(unit, &control); 6682 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_get(unit, port, pm_info, &control)); 6683 *enable = control.drop_tx_on_fault; 6684 6685 exit: 6686 SOC_FUNC_RETURN; 6687 } 6688 6689 6690 int pm4x10_port_tx_drop_on_remote_fault_set(int unit, int port, 6691 pm_info_t pm_info, int enable) 6692 { 6693 portmod_remote_fault_control_t control; 6694 SOC_INIT_FUNC_DEFS; 6695 6696 portmod_remote_fault_control_t_init(unit, &control); 6697 6698 _SOC_IF_ERR_EXIT(pm4x10_port_remote_fault_control_get(unit, port, pm_info, &control)); 6699 control.drop_tx_on_fault = enable; 6700 _SOC_IF_ERR_EXIT(pm4x10_port_remote_fault_control_set(unit, port, pm_info, &control)); 6701 6702 exit: 6703 SOC_FUNC_RETURN; 6704 } 6705 6706 int pm4x10_port_tx_drop_on_remote_fault_get (int unit, int port, 6707 pm_info_t pm_info, int* enable) 6708 { 6709 portmod_remote_fault_control_t control; 6710 SOC_INIT_FUNC_DEFS; 6711 6712 portmod_remote_fault_control_t_init(unit, &control); 6713 _SOC_IF_ERR_EXIT(pm4x10_port_remote_fault_control_get(unit, port, pm_info, &control)); 6714 *enable = control.drop_tx_on_fault; 6715 6716 exit: 6717 SOC_FUNC_RETURN; 6718 } 6719 6720 int pm4x10_port_local_fault_enable_set (int unit, int port, 6721 pm_info_t pm_info, int enable) 6722 { 6723 portmod_local_fault_control_t control; 6724 SOC_INIT_FUNC_DEFS; 6725 6726 portmod_local_fault_control_t_init(unit, &control); 6727 6728 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_get(unit, port, pm_info, &control)); 6729 control.enable = enable; 6730 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_set(unit, port, pm_info, &control)); 6731 6732 exit: 6733 SOC_FUNC_RETURN; 6734 } 6735 6736 int pm4x10_port_local_fault_enable_get (int unit, int port, 6737 pm_info_t pm_info, int* enable) 6738 { 6739 portmod_local_fault_control_t control; 6740 SOC_INIT_FUNC_DEFS; 6741 6742 portmod_local_fault_control_t_init(unit, &control); 6743 6744 _SOC_IF_ERR_EXIT(pm4x10_port_local_fault_control_get(unit, port, pm_info, &control)); 6745 *enable = control.enable; 6746 6747 exit: 6748 SOC_FUNC_RETURN; 6749 } 6750 6751 int pm4x10_port_local_fault_status_get(int unit, int port, 6752 pm_info_t pm_info, int* value) 6753 { 6754 int rv; 6755 SOC_INIT_FUNC_DEFS; 6756 6757 rv = xlmac_local_fault_status_get(unit, port, value); 6758 _SOC_IF_ERR_EXIT(rv); 6759 exit: 6760 SOC_FUNC_RETURN; 6761 } 6762 6763 int pm4x10_port_local_fault_control_set(int unit, int port, pm_info_t pm_info, 6764 const portmod_local_fault_control_t* control) 6765 { 6766 int rv; 6767 SOC_INIT_FUNC_DEFS; 6768 6769 rv = xlmac_local_fault_control_set(unit, port, control); 6770 _SOC_IF_ERR_EXIT(rv); 6771 exit: 6772 SOC_FUNC_RETURN; 6773 } 6774 6775 int pm4x10_port_local_fault_control_get(int unit, int port, pm_info_t pm_info, 6776 portmod_local_fault_control_t* control) 6777 { 6778 int rv; 6779 SOC_INIT_FUNC_DEFS; 6780 6781 rv = xlmac_local_fault_control_get(unit, port, control); 6782 _SOC_IF_ERR_EXIT(rv); 6783 exit: 6784 SOC_FUNC_RETURN; 6785 } 6786 6787 int pm4x10_port_remote_fault_status_get(int unit, int port, 6788 pm_info_t pm_info, int* value) 6789 { 6790 int rv; 6791 SOC_INIT_FUNC_DEFS; 6792 6793 rv = xlmac_remote_fault_status_get(unit, port, value); 6794 _SOC_IF_ERR_EXIT(rv); 6795 exit: 6796 SOC_FUNC_RETURN; 6797 } 6798 6799 int pm4x10_port_remote_fault_control_set(int unit, int port, pm_info_t pm_info, 6800 const portmod_remote_fault_control_t* control) 6801 { 6802 int rv; 6803 SOC_INIT_FUNC_DEFS; 6804 6805 rv = xlmac_remote_fault_control_set(unit, port, control); 6806 _SOC_IF_ERR_EXIT(rv); 6807 exit: 6808 SOC_FUNC_RETURN; 6809 } 6810 6811 int pm4x10_port_remote_fault_control_get(int unit, int port, pm_info_t pm_info, 6812 portmod_remote_fault_control_t* control) 6813 { 6814 int rv; 6815 SOC_INIT_FUNC_DEFS; 6816 6817 rv = xlmac_remote_fault_control_get(unit, port, control); 6818 _SOC_IF_ERR_EXIT(rv); 6819 exit: 6820 SOC_FUNC_RETURN; 6821 } 6822 6823 6824 int pm4x10_port_pause_control_set(int unit, int port, pm_info_t pm_info, 6825 const portmod_pause_control_t* control) 6826 { 6827 SOC_INIT_FUNC_DEFS; 6828 _SOC_IF_ERR_EXIT(xlmac_pause_control_set(unit, port, control)); 6829 exit: 6830 SOC_FUNC_RETURN; 6831 } 6832 6833 int pm4x10_port_pause_control_get(int unit, int port, pm_info_t pm_info, 6834 portmod_pause_control_t* control) 6835 { 6836 SOC_INIT_FUNC_DEFS; 6837 _SOC_IF_ERR_EXIT(xlmac_pause_control_get(unit, port, control)); 6838 exit: 6839 SOC_FUNC_RETURN; 6840 } 6841 6842 int pm4x10_port_llfc_control_set(int unit, int port, 6843 pm_info_t pm_info, const portmod_llfc_control_t* control) 6844 { 6845 SOC_INIT_FUNC_DEFS; 6846 _SOC_IF_ERR_EXIT(xlmac_llfc_control_set(unit, port, control)); 6847 exit: 6848 SOC_FUNC_RETURN; 6849 } 6850 6851 int pm4x10_port_llfc_control_get(int unit, int port, 6852 pm_info_t pm_info, portmod_llfc_control_t* control) 6853 { 6854 SOC_INIT_FUNC_DEFS; 6855 _SOC_IF_ERR_EXIT(xlmac_llfc_control_get(unit, port, control)); 6856 6857 exit: 6858 SOC_FUNC_RETURN; 6859 } 6860 6861 int pm4x10_port_core_access_get (int unit, int port, 6862 pm_info_t pm_info, int phyn, int max_cores, 6863 phymod_core_access_t* core_access_arr, 6864 int* nof_cores, 6865 int* is_most_ext) 6866 { 6867 int port_index; 6868 uint32 bitmap; 6869 int index; 6870 int done=0; 6871 int i,j, is_legacy_phy; 6872 uint32 xphy_id; 6873 phymod_core_access_t core_access; 6874 6875 SOC_INIT_FUNC_DEFS; 6876 6877 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 6878 &bitmap)); 6879 6880 if(phyn > PM_4x10_INFO(pm_info)->nof_phys[port_index]){ 6881 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 6882 (_SOC_MSG("phyn exceeded. max allowed %d. got %d"), 6883 PM_4x10_INFO(pm_info)->nof_phys[port_index] - 1, phyn)); 6884 } 6885 6886 if(phyn < 0) 6887 { 6888 phyn = PM_4x10_INFO(pm_info)->nof_phys[port_index] - 1; 6889 } 6890 6891 _SOC_IF_ERR_EXIT(phymod_core_access_t_init(&core_access_arr[0])); 6892 6893 if( phyn == 0 ){ 6894 sal_memcpy(&core_access_arr[0], &(PM_4x10_INFO(pm_info)->int_core_access), 6895 sizeof(phymod_core_access_t)); 6896 *nof_cores = 1; 6897 } else { 6898 index = 0; 6899 done = 0; 6900 for(i=0 ; (i< MAX_PORTS_PER_PM4X10); i++) { 6901 if(bitmap & (0x1U << i)) { 6902 xphy_id = PM_4x10_INFO(pm_info)->lane_conn[phyn-1][i].xphy_id; 6903 if(xphy_id != PORTMOD_XPHY_ID_INVALID){ 6904 if(index == 0){ 6905 _SOC_IF_ERR_EXIT(portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_phy)); 6906 sal_memcpy(&core_access_arr[index], &core_access, 6907 sizeof(phymod_core_access_t)); 6908 index++; 6909 } else { 6910 for( j = 0 ; (j < index) &&(!done) ; j++) { 6911 if((!sal_memcmp (&core_access_arr[j], &core_access, 6912 sizeof(phymod_core_access_t)))) { /* found a match */ 6913 done = 1; 6914 } 6915 } 6916 if((!done) && (index < max_cores)){ 6917 sal_memcpy(&core_access_arr[index], &core_access, 6918 sizeof(phymod_core_access_t)); 6919 index++; 6920 } 6921 } 6922 } 6923 } 6924 } 6925 *nof_cores = index; 6926 } 6927 if (is_most_ext) { 6928 if (phyn == PM_4x10_INFO(pm_info)->nof_phys[port_index]-1) { 6929 *is_most_ext = 1; 6930 } else { 6931 *is_most_ext = 0; 6932 } 6933 } 6934 6935 exit: 6936 SOC_FUNC_RETURN; 6937 } 6938 6939 /*! 6940 * pm4x10_port_frame_spacing_stretch_set 6941 * 6942 * @brief Port Mac Control Spacing Stretch 6943 * 6944 * @param [in] unit - unit id 6945 * @param [in] port - logical port 6946 * @param [in] spacing - 6947 */ 6948 int pm4x10_port_frame_spacing_stretch_set (int unit, int port, 6949 pm_info_t pm_info,int spacing) 6950 { 6951 return(xlmac_frame_spacing_stretch_set(unit, port, spacing)); 6952 } 6953 6954 /*! 6955 * pm4x10_port_frame_spacing_stretch_get 6956 * 6957 * @brief Port Mac Control Spacing Stretch 6958 * 6959 * @param [in] unit - unit id 6960 * @param [in] port - logical port 6961 * @param [in] spacing - 6962 */ 6963 int pm4x10_port_frame_spacing_stretch_get (int unit, int port, 6964 pm_info_t pm_info, 6965 const int *spacing) 6966 { 6967 return (xlmac_frame_spacing_stretch_get(unit, port, (int*)spacing)); 6968 } 6969 6970 /*! 6971 * pm4x10_port_diag_fifo_status_get 6972 * 6973 * @brief get port timestamps in fifo 6974 * 6975 * @param [in] unit - unit id 6976 * @param [in] port - logical port 6977 * @param [in] diag_info - 6978 */ 6979 int pm4x10_port_diag_fifo_status_get (int unit, int port,pm_info_t pm_info, 6980 const portmod_fifo_status_t* diag_info) 6981 { 6982 return(xlmac_diag_fifo_status_get(unit, port, diag_info)); 6983 } 6984 6985 int _xlport_pfc_config_set(int unit, int port, uint32 value) 6986 { 6987 int rv = SOC_E_UNAVAIL; 6988 uint32 rval32 = 0; 6989 6990 if (SOC_REG_IS_VALID(unit,XLPORT_MAC_RSV_MASKr)) { 6991 rv = READ_XLPORT_MAC_RSV_MASKr(unit, port, &rval32); 6992 if (SOC_SUCCESS(rv)) { 6993 /* XLPORT_MAC_RSV_MASK: Bit 18 PFC frame detected 6994 * Enable PFC Frame : Set 0. Go through 6995 * Disable PFC Frame : Set 1. Purged. 6996 */ 6997 if(value) { 6998 rval32 &= ~(1 << 18); 6999 } else { 7000 rval32 |= (1 << 18); 7001 } 7002 rv = WRITE_XLPORT_MAC_RSV_MASKr(unit, port, rval32); 7003 } 7004 } 7005 7006 return rv; 7007 } 7008 7009 int _xlport_pfc_config_get(int unit, int port, uint32* value) 7010 { 7011 int rv = SOC_E_NONE; 7012 uint32 rval32 = 0; 7013 7014 if (SOC_REG_IS_VALID(unit,XLPORT_MAC_RSV_MASKr)) { 7015 rv = READ_XLPORT_MAC_RSV_MASKr(unit, port, &rval32); 7016 if (SOC_SUCCESS(rv)) { 7017 /* XLPORT_MAC_RSV_MASK: Bit 18 PFC frame detected 7018 * Enable PFC Frame : Set 0. Go through 7019 * Disable PFC Frame : Set 1. Purged. 7020 */ 7021 *value = ((rval32 & 0x40000) >> 18) ? 0 : 1; 7022 } 7023 } 7024 7025 return rv; 7026 } 7027 7028 /*! 7029 * pm4x10_port_pfc_config_set 7030 * 7031 * @brief set pass control frames. 7032 * 7033 * @param [in] unit - unit id 7034 * @param [in] port - logical port 7035 * @param [in] pfc_cfg - 7036 */ 7037 int pm4x10_port_pfc_config_set (int unit, int port,pm_info_t pm_info, 7038 const portmod_pfc_config_t* pfc_cfg) 7039 { 7040 SOC_INIT_FUNC_DEFS; 7041 7042 if (pfc_cfg->classes != 8) { 7043 return SOC_E_PARAM; 7044 } 7045 _SOC_IF_ERR_EXIT(xlmac_pfc_config_set(unit, port, pfc_cfg)); 7046 _SOC_IF_ERR_EXIT(_xlport_pfc_config_set(unit, port, pfc_cfg->rxpass)); 7047 exit: 7048 SOC_FUNC_RETURN; 7049 } 7050 7051 7052 /*! 7053 * pm4x10_port_pfc_config_get 7054 * 7055 * @brief set pass control frames. 7056 * 7057 * @param [in] unit - unit id 7058 * @param [in] port - logical port 7059 * @param [in] pfc_cfg - 7060 */ 7061 int pm4x10_port_pfc_config_get (int unit, int port,pm_info_t pm_info, 7062 portmod_pfc_config_t* pfc_cfg) 7063 { 7064 SOC_INIT_FUNC_DEFS; 7065 7066 pfc_cfg->classes = 8; 7067 _SOC_IF_ERR_EXIT(xlmac_pfc_config_get(unit, port, pfc_cfg)); 7068 7069 _SOC_IF_ERR_EXIT(_xlport_pfc_config_get(unit, port, &pfc_cfg->rxpass)); 7070 exit: 7071 SOC_FUNC_RETURN; 7072 } 7073 7074 int pm4x10_port_pfc_control_set(int unit, int port, pm_info_t pm_info, const portmod_pfc_control_t* control) 7075 { 7076 7077 SOC_INIT_FUNC_DEFS; 7078 _SOC_IF_ERR_EXIT(xlmac_pfc_control_set(unit, port, control)); 7079 exit: 7080 SOC_FUNC_RETURN; 7081 7082 } 7083 7084 int pm4x10_port_pfc_control_get(int unit, int port, pm_info_t pm_info, portmod_pfc_control_t* control) 7085 { 7086 7087 SOC_INIT_FUNC_DEFS; 7088 _SOC_IF_ERR_EXIT(xlmac_pfc_control_get(unit, port, control)); 7089 exit: 7090 SOC_FUNC_RETURN; 7091 7092 } 7093 7094 /*! 7095 * pm4x10_port_eee_set 7096 * 7097 * @brief set EEE control and timers 7098 * 7099 * @param [in] unit - unit id 7100 * @param [in] port - logical port 7101 * @param [in] eee - 7102 */ 7103 int pm4x10_port_eee_set(int unit, int port, pm_info_t pm_info,const portmod_eee_t* eee) 7104 { 7105 return (xlmac_eee_set(unit, port, eee)); 7106 } 7107 7108 /*! 7109 * pm4x10_port_eee_get 7110 * 7111 * @brief get EEE control and timers 7112 * 7113 * @param [in] unit - unit id 7114 * @param [in] port - logical port 7115 * @param [in] eee - 7116 */ 7117 int pm4x10_port_eee_get(int unit, int port, pm_info_t pm_info, portmod_eee_t* eee) 7118 { 7119 return (xlmac_eee_get(unit, port, eee)); 7120 } 7121 7122 /*! 7123 * pm4x10_port_vlan_tag_set 7124 * 7125 * @brief vlan tag set. 7126 * 7127 * @param [in] unit - unit id 7128 * @param [in] port - logical port 7129 * @param [in] vlan_tag - 7130 */ 7131 int pm4x10_port_vlan_tag_set(int unit, int port, pm_info_t pm_info,const portmod_vlan_tag_t* vlan_tag) 7132 { 7133 return (xlmac_rx_vlan_tag_set (unit, port, vlan_tag->outer_vlan_tag, 7134 vlan_tag->inner_vlan_tag)); 7135 } 7136 7137 7138 /*! 7139 * pm4x10_port_vlan_tag_get 7140 * 7141 * @brief vlan tag get. 7142 * 7143 * @param [in] unit - unit id 7144 * @param [in] port - logical port 7145 * @param [in] vlan_tag - 7146 */ 7147 int pm4x10_port_vlan_tag_get(int unit, int port, pm_info_t pm_info, portmod_vlan_tag_t* vlan_tag) 7148 { 7149 return (xlmac_rx_vlan_tag_get (unit, port, (int*)&vlan_tag->outer_vlan_tag, 7150 (int*)&vlan_tag->inner_vlan_tag)); 7151 } 7152 7153 /*! 7154 * pm4x10_port_duplex_set 7155 * 7156 * @brief duplex set. 7157 * 7158 * @param [in] unit - unit id 7159 * @param [in] port - logical port 7160 * @param [in] enable - 7161 */ 7162 int pm4x10_port_duplex_set(int unit, int port, pm_info_t pm_info,int enable) 7163 { 7164 return (xlmac_duplex_set (unit, port, enable)); 7165 } 7166 7167 7168 /*! 7169 * pm4x10_port_duplex_get 7170 * 7171 * @brief duplex get. 7172 * 7173 * @param [in] unit - unit id 7174 * @param [in] port - logical port 7175 * @param [in] vlan_tag - 7176 */ 7177 int pm4x10_port_duplex_get(int unit, int port, pm_info_t pm_info, int* enable) 7178 { 7179 return (xlmac_duplex_get (unit, port, enable)); 7180 } 7181 7182 /*! 7183 * pm4x10_port_speed_get 7184 * 7185 * @brief duplex get. 7186 * 7187 * @param [in] unit - unit id 7188 * @param [in] port - logical port 7189 * @param [in] speed - 7190 */ 7191 int pm4x10_port_speed_get(int unit, int port, pm_info_t pm_info, int* speed) 7192 { 7193 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7194 phymod_phy_inf_config_t config; 7195 int nof_phys, rv; 7196 7197 rv = portmod_port_chain_phy_access_get(unit, port, pm_info, 7198 phy_access ,(1+MAX_PHYN), 7199 &nof_phys); 7200 if (rv) return(rv); 7201 7202 rv = phymod_phy_interface_config_get(&phy_access[0], 0,0, &config); 7203 if (rv) return (rv); 7204 7205 *speed = config.data_rate; 7206 return (rv); 7207 } 7208 7209 int pm4x10_port_phy_reg_read(int unit, int port, pm_info_t pm_info, int lane, int flags, int reg_addr, uint32* value) 7210 { 7211 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7212 int nof_phys; 7213 SOC_INIT_FUNC_DEFS; 7214 7215 _SOC_IF_ERR_EXIT 7216 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7217 phy_access ,(1+MAX_PHYN), 7218 &nof_phys)); 7219 _SOC_IF_ERR_EXIT 7220 (portmod_port_phychain_reg_read(unit, port, phy_access, nof_phys, lane, flags, reg_addr,value)); 7221 7222 exit: 7223 SOC_FUNC_RETURN; 7224 } 7225 7226 int pm4x10_port_phy_reg_write(int unit, int port, pm_info_t pm_info, int lane, int flags, int reg_addr, uint32 value) 7227 { 7228 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7229 int nof_phys; 7230 SOC_INIT_FUNC_DEFS; 7231 7232 _SOC_IF_ERR_EXIT 7233 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7234 phy_access ,(1+MAX_PHYN), 7235 &nof_phys)); 7236 _SOC_IF_ERR_EXIT 7237 (portmod_port_phychain_reg_write(unit, port, phy_access, nof_phys, lane, flags, reg_addr,value)); 7238 7239 exit: 7240 SOC_FUNC_RETURN; 7241 } 7242 7243 int pm4x10_port_check_legacy_phy (int unit, int port, pm_info_t pm_info, int *legacy_phy) 7244 { 7245 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7246 int nof_phys, xphy_id, is_legacy_phy; 7247 int port_index; 7248 uint32 bitmap; 7249 7250 SOC_INIT_FUNC_DEFS; 7251 7252 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 7253 &bitmap)); 7254 7255 *legacy_phy = 0; 7256 7257 if (PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 7258 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7259 (_SOC_MSG("phy reset is not supported"))); 7260 } 7261 7262 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 7263 phy_access ,(1+MAX_PHYN), 7264 &nof_phys)); 7265 while (nof_phys > 1) { 7266 nof_phys--; 7267 xphy_id = phy_access[nof_phys].access.addr; 7268 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 7269 if (is_legacy_phy) { 7270 *legacy_phy = 1; 7271 break; 7272 } 7273 } 7274 7275 exit: 7276 SOC_FUNC_RETURN; 7277 } 7278 7279 int pm4x10_port_reset_set (int unit, int port, pm_info_t pm_info, 7280 int reset_mode, int opcode, int direction) 7281 { 7282 phymod_core_access_t core_access[1+MAX_PHYN]; 7283 int nof_phys; 7284 int port_index; 7285 uint32 bitmap; 7286 7287 SOC_INIT_FUNC_DEFS; 7288 7289 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 7290 &bitmap)); 7291 7292 if (PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 7293 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7294 (_SOC_MSG("phy reset is not supported"))); 7295 } 7296 7297 _SOC_IF_ERR_EXIT 7298 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7299 (phymod_phy_access_t*)core_access, 7300 (1+MAX_PHYN), &nof_phys)); 7301 7302 _SOC_IF_ERR_EXIT 7303 (portmod_port_phychain_core_reset_set(unit, core_access, nof_phys, 7304 (phymod_reset_mode_t)reset_mode, 7305 (phymod_reset_direction_t)direction)); 7306 7307 exit: 7308 SOC_FUNC_RETURN; 7309 } 7310 7311 int pm4x10_port_reset_get (int unit, int port, pm_info_t pm_info, 7312 int reset_mode, int opcode, int* direction) 7313 { 7314 phymod_core_access_t core_access[1+MAX_PHYN]; 7315 int nof_phys; 7316 int port_index; 7317 uint32 bitmap; 7318 7319 SOC_INIT_FUNC_DEFS; 7320 7321 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 7322 &bitmap)); 7323 7324 if (PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 7325 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 7326 (_SOC_MSG("phy reset is not supported"))); 7327 } 7328 7329 _SOC_IF_ERR_EXIT 7330 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7331 (phymod_phy_access_t*)core_access, 7332 (1+MAX_PHYN), &nof_phys)); 7333 7334 _SOC_IF_ERR_EXIT 7335 (portmod_port_phychain_core_reset_get(unit, core_access, nof_phys, 7336 (phymod_reset_mode_t)reset_mode, 7337 (phymod_reset_direction_t*)direction)); 7338 7339 exit: 7340 SOC_FUNC_RETURN; 7341 } 7342 7343 /*Port remote Adv get*/ 7344 int pm4x10_port_adv_remote_get (int unit, int port, pm_info_t pm_info, 7345 int* ability_mask) 7346 { 7347 return (0); 7348 } 7349 7350 /*get port fec enable*/ 7351 int pm4x10_port_fec_enable_get(int unit, int port, pm_info_t pm_info, 7352 uint32 phy_flags, uint32_t* enable) 7353 { 7354 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7355 int nof_phys = 0; 7356 7357 SOC_INIT_FUNC_DEFS; 7358 7359 _SOC_IF_ERR_EXIT 7360 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7361 phy_access ,(1+MAX_PHYN), 7362 &nof_phys)); 7363 7364 _SOC_IF_ERR_EXIT 7365 (portmod_port_phychain_fec_enable_get(unit, port, phy_access, nof_phys, phy_flags, enable)); 7366 7367 exit: 7368 SOC_FUNC_RETURN; 7369 } 7370 7371 /*set port fec enable*/ 7372 int pm4x10_port_fec_enable_set(int unit, int port, pm_info_t pm_info, 7373 uint32 phy_flags, uint32_t enable) 7374 { 7375 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7376 int nof_phys = 0; 7377 7378 SOC_INIT_FUNC_DEFS; 7379 7380 _SOC_IF_ERR_EXIT 7381 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7382 phy_access ,(1+MAX_PHYN), 7383 &nof_phys)); 7384 7385 _SOC_IF_ERR_EXIT 7386 (portmod_port_phychain_fec_enable_set(unit, port, phy_access, nof_phys, phy_flags, enable)); 7387 7388 exit: 7389 SOC_FUNC_RETURN; 7390 } 7391 7392 /*get port auto negotiation local ability*/ 7393 int pm4x10_port_ability_advert_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 7394 portmod_port_ability_t* ability) 7395 { 7396 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7397 phymod_autoneg_ability_t an_ability; 7398 portmod_port_ability_t port_ability; 7399 7400 int nof_phys = 0, port_index, flags; 7401 uint32 bitmap; 7402 int rv; 7403 int phy_index, xphy_id, is_legacy_phy; 7404 7405 SOC_INIT_FUNC_DEFS; 7406 7407 sal_memset(&port_ability, 0, sizeof(portmod_port_ability_t)); 7408 phymod_autoneg_ability_t_init(&an_ability); 7409 7410 _SOC_IF_ERR_EXIT 7411 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7412 phy_access ,(1+MAX_PHYN), 7413 &nof_phys)); 7414 _SOC_IF_ERR_EXIT 7415 (portmod_port_phychain_autoneg_ability_get(unit, port, phy_access, nof_phys, phy_flags, 7416 &an_ability, &port_ability)); 7417 phy_index = nof_phys -1; 7418 if (phy_index) { 7419 xphy_id = phy_access[phy_index].access.addr; 7420 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 7421 7422 if (is_legacy_phy) { 7423 sal_memcpy(ability, &port_ability, sizeof(portmod_port_ability_t)); 7424 } 7425 7426 } else { 7427 /* 7428 * SGMII speed should be initialized to count but is initialized to 0 7429 * which is treated as 10M. so for sesto mask this out. 7430 */ 7431 if (nof_phys > 1) { 7432 #ifdef PHYMOD_SESTO_SUPPORT 7433 if (phy_access[nof_phys-1].type == phymodDispatchTypeSesto) { 7434 an_ability.sgmii_speed = phymod_CL37_SGMII_Count; 7435 } 7436 #endif /* PHYMOD_SESTO_SUPPORT */ 7437 } 7438 portmod_common_phy_to_port_ability(&an_ability, ability); 7439 } 7440 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 7441 &bitmap)); 7442 7443 rv = PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &ability->interface, 7444 port_index); 7445 _SOC_IF_ERR_EXIT(rv); 7446 7447 _SOC_IF_ERR_EXIT(xlmac_encap_get (unit, port, &flags, &ability->encap)); 7448 7449 exit: 7450 SOC_FUNC_RETURN; 7451 } 7452 7453 /* 7454 * Function: 7455 * _pm4x10_port_to_phy_ability 7456 * Purpose: 7457 * This function will translate the portAbility request, which passed 7458 * from BCM api to anAbility format required by phymod api. 7459 * 7460 * Parameters: 7461 * portAbility -(IN) port an ability request from BCM Api 7462 * anAbility -(OUT) phymod an ability to phymod api. 7463 * port_num_lanes -(IN) number of lane 7464 * line_interface -(IN) line interface 7465 * cx4_10g -(IN) cx4 port 7466 * an_cl72 -(IN) an cl72 configuration 7467 * an_fec -(IN) fec configuration 7468 * an_hg_mode -(IN) hg_mode 7469 * Returns: 7470 * None 7471 */ 7472 7473 void _pm4x10_port_to_phy_ability (portmod_port_ability_t *portAbility, 7474 phymod_autoneg_ability_t *anAbility, 7475 int port_num_lanes, 7476 int line_interface, 7477 int cx4_10g, 7478 int an_cl72, 7479 int an_fec, 7480 int hg_mode) 7481 { 7482 uint32_t an_tech_ability = 0; 7483 uint32_t an_bam37_ability = 0; 7484 uint32_t an_bam73_ability = 0; 7485 _shr_port_mode_t speed_full_duplex = portAbility->speed_full_duplex; 7486 phymod_autoneg_ability_t_init(anAbility); 7487 7488 /* 7489 * an_tech_ability 7490 */ 7491 if (port_num_lanes == 10 || 7492 port_num_lanes == 12 ) { 7493 if (speed_full_duplex & SOC_PA_SPEED_100GB) { 7494 PHYMOD_AN_CAP_100G_CR10_SET(an_tech_ability); 7495 } 7496 } else if (port_num_lanes == 4) { 7497 if (speed_full_duplex & SOC_PA_SPEED_100GB) { 7498 /* 7499 * This is only possible for port with external 7500 * phy in gearbox mode. 7501 */ 7502 if (portAbility->medium) { 7503 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 7504 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 7505 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 7506 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 7507 } else { 7508 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 7509 } 7510 } else { 7511 if (line_interface == SOC_PORT_IF_CR4){ 7512 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 7513 } else { 7514 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 7515 } 7516 } 7517 } 7518 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 7519 7520 if (portAbility->medium) { 7521 /* 7522 * If the medium is defined, medium configuration will be 7523 * used to determine which interface to advertise. 7524 */ 7525 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 7526 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 7527 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 7528 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 7529 } else { 7530 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 7531 } 7532 } else { 7533 /* 7534 * If the medium is not defined, it will look at line 7535 * interface. This case is for backward compatiblility 7536 * during transition time, will remove this support later. 7537 */ 7538 if (line_interface ==SOC_PORT_IF_CR4) { 7539 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 7540 } else { 7541 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 7542 } 7543 } 7544 } 7545 7546 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 7547 PHYMOD_AN_CAP_10G_KX4_SET(an_tech_ability); 7548 } 7549 } else if (port_num_lanes == 1) { 7550 /* port_num_lanes == 1 */ 7551 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 7552 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 7553 } 7554 if (speed_full_duplex & SOC_PA_SPEED_2500MB) { 7555 PHYMOD_AN_CAP_2P5G_X_SET(an_tech_ability); 7556 } 7557 if (speed_full_duplex & SOC_PA_SPEED_5000MB) { 7558 PHYMOD_AN_CAP_5G_KR1_SET(an_tech_ability); 7559 } 7560 if (speed_full_duplex & SOC_PA_SPEED_1000MB) { 7561 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 7562 } 7563 } 7564 7565 /* 7566 * an_bam73_ability 7567 */ 7568 if (port_num_lanes == 2) { /* 2 lanes */ 7569 if (speed_full_duplex & SOC_PA_SPEED_20GB) { 7570 if (portAbility->medium) { 7571 if (portAbility->medium & SOC_PA_MEDIUM_BACKPLANE) { 7572 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 7573 } else if (portAbility->medium & SOC_PA_MEDIUM_COPPER) { 7574 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 7575 } else { 7576 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 7577 } 7578 } else { 7579 if (line_interface ==SOC_PORT_IF_CR2) { 7580 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 7581 } else { 7582 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 7583 } 7584 } 7585 } 7586 } 7587 7588 /* 7589 * an_bam37_ability 7590 */ 7591 if (port_num_lanes == 4) { 7592 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 7593 PHYMOD_BAM_CL37_CAP_40G_SET(an_bam37_ability); 7594 } 7595 7596 if (speed_full_duplex & SOC_PA_SPEED_30GB) { 7597 PHYMOD_BAM_CL37_CAP_31P5G_SET(an_bam37_ability); 7598 } 7599 7600 if (speed_full_duplex & SOC_PA_SPEED_25GB) { 7601 PHYMOD_BAM_CL37_CAP_25P455G_SET(an_bam37_ability); 7602 } 7603 7604 if (speed_full_duplex & SOC_PA_SPEED_21GB) { 7605 PHYMOD_BAM_CL37_CAP_21G_X4_SET(an_bam37_ability); 7606 } 7607 7608 if (speed_full_duplex & SOC_PA_SPEED_20GB) { 7609 PHYMOD_BAM_CL37_CAP_20G_X4_SET(an_bam37_ability); 7610 PHYMOD_BAM_CL37_CAP_20G_X4_CX4_SET(an_bam37_ability); 7611 } 7612 7613 if (speed_full_duplex & SOC_PA_SPEED_16GB) { 7614 PHYMOD_BAM_CL37_CAP_16G_X4_SET(an_bam37_ability); 7615 } 7616 7617 if (speed_full_duplex & SOC_PA_SPEED_15GB) { 7618 PHYMOD_BAM_CL37_CAP_15G_X4_SET(an_bam37_ability); 7619 } 7620 7621 if (speed_full_duplex & SOC_PA_SPEED_13GB) { 7622 PHYMOD_BAM_CL37_CAP_13G_X4_SET(an_bam37_ability); 7623 } 7624 7625 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 7626 if (cx4_10g) { 7627 PHYMOD_BAM_CL37_CAP_10G_CX4_SET(an_bam37_ability); 7628 } else { 7629 PHYMOD_BAM_CL37_CAP_10G_HIGIG_SET(an_bam37_ability); 7630 } 7631 } 7632 7633 } else if (port_num_lanes == 2) { /* 2 lanes */ 7634 7635 if (speed_full_duplex & SOC_PA_SPEED_20GB){ 7636 if (hg_mode) { 7637 PHYMOD_BAM_CL37_CAP_20G_X2_SET(an_bam37_ability); 7638 } else { 7639 PHYMOD_BAM_CL37_CAP_20G_X2_CX4_SET(an_bam37_ability); 7640 } 7641 } 7642 7643 if (speed_full_duplex & SOC_PA_SPEED_16GB) { 7644 PHYMOD_BAM_CL37_CAP_15P75G_R2_SET(an_bam37_ability); 7645 } 7646 7647 if (speed_full_duplex & SOC_PA_SPEED_13GB) { 7648 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_bam37_ability); 7649 } 7650 7651 if (speed_full_duplex & SOC_PA_SPEED_11GB) { 7652 PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_SET(an_bam37_ability); 7653 } 7654 7655 if (speed_full_duplex & SOC_PA_SPEED_10GB) { 7656 PHYMOD_BAM_CL37_CAP_10G_X2_CX4_SET(an_bam37_ability); 7657 PHYMOD_BAM_CL37_CAP_10G_DXGXS_SET(an_bam37_ability); 7658 } 7659 } else if (port_num_lanes == 1) { 7660 7661 if (speed_full_duplex & SOC_PA_SPEED_2500MB) { 7662 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_bam37_ability); 7663 } 7664 } 7665 7666 anAbility->an_cap = an_tech_ability; 7667 anAbility->cl73bam_cap = an_bam73_ability; 7668 anAbility->cl37bam_cap = an_bam37_ability; 7669 7670 switch (portAbility->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 7671 case SOC_PA_PAUSE_TX: 7672 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 7673 break; 7674 case SOC_PA_PAUSE_RX: 7675 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 7676 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 7677 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 7678 break; 7679 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 7680 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 7681 break; 7682 } 7683 7684 if ((speed_full_duplex & SOC_PA_SPEED_10MB) || 7685 (speed_full_duplex & SOC_PA_SPEED_100MB) || 7686 (speed_full_duplex & SOC_PA_SPEED_1000MB)) { 7687 if (portAbility->medium) { 7688 if (!(portAbility->medium & SOC_PA_MEDIUM_FIBER)) { 7689 7690 PHYMOD_AN_CAP_SGMII_SET(anAbility); 7691 7692 /* also set the sgmii speed */ 7693 if (portAbility->speed_full_duplex & SOC_PA_SPEED_1000MB) { 7694 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 7695 } else if (portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 7696 anAbility->sgmii_speed = phymod_CL37_SGMII_100M; 7697 } else if (portAbility->speed_full_duplex & SOC_PA_SPEED_10MB) { 7698 anAbility->sgmii_speed = phymod_CL37_SGMII_10M; 7699 } else { 7700 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 7701 } 7702 } 7703 } else { 7704 if (SOC_PORT_IF_SGMII == line_interface) { 7705 7706 PHYMOD_AN_CAP_SGMII_SET(anAbility); 7707 7708 /* also set the sgmii speed */ 7709 if (portAbility->speed_full_duplex & SOC_PA_SPEED_1000MB) { 7710 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 7711 } else if (portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 7712 anAbility->sgmii_speed = phymod_CL37_SGMII_100M; 7713 } else if (portAbility->speed_full_duplex & SOC_PA_SPEED_10MB) { 7714 anAbility->sgmii_speed = phymod_CL37_SGMII_10M; 7715 } else { 7716 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 7717 } 7718 } else { 7719 if (portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 7720 PHYMOD_AN_CAP_100M_SET(anAbility->an_cap); 7721 } 7722 } 7723 } 7724 } 7725 7726 /* next check if we need to set cl37 attribute */ 7727 if (an_cl72) { 7728 anAbility->an_cl72 = 1; 7729 } 7730 if (hg_mode) { 7731 anAbility->an_hg2 = 1; 7732 } 7733 7734 /* 7735 * check if Cl74 fec is requested from AN BCM api. 7736 */ 7737 if (portAbility->fec & SOC_PA_FEC_NONE) { 7738 PHYMOD_AN_FEC_OFF_SET(anAbility->an_fec); 7739 } else if ((an_fec == 1) || portAbility->fec & SOC_PA_FEC_CL74) { 7740 /* The 'phy_an_fec=1' and FEC CL74 ability are all the phymod FEC CL74. */ 7741 PHYMOD_AN_FEC_CL74_SET(anAbility->an_fec); 7742 } 7743 7744 } 7745 7746 int pm4x10_port_ability_advert_set(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 7747 portmod_port_ability_t* ability) 7748 { 7749 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7750 int nof_phys = 0, port_index, rv; 7751 uint32_t bitmap, interface_modes; 7752 portmod_port_ability_t port_ability; 7753 phymod_autoneg_ability_t an_ability; 7754 portmod_access_get_params_t params; 7755 7756 int port_num_lanes, line_interface, cx4_10g; 7757 soc_port_if_t temp_line_intf; 7758 int an_cl72, an_fec, hg_mode; 7759 int total_num_lanes = 0; 7760 int line_side; 7761 SOC_INIT_FUNC_DEFS; 7762 7763 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 7764 &bitmap)); 7765 7766 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 7767 params.lane = -1; 7768 params.phyn = 0; 7769 params.sys_side = PORTMOD_SIDE_LINE; 7770 7771 _SOC_IF_ERR_EXIT 7772 (pm4x10_port_ability_local_get(unit, port, pm_info, phy_flags, &port_ability)); 7773 7774 /* Make sure to advertise only abilities supported by the port */ 7775 port_ability.pause &= ability->pause; 7776 port_ability.interface &= ability->interface; 7777 port_ability.medium &= ability->medium; 7778 port_ability.eee &= ability->eee; 7779 port_ability.loopback &= ability->loopback; 7780 port_ability.flags &= ability->flags; 7781 port_ability.speed_half_duplex &= ability->speed_half_duplex; 7782 port_ability.speed_full_duplex &= ability->speed_full_duplex; 7783 port_ability.fec &= ability->fec; 7784 port_ability.channel &= ability->channel; 7785 7786 /* coverity[Out-of-bounds access:FALSE] */ 7787 SHR_BITCOUNT_RANGE(&bitmap, port_num_lanes, 0, PM4X10_LANES_PER_CORE); 7788 rv = PM4x10_INTERFACE_TYPE_GET(unit, pm_info, &line_interface, port_index); 7789 _SOC_IF_ERR_EXIT(rv); 7790 rv = PM4x10_CX4_10G_GET(unit, pm_info, &cx4_10g, port_index); 7791 _SOC_IF_ERR_EXIT(rv); 7792 rv = PM4x10_AN_CL72_GET(unit, pm_info, &an_cl72, port_index); 7793 _SOC_IF_ERR_EXIT(rv); 7794 rv = PM4x10_AN_FEC_GET(unit, pm_info, &an_fec, port_index); 7795 _SOC_IF_ERR_EXIT(rv); 7796 rv = PM4x10_INTERFACE_MODES_GET(unit, pm_info, &interface_modes, 7797 port_index); 7798 _SOC_IF_ERR_EXIT(rv); 7799 hg_mode = (interface_modes & PHYMOD_INTF_MODES_HIGIG)? 1: 0; 7800 7801 7802 _SOC_IF_ERR_EXIT 7803 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7804 phy_access ,(1+MAX_PHYN), 7805 &nof_phys)); 7806 7807 /* 7808 * if line interface is CAUI -- check it is 4x25 or 10x10 7809 * change the line interface for this purpose. 7810 * 7811 * Default interface for 100G is CR10. However if line interface is Falcon 7812 * the interface should be CR4 (not CR10). Fix the line interface here.., 7813 */ 7814 if (nof_phys > 1) { 7815 portmod_port_line_interface_map_for_xphy(unit, &(phy_access[nof_phys-1]), port, line_interface, &temp_line_intf); 7816 line_interface = temp_line_intf; 7817 } 7818 7819 /* 7820 * Get the total number of line side lanes, if it is triple core mode (PM12x10). 7821 * and update the port_num_lanes with the new count. 7822 */ 7823 7824 if (interface_modes & PHYMOD_INTF_MODES_TRIPLE_CORE) { 7825 line_side = TRUE ; 7826 _SOC_IF_ERR_EXIT 7827 (portmod_port_lane_count_get(unit, port, line_side, 7828 &total_num_lanes)); 7829 port_num_lanes = total_num_lanes; 7830 } 7831 7832 _pm4x10_port_to_phy_ability(&port_ability, &an_ability, 7833 port_num_lanes, line_interface, cx4_10g, 7834 an_cl72, an_fec, hg_mode); 7835 7836 rv = PM4x10_AN_MASTER_LANE_GET(unit, pm_info, &an_ability.an_master_lane, 7837 port_index); 7838 _SOC_IF_ERR_EXIT(rv); 7839 7840 _SOC_IF_ERR_EXIT 7841 (portmod_port_phychain_autoneg_ability_set(unit, port, phy_access, nof_phys, phy_flags, &an_ability, &port_ability)); 7842 7843 LOG_VERBOSE(BSL_LS_BCM_PORT, 7844 (BSL_META_U(unit, 7845 "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x orig(HD=0x%08x, FD=0x%08x) \n" 7846 "Interface=0x%08x Medium=0x%08x Loopback=0x%08x Flags=0x%08x\n"), 7847 port_ability.speed_half_duplex, 7848 port_ability.speed_full_duplex, 7849 port_ability.pause, 7850 ability->speed_half_duplex, 7851 ability->speed_full_duplex, 7852 port_ability.interface, 7853 port_ability.medium, port_ability.loopback, 7854 port_ability.flags)); 7855 exit: 7856 SOC_FUNC_RETURN; 7857 } 7858 7859 /*Port ability remote Adv get*/ 7860 int pm4x10_port_ability_remote_get(int unit, int port, pm_info_t pm_info, uint32 phy_flags, 7861 portmod_port_ability_t* ability) 7862 { 7863 phymod_phy_access_t phy_access[1+MAX_PHYN]; 7864 int nof_phys; 7865 phymod_autoneg_ability_t an_ability; 7866 int phy_index, xphy_id, is_legacy_phy = 0; 7867 7868 SOC_INIT_FUNC_DEFS; 7869 7870 phymod_autoneg_ability_t_init(&an_ability); 7871 7872 _SOC_IF_ERR_EXIT 7873 (portmod_port_chain_phy_access_get(unit, port, pm_info, 7874 phy_access ,(1+MAX_PHYN), 7875 &nof_phys)); 7876 7877 phy_index = nof_phys -1; 7878 if (phy_index) { 7879 xphy_id = phy_access[phy_index].access.addr; 7880 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy)); 7881 } 7882 _SOC_IF_ERR_EXIT 7883 (portmod_port_phychain_autoneg_remote_ability_get(unit, port, phy_access, nof_phys, phy_flags, &an_ability, ability)); 7884 if (!is_legacy_phy) { 7885 portmod_common_phy_to_port_ability(&an_ability, ability); 7886 } 7887 7888 exit: 7889 SOC_FUNC_RETURN; 7890 } 7891 7892 int _xlport_rx_control_set(int unit, int port, int value) 7893 { 7894 int rv = SOC_E_UNAVAIL; 7895 uint32 rval32 = 0; 7896 7897 if (SOC_REG_IS_VALID(unit,XLPORT_MAC_RSV_MASKr)) { 7898 rv = READ_XLPORT_MAC_RSV_MASKr(unit, port, &rval32); 7899 if (SOC_SUCCESS(rv)) { 7900 /* XLPORT_MAC_RSV_MASK: Bit 11 Control Frame recieved 7901 * Enable Control Frame : Set 0. Packet go through 7902 * Disable Control Frame : Set 1. Packet is purged. 7903 */ 7904 if(value) { 7905 rval32 &= ~(1 << 11); 7906 } else { 7907 rval32 |= (1 << 11); 7908 } 7909 rv = WRITE_XLPORT_MAC_RSV_MASKr(unit, port, rval32); 7910 } 7911 } 7912 7913 return rv; 7914 } 7915 7916 int pm4x10_port_rx_control_set (int unit, int port, pm_info_t pm_info, 7917 const portmod_rx_control_t* rx_ctrl) 7918 { 7919 int phy_acc; 7920 uint32 reg_val; 7921 7922 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7923 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_RSV_MASKr(unit, phy_acc, ®_val)); 7924 7925 if (rx_ctrl->flags & PORTMOD_MAC_PASS_CONTROL_FRAME) { 7926 if (rx_ctrl->pass_control_frames) { 7927 reg_val &= ~(1 << 11); 7928 } else{ 7929 reg_val |= (1 << 11); 7930 } 7931 } 7932 7933 if (rx_ctrl->flags & PORTMOD_MAC_PASS_PFC_FRAME) { 7934 if (rx_ctrl->pass_pfc_frames) { 7935 reg_val &= ~(1 << 18); 7936 } else{ 7937 reg_val |= (1 << 18); 7938 } 7939 } 7940 7941 if (rx_ctrl->flags & PORTMOD_MAC_PASS_PAUSE_FRAME) { 7942 if (rx_ctrl->pass_pause_frames) { 7943 reg_val &= ~(1 << 12); 7944 } else{ 7945 reg_val |= (1 << 12); 7946 } 7947 } 7948 7949 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_RSV_MASKr(unit, phy_acc, reg_val)); 7950 7951 return (SOC_E_NONE); 7952 } 7953 7954 int pm4x10_port_rx_control_get (int unit, int port, pm_info_t pm_info, 7955 portmod_rx_control_t* rx_ctrl) 7956 { 7957 int phy_acc; 7958 uint32 reg_val; 7959 7960 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 7961 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_RSV_MASKr(unit, phy_acc, ®_val)); 7962 rx_ctrl->pass_control_frames = ((reg_val & 0x800) >> 11) ? 0 : 1; 7963 rx_ctrl->pass_pfc_frames = ((reg_val & 0x40000) >> 18) ? 0 : 1; 7964 rx_ctrl->pass_pause_frames = ((reg_val & 0x1000) >> 12) ? 0 : 1; 7965 7966 return (SOC_E_NONE); 7967 } 7968 7969 int pm4x10_port_tx_mac_sa_set(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 7970 { 7971 return (xlmac_tx_mac_sa_set(unit, port, mac_addr)); 7972 } 7973 7974 7975 int pm4x10_port_tx_mac_sa_get(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 7976 { 7977 return (xlmac_tx_mac_sa_get(unit, port, mac_addr)); 7978 } 7979 7980 int pm4x10_port_rx_mac_sa_set(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 7981 { 7982 return (xlmac_rx_mac_sa_set(unit, port, mac_addr)); 7983 } 7984 7985 7986 int pm4x10_port_rx_mac_sa_get(int unit, int port, pm_info_t pm_info, sal_mac_addr_t mac_addr) 7987 { 7988 return (xlmac_rx_mac_sa_get(unit, port, mac_addr)); 7989 } 7990 7991 int pm4x10_port_tx_average_ipg_set (int unit, int port, 7992 pm_info_t pm_info, int value) 7993 { 7994 return (xlmac_tx_average_ipg_set(unit, port, value)); 7995 } 7996 7997 7998 int pm4x10_port_tx_average_ipg_get (int unit, int port, 7999 pm_info_t pm_info, int* value) 8000 { 8001 return (xlmac_tx_average_ipg_get(unit, port, value)); 8002 } 8003 8004 int pm4x10_port_update (int unit, int port, pm_info_t pm_info, 8005 const portmod_port_update_control_t* update_control) 8006 { 8007 int link, flags = 0; 8008 int duplex = 0, tx_pause = 0, rx_pause = 0; 8009 phymod_autoneg_status_t autoneg; 8010 portmod_pause_control_t pause_control; 8011 portmod_port_ability_t local_advert, remote_advert; 8012 portmod_port_interface_config_t interface_config; 8013 int port_index, ref_clock, max_speed; 8014 uint32_t bitmap; 8015 phymod_phy_inf_config_t phy_interface_config; 8016 soc_port_if_t interface = SOC_PORT_IF_NULL; 8017 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8018 int nof_phys; 8019 int is_xlmac_en = 0; 8020 portmod_port_ts_adjust_t ts_adjust; 8021 8022 int sys_start_lane = -1; 8023 int sys_end_lane = -1; 8024 int line_start_lane = -1; 8025 int line_end_lane=-1; 8026 uint32 int_lane_mask=0xf; 8027 uint32_t serdes_link_status=0; 8028 phymod_phy_rx_lane_control_t rx_control; 8029 uint32 port_dynamic_state = 0; 8030 int mac_ts_enable; 8031 SOC_INIT_FUNC_DEFS; 8032 8033 _SOC_IF_ERR_EXIT(phymod_autoneg_status_t_init(&autoneg)); 8034 _SOC_IF_ERR_EXIT(portmod_pause_control_t_init(unit, &pause_control)); 8035 sal_memset(&local_advert, 0, sizeof(portmod_port_ability_t)); 8036 sal_memset(&remote_advert, 0, sizeof(portmod_port_ability_t)); 8037 sal_memset(&ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 8038 8039 _SOC_IF_ERR_EXIT 8040 (portmod_port_chain_phy_access_get(unit, port, pm_info, 8041 phy_access ,(1+MAX_PHYN), 8042 &nof_phys)); 8043 8044 if(update_control->link_status == -1) { 8045 _SOC_IF_ERR_EXIT(pm4x10_port_link_get(unit, port, pm_info,PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &link)); 8046 } else { 8047 link = update_control->link_status; 8048 } 8049 8050 _SOC_IF_ERR_EXIT(pm4x10_port_autoneg_status_get(unit, port, pm_info, &autoneg)); 8051 8052 /* 8053 * Update the interface type stored in the SW database when the port is in the AN mode 8054 * and link is up. The update has to be done before any possible early return in this 8055 * function or portmod_port_interface_config_get() will get outdated interface type 8056 * causing "BCM.0> ps" to show outdated interface types in the AN mode. 8057 */ 8058 if (link && autoneg.enabled && autoneg.locked) { 8059 /* update interface*/ 8060 _SOC_IF_ERR_EXIT(phymod_phy_inf_config_t_init(&phy_interface_config)); 8061 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 8062 _SOC_IF_ERR_EXIT(PM4x10_MAX_SPEED_GET(unit, pm_info, &max_speed, port_index)); 8063 8064 ref_clock = PM_4x10_INFO(pm_info)->ref_clk; 8065 phy_interface_config.data_rate = max_speed; 8066 phy_interface_config.ref_clock = ref_clock; 8067 _SOC_IF_ERR_EXIT 8068 (portmod_port_phychain_interface_config_get(unit, port, phy_access, nof_phys, 8069 0, ref_clock, &phy_interface_config, 8070 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 8071 _SOC_IF_ERR_EXIT 8072 (portmod_intf_from_phymod_intf(unit, phy_interface_config.interface_type, &interface)); 8073 _SOC_IF_ERR_EXIT 8074 (PM4x10_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 8075 _SOC_IF_ERR_EXIT 8076 (PM4x10_OUTMOST_PHY_INTERFACE_TYPE_SET(unit, pm_info, interface, port_index)); 8077 } 8078 8079 /* Following code applies to the phy 54290 */ 8080 if (PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK_GET(update_control)){ 8081 _SOC_IF_ERR_EXIT(_pm4x10_port_tricore_lane_info_get(unit, port, pm_info, 8082 &sys_start_lane, &sys_end_lane, 8083 &line_start_lane, &line_end_lane, 8084 &int_lane_mask, NULL)); 8085 /* only look at the lanes that are used. */ 8086 phy_access[0].access.lane_mask &= int_lane_mask; 8087 8088 if (nof_phys > 1){ 8089 _SOC_IF_ERR_EXIT 8090 (phymod_phy_link_status_get(&phy_access[0],&serdes_link_status)); 8091 8092 if(link) { 8093 _SOC_IF_ERR_EXIT 8094 (phymod_phy_rx_lane_control_get(&phy_access[0],&rx_control)); 8095 if(rx_control == phymodRxSquelchOn){ 8096 phymod_phy_rx_lane_control_set(&phy_access[0], 8097 phymodRxSquelchOff); 8098 } 8099 } else { 8100 /* if external phy and link is down, internal serdes link is up, 8101 force internal SerDes link to be down. */ 8102 if(serdes_link_status){ 8103 phymod_phy_rx_lane_control_set(&phy_access[0], 8104 phymodRxSquelchOn); 8105 phymod_phy_rx_lane_control_set(&phy_access[0], 8106 phymodRxSquelchOff); 8107 } 8108 } 8109 } 8110 8111 /* 8112 * PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK is set for XGS devices. Since XGS devices 8113 * already update their MAC registers elsewhere, there is an early return below to 8114 * avoid redundant works. 8115 */ 8116 return (SOC_E_NONE); 8117 } 8118 8119 if(!link) { 8120 /* PHY is down. Disable the MAC. */ 8121 if (PORTMOD_PORT_UPDATE_F_DISABLE_MAC_GET(update_control)) { 8122 _SOC_IF_ERR_EXIT(xlmac_enable_set(unit, port, 0, 0)); 8123 } 8124 8125 /* TBD - do we need phymod_link_down_event ? */ 8126 } else { 8127 _SOC_IF_ERR_EXIT(xlmac_enable_get(unit, port, 0, &is_xlmac_en)); 8128 if (is_xlmac_en == 0) { 8129 _SOC_IF_ERR_EXIT(xlmac_enable_set(unit, port, 0, 1)); 8130 if(PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 8131 _SOC_IF_ERR_EXIT(pm4x10_port_soft_reset(unit, port, pm_info, 0)); 8132 } 8133 } 8134 8135 /* TBD - do we need phymod_link_up_event ? */ 8136 8137 if(autoneg.enabled && autoneg.locked) { 8138 /* update MAC */ 8139 _SOC_IF_ERR_EXIT(pm4x10_port_interface_config_get(unit, port, pm_info, &interface_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 8140 flags = XLMAC_SPEED_SET_FLAGS_SOFT_RESET_DIS; 8141 _SOC_IF_ERR_EXIT(xlmac_speed_set(unit, port, flags, interface_config.speed)); 8142 8143 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 8144 _SOC_IF_ERR_EXIT(pm4x10_port_mac_timestamp_enable_get(unit, port, pm_info, 8145 &mac_ts_enable)); 8146 } else { 8147 mac_ts_enable = 1; 8148 } 8149 if (mac_ts_enable) { 8150 /*Set MAC Timestamp Delay*/ 8151 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 8152 _SOC_IF_ERR_EXIT(PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, &port_dynamic_state, port_index)); 8153 8154 if (!PORTMOD_PORT_IS_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED(port_dynamic_state)) { 8155 _SOC_IF_ERR_EXIT 8156 (_pm4x10_port_timestamp_adjust_wb_get(unit, 8157 port, 8158 pm_info, 8159 interface_config.speed, 8160 &ts_adjust)); 8161 _SOC_IF_ERR_EXIT 8162 (xlmac_timestamp_delay_set(unit, 8163 port, 8164 ts_adjust, 8165 interface_config.speed)); 8166 } 8167 _SOC_IF_ERR_EXIT(xlmac_timestamp_byte_adjust_set(unit, port, 0, interface_config.speed)); 8168 } 8169 8170 if(PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 8171 _SOC_IF_ERR_EXIT(pm4x10_port_soft_reset(unit, port, pm_info, 0)); 8172 } 8173 /* update pause in MAC on the base of local and remote pause ability*/ 8174 _SOC_IF_ERR_EXIT(pm4x10_port_duplex_get(unit, port, pm_info, &duplex)); 8175 _SOC_IF_ERR_EXIT(pm4x10_port_ability_advert_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_advert)); 8176 _SOC_IF_ERR_EXIT(pm4x10_port_ability_remote_get(unit, port, pm_info, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &remote_advert)); 8177 /* IEEE 802.3 Flow Control Resolution. 8178 * Please see $SDK/doc/pause-resolution.txt for more information. */ 8179 if (duplex) { 8180 tx_pause = \ 8181 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 8182 (local_advert.pause & SOC_PA_PAUSE_RX)) || \ 8183 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 8184 !(remote_advert.pause & SOC_PA_PAUSE_TX) && \ 8185 (local_advert.pause & SOC_PA_PAUSE_TX)); 8186 rx_pause = \ 8187 ((remote_advert.pause & SOC_PA_PAUSE_RX) && \ 8188 (local_advert.pause & SOC_PA_PAUSE_RX)) || \ 8189 ((local_advert.pause & SOC_PA_PAUSE_RX) && \ 8190 (remote_advert.pause & SOC_PA_PAUSE_TX) && \ 8191 !(local_advert.pause & SOC_PA_PAUSE_TX)); 8192 } 8193 else { 8194 rx_pause = tx_pause = 0; 8195 } 8196 _SOC_IF_ERR_EXIT(pm4x10_port_pause_control_get(unit, port, pm_info, &pause_control)); 8197 if ((pause_control.rx_enable != rx_pause) || (pause_control.tx_enable != tx_pause)) { 8198 pause_control.rx_enable = rx_pause; 8199 pause_control.tx_enable = tx_pause; 8200 _SOC_IF_ERR_EXIT(pm4x10_port_pause_control_set(unit, port, pm_info, &pause_control)); 8201 } 8202 } 8203 8204 _SOC_IF_ERR_EXIT(PM_DRIVER(pm_info)->f_portmod_port_lag_failover_status_toggle(unit, port, pm_info)); 8205 } 8206 8207 exit: 8208 SOC_FUNC_RETURN; 8209 } 8210 8211 int pm4x10_port_drv_name_get (int unit, int port, pm_info_t pm_info, 8212 char* buf, int len) 8213 { 8214 strncpy(buf, "PM4X10 Driver", len); 8215 return (SOC_E_NONE); 8216 } 8217 8218 int pm4x10_port_local_fault_status_clear(int unit, int port, pm_info_t pm_info) 8219 { 8220 int lcl_fault, rmt_fault; 8221 8222 SOC_IF_ERROR_RETURN (pm4x10_port_clear_rx_lss_status_get (unit, port, pm_info, &lcl_fault, &rmt_fault)); 8223 if (lcl_fault) { 8224 SOC_IF_ERROR_RETURN (pm4x10_port_clear_rx_lss_status_set(unit, port, pm_info, 0, rmt_fault)); 8225 } 8226 return (pm4x10_port_clear_rx_lss_status_set (unit, port, pm_info, 1, rmt_fault)); 8227 } 8228 8229 int pm4x10_port_remote_fault_status_clear(int unit, int port, pm_info_t pm_info) 8230 { 8231 int lcl_fault, rmt_fault; 8232 8233 SOC_IF_ERROR_RETURN (pm4x10_port_clear_rx_lss_status_get (unit, port, pm_info, &lcl_fault, &rmt_fault)); 8234 if (rmt_fault) { 8235 SOC_IF_ERROR_RETURN (pm4x10_port_clear_rx_lss_status_set(unit, port, pm_info, lcl_fault, 0)); 8236 } 8237 return (pm4x10_port_clear_rx_lss_status_set (unit, port, pm_info, lcl_fault, 1)); 8238 } 8239 8240 8241 int pm4x10_port_clear_rx_lss_status_set (int unit, soc_port_t port, 8242 pm_info_t pm_info, int lcl_fault, int rmt_fault) 8243 { 8244 return (xlmac_clear_rx_lss_status_set (unit, port, lcl_fault, rmt_fault)); 8245 } 8246 8247 int pm4x10_port_clear_rx_lss_status_get (int unit, soc_port_t port, 8248 pm_info_t pm_info, int *lcl_fault, int *rmt_fault) 8249 { 8250 return (xlmac_clear_rx_lss_status_get (unit, port, lcl_fault, rmt_fault)); 8251 } 8252 8253 int pm4x10_port_lag_failover_status_toggle (int unit, soc_port_t port, pm_info_t pm_info) 8254 { 8255 int phy_acc; 8256 uint32_t rval; 8257 int link = 0; 8258 soc_timeout_t to; 8259 8260 SOC_INIT_FUNC_DEFS; 8261 8262 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8263 8264 /* Link status to IPIPE is updated by H/W and driven based on both the 8265 * rising edge of XLPORT_LAG_FAILOVER_CONFIG.LINK_STATUS_UP and 8266 * actual link up status from Serdes. 8267 * In some loopback scenarios it may take longer time to see Serdes link up status. 8268 */ 8269 soc_timeout_init(&to, 10000, 0); 8270 8271 do { 8272 _SOC_IF_ERR_EXIT(pm4x10_port_mac_link_get(unit, port, pm_info, &link)); 8273 if (link) { 8274 break; 8275 } 8276 } while(!soc_timeout_check(&to)); 8277 8278 /* Toggle link_status_up bit to notify IPIPE on link up */ 8279 _SOC_IF_ERR_EXIT(READ_XLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, &rval)); 8280 soc_reg_field_set(unit, XLPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 1); 8281 _SOC_IF_ERR_EXIT(WRITE_XLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval)); 8282 soc_reg_field_set(unit, XLPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 0); 8283 _SOC_IF_ERR_EXIT(WRITE_XLPORT_LAG_FAILOVER_CONFIGr(unit, phy_acc, rval)); 8284 8285 exit: 8286 SOC_FUNC_RETURN; 8287 } 8288 8289 int pm4x10_port_lag_failover_loopback_set (int unit, soc_port_t port, 8290 pm_info_t pm_info, int value) 8291 { 8292 return (xlmac_lag_failover_loopback_set(unit, port, value)); 8293 } 8294 8295 int pm4x10_port_lag_failover_loopback_get (int unit, soc_port_t port, 8296 pm_info_t pm_info, int *value) 8297 { 8298 return(xlmac_lag_failover_loopback_get(unit, port, value)); 8299 } 8300 8301 int pm4x10_port_mode_set(int unit, soc_port_t port, 8302 pm_info_t pm_info, const portmod_port_mode_info_t *mode) 8303 { 8304 int phy_acc; 8305 SOC_INIT_FUNC_DEFS; 8306 8307 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8308 8309 _SOC_IF_ERR_EXIT(_xlport_mode_set(unit, phy_acc, mode->cur_mode)); 8310 8311 exit: 8312 SOC_FUNC_RETURN; 8313 } 8314 8315 int pm4x10_port_mode_get(int unit, soc_port_t port, 8316 pm_info_t pm_info, portmod_port_mode_info_t *mode) 8317 { 8318 int port_index, rv, phy_acc; 8319 uint32 bitmap; 8320 8321 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8322 8323 rv = _pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap); 8324 if (rv) return (rv); 8325 8326 return(_xlport_mode_get(unit, phy_acc, port_index, &mode->cur_mode, &mode->lanes)); 8327 } 8328 8329 int 8330 pm4x10_port_trunk_hwfailover_config_set(int unit, soc_port_t port, pm_info_t pm_info, int hw_count) 8331 { 8332 int old_failover_en=0, new_failover_en = 0; 8333 int old_link_status_sel=0, new_link_status_sel=0; 8334 int old_reset_flow_control=0, new_reset_flow_control = 0; 8335 int lag_failover_lpbk; 8336 8337 if (hw_count) { 8338 new_failover_en = 1; 8339 new_link_status_sel = 1; 8340 new_reset_flow_control = 1; 8341 } 8342 8343 SOC_IF_ERROR_RETURN (xlmac_lag_failover_loopback_get(unit, port, &lag_failover_lpbk)); 8344 if (lag_failover_lpbk) return (SOC_E_NONE); 8345 8346 8347 SOC_IF_ERROR_RETURN (xlmac_lag_failover_en_get(unit, port, &old_failover_en)); 8348 SOC_IF_ERROR_RETURN (xlmac_sw_link_status_select_get (unit, port, &old_link_status_sel)); 8349 8350 if (old_failover_en != new_failover_en || 8351 old_link_status_sel != new_link_status_sel) { 8352 8353 SOC_IF_ERROR_RETURN (xlmac_sw_link_status_select_set (unit, port, new_link_status_sel)); 8354 SOC_IF_ERROR_RETURN (xlmac_lag_failover_en_set(unit, port, new_failover_en)); 8355 } 8356 8357 SOC_IF_ERROR_RETURN (xlmac_reset_fc_timers_on_link_dn_get(unit, 8358 port, &old_reset_flow_control)); 8359 if (old_reset_flow_control != new_reset_flow_control) { 8360 SOC_IF_ERROR_RETURN (xlmac_reset_fc_timers_on_link_dn_set(unit, 8361 port, new_reset_flow_control)); 8362 } 8363 8364 return 0; 8365 } 8366 8367 int 8368 pm4x10_port_trunk_hwfailover_config_get(int unit, soc_port_t port, pm_info_t pm_info, 8369 int *enable) 8370 { 8371 return (xlmac_lag_failover_en_get(unit, port, enable)); 8372 } 8373 8374 8375 int 8376 pm4x10_port_trunk_hwfailover_status_get(int unit, soc_port_t port, pm_info_t pm_info, 8377 int *loopback) 8378 { 8379 return (xlmac_lag_failover_loopback_get(unit, port, loopback)); 8380 } 8381 8382 int pm4x10_port_diag_ctrl(int unit, soc_port_t port, pm_info_t pm_info, 8383 uint32 inst, int op_type, int op_cmd, const void *arg) 8384 { 8385 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8386 phymod_tx_t ln_txparam[PM4X10_LANES_PER_CORE]; 8387 int nof_phys, i; 8388 uint32 lane_map; 8389 portmod_access_get_params_t params; 8390 8391 SOC_IF_ERROR_RETURN(portmod_access_get_params_t_init(unit, ¶ms)); 8392 for (i = 0; i < PM4X10_LANES_PER_CORE; i++) { 8393 SOC_IF_ERROR_RETURN(phymod_tx_t_init(&ln_txparam[i])); 8394 } 8395 8396 if( PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_INT ) { 8397 params.phyn = 0 ; 8398 } else { 8399 /* most external PHY_DIAG_DEV_DFLT and PHY_DIAG_DEV_EXT */ 8400 params.phyn = -1 ; 8401 } 8402 8403 if(PHY_DIAG_INST_INTF(inst) == PHY_DIAG_INTF_SYS ){ 8404 params.sys_side = PORTMOD_SIDE_SYSTEM; 8405 } else { /* line side is default */ 8406 params.sys_side = PORTMOD_SIDE_LINE; 8407 } 8408 8409 params.apply_lane_mask = 1; 8410 8411 SOC_IF_ERROR_RETURN(pm4x10_port_phy_lane_access_get(unit, port, pm_info, 8412 ¶ms, 1, phy_access, &nof_phys, NULL)); 8413 8414 lane_map = phy_access[0].access.lane_mask; 8415 8416 switch(op_cmd) { 8417 case PHY_DIAG_CTRL_DSC: 8418 LOG_INFO(BSL_LS_SOC_PHY, 8419 (BSL_META_U(unit, 8420 "pm4x10_port_diag_ctrl: " 8421 "u=%d p=%d PHY_DIAG_CTRL_DSC 0x%x\n"), 8422 unit, port, PHY_DIAG_CTRL_DSC)); 8423 8424 SOC_IF_ERROR_RETURN 8425 (portmod_port_phychain_pmd_info_dump(unit, phy_access, nof_phys, 8426 (void*)arg)); 8427 8428 break; 8429 8430 case PHY_DIAG_CTRL_PCS: 8431 LOG_INFO(BSL_LS_SOC_PHY, 8432 (BSL_META_U(unit, 8433 "pm4x10_port_diag_ctrl: " 8434 "u=%d p=%d PHY_DIAG_CTRL_PCS 0x%x\n"), 8435 unit, port, PHY_DIAG_CTRL_PCS)); 8436 8437 SOC_IF_ERROR_RETURN 8438 (portmod_port_phychain_pcs_info_dump(unit, phy_access, nof_phys, 8439 (void*)arg)); 8440 break; 8441 8442 case PHY_DIAG_CTRL_LINKMON_MODE: 8443 LOG_INFO(BSL_LS_SOC_PHY, 8444 (BSL_META_U(unit, 8445 "pm4x10_port_diag_ctrl: " 8446 "u=%d p=%d PHY_DIAG_CTRL_LINKMON_MODE 0x%x\n"), 8447 unit, port, PHY_DIAG_CTRL_LINKMON_MODE)); 8448 8449 if(phy_access[0].access.lane_mask){ 8450 SOC_IF_ERROR_RETURN 8451 (portmod_pm_phy_link_mon_enable_set(phy_access, nof_phys, PTR_TO_INT(arg))); 8452 } 8453 break; 8454 8455 case PHY_DIAG_CTRL_LINKMON_STATUS: 8456 LOG_INFO(BSL_LS_SOC_PHY, 8457 (BSL_META_U(unit, 8458 "pm4x10_port_diag_ctrl: " 8459 "u=%d p=%d PHY_DIAG_CTRL_LINKMON_STATUS 0x%x\n"), 8460 unit, port, PHY_DIAG_CTRL_LINKMON_STATUS)); 8461 8462 if(phy_access[0].access.lane_mask){ 8463 SOC_IF_ERROR_RETURN 8464 (portmod_pm_phy_link_mon_status_get(phy_access, nof_phys)); 8465 } 8466 break; 8467 8468 8469 default: 8470 if(op_type == PHY_DIAG_CTRL_SET) { 8471 LOG_INFO(BSL_LS_SOC_PHY, 8472 (BSL_META_U(unit, 8473 "pm4x10_port_diag_ctrl: " 8474 "u=%d p=%d PHY_DIAG_CTRL_SET 0x%x\n"), 8475 unit, port, PHY_DIAG_CTRL_SET)); 8476 if (!SAL_BOOT_SIMULATION) { 8477 if( !(phy_access->access.lane_mask == 0)){ 8478 SOC_IF_ERROR_RETURN(portmod_pm_phy_control_set(phy_access, nof_phys, op_cmd, ln_txparam, lane_map, PTR_TO_INT(arg))); 8479 } 8480 } 8481 } else if(op_type == PHY_DIAG_CTRL_GET) { 8482 LOG_INFO(BSL_LS_SOC_PHY, 8483 (BSL_META_U(unit, 8484 "pm4x10_port_diag_ctrl: " 8485 "u=%d p=%d PHY_DIAG_CTRL_GET 0x%x\n"), 8486 unit, port, PHY_DIAG_CTRL_GET)); 8487 if (!SAL_BOOT_SIMULATION) { 8488 if( !(phy_access->access.lane_mask == 0)){ 8489 SOC_IF_ERROR_RETURN(portmod_pm_phy_control_get(phy_access,nof_phys,op_cmd, ln_txparam, lane_map, (uint32 *)arg)); 8490 } else { 8491 *(uint32 *)arg = 0; 8492 } 8493 } 8494 } else { 8495 return (SOC_E_UNAVAIL); 8496 } 8497 break ; 8498 } 8499 return (SOC_E_NONE); 8500 } 8501 8502 int 8503 pm4x10_port_ref_clk_get(int unit, soc_port_t port, pm_info_t pm_info, int *ref_clk) 8504 { 8505 *ref_clk = pm_info->pm_data.pm4x10_db->ref_clk; 8506 8507 return (SOC_E_NONE); 8508 } 8509 8510 int pm4x10_port_lag_remove_failover_lpbk_get(int unit, int port, pm_info_t pm_info, int *val) 8511 { 8512 return (xlmac_lag_remove_failover_lpbk_get(unit, port, val)); 8513 } 8514 8515 int pm4x10_port_lag_remove_failover_lpbk_set(int unit, int port, pm_info_t pm_info, int val) 8516 { 8517 return (xlmac_lag_remove_failover_lpbk_set(unit, port, val)); 8518 } 8519 8520 int pm4x10_port_lag_failover_disable(int unit, int port, pm_info_t pm_info) 8521 { 8522 return (xlmac_lag_failover_disable(unit, port)); 8523 } 8524 8525 int pm4x10_port_mac_ctrl_set(int unit, int port, 8526 pm_info_t pm_info, uint64 ctrl) 8527 { 8528 return(xlmac_mac_ctrl_set(unit, port, ctrl)); 8529 } 8530 8531 int pm4x10_port_drain_cell_get(int unit, int port, 8532 pm_info_t pm_info, portmod_drain_cells_t *drain_cells) 8533 { 8534 return (xlmac_drain_cell_get(unit, port, drain_cells)); 8535 } 8536 8537 int pm4x10_port_drain_cell_stop (int unit, int port, 8538 pm_info_t pm_info, const portmod_drain_cells_t *drain_cells) 8539 { 8540 return(xlmac_drain_cell_stop (unit, port, drain_cells)); 8541 } 8542 8543 int pm4x10_port_drain_cell_start(int unit, int port, pm_info_t pm_info) 8544 { 8545 return (xlmac_drain_cell_start(unit, port)); 8546 } 8547 8548 int pm4x10_port_txfifo_cell_cnt_get(int unit, int port, 8549 pm_info_t pm_info, uint32* fval) 8550 { 8551 return(xlmac_txfifo_cell_cnt_get(unit, port, fval)); 8552 } 8553 8554 int pm4x10_port_egress_queue_drain_get(int unit, int port, 8555 pm_info_t pm_info, uint64 *ctrl, int *rx) 8556 { 8557 return (xlmac_egress_queue_drain_get(unit, port, ctrl, rx)); 8558 } 8559 8560 int pm4x10_port_drain_cells_rx_enable (int unit, int port, 8561 pm_info_t pm_info, int rx_en) 8562 { 8563 return (xlmac_drain_cells_rx_enable(unit, port, rx_en)); 8564 } 8565 8566 int pm4x10_port_egress_queue_drain_rx_en(int unit, int port, 8567 pm_info_t pm_info, int rx_en) 8568 { 8569 return (xlmac_egress_queue_drain_rx_en(unit, port, rx_en)); 8570 } 8571 8572 int pm4x10_port_mac_reset_set(int unit, int port, 8573 pm_info_t pm_info, int val) 8574 { 8575 int rv; 8576 SOC_INIT_FUNC_DEFS; 8577 8578 /* if callback defined, go to local soft reset function */ 8579 rv = (PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) ? pm4x10_port_soft_reset(unit, port, pm_info, val) : xlmac_soft_reset_set(unit, port, val); 8580 _SOC_IF_ERR_EXIT(rv); 8581 8582 exit: 8583 SOC_FUNC_RETURN; 8584 } 8585 8586 int pm4x10_port_mac_reset_get (int unit, int port, pm_info_t pm_info, int* val) 8587 { 8588 return (xlmac_soft_reset_get(unit, port, val)); 8589 } 8590 8591 int pm4x10_port_mac_reset_check(int unit, int port, pm_info_t pm_info, 8592 int enable, int* reset) 8593 { 8594 return (xlmac_reset_check(unit, port, enable, reset)); 8595 } 8596 8597 int pm4x10_port_core_num_get(int unit, int port, pm_info_t pm_info, 8598 int* core_num) 8599 { 8600 *core_num = PM_4x10_INFO(pm_info)->core_num; 8601 return (SOC_E_NONE); 8602 } 8603 8604 int pm4x10_port_e2ecc_hdr_set (int unit, int port, pm_info_t pm_info, 8605 const portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr) 8606 { 8607 return (xlmac_e2ecc_hdr_set (unit, port, (uint32_t *)e2ecc_hdr->words)); 8608 } 8609 8610 8611 int pm4x10_port_e2ecc_hdr_get (int unit, int port, pm_info_t pm_info, 8612 portmod_port_higig_e2ecc_hdr_t* e2ecc_hdr) 8613 { 8614 return (xlmac_e2ecc_hdr_get (unit, port, e2ecc_hdr->words)); 8615 } 8616 8617 int pm4x10_port_e2e_enable_set (int unit, int port, pm_info_t pm_info, int enable) 8618 { 8619 return (xlmac_e2e_enable_set(unit, port, enable)); 8620 } 8621 8622 8623 int pm4x10_port_e2e_enable_get (int unit, int port, pm_info_t pm_info, int *enable) 8624 { 8625 return (xlmac_e2e_enable_get(unit, port, enable)); 8626 } 8627 8628 int pm4x10_port_fallback_lane_get(int unit, int port, pm_info_t pm_info, int* fallback_lane) 8629 { 8630 int port_index; 8631 uint32_t bitmap; 8632 8633 SOC_INIT_FUNC_DEFS; 8634 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 8635 &bitmap)); 8636 _SOC_IF_ERR_EXIT(PM4x10_PORT_FALLBACK_LANE_GET(unit, pm_info, fallback_lane, 8637 port_index)); 8638 8639 exit: 8640 SOC_FUNC_RETURN; 8641 8642 } 8643 8644 /* in_out: 1= in reset, 0= in and out of reset */ 8645 STATIC 8646 int pm4x10_port_soft_reset(int unit, int port, pm_info_t pm_info, int in_out) 8647 { 8648 int rv, rx_enable = 0; 8649 int phy_port, block, bindex, i; 8650 portmod_drain_cells_t drain_cells; 8651 uint32 cell_count; 8652 uint64 mac_ctrl; 8653 soc_timeout_t to; 8654 SOC_INIT_FUNC_DEFS; 8655 8656 /* Callback soft reset function */ 8657 if (PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 8658 rv = PM_4x10_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePre); 8659 _SOC_IF_ERR_EXIT(rv); 8660 } 8661 8662 if(in_out == 0) { 8663 8664 rv = xlmac_egress_queue_drain_get(unit, port, &mac_ctrl, &rx_enable); 8665 _SOC_IF_ERR_EXIT(rv); 8666 8667 /* Drain cells */ 8668 rv = xlmac_drain_cell_get(unit, port, &drain_cells); 8669 _SOC_IF_ERR_EXIT(rv); 8670 8671 /* Start TX FIFO draining */ 8672 rv = xlmac_drain_cell_start(unit, port); 8673 _SOC_IF_ERR_EXIT(rv); 8674 8675 /* De-assert SOFT_RESET to let the drain start */ 8676 rv = xlmac_soft_reset_set(unit, port, 0); 8677 _SOC_IF_ERR_EXIT(rv); 8678 8679 /* Wait until TX fifo cell count is 0 */ 8680 soc_timeout_init(&to, 250000, 0); 8681 for (;;) { 8682 rv = xlmac_txfifo_cell_cnt_get(unit, port, &cell_count); 8683 _SOC_IF_ERR_EXIT(rv); 8684 if (cell_count == 0) { 8685 break; 8686 } 8687 if (soc_timeout_check(&to)) { 8688 LOG_ERROR(BSL_LS_BCM_PORT, 8689 (BSL_META_UP(unit, port, 8690 "ERROR: u=%d p=%d timeout draining " 8691 "TX FIFO (%d cells remain)\n"), 8692 unit, port, cell_count)); 8693 return SOC_E_INTERNAL; 8694 } 8695 } 8696 8697 /* Stop TX FIFO draining */ 8698 rv = xlmac_drain_cell_stop (unit, port, &drain_cells); 8699 _SOC_IF_ERR_EXIT(rv); 8700 8701 /* Reset port FIFO */ 8702 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 8703 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 8704 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 8705 if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) || 8706 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORTB0)) { 8707 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 8708 _SOC_IF_ERR_EXIT(portmod_port_soft_reset_toggle(unit, port, bindex)); 8709 break; 8710 } 8711 } 8712 } 8713 8714 /* Put port into SOFT_RESET */ 8715 rv = xlmac_soft_reset_set(unit, port, 1); 8716 _SOC_IF_ERR_EXIT(rv); 8717 8718 if (in_out == 0) { 8719 8720 /* Callback soft reset function */ 8721 if (PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 8722 rv = PM_4x10_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypeDuring); 8723 _SOC_IF_ERR_EXIT(rv); 8724 soc_reg64_field32_set (unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); /*make sure restored data wont put mac back in reset*/ 8725 } 8726 8727 /* Enable TX, set RX, de-assert SOFT_RESET */ 8728 rv = xlmac_egress_queue_drain_rx_en(unit, port, rx_enable); 8729 _SOC_IF_ERR_EXIT(rv); 8730 8731 /* Restore XLMAC_CTRL to original value */ 8732 rv = xlmac_mac_ctrl_set(unit, port, mac_ctrl); 8733 _SOC_IF_ERR_EXIT(rv); 8734 } 8735 8736 /* Callback soft reset function */ 8737 if (PM_4x10_INFO(pm_info)->portmod_mac_soft_reset) { 8738 rv = PM_4x10_INFO(pm_info)->portmod_mac_soft_reset(unit, port, portmodCallBackActionTypePost); 8739 _SOC_IF_ERR_EXIT(rv); 8740 } 8741 8742 exit: 8743 SOC_FUNC_RETURN; 8744 } 8745 8746 /*Port discard set*/ 8747 int pm4x10_port_discard_set(int unit, int port, pm_info_t pm_info, int discard) 8748 { 8749 return(xlmac_discard_set(unit, port, discard)); 8750 } 8751 8752 /*Port soft reset set set*/ 8753 int pm4x10_port_soft_reset_set(int unit, int port, pm_info_t pm_info, int idx, 8754 int val, int flags) 8755 { 8756 SOC_INIT_FUNC_DEFS; 8757 8758 if (PORTMOD_PORT_REG_ACCESS_DIRECT == flags) { 8759 _SOC_IF_ERR_EXIT(_pm4x10_port_soft_reset_set_by_phyport(unit, port, 8760 pm_info, idx, val)); 8761 } else { 8762 _SOC_IF_ERR_EXIT(_pm4x10_port_soft_reset_set(unit, port, pm_info, idx, val)); 8763 } 8764 8765 exit: 8766 SOC_FUNC_RETURN; 8767 } 8768 8769 /*Port tx_en=0 and softreset mac*/ 8770 int pm4x10_port_tx_down(int unit, int port, pm_info_t pm_info) 8771 { 8772 SOC_INIT_FUNC_DEFS; 8773 8774 _SOC_IF_ERR_EXIT(xlmac_tx_enable_set(unit, port, 0)); 8775 _SOC_IF_ERR_EXIT(xlmac_discard_set(unit, port, 0)); 8776 _SOC_IF_ERR_EXIT(xlmac_soft_reset_set(unit, port, 1)); 8777 8778 exit: 8779 SOC_FUNC_RETURN; 8780 } 8781 8782 int pm4x10_port_pgw_reconfig (int unit, int port, pm_info_t pm_info, 8783 const portmod_port_mode_info_t *pmode, int phy_port, int flags) 8784 { 8785 int rv, idx; 8786 int phy_acc; 8787 uint32 reg_val; 8788 soc_field_t port_fields[] = {PORT0f, PORT1f, PORT2f, PORT3f}; 8789 8790 SOC_INIT_FUNC_DEFS; 8791 8792 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 8793 8794 if (PORTMOD_PORT_PGW_MAC_RESET == flags) { 8795 rv = xlmac_discard_set(unit, port, 1); 8796 _SOC_IF_ERR_EXIT(rv); 8797 rv = xlmac_rx_enable_set(unit, port, 0); 8798 _SOC_IF_ERR_EXIT(rv); 8799 rv = xlmac_tx_enable_set(unit, port, 0); 8800 _SOC_IF_ERR_EXIT(rv); 8801 rv = xlmac_soft_reset_set(unit, port, 1); 8802 _SOC_IF_ERR_EXIT(rv); 8803 8804 _SOC_IF_ERR_EXIT(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 8805 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 1); 8806 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 8807 8808 } else if (PORTMOD_PORT_PGW_POWER_SAVE == flags) { 8809 _SOC_IF_ERR_EXIT(READ_XLPORT_POWER_SAVEr(unit, phy_acc, ®_val)); 8810 soc_reg_field_set(unit, XLPORT_POWER_SAVEr, ®_val, XPORT_CORE0f, 1); 8811 _SOC_IF_ERR_EXIT(WRITE_XLPORT_POWER_SAVEr(unit, phy_acc, reg_val)); 8812 8813 } else if (PORTMOD_PORT_PGW_MAC_UNRESET == flags) { 8814 _SOC_IF_ERR_EXIT(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 8815 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, XMAC0_RESETf, 0); 8816 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 8817 } else if (PORTMOD_PORT_PGW_CONFIGURE == flags) { 8818 /* 10/20/40G RECONFIGURE SEQUENCE */ 8819 idx = pmode->port_index; 8820 8821 /* 1.a st SOFT_RESET field in XLMAC_CTRL for new ports that use XLMAC */ 8822 rv = xlmac_soft_reset_set(unit, port, 1); 8823 _SOC_IF_ERR_EXIT(rv); 8824 8825 /* 1.a set PORT[subport] field in XLPORT_SOFT_RESET for all new ports */ 8826 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 8827 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, port_fields[idx], 1); 8828 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 8829 8830 /* Port enable */ 8831 _SOC_IF_ERR_EXIT(READ_XLPORT_ENABLE_REGr(unit, phy_acc, ®_val)); 8832 soc_reg_field_set (unit, XLPORT_ENABLE_REGr, ®_val, 8833 port_fields[idx], 1); 8834 _SOC_IF_ERR_EXIT(WRITE_XLPORT_ENABLE_REGr(unit, phy_acc, reg_val)); 8835 8836 /* set port mode */ 8837 _SOC_IF_ERR_EXIT(pm4x10_port_mode_set(unit, port, pm_info, pmode)); 8838 8839 /* Release XLPORT SOFT RESET */ 8840 _SOC_IF_ERR_EXIT(READ_XLPORT_SOFT_RESETr(unit, phy_acc, ®_val)); 8841 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, ®_val, port_fields[idx], 0); 8842 _SOC_IF_ERR_EXIT(WRITE_XLPORT_SOFT_RESETr(unit, phy_acc, reg_val)); 8843 8844 /*Release Mac Soft Reset */ 8845 rv = xlmac_soft_reset_set(unit, port, 0); 8846 _SOC_IF_ERR_EXIT(rv); 8847 } 8848 exit: 8849 SOC_FUNC_RETURN; 8850 } 8851 8852 int pm4x10_port_notify(int unit, int port, pm_info_t pm_info, int link) { 8853 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8854 int nof_phys; 8855 portmod_port_interface_config_t interface_config; 8856 SOC_INIT_FUNC_DEFS; 8857 8858 _SOC_IF_ERR_EXIT 8859 (portmod_port_chain_phy_access_get(unit, port, pm_info, 8860 phy_access ,(1+MAX_PHYN), 8861 &nof_phys)); 8862 /* If nof phys > 1 change the internal phy speed based on the external 8863 link speed if the link is up*/ 8864 if (nof_phys > 1) { 8865 if (link) { 8866 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, 8867 port, 8868 &interface_config, 8869 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 8870 /* Set the interface config to internal phy */ 8871 _SOC_IF_ERR_EXIT(portmod_port_interface_config_set(unit, 8872 port, 8873 &interface_config, 8874 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 8875 } else { 8876 /*TBD*/ 8877 } 8878 } 8879 exit: 8880 SOC_FUNC_RETURN; 8881 } 8882 8883 int pm4x10_port_timesync_config_set(int unit, int port, pm_info_t pm_info, const portmod_phy_timesync_config_t* config) 8884 { 8885 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8886 int nof_phys; 8887 SOC_INIT_FUNC_DEFS; 8888 8889 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8890 phy_access ,(1+MAX_PHYN), 8891 &nof_phys)); 8892 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_config_set(unit, port, phy_access, 8893 nof_phys,config)); 8894 exit: 8895 SOC_FUNC_RETURN; 8896 } 8897 8898 int pm4x10_port_timesync_config_get(int unit, int port, pm_info_t pm_info, portmod_phy_timesync_config_t* config) 8899 { 8900 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8901 int nof_phys; 8902 SOC_INIT_FUNC_DEFS; 8903 8904 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8905 phy_access ,(1+MAX_PHYN), 8906 &nof_phys)); 8907 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_config_get(unit, port, phy_access, 8908 nof_phys,config)); 8909 exit: 8910 SOC_FUNC_RETURN; 8911 } 8912 8913 int pm4x10_port_timesync_enable_set(int unit, int port, pm_info_t pm_info, uint32 enable) 8914 { 8915 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8916 int nof_phys; 8917 SOC_INIT_FUNC_DEFS; 8918 8919 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8920 phy_access ,(1+MAX_PHYN), 8921 &nof_phys)); 8922 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_enable_set(unit, phy_access, 8923 nof_phys,enable)); 8924 exit: 8925 SOC_FUNC_RETURN; 8926 } 8927 8928 int pm4x10_port_timesync_enable_get(int unit, int port, pm_info_t pm_info, uint32* enable) 8929 { 8930 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8931 int nof_phys; 8932 SOC_INIT_FUNC_DEFS; 8933 8934 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8935 phy_access ,(1+MAX_PHYN), 8936 &nof_phys)); 8937 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_enable_get(unit, phy_access, 8938 nof_phys,enable)); 8939 8940 exit: 8941 SOC_FUNC_RETURN; 8942 } 8943 8944 int pm4x10_port_timesync_nco_addend_set(int unit, int port, pm_info_t pm_info, uint32 freq_step) 8945 { 8946 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8947 int nof_phys; 8948 SOC_INIT_FUNC_DEFS; 8949 8950 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8951 phy_access ,(1+MAX_PHYN), 8952 &nof_phys)); 8953 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_nco_addend_set(unit, phy_access, 8954 nof_phys,freq_step)); 8955 exit: 8956 SOC_FUNC_RETURN; 8957 } 8958 8959 int pm4x10_port_timesync_nco_addend_get(int unit, int port, pm_info_t pm_info, uint32* freq_step) 8960 { 8961 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8962 int nof_phys; 8963 SOC_INIT_FUNC_DEFS; 8964 8965 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8966 phy_access ,(1+MAX_PHYN), 8967 &nof_phys)); 8968 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_nco_addend_get(unit, phy_access, 8969 nof_phys,freq_step)); 8970 exit: 8971 SOC_FUNC_RETURN; 8972 } 8973 8974 int pm4x10_port_timesync_framesync_mode_set(int unit, int port, pm_info_t pm_info, 8975 const portmod_timesync_framesync_t* framesync) 8976 { 8977 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8978 int nof_phys; 8979 SOC_INIT_FUNC_DEFS; 8980 8981 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8982 phy_access ,(1+MAX_PHYN), 8983 &nof_phys)); 8984 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_framesync_mode_set(unit, phy_access, 8985 nof_phys,framesync)); 8986 exit: 8987 SOC_FUNC_RETURN; 8988 } 8989 8990 int pm4x10_port_timesync_framesync_mode_get(int unit, int port, pm_info_t pm_info, 8991 portmod_timesync_framesync_t* framesync) 8992 { 8993 phymod_phy_access_t phy_access[1+MAX_PHYN]; 8994 int nof_phys; 8995 SOC_INIT_FUNC_DEFS; 8996 8997 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 8998 phy_access ,(1+MAX_PHYN), 8999 &nof_phys)); 9000 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_framesync_mode_get(unit, phy_access, 9001 nof_phys,framesync)); 9002 exit: 9003 SOC_FUNC_RETURN; 9004 } 9005 9006 int pm4x10_port_timesync_local_time_set(int unit, int port, pm_info_t pm_info, const uint64 local_time) 9007 { 9008 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9009 int nof_phys; 9010 SOC_INIT_FUNC_DEFS; 9011 9012 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9013 phy_access ,(1+MAX_PHYN), 9014 &nof_phys)); 9015 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_local_time_set(unit, phy_access, 9016 nof_phys,local_time)); 9017 exit: 9018 SOC_FUNC_RETURN; 9019 } 9020 9021 9022 int pm4x10_port_timesync_local_time_get(int unit, int port, pm_info_t pm_info, uint64* local_time) 9023 { 9024 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9025 int nof_phys; 9026 SOC_INIT_FUNC_DEFS; 9027 9028 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9029 phy_access ,(1+MAX_PHYN), 9030 &nof_phys)); 9031 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_local_time_get(unit, phy_access, nof_phys, 9032 local_time)); 9033 exit: 9034 SOC_FUNC_RETURN; 9035 } 9036 9037 int pm4x10_port_timesync_load_ctrl_set(int unit, int port, pm_info_t pm_info, 9038 uint32 load_once, uint32 load_always) 9039 { 9040 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9041 int nof_phys; 9042 SOC_INIT_FUNC_DEFS; 9043 9044 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9045 phy_access ,(1+MAX_PHYN), 9046 &nof_phys)); 9047 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_load_ctrl_set(unit, phy_access, nof_phys, 9048 load_once, load_always)); 9049 exit: 9050 SOC_FUNC_RETURN; 9051 } 9052 9053 int pm4x10_port_timesync_load_ctrl_get(int unit, int port, pm_info_t pm_info, 9054 uint32* load_once, uint32* load_always) 9055 { 9056 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9057 int nof_phys; 9058 SOC_INIT_FUNC_DEFS; 9059 9060 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9061 phy_access ,(1+MAX_PHYN), 9062 &nof_phys)); 9063 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_load_ctrl_get(unit, phy_access, nof_phys, 9064 load_once, load_always)); 9065 exit: 9066 SOC_FUNC_RETURN; 9067 } 9068 9069 int pm4x10_port_timesync_tx_timestamp_offset_set(int unit, int port, pm_info_t pm_info, uint32 ts_offset) 9070 { 9071 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9072 int nof_phys; 9073 SOC_INIT_FUNC_DEFS; 9074 9075 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9076 phy_access ,(1+MAX_PHYN), 9077 &nof_phys)); 9078 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_tx_timestamp_offset_set(unit, phy_access, nof_phys, 9079 ts_offset)); 9080 exit: 9081 SOC_FUNC_RETURN; 9082 } 9083 9084 int pm4x10_port_timesync_tx_timestamp_offset_get(int unit, int port, pm_info_t pm_info, uint32* ts_offset) 9085 { 9086 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9087 int nof_phys; 9088 SOC_INIT_FUNC_DEFS; 9089 9090 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9091 phy_access ,(1+MAX_PHYN), 9092 &nof_phys)); 9093 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_tx_timestamp_offset_get(unit, phy_access, nof_phys, 9094 ts_offset)); 9095 exit: 9096 SOC_FUNC_RETURN; 9097 } 9098 9099 int pm4x10_port_timesync_rx_timestamp_offset_set(int unit, int port, pm_info_t pm_info, uint32 ts_offset) 9100 { 9101 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9102 int nof_phys; 9103 SOC_INIT_FUNC_DEFS; 9104 9105 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9106 phy_access ,(1+MAX_PHYN), 9107 &nof_phys)); 9108 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_rx_timestamp_offset_set(unit, phy_access, nof_phys, 9109 ts_offset)); 9110 exit: 9111 SOC_FUNC_RETURN; 9112 } 9113 9114 int pm4x10_port_timesync_rx_timestamp_offset_get(int unit, int port, pm_info_t pm_info, uint32* ts_offset) 9115 { 9116 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9117 int nof_phys; 9118 SOC_INIT_FUNC_DEFS; 9119 9120 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9121 phy_access ,(1+MAX_PHYN), 9122 &nof_phys)); 9123 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_rx_timestamp_offset_get(unit, phy_access, nof_phys, 9124 ts_offset)); 9125 exit: 9126 SOC_FUNC_RETURN; 9127 } 9128 9129 /* 9130 *Function: 9131 * pm4x10_port_timestamp_adjust_set 9132 * 9133 *Purpose: 9134 * It sets tsts,osts adjustment into MAC registers directly. 9135 */ 9136 int 9137 pm4x10_port_timestamp_adjust_set(int unit, int port, pm_info_t pm_info, 9138 const soc_port_timestamp_adjust_t *ts_adjust) 9139 { 9140 int port_index; 9141 uint32_t bitmap, port_dynamic_state; 9142 portmod_port_interface_config_t port_intf_config; 9143 portmod_port_ts_adjust_t portmod_ts_adjust; 9144 SOC_INIT_FUNC_DEFS; 9145 9146 sal_memset(&port_intf_config, 0, sizeof(portmod_port_interface_config_t)); 9147 sal_memset(&portmod_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 9148 9149 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 9150 _SOC_IF_ERR_EXIT 9151 (pm4x10_port_interface_config_get(unit, port, pm_info, &port_intf_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 9152 portmod_ts_adjust.speed = port_intf_config.speed; 9153 portmod_ts_adjust.osts_adjust = ts_adjust->osts_adjust; 9154 portmod_ts_adjust.tsts_adjust = ts_adjust->tsts_adjust; 9155 _SOC_IF_ERR_EXIT(xlmac_timestamp_delay_set(unit, port, portmod_ts_adjust, port_intf_config.speed)); 9156 9157 _SOC_IF_ERR_EXIT(PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, &port_dynamic_state, port_index)); 9158 PORTMOD_PORT_DEFAULT_TIMESTAMP_ADJUSTMENT_UPDATED_SET(port_dynamic_state); 9159 _SOC_IF_ERR_EXIT(PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, port_dynamic_state, port_index)); 9160 exit: 9161 SOC_FUNC_RETURN; 9162 } 9163 9164 /* 9165 *Function: 9166 * pm4x10_port_timestamp_adjust_get 9167 * 9168 *Purpose: 9169 * Get the tsts,osts adjustment from MAC register. 9170 */ 9171 int 9172 pm4x10_port_timestamp_adjust_get(int unit, int port, pm_info_t pm_info, 9173 soc_port_timestamp_adjust_t *ts_adjust) 9174 { 9175 portmod_port_ts_adjust_t portmod_ts_adjust; 9176 SOC_INIT_FUNC_DEFS; 9177 9178 sal_memset(&portmod_ts_adjust, 0, sizeof(portmod_port_ts_adjust_t)); 9179 9180 _SOC_IF_ERR_EXIT(xlmac_timestamp_delay_get(unit, port, &portmod_ts_adjust)); 9181 ts_adjust->osts_adjust = portmod_ts_adjust.osts_adjust; 9182 ts_adjust->tsts_adjust = portmod_ts_adjust.tsts_adjust; 9183 9184 exit: 9185 SOC_FUNC_RETURN; 9186 } 9187 9188 int pm4x10_port_phy_intr_enable_set(int unit, int port, pm_info_t pm_info, uint32 intr_enable) 9189 { 9190 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9191 int nof_phys; 9192 SOC_INIT_FUNC_DEFS; 9193 9194 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9195 phy_access ,(1+MAX_PHYN), 9196 &nof_phys)); 9197 SOC_IF_ERROR_RETURN(portmod_port_phychain_phy_intr_enable_set(unit, phy_access, nof_phys, 9198 intr_enable)); 9199 exit: 9200 SOC_FUNC_RETURN; 9201 } 9202 9203 int pm4x10_port_phy_intr_enable_get(int unit, int port, pm_info_t pm_info, uint32* intr_enable) 9204 { 9205 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9206 int nof_phys; 9207 SOC_INIT_FUNC_DEFS; 9208 9209 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9210 phy_access ,(1+MAX_PHYN), 9211 &nof_phys)); 9212 SOC_IF_ERROR_RETURN(portmod_port_phychain_phy_intr_enable_get(unit, phy_access, nof_phys, 9213 intr_enable)); 9214 exit: 9215 SOC_FUNC_RETURN; 9216 } 9217 9218 int pm4x10_port_phy_intr_status_get(int unit, int port, pm_info_t pm_info, uint32* intr_enable) 9219 { 9220 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9221 int nof_phys; 9222 SOC_INIT_FUNC_DEFS; 9223 9224 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9225 phy_access ,(1+MAX_PHYN), 9226 &nof_phys)); 9227 SOC_IF_ERROR_RETURN(portmod_port_phychain_phy_intr_status_get(unit, phy_access, nof_phys, 9228 intr_enable)); 9229 exit: 9230 SOC_FUNC_RETURN; 9231 } 9232 9233 int pm4x10_port_phy_intr_status_clear(int unit, int port, pm_info_t pm_info) 9234 { 9235 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9236 int nof_phys; 9237 SOC_INIT_FUNC_DEFS; 9238 9239 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9240 phy_access ,(1+MAX_PHYN), 9241 &nof_phys)); 9242 SOC_IF_ERROR_RETURN(portmod_port_phychain_phy_intr_status_clear(unit, phy_access, nof_phys)); 9243 9244 exit: 9245 SOC_FUNC_RETURN; 9246 } 9247 9248 int pm4x10_port_phy_timesync_do_sync(int unit, int port, pm_info_t pm_info ) 9249 { 9250 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9251 int nof_phys; 9252 SOC_INIT_FUNC_DEFS; 9253 9254 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9255 phy_access ,(1+MAX_PHYN), 9256 &nof_phys)); 9257 SOC_IF_ERROR_RETURN(portmod_port_phychain_phy_timesync_do_sync(unit, phy_access, nof_phys )); 9258 exit: 9259 SOC_FUNC_RETURN; 9260 } 9261 9262 int pm4x10_port_timesync_capture_timestamp_get(int unit, int port, pm_info_t pm_info, uint64* cap_ts) 9263 { 9264 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9265 int nof_phys; 9266 SOC_INIT_FUNC_DEFS; 9267 9268 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9269 phy_access ,(1+MAX_PHYN), 9270 &nof_phys)); 9271 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_capture_timestamp_get(unit, phy_access, nof_phys, 9272 cap_ts)); 9273 exit: 9274 SOC_FUNC_RETURN; 9275 } 9276 9277 9278 int pm4x10_port_timesync_heartbeat_timestamp_get(int unit, int port, pm_info_t pm_info, uint64* hb_ts) 9279 { 9280 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9281 int nof_phys; 9282 SOC_INIT_FUNC_DEFS; 9283 9284 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9285 phy_access ,(1+MAX_PHYN), 9286 &nof_phys)); 9287 SOC_IF_ERROR_RETURN(portmod_port_phychain_timesync_heartbeat_timestamp_get(unit, phy_access, nof_phys, 9288 hb_ts)); 9289 exit: 9290 SOC_FUNC_RETURN; 9291 } 9292 9293 int pm4x10_port_edc_config_set(int unit, int port, pm_info_t pm_info, 9294 const portmod_edc_config_t* config) 9295 { 9296 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9297 int nof_phys; 9298 SOC_INIT_FUNC_DEFS; 9299 9300 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9301 phy_access ,(1+MAX_PHYN), 9302 &nof_phys)); 9303 SOC_IF_ERROR_RETURN(portmod_port_phychain_edc_config_set(unit, phy_access, nof_phys, config)); 9304 exit: 9305 SOC_FUNC_RETURN; 9306 } 9307 9308 int pm4x10_port_edc_config_get(int unit, int port, pm_info_t pm_info, 9309 portmod_edc_config_t* config) 9310 { 9311 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9312 int nof_phys; 9313 SOC_INIT_FUNC_DEFS; 9314 9315 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9316 phy_access ,(1+MAX_PHYN), 9317 &nof_phys)); 9318 SOC_IF_ERROR_RETURN(portmod_port_phychain_edc_config_get(unit, phy_access, nof_phys, config)); 9319 exit: 9320 SOC_FUNC_RETURN; 9321 } 9322 9323 /* get interrupt value. */ 9324 int pm4x10_port_interrupt_enable_get (int unit, int port, pm_info_t pm_info, 9325 int intr_type, uint32 *val) 9326 { 9327 uint32 reg_val; 9328 int phy_acc; 9329 pm_version_t pm_version; 9330 SOC_INIT_FUNC_DEFS; 9331 9332 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9333 _SOC_IF_ERR_EXIT(READ_XLPORT_INTR_ENABLEr(unit, phy_acc, ®_val)); 9334 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 9335 9336 switch(intr_type) { 9337 case portmodIntrTypeMibTxMemErr: 9338 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, MIB_TX_MEM_ERRf); 9339 break; 9340 case portmodIntrTypeMibRxMemErr: 9341 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, MIB_RX_MEM_ERRf); 9342 break; 9343 case portmodIntrTypeMacTxCdcMemErr: 9344 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9345 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, MAC_TX_CDC_MEM_ERRf); 9346 break; 9347 } 9348 else { 9349 return SOC_E_UNAVAIL; 9350 } 9351 case portmodIntrTypeMacRxCdcMemErr: 9352 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9353 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, MAC_RX_CDC_MEM_ERRf); 9354 break; 9355 } 9356 else { 9357 return SOC_E_UNAVAIL; 9358 } 9359 case portmodIntrTypeTscErr: 9360 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, TSC_ERRf); 9361 break; 9362 case portmodIntrTypeRxFcReqFull: 9363 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, RX_FLOWCONTROL_REQ_FULLf); 9364 break; 9365 case portmodIntrTypeLinkdown: 9366 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9367 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, LINK_DOWNf); 9368 break; 9369 } 9370 else { 9371 return SOC_E_UNAVAIL; 9372 } 9373 case portmodIntrTypeMacErr: 9374 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9375 *val = soc_reg_field_get(unit, XLPORT_INTR_ENABLEr, reg_val, MAC_ERRf); 9376 break; 9377 } 9378 else { 9379 return SOC_E_UNAVAIL; 9380 } 9381 case portmodIntrTypeTxPktUnderflow : 9382 case portmodIntrTypeTxPktOverflow : 9383 case portmodIntrTypeTxLlfcMsgOverflow : 9384 case portmodIntrTypeTxTSFifoOverflow : 9385 case portmodIntrTypeRxPktOverflow : 9386 case portmodIntrTypeRxMsgOverflow : 9387 case portmodIntrTypeTxCdcSingleBitErr : 9388 case portmodIntrTypeTxCdcDoubleBitErr : 9389 case portmodIntrTypeRxCdcSingleBitErr : 9390 case portmodIntrTypeRxCdcDoubleBitErr : 9391 case portmodIntrTypeLocalFaultStatus : 9392 case portmodIntrTypeRemoteFaultStatus : 9393 case portmodIntrTypeLinkInterruptionStatus : 9394 case portmodIntrTypeTsEntryValid : 9395 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9396 _SOC_IF_ERR_EXIT(xlmac_interrupt_enable_get(unit, port, intr_type, val)); 9397 break; 9398 } 9399 else { 9400 return SOC_E_UNAVAIL; 9401 } 9402 default: 9403 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 9404 break; 9405 } 9406 9407 exit: 9408 SOC_FUNC_RETURN; 9409 } 9410 9411 /* set interrupt value. */ 9412 int pm4x10_port_interrupt_enable_set (int unit, int port, pm_info_t pm_info, 9413 int intr_type, uint32 val) 9414 { 9415 uint32 reg_val; 9416 int phy_acc; 9417 pm_version_t pm_version; 9418 SOC_INIT_FUNC_DEFS; 9419 9420 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9421 _SOC_IF_ERR_EXIT(READ_XLPORT_INTR_ENABLEr(unit, phy_acc, ®_val)); 9422 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 9423 9424 switch(intr_type) { 9425 case portmodIntrTypeMibTxMemErr: 9426 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, MIB_TX_MEM_ERRf, val); 9427 break; 9428 case portmodIntrTypeMibRxMemErr: 9429 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, MIB_RX_MEM_ERRf, val); 9430 break; 9431 case portmodIntrTypeMacTxCdcMemErr: 9432 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9433 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, MAC_TX_CDC_MEM_ERRf, val); 9434 break; 9435 } 9436 else { 9437 return SOC_E_UNAVAIL; 9438 } 9439 case portmodIntrTypeMacRxCdcMemErr: 9440 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9441 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, MAC_RX_CDC_MEM_ERRf, val); 9442 break; 9443 } 9444 else { 9445 return SOC_E_UNAVAIL; 9446 } 9447 case portmodIntrTypeTscErr: 9448 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, TSC_ERRf, val); 9449 break; 9450 case portmodIntrTypeRxFcReqFull: 9451 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, RX_FLOWCONTROL_REQ_FULLf, val); 9452 break; 9453 case portmodIntrTypeLinkdown: 9454 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9455 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, LINK_DOWNf, val); 9456 break; 9457 } 9458 else { 9459 return SOC_E_UNAVAIL; 9460 } 9461 case portmodIntrTypeMacErr: 9462 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9463 soc_reg_field_set(unit, XLPORT_INTR_ENABLEr, ®_val, MAC_ERRf, val); 9464 break; 9465 } 9466 else { 9467 return SOC_E_UNAVAIL; 9468 } 9469 case portmodIntrTypeTxPktUnderflow : 9470 case portmodIntrTypeTxPktOverflow : 9471 case portmodIntrTypeTxLlfcMsgOverflow : 9472 case portmodIntrTypeTxTSFifoOverflow : 9473 case portmodIntrTypeRxPktOverflow : 9474 case portmodIntrTypeRxMsgOverflow : 9475 case portmodIntrTypeTxCdcSingleBitErr : 9476 case portmodIntrTypeTxCdcDoubleBitErr : 9477 case portmodIntrTypeRxCdcSingleBitErr : 9478 case portmodIntrTypeRxCdcDoubleBitErr : 9479 case portmodIntrTypeLocalFaultStatus : 9480 case portmodIntrTypeRemoteFaultStatus : 9481 case portmodIntrTypeLinkInterruptionStatus : 9482 case portmodIntrTypeTsEntryValid : 9483 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9484 _SOC_IF_ERR_EXIT(xlmac_interrupt_enable_set(unit, port, intr_type, val)); 9485 break; 9486 } 9487 else { 9488 return SOC_E_UNAVAIL; 9489 } 9490 default: 9491 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 9492 break; 9493 } 9494 _SOC_IF_ERR_EXIT(WRITE_XLPORT_INTR_ENABLEr(unit, phy_acc, reg_val)); 9495 9496 exit: 9497 SOC_FUNC_RETURN; 9498 } 9499 9500 /* get interrupt value. */ 9501 int pm4x10_port_interrupt_get (int unit, int port, pm_info_t pm_info, 9502 int intr_type, uint32* val) 9503 { 9504 uint32 reg_val; 9505 int phy_acc; 9506 pm_version_t pm_version; 9507 SOC_INIT_FUNC_DEFS; 9508 9509 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9510 _SOC_IF_ERR_EXIT(READ_XLPORT_INTR_STATUSr(unit, phy_acc, ®_val)); 9511 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 9512 9513 switch(intr_type) { 9514 case portmodIntrTypeMibTxMemErr: 9515 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MIB_TX_MEM_ERRf); 9516 break; 9517 case portmodIntrTypeMibRxMemErr: 9518 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MIB_RX_MEM_ERRf); 9519 break; 9520 case portmodIntrTypeMacTxCdcMemErr: 9521 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9522 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_TX_CDC_MEM_ERRf); 9523 break; 9524 } 9525 else { 9526 return SOC_E_UNAVAIL; 9527 } 9528 case portmodIntrTypeMacRxCdcMemErr: 9529 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9530 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_RX_CDC_MEM_ERRf); 9531 break; 9532 } 9533 else { 9534 return SOC_E_UNAVAIL; 9535 } 9536 case portmodIntrTypeTscErr: 9537 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, TSC_ERRf); 9538 break; 9539 case portmodIntrTypeRxFcReqFull: 9540 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, RX_FLOWCONTROL_REQ_FULLf); 9541 break; 9542 case portmodIntrTypeLinkdown: 9543 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9544 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, LINK_DOWNf); 9545 break; 9546 } 9547 else { 9548 return SOC_E_UNAVAIL; 9549 } 9550 case portmodIntrTypeMacErr: 9551 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9552 *val = soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_ERRf); 9553 break; 9554 } 9555 else { 9556 return SOC_E_UNAVAIL; 9557 } 9558 case portmodIntrTypeTxPktUnderflow : 9559 case portmodIntrTypeTxPktOverflow : 9560 case portmodIntrTypeTxLlfcMsgOverflow : 9561 case portmodIntrTypeTxTSFifoOverflow : 9562 case portmodIntrTypeRxPktOverflow : 9563 case portmodIntrTypeRxMsgOverflow : 9564 case portmodIntrTypeTxCdcSingleBitErr : 9565 case portmodIntrTypeTxCdcDoubleBitErr : 9566 case portmodIntrTypeRxCdcSingleBitErr : 9567 case portmodIntrTypeRxCdcDoubleBitErr : 9568 case portmodIntrTypeLocalFaultStatus : 9569 case portmodIntrTypeRemoteFaultStatus : 9570 case portmodIntrTypeLinkInterruptionStatus : 9571 case portmodIntrTypeTsEntryValid : 9572 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9573 _SOC_IF_ERR_EXIT(xlmac_interrupt_status_get(unit, port, intr_type, val)); 9574 break; 9575 } 9576 else { 9577 return SOC_E_UNAVAIL; 9578 } 9579 default: 9580 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid interrupt type"))); 9581 break; 9582 } 9583 exit: 9584 SOC_FUNC_RETURN; 9585 } 9586 9587 int pm4x10_port_interrupts_get (int unit, int port, pm_info_t pm_info, 9588 int arr_max_size, uint32* intr_arr, uint32* size) 9589 { 9590 uint32 reg_val, cnt=0; 9591 int phy_acc; 9592 uint32 mac_intr_cnt = 0; 9593 pm_version_t pm_version; 9594 SOC_INIT_FUNC_DEFS; 9595 9596 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9597 _SOC_IF_ERR_EXIT(READ_XLPORT_INTR_STATUSr(unit, phy_acc, ®_val)); 9598 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 9599 9600 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MIB_TX_MEM_ERRf)) { 9601 if (cnt >= arr_max_size) { 9602 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9603 } 9604 intr_arr[cnt++] = portmodIntrTypeMibTxMemErr; 9605 } 9606 9607 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MIB_RX_MEM_ERRf)) { 9608 if (cnt >= arr_max_size) { 9609 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9610 } 9611 intr_arr[cnt++] = portmodIntrTypeMibRxMemErr; 9612 } 9613 9614 if(PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9615 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_TX_CDC_MEM_ERRf)) { 9616 if (cnt >= arr_max_size) { 9617 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9618 } 9619 intr_arr[cnt++] = portmodIntrTypeMacTxCdcMemErr; 9620 } 9621 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_RX_CDC_MEM_ERRf)) { 9622 if (cnt >= arr_max_size) { 9623 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9624 } 9625 intr_arr[cnt++] = portmodIntrTypeMacRxCdcMemErr; 9626 } 9627 } 9628 9629 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, TSC_ERRf)) { 9630 if (cnt >= arr_max_size) { 9631 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9632 } 9633 intr_arr[cnt++] = portmodIntrTypeTscErr; 9634 } 9635 if (soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, RX_FLOWCONTROL_REQ_FULLf)) { 9636 if (cnt >= arr_max_size) { 9637 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9638 } 9639 intr_arr[cnt++] = portmodIntrTypeRxFcReqFull; 9640 } 9641 9642 if(!PORTMOD_PM4x10_IS_GEN1(pm_version)) { 9643 if(soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, LINK_DOWNf)) { 9644 if (cnt >= arr_max_size) { 9645 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9646 } 9647 intr_arr[cnt++] = portmodIntrTypeLinkdown; 9648 } 9649 9650 if(soc_reg_field_get(unit, XLPORT_INTR_STATUSr, reg_val, MAC_ERRf)) { 9651 if (cnt >= arr_max_size) { 9652 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Insufficient Array size"))); 9653 } 9654 intr_arr[cnt++] = portmodIntrTypeMacErr; 9655 } 9656 9657 _SOC_IF_ERR_EXIT(xlmac_interrupts_status_get(unit, port, (arr_max_size- cnt), (intr_arr + cnt), &mac_intr_cnt)); 9658 cnt += mac_intr_cnt; 9659 } 9660 9661 *size = cnt; 9662 9663 exit: 9664 SOC_FUNC_RETURN; 9665 } 9666 9667 /*! 9668 * pm4x10_port_eee_clock_set 9669 * 9670 * @brief set EEE Config. 9671 * 9672 * @param [in] unit - unit id 9673 * @param [in] port - logical port 9674 * @param [in] eee - 9675 */ 9676 int pm4x10_port_eee_clock_set(int unit, int port, pm_info_t pm_info, 9677 const portmod_eee_clock_t* eee_clk) 9678 { 9679 int phy_acc; 9680 SOC_INIT_FUNC_DEFS; 9681 9682 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9683 9684 _SOC_IF_ERR_EXIT(WRITE_XLPORT_EEE_CLOCK_GATEr(unit, phy_acc, eee_clk->clock_gate)); 9685 _SOC_IF_ERR_EXIT(WRITE_XLPORT_EEE_CORE0_CLOCK_GATE_COUNTERr(unit, phy_acc, eee_clk->clock_count)); 9686 _SOC_IF_ERR_EXIT(WRITE_XLPORT_EEE_DURATION_TIMER_PULSEr(unit, phy_acc, eee_clk->timer_pulse)); 9687 9688 exit: 9689 SOC_FUNC_RETURN; 9690 } 9691 9692 9693 /*! 9694 * portmod_port_eee_clock_get 9695 * 9696 * @brief set EEE Config. 9697 * 9698 * @param [in] unit - unit id 9699 * @param [in] port - logical port 9700 * @param [out] eee - 9701 */ 9702 int pm4x10_port_eee_clock_get (int unit, int port, pm_info_t pm_info, 9703 portmod_eee_clock_t* eee_clk) 9704 { 9705 int phy_acc; 9706 SOC_INIT_FUNC_DEFS; 9707 9708 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9709 9710 _SOC_IF_ERR_EXIT(READ_XLPORT_EEE_CLOCK_GATEr(unit, phy_acc, &eee_clk->clock_gate)); 9711 _SOC_IF_ERR_EXIT(READ_XLPORT_EEE_CORE0_CLOCK_GATE_COUNTERr(unit, phy_acc, &eee_clk->clock_count)); 9712 _SOC_IF_ERR_EXIT(READ_XLPORT_EEE_DURATION_TIMER_PULSEr(unit, phy_acc, &eee_clk->timer_pulse)); 9713 9714 exit: 9715 SOC_FUNC_RETURN; 9716 } 9717 9718 int pm4x10_port_failover_mode_set(int unit, int port, pm_info_t pm_info, phymod_failover_mode_t failover) 9719 { 9720 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9721 int nof_phys; 9722 int port_index; 9723 uint32 bitmap; 9724 9725 SOC_INIT_FUNC_DEFS; 9726 9727 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 9728 &bitmap)); 9729 9730 if (PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 9731 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 9732 (_SOC_MSG("phy failover is not supported"))); 9733 } 9734 9735 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9736 phy_access ,(1+MAX_PHYN), 9737 &nof_phys)); 9738 9739 SOC_IF_ERROR_RETURN(portmod_port_phychain_failover_mode_set(unit, phy_access, nof_phys, failover)); 9740 9741 exit: 9742 SOC_FUNC_RETURN; 9743 } 9744 9745 int pm4x10_port_failover_mode_get(int unit, int port, pm_info_t pm_info, phymod_failover_mode_t* failover) 9746 { 9747 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9748 int nof_phys; 9749 int port_index; 9750 uint32 bitmap; 9751 9752 SOC_INIT_FUNC_DEFS; 9753 9754 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, 9755 &bitmap)); 9756 9757 if (PM_4x10_INFO(pm_info)->nof_phys[port_index] == 0) { 9758 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 9759 (_SOC_MSG("phy failover is not supported"))); 9760 } 9761 9762 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9763 phy_access ,(1+MAX_PHYN), 9764 &nof_phys)); 9765 9766 SOC_IF_ERROR_RETURN(portmod_port_phychain_failover_mode_get(unit, phy_access, nof_phys, failover)); 9767 9768 exit: 9769 SOC_FUNC_RETURN; 9770 } 9771 9772 int pm4x10_port_flow_control_set (int unit, int port, pm_info_t pm_info, 9773 int merge_mode_en, int parallel_fc_en) 9774 { 9775 int phy_acc, rv; 9776 uint32 rval; 9777 9778 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 9779 9780 rv = READ_XLPORT_FLOW_CONTROL_CONFIGr(unit, phy_acc, &rval); 9781 if (SOC_FAILURE(rv)) return (rv); 9782 9783 soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval, MERGE_MODE_ENf, merge_mode_en); 9784 soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval, PARALLEL_FC_ENf, parallel_fc_en); 9785 9786 return(WRITE_XLPORT_FLOW_CONTROL_CONFIGr(unit, phy_acc, rval)); 9787 } 9788 9789 int pm4x10_port_lane_map_set(int unit, int port, pm_info_t pm_info, uint32 flags, const phymod_lane_map_t* lane_map) 9790 { 9791 SOC_INIT_FUNC_DEFS; 9792 9793 PM_4x10_INFO(pm_info)->lane_map = *lane_map; 9794 9795 9796 SOC_FUNC_RETURN; 9797 } 9798 9799 int pm4x10_port_lane_map_get(int unit, int port, pm_info_t pm_info, uint32 flags, phymod_lane_map_t* lane_map) 9800 { 9801 SOC_INIT_FUNC_DEFS; 9802 9803 *lane_map = PM_4x10_INFO(pm_info)->lane_map; 9804 9805 9806 SOC_FUNC_RETURN; 9807 } 9808 9809 int pm4x10_xphy_lane_attach_to_pm (int unit, pm_info_t pm_info, int iphy, int phyn, const portmod_xphy_lane_connection_t* lane_conn) 9810 { 9811 portmod_xphy_lane_connection_t *candidate_lane_conn = NULL; 9812 int lane_index = 0, phy_index = 0; 9813 int pm_is_active = 0, rv = 0; 9814 int nof_phys = 0; 9815 uint32 xphy_id; 9816 int lane_mask; 9817 uint32 active_lanes; 9818 SOC_INIT_FUNC_DEFS; 9819 9820 /* Validate parameters */ 9821 _SOC_IF_ERR_EXIT(portmod_xphy_lane_connection_t_validate(unit,lane_conn)); 9822 9823 if (MAX_PHYN <= phyn){ 9824 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid Ext PHY location."))); 9825 } 9826 /* Making sure the port macro is not active */ 9827 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isActive], &pm_is_active); 9828 _SOC_IF_ERR_EXIT(rv); 9829 9830 /* Attaching the external phy to the phy chain of the port macro */ 9831 9832 /* find lane index corresponding to internal physical port */ 9833 lane_index = 0; 9834 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy_index) { 9835 if (phy_index == iphy) { 9836 break; 9837 } 9838 lane_index++; 9839 } 9840 9841 if (!SOC_WARM_BOOT(unit)) { 9842 rv = PM4x10_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, lane_conn, phyn-1, lane_index); 9843 _SOC_IF_ERR_EXIT(rv); 9844 candidate_lane_conn = &(PM_4x10_INFO(pm_info)->lane_conn[phyn-1][lane_index]); 9845 sal_memcpy(candidate_lane_conn, lane_conn, sizeof(portmod_xphy_lane_connection_t)); 9846 9847 xphy_id = candidate_lane_conn->xphy_id; 9848 lane_mask = candidate_lane_conn->ss_lane_mask; 9849 9850 /* 9851 * Keeping track of the xphy lane usage. If the xphy lane is connected 9852 * it will set the corresponding bit to mark as lane is active. 9853 */ 9854 9855 if ((lane_mask != -1) && (xphy_id != PORTMOD_XPHY_ID_INVALID)) { 9856 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_get(unit, xphy_id, &active_lanes)); 9857 active_lanes |= lane_mask; 9858 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_set(unit,xphy_id, active_lanes)); 9859 } 9860 9861 PM4x10_PORT_NUM_PHYS_GET(unit, pm_info, &nof_phys, lane_index); 9862 if (nof_phys <= phyn) { 9863 nof_phys = phyn + 1; 9864 rv = PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, &nof_phys, lane_index); 9865 _SOC_IF_ERR_EXIT(rv); 9866 PM_4x10_INFO(pm_info)->nof_phys[lane_index] = phyn+1; 9867 } 9868 } 9869 9870 exit: 9871 SOC_FUNC_RETURN; 9872 } 9873 9874 int pm4x10_xphy_lane_detach_from_pm (int unit, pm_info_t pm_info, int iphy, int phyn, portmod_xphy_lane_connection_t* lane_conn) 9875 { 9876 portmod_xphy_lane_connection_t *candidate_lane_conn = NULL; 9877 int lane_index = 0, phy_index = 0; 9878 int pm_is_active = 0, rv = 0; 9879 int nof_phys = 0; 9880 uint32 active_lanes; 9881 uint32 xphy_id; 9882 int lane_mask; 9883 SOC_INIT_FUNC_DEFS; 9884 9885 if (MAX_PHYN <= phyn){ 9886 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid Ext PHY location."))); 9887 } 9888 /* Making sure the port macro is not active */ 9889 rv = SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, pm_info->wb_vars_ids[isActive], &pm_is_active); 9890 _SOC_IF_ERR_EXIT(rv); 9891 9892 /* Attaching the external phy to the phy chain of the port macro */ 9893 9894 /* find lane index corresponding to internal physical port */ 9895 lane_index = 0; 9896 PORTMOD_PBMP_ITER(PM_4x10_INFO(pm_info)->phys, phy_index) { 9897 if (phy_index == iphy) { 9898 break; 9899 } 9900 lane_index++; 9901 } 9902 9903 if (!SOC_WARM_BOOT(unit)) { 9904 candidate_lane_conn = &(PM_4x10_INFO(pm_info)->lane_conn[phyn-1][lane_index]); 9905 9906 xphy_id = candidate_lane_conn->xphy_id; 9907 lane_mask = candidate_lane_conn->ss_lane_mask; 9908 9909 if ((lane_mask != -1) && (xphy_id != PORTMOD_XPHY_ID_INVALID)) { 9910 9911 /* 9912 * Keeping track of the xphy lane usage. If the xphy lane is disconnected 9913 * it will clear the corresponding bit to mark as lane is not active. 9914 * When none of the lane are active, it clear intialization status, 9915 * phy_type and probe status. When it probe again, it will re-initialize 9916 * this xphy again. 9917 */ 9918 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_get(unit, xphy_id, &active_lanes)); 9919 active_lanes &= ~lane_mask; 9920 _SOC_IF_ERR_EXIT(portmod_xphy_active_lane_set(unit, xphy_id, active_lanes)); 9921 9922 if (active_lanes == 0) { /* none of the lanes are active */ 9923 _SOC_IF_ERR_EXIT(portmod_xphy_core_probed_set(unit, xphy_id, 0)); 9924 _SOC_IF_ERR_EXIT(portmod_xphy_phy_type_set(unit,xphy_id,phymodDispatchTypeInvalid)); 9925 _SOC_IF_ERR_EXIT(portmod_xphy_is_initialized_set(unit, xphy_id,0)); 9926 } 9927 } 9928 9929 portmod_xphy_lane_connection_t_init(unit, candidate_lane_conn); 9930 rv = PM4x10_PORT_LANE_CONNECTION_DB_SET(unit, pm_info, candidate_lane_conn, phyn-1, lane_index); 9931 _SOC_IF_ERR_EXIT(rv); 9932 9933 if (phyn > 0) { 9934 nof_phys = phyn; 9935 rv = PM4x10_PORT_NUM_PHYS_SET(unit, pm_info, &nof_phys, lane_index); 9936 _SOC_IF_ERR_EXIT(rv); 9937 PM_4x10_INFO(pm_info)->nof_phys[lane_index] = nof_phys; 9938 } 9939 } 9940 9941 exit: 9942 SOC_FUNC_RETURN; 9943 } 9944 9945 int pm4x10_port_control_phy_timesync_set(int unit, int port, pm_info_t pm_info, const portmod_port_control_phy_timesync_t config, uint64 value) 9946 { 9947 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9948 int nof_phys; 9949 SOC_INIT_FUNC_DEFS; 9950 9951 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9952 phy_access ,(1+MAX_PHYN), 9953 &nof_phys)); 9954 9955 SOC_IF_ERROR_RETURN(portmod_port_phychain_control_phy_timesync_set(unit, port, phy_access, nof_phys, 9956 config, value)); 9957 9958 exit: 9959 SOC_FUNC_RETURN; 9960 } 9961 9962 int pm4x10_port_control_phy_timesync_get(int unit, int port, pm_info_t pm_info, const portmod_port_control_phy_timesync_t config, uint64* value) 9963 { 9964 phymod_phy_access_t phy_access[1+MAX_PHYN]; 9965 int nof_phys; 9966 SOC_INIT_FUNC_DEFS; 9967 9968 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 9969 phy_access ,(1+MAX_PHYN), 9970 &nof_phys)); 9971 9972 SOC_IF_ERROR_RETURN(portmod_port_phychain_control_phy_timesync_get(unit, port, phy_access, nof_phys, 9973 config, value)); 9974 9975 exit: 9976 SOC_FUNC_RETURN; 9977 } 9978 9979 int pm4x10_port_update_dynamic_state(int unit, int port, pm_info_t pm_info, uint32_t port_dynamic_state) { 9980 9981 int rv = 0; 9982 int port_index; 9983 uint32_t bitmap; 9984 phymod_an_mode_type_t an_mode; 9985 uint32_t an_updated = FALSE, tmp_state; 9986 SOC_INIT_FUNC_DEFS; 9987 9988 9989 rv = _pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap); 9990 if (SOC_FAILURE(rv)) { 9991 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Unable to retrieve the port index"))); 9992 } 9993 9994 if (PORTMOD_PORT_IS_AUTONEG_MODE_UPDATED(port_dynamic_state)) { 9995 rv = PM4x10_PORT_DYNAMIC_STATE_GET(unit, pm_info, &tmp_state, 9996 port_index); 9997 _SOC_IF_ERR_EXIT(rv); 9998 /*we need to change the data base An_mode based on the new value */ 9999 switch (port_dynamic_state >> 16 & 0xffff) { 10000 case SOC_PHY_CONTROL_AUTONEG_MODE_CL37: 10001 an_mode = phymod_AN_MODE_CL37; 10002 an_updated = TRUE; 10003 break; 10004 case SOC_PHY_CONTROL_AUTONEG_MODE_CL37_BAM: 10005 an_mode = phymod_AN_MODE_CL37BAM; 10006 an_updated = TRUE; 10007 break; 10008 case SOC_PHY_CONTROL_AUTONEG_MODE_CL73: 10009 an_mode = phymod_AN_MODE_CL73; 10010 an_updated = TRUE; 10011 break; 10012 case SOC_PHY_CONTROL_AUTONEG_MODE_CL73_BAM: 10013 an_mode = phymod_AN_MODE_CL73BAM; 10014 an_updated = TRUE; 10015 break; 10016 default: 10017 break; 10018 } 10019 } else if (PORTMOD_PORT_IS_DEFAULT_TX_PARAMS_UPDATED(port_dynamic_state)) { 10020 rv = PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, 10021 port_dynamic_state, port_index); 10022 _SOC_IF_ERR_EXIT(rv); 10023 } 10024 if (an_updated == TRUE) { 10025 rv = PM4x10_AN_MODE_SET(unit, pm_info, an_mode, port_index); 10026 _SOC_IF_ERR_EXIT(rv); 10027 PORTMOD_PORT_AUTONEG_MODE_UPDATED_SET(tmp_state); 10028 rv = PM4x10_PORT_DYNAMIC_STATE_SET(unit, pm_info, tmp_state, 10029 port_index); 10030 _SOC_IF_ERR_EXIT(rv); 10031 } 10032 10033 exit: 10034 SOC_FUNC_RETURN; 10035 10036 } 10037 10038 int pm4x10_port_phy_op_mode_get(int unit, int port, pm_info_t pm_info, phymod_operation_mode_t* val) 10039 { 10040 uint32 bitmap; 10041 int port_index, rv = 0, nof_phys = 0; 10042 phymod_phy_access_t phy_access[1+MAX_PHYN]; 10043 phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer; 10044 SOC_INIT_FUNC_DEFS; 10045 10046 rv = _pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap); 10047 if SOC_FAILURE(rv) return (rv); 10048 10049 _SOC_IF_ERR_EXIT 10050 (portmod_port_chain_phy_access_get(unit, port, pm_info, 10051 phy_access ,(1+MAX_PHYN), 10052 &nof_phys)); 10053 rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, nof_phys, &phy_op_mode); 10054 if (SOC_SUCCESS(rv)) { 10055 *val = phy_op_mode; 10056 } else if (rv == SOC_E_UNAVAIL) { 10057 rv = PM4x10_PORT_OP_MODE_GET(unit, pm_info, val, port_index); 10058 } 10059 _SOC_IF_ERR_EXIT(rv); 10060 10061 exit: 10062 SOC_FUNC_RETURN; 10063 10064 } 10065 10066 int pm4x10_port_medium_config_set(int unit, int port, pm_info_t pm_info, soc_port_medium_t medium, soc_phy_config_t* config) 10067 { 10068 int rv; 10069 SOC_INIT_FUNC_DEFS; 10070 10071 rv = portmod_port_phychain_medium_config_set(unit, port, medium, config); 10072 if (SOC_FAILURE(rv)) return (rv); 10073 10074 SOC_FUNC_RETURN; 10075 } 10076 10077 int pm4x10_port_medium_config_get(int unit, int port, pm_info_t pm_info, soc_port_medium_t medium, soc_phy_config_t* config) 10078 { 10079 int rv; 10080 SOC_INIT_FUNC_DEFS; 10081 10082 rv = portmod_port_phychain_medium_config_get(unit, port, medium, config); 10083 10084 if (SOC_FAILURE(rv)) return (rv); 10085 10086 SOC_FUNC_RETURN; 10087 } 10088 10089 int pm4x10_port_medium_get(int unit, int port, pm_info_t pm_info, soc_port_medium_t* medium) 10090 { 10091 int rv; 10092 SOC_INIT_FUNC_DEFS; 10093 10094 rv = portmod_port_phychain_medium_get(unit, port, medium); 10095 if (SOC_FAILURE(rv)) return (rv); 10096 10097 SOC_FUNC_RETURN; 10098 } 10099 10100 int pm4x10_port_multi_get(int unit, int port, pm_info_t pm_info, portmod_multi_get_t* multi_get) 10101 { 10102 phymod_phy_access_t phy_access[1+MAX_PHYN]; 10103 int nof_phys; 10104 SOC_INIT_FUNC_DEFS; 10105 10106 _SOC_IF_ERR_EXIT 10107 (portmod_port_chain_phy_access_get(unit, port, pm_info, 10108 phy_access ,(1+MAX_PHYN), 10109 &nof_phys)); 10110 _SOC_IF_ERR_EXIT 10111 (portmod_port_phychain_multi_get(unit, port, phy_access, nof_phys, multi_get)); 10112 10113 exit: 10114 SOC_FUNC_RETURN; 10115 10116 } 10117 10118 int pm4x10_port_polarity_set(int unit, int port, pm_info_t pm_info, const phymod_polarity_t* polarity) 10119 { 10120 SOC_INIT_FUNC_DEFS; 10121 10122 PM_4x10_INFO(pm_info)->polarity = *polarity; 10123 10124 10125 SOC_FUNC_RETURN; 10126 } 10127 10128 int pm4x10_port_polarity_get(int unit, int port, pm_info_t pm_info, phymod_polarity_t* polarity) 10129 { 10130 SOC_INIT_FUNC_DEFS; 10131 10132 *polarity = PM_4x10_INFO(pm_info)->polarity; 10133 10134 10135 SOC_FUNC_RETURN; 10136 } 10137 10138 int pm4x10_pm_is_in_pm12x10(int unit, pm_info_t pm_info, int* in_pm12x10) 10139 { 10140 SOC_INIT_FUNC_DEFS; 10141 10142 if (PM_4x10_INFO(pm_info)->in_pm12x10){ 10143 *in_pm12x10 = 1; 10144 } else { 10145 *in_pm12x10 = 0; 10146 } 10147 10148 SOC_FUNC_RETURN; 10149 10150 } 10151 10152 /* 10153 * This function will be called during speed change or flexport. 10154 * This function returns pll_div value by looking up the static table. 10155 * In flexport scenario, this funciton might be called before port is attached. The port number may be invalid(-1). 10156 * So this function can't access registers by logical port number, or access Warmboot DB. 10157 */ 10158 int pm4x10_port_pll_div_get(int unit, int port, pm_info_t pm_info, 10159 const portmod_port_resources_t* port_resource, 10160 uint32_t* pll_div) 10161 { 10162 pm_version_t pm_version; 10163 SOC_INIT_FUNC_DEFS; 10164 10165 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 10166 10167 switch (port_resource->speed){ 10168 case 10: 10169 case 100: 10170 case 1000: 10171 case 2500: 10172 if (PORTMOD_SERDES_1000X_AT_6250_GET(port_resource->flag)) { 10173 *pll_div = phymod_TSCE_PLL_DIV40; 10174 } else if (PORTMOD_SERDES_1000X_AT_12500_GET(port_resource->flag)) { 10175 *pll_div = phymod_TSCE_PLL_DIV80; 10176 } else { 10177 *pll_div = phymod_TSCE_PLL_DIV66; 10178 } 10179 break; 10180 case 5000: 10181 if (PORTMOD_SERDES_1000X_AT_12500_GET(port_resource->flag)) { 10182 *pll_div = phymod_TSCE_PLL_DIV80; 10183 } else { 10184 if (PORTMOD_PM4x10_IS_GEN2_16nm(pm_version)) { 10185 *pll_div = phymod_TSCE_PLL_DIV66; 10186 } else { 10187 *pll_div = phymod_TSCE_PLL_DIV40; 10188 } 10189 } 10190 break; 10191 case 10000: 10192 if (port_resource->num_lane == 1){ 10193 *pll_div = phymod_TSCE_PLL_DIV66; 10194 } else { 10195 if (PORTMOD_PM4x10_IS_GEN2_16nm(pm_version)) { 10196 *pll_div = phymod_TSCE_PLL_DIV80; 10197 } else { 10198 *pll_div = phymod_TSCE_PLL_DIV40; 10199 } 10200 } 10201 break; 10202 case 105000: 10203 *pll_div = phymod_TSCE_PLL_DIV42; 10204 break; 10205 case 11000: 10206 if (port_resource->num_lane == 1){ 10207 *pll_div = phymod_TSCE_PLL_DIV70; 10208 } else { 10209 *pll_div = phymod_TSCE_PLL_DIV42; 10210 } 10211 break; 10212 case 12000: 10213 *pll_div = phymod_TSCE_PLL_DIV80; 10214 break; 10215 case 13000: 10216 if (port_resource->num_lane == 2){ 10217 *pll_div = phymod_TSCE_PLL_DIV42; 10218 } else { 10219 *pll_div = phymod_TSCE_PLL_DIV52; 10220 } 10221 break; 10222 case 15000: 10223 *pll_div = phymod_TSCE_PLL_DIV66; 10224 break; 10225 case 15700: 10226 *pll_div = phymod_TSCE_PLL_DIV52; 10227 break; 10228 case 16000: 10229 *pll_div = phymod_TSCE_PLL_DIV64; 10230 break; 10231 case 20000: 10232 if (port_resource->num_lane == 2){ 10233 *pll_div = phymod_TSCE_PLL_DIV66; 10234 } else { 10235 if (PORTMOD_PM4x10_IS_GEN2_16nm(pm_version)) { 10236 *pll_div = phymod_TSCE_PLL_DIV80; 10237 } else { 10238 *pll_div = phymod_TSCE_PLL_DIV40; 10239 } 10240 } 10241 break; 10242 case 21000: 10243 if (port_resource->num_lane == 2){ 10244 *pll_div = phymod_TSCE_PLL_DIV70; 10245 } else { 10246 *pll_div = phymod_TSCE_PLL_DIV42; 10247 } 10248 break; 10249 case 25000: 10250 if (port_resource->num_lane == 2){ 10251 *pll_div = phymod_TSCE_PLL_DIV80; 10252 } else { 10253 *pll_div = phymod_TSCE_PLL_DIV42; 10254 } 10255 break; 10256 case 25450: 10257 *pll_div = phymod_TSCE_PLL_DIV42; 10258 break; 10259 case 30000: 10260 case 32000: 10261 *pll_div = phymod_TSCE_PLL_DIV52; 10262 break; 10263 case 40000: 10264 *pll_div = phymod_TSCE_PLL_DIV66; 10265 break; 10266 case 42000: 10267 *pll_div = phymod_TSCE_PLL_DIV70; 10268 break; 10269 case 48000: 10270 *pll_div = phymod_TSCE_PLL_DIV80; 10271 break; 10272 case 100000: 10273 *pll_div = phymod_TSCE_PLL_DIV66; 10274 break; 10275 case 106000: 10276 case 107000: 10277 *pll_div = phymod_TSCE_PLL_DIV70; 10278 break; 10279 case 120000: 10280 *pll_div = phymod_TSCE_PLL_DIV66; 10281 break; 10282 case 127000: 10283 *pll_div = phymod_TSCE_PLL_DIV70; 10284 break; 10285 default: 10286 *pll_div = phymod_TSCE_PLL_DIV66; 10287 break; 10288 } 10289 10290 exit: 10291 SOC_FUNC_RETURN; 10292 } 10293 10294 #define VCO_6P25G 0x1 10295 #define VCO_10P3125G 0x2 10296 #define VCO_10P9375G 0x4 10297 #define VCO_12P5G 0x8 10298 #define VCO_6P5625G 0x10 10299 #define VCO_6P25G_10P3125G (VCO_6P25G | VCO_10P3125G) 10300 #define VCO_6P25G_10P9375G (VCO_6P25G | VCO_10P9375G) 10301 #define VCO_10P3125G_10P9375G (VCO_10P3125G | VCO_10P9375G) 10302 #define VCO_6P25G_12P5G (VCO_6P25G | VCO_12P5G) 10303 #define VCO_6P25G_6P5625G (VCO_6P25G | VCO_6P5625G) 10304 10305 STATIC 10306 int _pm4x10_port_vcobitmap_to_vcos(int unit, pm_info_t pm_info, int vco_bmp, portmod_dual_vcos_t* dual_vco) 10307 { 10308 pm_version_t pm_version; 10309 SOC_INIT_FUNC_DEFS; 10310 10311 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 10312 10313 if (PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 10314 /* PLL1 always is 6.25G in TSCE_DPLL Gen3 */ 10315 switch (vco_bmp) { 10316 case VCO_6P25G: 10317 case VCO_10P3125G: 10318 case VCO_6P25G_10P3125G: 10319 dual_vco->vco_0 = portmodVCO10P3125G; 10320 dual_vco->vco_1 = portmodVCO6P25G; 10321 break; 10322 case VCO_10P9375G: 10323 case VCO_6P25G_10P9375G: 10324 dual_vco->vco_0 = portmodVCO10P9375G; 10325 dual_vco->vco_1 = portmodVCO6P25G; 10326 break; 10327 case VCO_12P5G: 10328 case VCO_6P25G_12P5G: 10329 dual_vco->vco_0 = portmodVCO12P5G; 10330 dual_vco->vco_1 = portmodVCO6P25G; 10331 break; 10332 case VCO_6P5625G: 10333 case VCO_6P25G_6P5625G: 10334 dual_vco->vco_0 = portmodVCO6P5625G; 10335 dual_vco->vco_1 = portmodVCO6P25G; 10336 break; 10337 default: 10338 LOG_ERROR(BSL_LS_SOC_PORT, 10339 (BSL_META_U(unit, "fail to get vcos -- no vcos combination vco_bmp 0x%x\n"), vco_bmp)); 10340 return SOC_E_PARAM; 10341 } 10342 } else { /* Convert dual vcos for other PM version in future */ 10343 return SOC_E_INTERNAL; 10344 } 10345 10346 exit: 10347 SOC_FUNC_RETURN; 10348 } 10349 10350 STATIC 10351 int _pm4x10_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) 10352 { 10353 int index, port_index; 10354 int vco_bitmap[4] = {0}; 10355 int vco_bmp = 0; 10356 int pll_divider_req = 66; 10357 uint32_t bitmap; 10358 SOC_INIT_FUNC_DEFS; 10359 10360 /* Get pll_divider_req only when port is valid. 10361 * That port ID is -1 means that the port is new port in flexport, such as 40G --> 4x10G 10362 */ 10363 if (port != -1) { 10364 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get (unit, port, pm_info, &port_index, &bitmap)); 10365 _SOC_IF_ERR_EXIT(PM4x10_PORT_PLL_DIVIDER_REQ_GET(unit, pm_info, &pll_divider_req, port_index)); 10366 } 10367 10368 for (index = 0; index < size; index++) { 10369 switch (speed_config_list[index].num_lanes) { 10370 case 1: 10371 if (speed_config_list[index].speed == 10 || 10372 speed_config_list[index].speed == 100 || 10373 speed_config_list[index].speed == 1000 || 10374 speed_config_list[index].speed == 5000) { 10375 if (pll_divider_req == 40) { 10376 vco_bitmap[index] = VCO_6P25G; 10377 } else { 10378 vco_bitmap[index] = VCO_10P3125G; 10379 } 10380 } else if (speed_config_list[index].speed ==2500) { 10381 vco_bitmap[index] = VCO_6P25G; 10382 } else if (speed_config_list[index].speed == 10000) { 10383 vco_bitmap[index] = VCO_10P3125G; 10384 } else if (speed_config_list[index].speed == 11000) { 10385 vco_bitmap[index] = VCO_10P9375G; 10386 } else if (speed_config_list[index].speed == 12000) { 10387 vco_bitmap[index] = VCO_12P5G; 10388 } 10389 break; 10390 case 2: 10391 if (speed_config_list[index].speed == 20000) { 10392 vco_bitmap[index] = VCO_10P3125G; 10393 } else if (speed_config_list[index].speed == 21000) { 10394 vco_bitmap[index] = VCO_10P9375G; 10395 } else if (speed_config_list[index].speed == 24000) { 10396 vco_bitmap[index] = VCO_12P5G; 10397 } 10398 break; 10399 case 4: 10400 if (speed_config_list[index].speed == 10000) { 10401 vco_bitmap[index] = VCO_6P25G; 10402 } else if (speed_config_list[index].speed == 20000) { 10403 vco_bitmap[index] = VCO_6P25G; 10404 } else if (speed_config_list[index].speed == 21000) { 10405 vco_bitmap[index] = VCO_6P5625G; 10406 } else if (speed_config_list[index].speed == 40000) { 10407 vco_bitmap[index] = VCO_10P3125G; 10408 } else if (speed_config_list[index].speed == 42000) { 10409 vco_bitmap[index] = VCO_10P9375G; 10410 } else if (speed_config_list[index].speed == 48000) { 10411 vco_bitmap[index] = VCO_12P5G; 10412 } 10413 break; 10414 default: 10415 LOG_ERROR(BSL_LS_SOC_PORT, 10416 (BSL_META_U(unit, "fail to get vcos -- no vco matches lane %d speed %d\n"), 10417 speed_config_list[index].num_lanes, speed_config_list[index].speed)); 10418 return SOC_E_PARAM; 10419 } 10420 vco_bmp |= vco_bitmap[index]; 10421 } 10422 10423 _SOC_IF_ERR_EXIT(_pm4x10_port_vcobitmap_to_vcos(unit, pm_info, vco_bmp, dual_vco)); 10424 10425 exit: 10426 SOC_FUNC_RETURN; 10427 } 10428 10429 STATIC 10430 int _pm4x10_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) 10431 { 10432 int pll_index; 10433 portmod_dual_vcos_t dual_vcos; 10434 uint32_t *vco = (uint32_t *)&dual_vcos; 10435 uint32_t *div = (uint32_t *)dual_plls; 10436 SOC_INIT_FUNC_DEFS; 10437 10438 portmod_dual_vcos_t_init(unit, &dual_vcos); 10439 10440 _SOC_IF_ERR_EXIT(_pm4x10_port_vcos_get(unit, port, pm_info, speed_config, size, &dual_vcos)); 10441 /* Only support refclock 156.25M now */ 10442 for (pll_index = 0; pll_index <2; pll_index++) { 10443 switch (*(vco + pll_index)){ 10444 case portmodVCO10P3125G: 10445 *(div + pll_index) = phymod_TSCE_PLL_DIV66; 10446 break; 10447 case portmodVCO10P9375G: 10448 *(div + pll_index) = phymod_TSCE_PLL_DIV70; 10449 break; 10450 case portmodVCO12P5G: 10451 *(div + pll_index) = phymod_TSCE_PLL_DIV80; 10452 break; 10453 case portmodVCO6P5625G: 10454 *(div + pll_index) = phymod_TSCE_PLL_DIV42; 10455 break; 10456 case portmodVCO6P25G: 10457 *(div + pll_index) = phymod_TSCE_PLL_DIV40; 10458 break; 10459 default: 10460 *(div + pll_index) = phymod_TSCE_PLL_DIV66; 10461 break; 10462 } 10463 } 10464 10465 exit: 10466 SOC_FUNC_RETURN; 10467 } 10468 10469 10470 int pm4x10_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) 10471 { 10472 pm_version_t pm_version; 10473 SOC_INIT_FUNC_DEFS; 10474 10475 _SOC_IF_ERR_EXIT(_pm4x10_pm_version_get(unit, pm_info, &pm_version)); 10476 /* Add other dual PLLs PM here*/ 10477 if (!PORTMOD_PM4x10_IS_GEN3_28nm(pm_version)) { 10478 return SOC_E_UNAVAIL; 10479 } 10480 10481 if (size == 0) { 10482 return SOC_E_PARAM; 10483 } 10484 10485 _SOC_IF_ERR_EXIT(_pm4x10_port_vcos_get(unit, port, pm_info, speed_config_list, size, dual_vco)); 10486 10487 exit: 10488 SOC_FUNC_RETURN; 10489 } 10490 10491 int pm4x10_port_master_set(int unit, int port, pm_info_t pm_info, int master_mode) 10492 { 10493 SOC_INIT_FUNC_DEFS; 10494 10495 _SOC_IF_ERR_EXIT(portmod_port_phychain_master_set(unit, port, pm_info, master_mode)); 10496 10497 exit: 10498 SOC_FUNC_RETURN; 10499 } 10500 10501 int pm4x10_port_master_get(int unit, int port, pm_info_t pm_info, int* master_mode) 10502 { 10503 SOC_INIT_FUNC_DEFS; 10504 10505 _SOC_IF_ERR_EXIT(portmod_port_phychain_master_get(unit, port, pm_info, master_mode)); 10506 10507 exit: 10508 SOC_FUNC_RETURN; 10509 } 10510 10511 /* 10512 * Function: 10513 * _pm4x10_preemption_rx_frag_size_set 10514 * Purpose: 10515 * This function configures preemption rx fragment size 10516 * of final and non-final fragments. 10517 * 10518 * Parameters: 10519 * unit -(IN) Device unit number 10520 * port -(IN) logical port 10521 * final_frag -(IN) if set indicates final fragment 10522 * value -(IN) value of fragment size 10523 */ 10524 STATIC 10525 int _pm4x10_preemption_rx_frag_size_set(int unit, int port, pm_info_t pm_info, 10526 uint32 frag, uint32 value) 10527 { 10528 int phy_acc; 10529 uint32_t rval; 10530 soc_field_t field; 10531 SOC_INIT_FUNC_DEFS; 10532 10533 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 10534 10535 _SOC_IF_ERR_EXIT(READ_XLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, &rval)); 10536 10537 if (frag == PORTMOD_PREEMPTION_FINAL_FRAG) { 10538 field = MIN_FINAL_FRAG_SIZEf; 10539 } else { 10540 field = MIN_NON_FINAL_FRAG_SIZEf; 10541 } 10542 10543 soc_reg_field_set(unit, XLPORT_MIB_MIN_FRAG_SIZEr, &rval, field, value); 10544 _SOC_IF_ERR_EXIT(WRITE_XLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, rval)); 10545 10546 exit: 10547 SOC_FUNC_RETURN; 10548 10549 } 10550 10551 /* 10552 * Function: 10553 * _pm4x10_preemption_rx_frag_size_get 10554 * Purpose: 10555 * This function configures preemption rx fragment size 10556 * of final and non-final fragments. 10557 * 10558 * Parameters: 10559 * unit -(IN) Device unit number 10560 * port -(IN) logical port 10561 * final_frag -(IN) if set indicates final fragment 10562 * value -(OUT) value of fragment size 10563 */ 10564 STATIC 10565 int _pm4x10_preemption_rx_frag_size_get(int unit, int port, pm_info_t pm_info, 10566 uint32 frag, uint32 *value) 10567 { 10568 int phy_acc; 10569 uint32_t rval; 10570 soc_field_t field; 10571 SOC_INIT_FUNC_DEFS; 10572 10573 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 10574 10575 _SOC_IF_ERR_EXIT(READ_XLPORT_MIB_MIN_FRAG_SIZEr(unit, phy_acc, &rval)); 10576 10577 if (frag == PORTMOD_PREEMPTION_FINAL_FRAG) { 10578 field = MIN_FINAL_FRAG_SIZEf; 10579 } else { 10580 field = MIN_NON_FINAL_FRAG_SIZEf; 10581 } 10582 10583 *value = soc_reg_field_get(unit, XLPORT_MIB_MIN_FRAG_SIZEr, rval, field); 10584 10585 exit: 10586 SOC_FUNC_RETURN; 10587 10588 } 10589 10590 /* 10591 * Function: 10592 * pm4x10_preemption_control_set 10593 * Purpose: 10594 * This function configures preemption feature parameters 10595 * The application layer has to call this function with 10596 * associated preemption-controls to configure parameters. 10597 * Parameters: 10598 * unit -(IN) Device unit number 10599 * port -(IN) logical port 10600 * type -(IN) preemption parameter to be configured 10601 * value -(IN) value 10602 * Returns: 10603 * Status 10604 */ 10605 int pm4x10_preemption_control_set(int unit, int port, pm_info_t pm_info, 10606 portmod_preemption_control_t type, 10607 uint32 value) 10608 { 10609 SOC_INIT_FUNC_DEFS; 10610 10611 switch(type) { 10612 case portmodPreemptionControlInvalid: 10613 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10614 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 10615 break; 10616 case portmodPreemptionControlPreemptionSupport: 10617 /* Enable/disable port preemption capability support */ 10618 _SOC_IF_ERR_EXIT(xlmac_preemption_mode_set(unit, port, value)); 10619 break; 10620 case portmodPreemptionControlEnableTx: 10621 /* 10622 * Enable/disable port preemption on tx side 10623 * if verify_enable = 1 10624 * this function call blocks until, verify operation is complete 10625 * if verify_enable = 0 10626 * means static preemption, function call returns immediately 10627 * after enabling preemption in the hardware in tx direction 10628 */ 10629 _SOC_IF_ERR_EXIT(xlmac_preemption_tx_enable_set(unit, port, value)); 10630 break; 10631 case portmodPreemptionControlVerifyEnable: 10632 /* 10633 * Enable/disable verify operation. 10634 * Before enabling the verify operation on a port, 10635 * the number of attempts for a veriy operation and 10636 * the timeout for each verify operation should be configured 10637 */ 10638 _SOC_IF_ERR_EXIT( 10639 xlmac_preemption_verify_enable_set(unit, port, value)); 10640 break; 10641 case portmodPreemptionControlVerifyTime: 10642 /* 10643 * Configuring the verify timeout is valid only when verify 10644 * operation is enabled. 10645 * The timeout here means, if verify operation is not complete 10646 * success/failure/inprogress after the (timeout + 1) millisecs 10647 * the MAC sends another verify message to the link partner 10648 */ 10649 _SOC_IF_ERR_EXIT( 10650 xlmac_preemption_verify_time_set(unit, port, value)); 10651 break; 10652 case portmodPreemptionControlVerifyAttempts: 10653 /* 10654 * Configuring the number of verify attempts is valid only when 10655 * verify operation is enabled. 10656 * If verify operation is not complete success/failure/inprogress 10657 * after the (timeout + 1) millisecs the MAC sends another verify 10658 * to the link partner. The MAC tries for (num_verify_attempts + 1) 10659 * to complete the verify operation. 10660 */ 10661 _SOC_IF_ERR_EXIT( 10662 xlmac_preemption_verify_attempts_set(unit, port, value)); 10663 break; 10664 case portmodPreemptionControlNonFinalFragSizeRx: 10665 /* configure non-final rx fragment size */ 10666 _SOC_IF_ERR_EXIT( 10667 _pm4x10_preemption_rx_frag_size_set(unit, port, pm_info, 10668 PORTMOD_PREEMPTION_NON_FINAL_FRAG, 10669 value)); 10670 break; 10671 case portmodPreemptionControlFinalFragSizeRx: 10672 /* configure final rx fragment size */ 10673 _SOC_IF_ERR_EXIT( 10674 _pm4x10_preemption_rx_frag_size_set(unit, port, pm_info, 10675 PORTMOD_PREEMPTION_FINAL_FRAG, 10676 value)); 10677 break; 10678 default: 10679 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10680 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 10681 break; 10682 } 10683 10684 exit: 10685 SOC_FUNC_RETURN; 10686 10687 } 10688 10689 /* 10690 * Function: 10691 * pm4x10_preemption_control_get 10692 * Purpose: 10693 * This function gets the value of preemption parameters 10694 * configured. The application layer has to call this function with 10695 * associated preemption-controls to configure parameters. 10696 * Parameters: 10697 * unit -(IN) Device unit number 10698 * port -(IN) logical port 10699 * type -(IN) preemption parameter to be configured 10700 * value -(OUT) value returned from hardware 10701 * Returns: 10702 * Status 10703 */ 10704 int pm4x10_preemption_control_get(int unit, int port, pm_info_t pm_info, 10705 portmod_preemption_control_t type, 10706 uint32 *value) 10707 { 10708 SOC_INIT_FUNC_DEFS; 10709 10710 switch(type) { 10711 case portmodPreemptionControlInvalid: 10712 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10713 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 10714 break; 10715 case portmodPreemptionControlPreemptionSupport: 10716 _SOC_IF_ERR_EXIT(xlmac_preemption_mode_get(unit, port, value)); 10717 break; 10718 case portmodPreemptionControlEnableTx: 10719 _SOC_IF_ERR_EXIT(xlmac_preemption_tx_enable_get(unit, port, value)); 10720 break; 10721 case portmodPreemptionControlVerifyEnable: 10722 _SOC_IF_ERR_EXIT( 10723 xlmac_preemption_verify_enable_get(unit, port, value)); 10724 break; 10725 case portmodPreemptionControlVerifyTime: 10726 _SOC_IF_ERR_EXIT( 10727 xlmac_preemption_verify_time_get(unit, port, value)); 10728 break; 10729 case portmodPreemptionControlVerifyAttempts: 10730 _SOC_IF_ERR_EXIT( 10731 xlmac_preemption_verify_attempts_get(unit, port, value)); 10732 break; 10733 case portmodPreemptionControlNonFinalFragSizeRx: 10734 /* get non-final rx fragment size */ 10735 _SOC_IF_ERR_EXIT( 10736 _pm4x10_preemption_rx_frag_size_get(unit, port, pm_info, 10737 PORTMOD_PREEMPTION_NON_FINAL_FRAG, 10738 value)); 10739 break; 10740 case portmodPreemptionControlFinalFragSizeRx: 10741 /* get final rx fragment size */ 10742 _SOC_IF_ERR_EXIT( 10743 _pm4x10_preemption_rx_frag_size_get(unit, port, pm_info, 10744 PORTMOD_PREEMPTION_FINAL_FRAG, 10745 value)); 10746 break; 10747 default: 10748 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10749 (_SOC_MSG("Invalid preemption control type(%d)"), type)); 10750 break; 10751 } 10752 10753 exit: 10754 SOC_FUNC_RETURN; 10755 } 10756 10757 /*! 10758 * pm4x10_preemption_tx_status_get 10759 * 10760 * @brief Get the preemption status on the transmit side Indicates if 10761 * preemption on a port is 10762 * Inactive: (Verifiy is enabled but its status is either failed 10763 * or not initiated) or (preemption is not enabled) 10764 * Verify in progress: Preemption is enabled and Verify is 10765 * enabled and its operation is in progress 10766 * Active: Preemption is enabled and ((Verify is enabled and 10767 * succeeded) or (Verify is NOT enabled)) 10768 * 10769 * @param [in] unit - unit id 10770 * @param [in] port - logical port 10771 * @param [out] value - indicates preemption status in tx direction. 10772 */ 10773 int pm4x10_preemption_tx_status_get(int unit, int port, 10774 pm_info_t pm_info, 10775 uint32* value) 10776 { 10777 return (xlmac_preemption_tx_status_get(unit, port, 10778 XLMAC_PREEMPTION_TX_STATUS, 10779 value)); 10780 } 10781 10782 /*! 10783 * pm4x10_preemption_verify_status_get 10784 * 10785 * @brief Get the preemption verify status. 10786 * This function gets verify operation status or verify count 10787 * status based on the verify status type argument. 10788 * 10789 * @param [in] unit - unit id 10790 * @param [in] port - logical port 10791 * @param [in] type - portmod_preemption_verify_status_type_t 10792 * @param [out] value - indicates preemption verify op status 10793 */ 10794 int pm4x10_preemption_verify_status_get(int unit, int port, 10795 pm_info_t pm_info, 10796 portmod_preemption_verify_status_type_t type, 10797 uint32* value) 10798 { 10799 SOC_INIT_FUNC_DEFS; 10800 10801 switch (type) { 10802 case portmodPreemptionVerifyStatus: 10803 _SOC_IF_ERR_EXIT(xlmac_preemption_tx_status_get(unit, port, 10804 XLMAC_PREEMPTION_VERIFY_STATUS, 10805 value)); 10806 break; 10807 case portmodPreemptionVerifyCountStatus: 10808 _SOC_IF_ERR_EXIT(xlmac_preemption_tx_status_get(unit, port, 10809 XLMAC_PREEMPTION_VERIFY_CNT_STATUS, 10810 value)); 10811 break; 10812 default: 10813 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10814 (_SOC_MSG("Invalid verify status type(%d)"), type)); 10815 break; 10816 } 10817 exit: 10818 SOC_FUNC_RETURN; 10819 } 10820 int pm4x10_port_lane_count_get (int unit, int port, pm_info_t pm_info, int line_side, int* num_lanes) 10821 { 10822 portmod_access_get_params_t params; 10823 phymod_phy_access_t phy_access; 10824 int nof_phys; 10825 int is_outer_most = 0; 10826 SOC_INIT_FUNC_DEFS; 10827 10828 /* coverity[check_return] */ 10829 portmod_access_get_params_t_init(unit, ¶ms); 10830 10831 if(line_side){ 10832 params.sys_side = PORTMOD_SIDE_LINE; 10833 } else { 10834 params.sys_side = PORTMOD_SIDE_SYSTEM; 10835 } 10836 10837 _SOC_IF_ERR_EXIT(pm4x10_port_phy_lane_access_get(unit, port, pm_info, 10838 ¶ms, 1 , &phy_access, 10839 &nof_phys, &is_outer_most)); 10840 10841 *num_lanes = 0; 10842 PORTMOD_BIT_COUNT(phy_access.access.lane_mask,*num_lanes); 10843 10844 exit: 10845 SOC_FUNC_RETURN; 10846 } 10847 10848 /*! 10849 * portmod_preemption_force_rx_eop_mode_set 10850 * 10851 * @brief Set preemption forced rx lost eop(end of packet) sequence mode 10852 * setting. The rx lost eop sequence can be either software or hardware 10853 * enforced. 10854 * If HW based rx lost eop is enabled, link down or rx disable even 10855 * forces rx_lost_eop sequence after some internal delay if preempt 10856 * packet EOP was not sent. 10857 * If Sw based rx lost eop is enabled, the application rx eop sequence 10858 * When SW rx lost EOP is enabled(done by application layer), rising 10859 * edge MAC forces rx_lost_eop sequence after some internal delay if 10860 * preempt packet EOP was not sent. 10861 * 10862 * @param [in] unit - unit id 10863 * @param [in] port - logical port 10864 * @param [in] type - portmod_preemption_force_rx_eop_mode_t 10865 * @param [in] value - enable/disable 10866 */ 10867 int pm4x10_preemption_force_rx_eop_mode_set(int unit, int port, 10868 pm_info_t pm_info, 10869 portmod_preemption_force_rx_eop_mode_t type, 10870 uint32 value) 10871 { 10872 SOC_INIT_FUNC_DEFS; 10873 10874 switch (type) { 10875 case portmodPreemptionForceSwRxEop: 10876 _SOC_IF_ERR_EXIT(xlmac_preemption_force_rx_lost_eop_set(unit, port, 10877 XLMAC_PREEMPTION_FORCE_SW_RX_EOP, 10878 value)); 10879 break; 10880 case portmodPreemptionForceAutoHwEop: 10881 _SOC_IF_ERR_EXIT(xlmac_preemption_force_rx_lost_eop_set(unit, port, 10882 XLMAC_PREEMPTION_FORCE_AUTO_HW_RX_EOP, 10883 value)); 10884 break; 10885 default: 10886 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10887 (_SOC_MSG("Invalid Force RX lost EOP type(%d)"), type)); 10888 break; 10889 } 10890 10891 exit: 10892 SOC_FUNC_RETURN; 10893 } 10894 10895 /*! 10896 * pm4x10_preemption_force_rx_eop_mode_get 10897 * 10898 * @brief Get preemption forced rx lost eop(end of packet) sequence mode 10899 * setting. The rx lost eop sequence can be either software or hardware 10900 * enforced. 10901 * This functin returns the rx lost eop setting based on the type 10902 * of lost eop is enforced. 10903 * 10904 * 10905 * @param [in] unit - unit id 10906 * @param [in] port - logical port 10907 * @param [in] type - portmod_preemption_force_rx_eop_mode_t 10908 * @param [in] value - enable/disable 10909 */ 10910 int pm4x10_preemption_force_rx_eop_mode_get(int unit, int port, 10911 pm_info_t pm_info, 10912 portmod_preemption_force_rx_eop_mode_t type, 10913 uint32 *value) 10914 { 10915 SOC_INIT_FUNC_DEFS; 10916 10917 switch (type) { 10918 case portmodPreemptionForceSwRxEop: 10919 _SOC_IF_ERR_EXIT(xlmac_preemption_force_rx_lost_eop_get(unit, port, 10920 XLMAC_PREEMPTION_FORCE_SW_RX_EOP, 10921 value)); 10922 break; 10923 case portmodPreemptionForceAutoHwEop: 10924 _SOC_IF_ERR_EXIT(xlmac_preemption_force_rx_lost_eop_get(unit, port, 10925 XLMAC_PREEMPTION_FORCE_AUTO_HW_RX_EOP, 10926 value)); 10927 break; 10928 default: 10929 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 10930 (_SOC_MSG("Invalid Force RX lost EOP type(%d)"), type)); 10931 break; 10932 } 10933 10934 exit: 10935 SOC_FUNC_RETURN; 10936 } 10937 10938 /*! 10939 * pm4x10_preemption_rx_timeout_set 10940 * 10941 * @brief Set specified preemption rx timeout and timeout count. 10942 * This function should only be called during device init. 10943 * There are 2 rx parameters rx timeout enable, rx timeout value in microsec 10944 * that can be configured using this function. 10945 * If set, enables TIMEOUT mechanism for Rx preempt traffic. 10946 * Timeout value in microsec, this configuration indicates link idle 10947 * time(in microsec) after which Rx timeout will force rx_lost_eop sequence 10948 * if preempt packet EOP was not sent. 10949 * 10950 * @param [in] unit - unit id 10951 * @param [in] port - logical port 10952 * @param [in] enable - enables timeout for rx preempt traffic 10953 * @param [in] timeout_cnt - timeout in microsecs 10954 */ 10955 int pm4x10_preemption_rx_timeout_set(int unit, int port, pm_info_t pm_info, 10956 uint32 enable, uint32 timeout_cnt) 10957 { 10958 return (xlmac_preemption_rx_timeout_info_set(unit, port, enable, 10959 timeout_cnt)); 10960 } 10961 10962 /*! 10963 * pm4x10_preemption_rx_timeout_set 10964 * 10965 * @brief Get specified preemption rx timeout and timeout count. 10966 * 10967 * @param [in] unit - unit id 10968 * @param [in] port - logical port 10969 * @param [in] enable - enables timeout for rx preempt traffic 10970 * @param [out] timeout_cnt - timeout in millisec 10971 */ 10972 int pm4x10_preemption_rx_timeout_get(int unit, int port, pm_info_t pm_info, 10973 uint32 *enable, uint32 *timeout_cnt) 10974 { 10975 return (xlmac_preemption_rx_timeout_info_get(unit, port, enable, 10976 timeout_cnt)); 10977 } 10978 10979 STATIC 10980 int _pm4x10_phy_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info) 10981 { 10982 phymod_phy_access_t phy_access[1+MAX_PHYN]; 10983 int nof_phys; 10984 phymod_ts_fifo_status_t phy_ts_tx_info; 10985 SOC_INIT_FUNC_DEFS; 10986 10987 _SOC_IF_ERR_EXIT(phymod_ts_fifo_status_t_init(&phy_ts_tx_info)); 10988 10989 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 10990 phy_access ,(1+MAX_PHYN), 10991 &nof_phys)); 10992 _SOC_IF_ERR_EXIT(portmod_port_phychain_timesync_tx_info_get(unit, port, phy_access, 10993 nof_phys, &phy_ts_tx_info)); 10994 10995 tx_info->timestamps_in_fifo = phy_ts_tx_info.ts_in_fifo_lo; 10996 tx_info->timestamps_in_fifo_hi = phy_ts_tx_info.ts_in_fifo_hi; 10997 tx_info->sequence_id = phy_ts_tx_info.ts_seq_id; 10998 tx_info->timestamp_sub_nanosec = phy_ts_tx_info.ts_sub_nanosec; 10999 11000 exit: 11001 SOC_FUNC_RETURN; 11002 } 11003 11004 /* 11005 * pm4x10_port_timesync_tx_info_get 11006 * 11007 * @brief get port timestamps in fifo 11008 * 11009 * @param [in] unit - unit id 11010 * @param [in] port - logical port 11011 * @param [inout] tx_info - timestamp and seq id form fifo 11012 */ 11013 11014 int pm4x10_port_timesync_tx_info_get(int unit, int port, pm_info_t pm_info, portmod_fifo_status_t* tx_info) 11015 { 11016 int phy_acc, mac_ts_disable; 11017 uint32 reg_val; 11018 SOC_INIT_FUNC_DEFS; 11019 11020 mac_ts_disable = 0; 11021 11022 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11023 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 11024 _SOC_IF_ERR_EXIT(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 11025 mac_ts_disable = soc_reg_field_get(unit, XLPORT_MAC_CONTROLr, reg_val, XLMAC_TS_DISABLEf); 11026 } 11027 11028 /* 11029 * 1 = disable MAC timestamp, use TSC for timestamp. 11030 * 0 = legacy mode, use MAC for timestamp. 11031 */ 11032 if (mac_ts_disable) { 11033 _SOC_IF_ERR_EXIT(_pm4x10_phy_timesync_tx_info_get(unit, port, pm_info, tx_info)); 11034 } else { 11035 _SOC_IF_ERR_EXIT(xlmac_timesync_tx_info_get(unit, port, tx_info)); 11036 } 11037 11038 exit: 11039 SOC_FUNC_RETURN; 11040 } 11041 11042 int pm4x10_port_lane_mask_get (int unit, int port, pm_info_t pm_info, 11043 const portmod_access_get_params_t *params, 11044 int* lane_mask, int *xphy_id) 11045 { 11046 phymod_phy_access_t phy_access; 11047 portmod_access_get_params_t tmp_params; 11048 int nof_phys; 11049 int is_outer_most = 0; 11050 SOC_INIT_FUNC_DEFS; 11051 11052 /* coverity[check_return] */ 11053 portmod_access_get_params_t_init(unit, &tmp_params); 11054 sal_memcpy(&tmp_params, params, 11055 sizeof(portmod_access_get_params_t)); 11056 11057 tmp_params.lane = -1; 11058 11059 _SOC_IF_ERR_EXIT(pm4x10_port_phy_lane_access_get(unit, port, pm_info, 11060 &tmp_params, 1 , &phy_access, 11061 &nof_phys, &is_outer_most)); 11062 11063 *lane_mask = phy_access.access.lane_mask; 11064 11065 if ( tmp_params.phyn > 0 ) { 11066 *xphy_id = PM_4x10_INFO(pm_info)->lane_conn[0][0].xphy_id; 11067 } else { 11068 *xphy_id = PORTMOD_XPHY_ID_INVALID; 11069 } 11070 11071 exit: 11072 SOC_FUNC_RETURN; 11073 } 11074 11075 int pm4x10_port_mac_timestamp_enable_set(int unit, int port, pm_info_t pm_info, int enable) 11076 { 11077 int phy_acc; 11078 uint32 reg_val; 11079 11080 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11081 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 11082 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 11083 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, ®_val, 11084 XLMAC_TS_DISABLEf, (enable) ? 0 : 1); 11085 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, phy_acc, reg_val)); 11086 } else { 11087 return SOC_E_UNAVAIL; 11088 } 11089 11090 if (!enable) { 11091 /* Disable XLMAC byte_adjust if MAC timestamp is disabled. 11092 * Otherwise, it will affect the timestamp value of PHY timestamping. 11093 */ 11094 SOC_IF_ERROR_RETURN 11095 (xlmac_timestamp_byte_adjust_set(unit, 11096 port, 11097 XLMAC_TIMESTAMP_BYTE_ADJUST_CLEAR, 11098 0)); 11099 } 11100 11101 return (SOC_E_NONE); 11102 } 11103 11104 int pm4x10_port_mac_timestamp_enable_get(int unit, int port, pm_info_t pm_info, int* enable) 11105 { 11106 int phy_acc, tmp; 11107 uint32 reg_val; 11108 11109 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11110 if (soc_reg_field_valid(unit, XLPORT_MAC_CONTROLr, XLMAC_TS_DISABLEf)) { 11111 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, phy_acc, ®_val)); 11112 tmp = soc_reg_field_get(unit, XLPORT_MAC_CONTROLr, reg_val, XLMAC_TS_DISABLEf); 11113 } else { 11114 return SOC_E_UNAVAIL; 11115 } 11116 11117 if (tmp) { 11118 *enable = FALSE; 11119 } else { 11120 *enable = TRUE; 11121 } 11122 11123 return (SOC_E_NONE); 11124 } 11125 11126 /* 11127 *Function: 11128 * _pm4x10_txpi_lane_select_set 11129 * 11130 *Purpose: 11131 * Set Portmacro TXPI lane select 11132 * Defaults to using TXPI for it's own lane 11133 * This is a core level API 11134 */ 11135 STATIC 11136 int _pm4x10_txpi_lane_select_set(int unit, int port, pm_info_t pm_info, uint32_t *lane_select) 11137 { 11138 int phy_acc; 11139 uint32 reg_val = 0; 11140 SOC_INIT_FUNC_DEFS; 11141 11142 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11143 11144 soc_reg_field_set(unit, XLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_0f, lane_select[0]); 11145 soc_reg_field_set(unit, XLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_1f, lane_select[1]); 11146 soc_reg_field_set(unit, XLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_2f, lane_select[2]); 11147 soc_reg_field_set(unit, XLPORT_TXPI_LANE_SELECTIONr, ®_val, TXPI_LANE_SELECTION_3f, lane_select[3]); 11148 _SOC_IF_ERR_EXIT(WRITE_XLPORT_TXPI_LANE_SELECTIONr(unit, phy_acc, reg_val)); 11149 11150 exit: 11151 SOC_FUNC_RETURN; 11152 } 11153 11154 /* 11155 *Function: 11156 * _pm4x10_port_phy_txpi_mode_set 11157 * 11158 *Purpose: 11159 * Set PMD TXPI mode: normal or external PD 11160 * This is a port level API 11161 */ 11162 STATIC 11163 int _pm4x10_port_phy_txpi_mode_set(int unit, int port, pm_info_t pm_info, uint32 mode) 11164 { 11165 phymod_phy_access_t phy_access[1+MAX_PHYN]; 11166 int nof_phys; 11167 phymod_txpi_config_t config; 11168 SOC_INIT_FUNC_DEFS; 11169 11170 config.enable = mode ? 1: 0; 11171 config.mode = mode; 11172 11173 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 11174 phy_access ,(1+MAX_PHYN), 11175 &nof_phys)); 11176 SOC_IF_ERROR_RETURN(portmod_port_phychain_txpi_config_set(unit, phy_access, nof_phys, &config)); 11177 11178 exit: 11179 SOC_FUNC_RETURN; 11180 } 11181 11182 /* 11183 *Function: 11184 * pm4x10_port_txpi_override_set 11185 * 11186 *Purpose: 11187 * Override Portmacro TXPI SDM value 11188 * Defaults to using value from CMIC 11189 * This is a port level API 11190 */ 11191 int pm4x10_port_txpi_override_set (int unit, int port, pm_info_t pm_info, const portmod_txpi_override_t *override) 11192 { 11193 int phy_acc; 11194 uint32 reg_val_en, bitmap; 11195 int i, first_index; 11196 int64 reg_value; 11197 11198 soc_field_t field[MAX_PORTS_PER_PM4X10] = {TXPI_CSR_OVER_EN_0f, TXPI_CSR_OVER_EN_1f, TXPI_CSR_OVER_EN_2f, TXPI_CSR_OVER_EN_3f}; 11199 soc_reg_t over_reg_low[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_CSR_OVER_VAL_0_LOWr, XLPORT_TXPI_CSR_OVER_VAL_1_LOWr, 11200 XLPORT_TXPI_CSR_OVER_VAL_2_LOWr, XLPORT_TXPI_CSR_OVER_VAL_3_LOWr}; 11201 soc_reg_t over_reg_high[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_CSR_OVER_VAL_0_HIGHr, XLPORT_TXPI_CSR_OVER_VAL_1_HIGHr, 11202 XLPORT_TXPI_CSR_OVER_VAL_2_HIGHr, XLPORT_TXPI_CSR_OVER_VAL_3_HIGHr}; 11203 SOC_INIT_FUNC_DEFS; 11204 11205 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11206 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 11207 11208 /* Enable TXPI DSM override */ 11209 _SOC_IF_ERR_EXIT(READ_XLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, ®_val_en)); 11210 for (i = 0; i < MAX_PORTS_PER_PM4X10; i++) { 11211 if (bitmap & (0x1 << i)) { 11212 soc_reg_field_set(unit, XLPORT_TXPI_CSR_OVER_ENr, ®_val_en, field[i], override->enable ? TRUE : FALSE); 11213 } 11214 } 11215 _SOC_IF_ERR_EXIT(WRITE_XLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, reg_val_en)); 11216 11217 /* Write TXPI DSM override value. Low 32 bits must be wroten before high regist 11218 *reg_value = txpi_dsm_value_1ppm * override->value; 11219 */ 11220 COMPILER_64_SET(reg_value, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 11221 COMPILER_64_UMUL_32(reg_value, override->value); 11222 11223 for (i = 0; i < MAX_PORTS_PER_PM4X10; i++) { 11224 if (bitmap & (0x1 << i)) { 11225 soc_reg32_set(unit, over_reg_low[i], phy_acc, 0, override->enable ? COMPILER_64_LO(reg_value) : 0); 11226 soc_reg32_set(unit, over_reg_high[i], phy_acc, 0, override->enable ? (COMPILER_64_HI(reg_value) & 0xffff) : 0); 11227 } 11228 } 11229 11230 exit: 11231 SOC_FUNC_RETURN; 11232 } 11233 11234 /* 11235 *Function: 11236 * pm4x10_port_txpi_override_get 11237 * 11238 *Purpose: 11239 * Get Portmacro TXPI SDM override status and value 11240 * Defaults to using value from CMIC 11241 * This is a port level API 11242 */ 11243 int pm4x10_port_txpi_override_get (int unit, int port, pm_info_t pm_info, portmod_txpi_override_t *override) 11244 { 11245 int phy_acc; 11246 uint32 reg_val_en, bitmap; 11247 int first_index; 11248 uint32 reg_value_lo, reg_value_hi; 11249 int64 tmp_reg_val64, txpi_dsm_value_1ppm; 11250 11251 soc_field_t field[MAX_PORTS_PER_PM4X10] = {TXPI_CSR_OVER_EN_0f, TXPI_CSR_OVER_EN_1f, TXPI_CSR_OVER_EN_2f, TXPI_CSR_OVER_EN_3f}; 11252 soc_reg_t over_reg_low[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_CSR_OVER_VAL_0_LOWr, XLPORT_TXPI_CSR_OVER_VAL_1_LOWr, 11253 XLPORT_TXPI_CSR_OVER_VAL_2_LOWr, XLPORT_TXPI_CSR_OVER_VAL_3_LOWr}; 11254 soc_reg_t over_reg_high[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_CSR_OVER_VAL_0_HIGHr, XLPORT_TXPI_CSR_OVER_VAL_1_HIGHr, 11255 XLPORT_TXPI_CSR_OVER_VAL_2_HIGHr, XLPORT_TXPI_CSR_OVER_VAL_3_HIGHr}; 11256 SOC_INIT_FUNC_DEFS; 11257 11258 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11259 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 11260 11261 /*Get enable status of TXPI DSM override */ 11262 _SOC_IF_ERR_EXIT(READ_XLPORT_TXPI_CSR_OVER_ENr(unit, phy_acc, ®_val_en)); 11263 override->enable = soc_reg_field_get(unit, XLPORT_TXPI_CSR_OVER_ENr, reg_val_en, field[first_index]); 11264 11265 /* Get TXPI DSM override value */ 11266 if (override->enable == TRUE) { 11267 /* The LOW register should be read first before reading from the HIGH register. */ 11268 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, over_reg_low[first_index], 11269 phy_acc, 0, ®_value_lo)); 11270 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, over_reg_high[first_index], 11271 phy_acc, 0, ®_value_hi)); 11272 /* 11273 * bit47 : 0 -- positive; 1 -- negative. 11274 * If it is negative, the high 16 bits must be filled with 1. 11275 */ 11276 reg_value_hi = (reg_value_hi & 0x8000) ? (reg_value_hi | 0xffff0000) : (reg_value_hi & 0xffff); 11277 11278 /* 11279 *Use COMPILER_64_XXX macros to put together 64 bit variables txpi_dsm_value_1ppm and tmp_reg_val64 11280 *and then generate the override->value 11281 */ 11282 COMPILER_64_SET(txpi_dsm_value_1ppm, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 11283 COMPILER_64_SET(tmp_reg_val64, reg_value_hi, reg_value_lo); 11284 COMPILER_64_UDIV_64(tmp_reg_val64,txpi_dsm_value_1ppm); 11285 11286 COMPILER_64_TO_32_LO(override->value, tmp_reg_val64); 11287 } else { 11288 override->value = 0; 11289 } 11290 11291 exit: 11292 SOC_FUNC_RETURN; 11293 } 11294 11295 /* 11296 *Function: 11297 * pm4x10_port_txpi_sdm_data_get 11298 * 11299 *Purpose: 11300 * Get Portmacro TXPI SDM value of resolution 11301 * This is a port level API 11302 */ 11303 int pm4x10_port_txpi_sdm_data_get(int unit, int port, pm_info_t pm_info, int *value) 11304 11305 { 11306 int phy_acc; 11307 uint32 bitmap; 11308 int first_index; 11309 uint32 reg_value_lo, reg_value_hi; 11310 int64 tmp_reg_val64, txpi_dsm_value_1ppm; 11311 11312 soc_reg_t data_reg_low[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_DATA_OUT_STS_0_LOWr, XLPORT_TXPI_DATA_OUT_STS_1_LOWr, 11313 XLPORT_TXPI_DATA_OUT_STS_2_LOWr, XLPORT_TXPI_DATA_OUT_STS_3_LOWr}; 11314 soc_reg_t data_reg_high[MAX_PORTS_PER_PM4X10] = {XLPORT_TXPI_DATA_OUT_STS_0_HIGHr, XLPORT_TXPI_DATA_OUT_STS_1_HIGHr, 11315 XLPORT_TXPI_DATA_OUT_STS_2_HIGHr, XLPORT_TXPI_DATA_OUT_STS_3_HIGHr}; 11316 SOC_INIT_FUNC_DEFS; 11317 11318 PM4x10_PHY_ACCESS_GET(unit, port, pm_info, phy_acc); 11319 _SOC_IF_ERR_EXIT(_pm4x10_port_index_get(unit, port, pm_info, &first_index, &bitmap)); 11320 11321 /* get the first sub-port if the port is dual-lane or quad-lane mode. 11322 * The LOW register should be read first before reading from the HIGH register. 11323 */ 11324 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, data_reg_low[first_index], 11325 phy_acc, 0, ®_value_lo)); 11326 _SOC_IF_ERR_EXIT(soc_reg32_get(unit, data_reg_high[first_index], 11327 phy_acc, 0, ®_value_hi)); 11328 /* 11329 * bit47 : 0 -- positive; 1 -- negative. 11330 * If it is negative, the high 16 bits must be filled with 1. 11331 */ 11332 reg_value_hi = (reg_value_hi & 0x8000) ? (reg_value_hi | 0xffff0000) : (reg_value_hi & 0xffff); 11333 11334 /* 11335 *Use COMPILER_64_XXX macros to put together 64 bit variables txpi_dsm_value_1ppm and tmp_reg_val64 11336 *and then generate the override->value 11337 */ 11338 COMPILER_64_SET(txpi_dsm_value_1ppm, TXPI_DSM_VALUE_1PPM_HI, TXPI_DSM_VALUE_1PPM_LO); 11339 COMPILER_64_SET(tmp_reg_val64, reg_value_hi, reg_value_lo); 11340 COMPILER_64_UDIV_64(tmp_reg_val64,txpi_dsm_value_1ppm); 11341 11342 COMPILER_64_TO_32_LO(*value, tmp_reg_val64); 11343 11344 exit: 11345 SOC_FUNC_RETURN; 11346 } 11347 11348 11349 int pm4x10_port_synce_clk_ctrl_set(int unit, int port, pm_info_t pm_info, 11350 const portmod_port_synce_clk_ctrl_t* cfg) 11351 { 11352 phymod_synce_clk_ctrl_t phy_synce_cfg; 11353 phymod_phy_access_t phy_access[1+MAX_PHYN]; 11354 int nof_phys; 11355 SOC_INIT_FUNC_DEFS; 11356 11357 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 11358 phy_access ,(1+MAX_PHYN), 11359 &nof_phys)); 11360 11361 phymod_synce_clk_ctrl_t_init(&phy_synce_cfg); 11362 phy_synce_cfg.stg0_mode = cfg->stg0_mode; 11363 phy_synce_cfg.stg1_mode = cfg->stg1_mode; 11364 phy_synce_cfg.sdm_val = cfg->sdm_val; 11365 11366 _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_set(&phy_access[0], 11367 phy_synce_cfg)); 11368 11369 exit: 11370 SOC_FUNC_RETURN; 11371 } 11372 11373 int pm4x10_port_synce_clk_ctrl_get(int unit, int port, pm_info_t pm_info, 11374 portmod_port_synce_clk_ctrl_t* cfg) 11375 { 11376 phymod_synce_clk_ctrl_t phy_synce_cfg; 11377 phymod_phy_access_t phy_access[1+MAX_PHYN]; 11378 int nof_phys; 11379 SOC_INIT_FUNC_DEFS; 11380 11381 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, 11382 phy_access ,(1+MAX_PHYN), 11383 &nof_phys)); 11384 11385 phymod_synce_clk_ctrl_t_init(&phy_synce_cfg); 11386 11387 _SOC_IF_ERR_EXIT(phymod_phy_synce_clk_ctrl_get(&phy_access[0], 11388 &phy_synce_cfg)); 11389 11390 cfg->stg0_mode = phy_synce_cfg.stg0_mode; 11391 cfg->stg1_mode = phy_synce_cfg.stg1_mode; 11392 cfg->sdm_val = phy_synce_cfg.sdm_val; 11393 11394 exit: 11395 SOC_FUNC_RETURN; 11396 } 11397 11398 #endif /* PORTMOD_PM4X10_SUPPORT */ 11399 11400 #undef _ERR_MSG_MODULE_NAME 11401