portmod_common.c (128049B)
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 #include <soc/drv.h> 10 #include <soc/portmod/portmod.h> 11 #include <soc/portmod/portmod_internal.h> 12 #include <soc/portmod/portmod_common.h> 13 #include <soc/portmod/portmod_system.h> 14 #include <soc/portmod/portmod_chain.h> 15 #include <soc/portmod/portmod_legacy_phy.h> 16 #include <soc/phy/phymod_port_control.h> 17 18 #ifdef CRASH_RECOVERY_SUPPORT 19 #include <soc/hwstate/hw_log.h> 20 #include <soc/dcmn/dcmn_crash_recovery.h> 21 #endif /* CRASH_RECOVERY_SUPPORT */ 22 23 #ifdef _ERR_MSG_MODULE_NAME 24 #error "_ERR_MSG_MODULE_NAME redefined" 25 #endif 26 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 27 28 29 #define PORT_MAX_PHY_ACCESS_STRUCTURES (6) 30 #define PM_MDIO_BUS_COUNT (8) 31 32 #define MAC_WAN_MODE_THROTTLE_10G_TO_5G 256 33 #define MAC_WAN_MODE_THROTTLE_10G_TO_2P5G 257 34 35 #include <soc/portmod/portmod_dispatch.h> 36 37 STATIC int _portmod_common_ext_phy_addr_get(int unit, soc_port_t port, uint32 *xphy_id); 38 39 int 40 portmod_common_phy_prbs_config_set(int unit, int port, pm_info_t pm_info, int flags, const phymod_prbs_t* config) 41 { 42 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 43 int chain_length = 0; 44 45 46 SOC_INIT_FUNC_DEFS; 47 48 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 49 PORT_MAX_PHY_ACCESS_STRUCTURES, 50 &chain_length)); 51 _SOC_IF_ERR_EXIT(portmod_port_phychain_prbs_config_set(unit, phy_access, chain_length, flags, config)); 52 53 exit: 54 SOC_FUNC_RETURN; 55 } 56 57 int 58 portmod_common_phy_prbs_config_get(int unit, int port, pm_info_t pm_info, int flags, phymod_prbs_t* config) 59 { 60 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 61 int chain_length = 0; 62 63 SOC_INIT_FUNC_DEFS; 64 65 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 66 PORT_MAX_PHY_ACCESS_STRUCTURES, 67 &chain_length)); 68 _SOC_IF_ERR_EXIT(portmod_port_phychain_prbs_config_get(unit, phy_access, chain_length, flags, config)); 69 70 exit: 71 SOC_FUNC_RETURN; 72 } 73 74 int portmod_commmon_portmod_to_phymod_loopback_type(int unit, portmod_loopback_mode_t loopback_type, phymod_loopback_mode_t *phymod_lb_type) 75 { 76 77 SOC_INIT_FUNC_DEFS; 78 switch(loopback_type){ 79 case portmodLoopbackPhyGloopPCS: 80 *phymod_lb_type = phymodLoopbackGlobal; 81 break; 82 case portmodLoopbackPhyGloopPMD: 83 *phymod_lb_type = phymodLoopbackGlobalPMD; 84 break; 85 case portmodLoopbackPhyRloopPCS: 86 *phymod_lb_type = phymodLoopbackRemotePCS; 87 break; 88 case portmodLoopbackPhyRloopPMD: 89 *phymod_lb_type = phymodLoopbackRemotePMD; 90 break; 91 default: 92 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("unsupported loopback type %d", loopback_type)); 93 } 94 exit: 95 SOC_FUNC_RETURN; 96 } 97 98 int 99 portmod_common_phy_loopback_set(int unit, int port, pm_info_t pm_info, portmod_loopback_mode_t loopback_type, int enable) 100 { 101 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 102 int chain_length = 0; 103 phymod_loopback_mode_t phymod_lb_type; 104 105 SOC_INIT_FUNC_DEFS; 106 107 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, loopback_type, &phymod_lb_type)); 108 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 109 PORT_MAX_PHY_ACCESS_STRUCTURES, 110 &chain_length)); 111 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_set (unit, port, phy_access, chain_length, phymod_lb_type, enable)); 112 113 exit: 114 SOC_FUNC_RETURN; 115 } 116 117 int 118 portmod_common_phy_loopback_get(int unit, int port, pm_info_t pm_info, portmod_loopback_mode_t loopback_type, int *enable) 119 { 120 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 121 int chain_length = 0; 122 phymod_loopback_mode_t phymod_lb_type; 123 uint32_t tmp_enable=0; 124 125 SOC_INIT_FUNC_DEFS; 126 127 _SOC_IF_ERR_EXIT(portmod_commmon_portmod_to_phymod_loopback_type(unit, loopback_type, &phymod_lb_type)); 128 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 129 PORT_MAX_PHY_ACCESS_STRUCTURES, 130 &chain_length)); 131 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_get(unit, port, phy_access, chain_length, phymod_lb_type, &tmp_enable)); 132 *enable = tmp_enable; 133 exit: 134 SOC_FUNC_RETURN; 135 } 136 137 int portmod_common_phy_prbs_enable_set(int unit, int port, pm_info_t pm_info, int flags, int enable) 138 { 139 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 140 int chain_length = 0; 141 142 SOC_INIT_FUNC_DEFS; 143 144 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 145 PORT_MAX_PHY_ACCESS_STRUCTURES, 146 &chain_length)); 147 _SOC_IF_ERR_EXIT(portmod_port_phychain_prbs_enable_set(unit, phy_access, chain_length, flags, enable)); 148 149 exit: 150 SOC_FUNC_RETURN; 151 } 152 153 154 int portmod_common_phy_prbs_enable_get(int unit, int port, pm_info_t pm_info, int flags, int* enable) 155 { 156 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 157 int chain_length = 0; 158 uint32_t tmp_enable; 159 160 SOC_INIT_FUNC_DEFS; 161 162 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 163 PORT_MAX_PHY_ACCESS_STRUCTURES, 164 &chain_length)); 165 _SOC_IF_ERR_EXIT(portmod_port_phychain_prbs_enable_get(unit, phy_access, chain_length, flags, &tmp_enable)); 166 *enable = tmp_enable; 167 exit: 168 SOC_FUNC_RETURN; 169 } 170 171 172 int portmod_common_phy_prbs_status_get(int unit, int port, pm_info_t pm_info, int flags, phymod_prbs_status_t* status) 173 { 174 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 175 int chain_length = 0; 176 177 SOC_INIT_FUNC_DEFS; 178 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 179 PORT_MAX_PHY_ACCESS_STRUCTURES, 180 &chain_length)); 181 _SOC_IF_ERR_EXIT(portmod_port_phychain_prbs_status_get(unit, phy_access, chain_length, flags, status)); 182 exit: 183 SOC_FUNC_RETURN; 184 } 185 186 int portmod_common_phy_firmware_mode_set(int unit, int port, phymod_firmware_mode_t fw_mode) 187 { 188 SOC_INIT_FUNC_DEFS; 189 SOC_FUNC_RETURN; 190 } 191 192 193 int portmod_common_phy_firmware_mode_get(int unit, int port, phymod_firmware_mode_t *fw_mode) 194 { 195 SOC_INIT_FUNC_DEFS; 196 SOC_FUNC_RETURN; 197 } 198 199 /*! 200 * portmod_common_pmd_lane_config_decode 201 * 202 * @brief decode the lane_config passed in from multi_resource_set 203 * 204 * @param [in] unit - lane_config 205 * @param [out] name - portmod_lane_config. 206 */ 207 int portmod_common_pmd_lane_config_decode(uint32_t lane_config, portmod_pmd_lane_config_t* portmod_lane_config) 208 { 209 SOC_INIT_FUNC_DEFS; 210 portmod_lane_config->pmd_firmware_lane_config.DfeOn = PORTMOD_PORT_PHY_LANE_CONFIG_DFE_GET(lane_config); 211 portmod_lane_config->pmd_firmware_lane_config.LpDfeOn = PORTMOD_PORT_PHY_LANE_CONFIG_LP_DFE_GET(lane_config); 212 portmod_lane_config->pmd_firmware_lane_config.ForceBrDfe = PORTMOD_PORT_PHY_LANE_CONFIG_BR_DFE_GET(lane_config); 213 portmod_lane_config->pmd_firmware_lane_config.MediaType = PORTMOD_PORT_PHY_LANE_CONFIG_MEDIUM_GET(lane_config); 214 portmod_lane_config->pmd_firmware_lane_config.UnreliableLos = PORTMOD_PORT_PHY_LANE_CONFIG_UNRELIABLE_LOS_GET(lane_config); 215 portmod_lane_config->pmd_firmware_lane_config.ScramblingDisable = PORTMOD_PORT_PHY_LANE_CONFIG_SCRAMBLING_DISABLE_GET(lane_config); 216 portmod_lane_config->pmd_firmware_lane_config.Cl72AutoPolEn = PORTMOD_PORT_PHY_LANE_CONFIG_CL72_POLARITY_AUTO_EN_GET(lane_config); 217 portmod_lane_config->pmd_firmware_lane_config.Cl72RestTO = PORTMOD_PORT_PHY_LANE_CONFIG_CL72_RESTART_TIMEOUT_EN_GET(lane_config); 218 portmod_lane_config->pmd_firmware_lane_config.ForceExtenedReach = PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_ES_GET(lane_config); 219 portmod_lane_config->pmd_firmware_lane_config.ForceNormalReach = PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NS_GET(lane_config); 220 portmod_lane_config->pmd_firmware_lane_config.LpPrecoderEnabled = PORTMOD_PORT_PHY_LANE_CONFIG_LP_PREC_EN_GET(lane_config); 221 portmod_lane_config->pmd_firmware_lane_config.ForcePAM4Mode = PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_PAM4_GET(lane_config); 222 portmod_lane_config->pmd_firmware_lane_config.ForceNRZMode = PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NRZ_GET(lane_config); 223 portmod_lane_config->pam4_channel_loss = PORTMOD_PORT_PHY_LANE_CONFIG_PAM4_CHANNEL_LOSS_GET(lane_config); 224 225 SOC_FUNC_RETURN; 226 } 227 228 /*! 229 * portmod_common_pmd_lane_config_encode 230 * 231 * @brief encode the portmod lane_config passed into a 32-bit encoded value 232 * 233 * @param [in] unit - portmod_lane_config 234 * @param [out] name - lane_config 235 */ 236 int portmod_common_pmd_lane_config_encode(portmod_pmd_lane_config_t* portmod_lane_config, uint32_t* lane_config) 237 { 238 SOC_INIT_FUNC_DEFS; 239 240 *lane_config = 0; 241 if (portmod_lane_config->pmd_firmware_lane_config.DfeOn) { 242 PORTMOD_PORT_PHY_LANE_CONFIG_DFE_SET(*lane_config); 243 } 244 245 if (portmod_lane_config->pmd_firmware_lane_config.LpDfeOn) { 246 PORTMOD_PORT_PHY_LANE_CONFIG_LP_DFE_SET(*lane_config); 247 } 248 249 if (portmod_lane_config->pmd_firmware_lane_config.ForceBrDfe) { 250 PORTMOD_PORT_PHY_LANE_CONFIG_BR_DFE_SET(*lane_config); 251 } 252 253 PORTMOD_PORT_PHY_LANE_CONFIG_MEDIUM_SET(*lane_config, 254 portmod_lane_config->pmd_firmware_lane_config.MediaType); 255 256 if (portmod_lane_config->pmd_firmware_lane_config.UnreliableLos) { 257 PORTMOD_PORT_PHY_LANE_CONFIG_UNRELIABLE_LOS_SET(*lane_config); 258 } 259 260 if (portmod_lane_config->pmd_firmware_lane_config.ScramblingDisable) { 261 PORTMOD_PORT_PHY_LANE_CONFIG_SCRAMBLING_DISABLE_SET(*lane_config); 262 } 263 if (portmod_lane_config->pmd_firmware_lane_config.Cl72AutoPolEn) { 264 PORTMOD_PORT_PHY_LANE_CONFIG_CL72_POLARITY_AUTO_EN_SET(*lane_config); 265 } 266 if (portmod_lane_config->pmd_firmware_lane_config.Cl72RestTO) { 267 PORTMOD_PORT_PHY_LANE_CONFIG_CL72_RESTART_TIMEOUT_EN_SET(*lane_config); 268 } 269 if (portmod_lane_config->pmd_firmware_lane_config.ForceExtenedReach) { 270 PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_ES_SET(*lane_config); 271 } 272 if (portmod_lane_config->pmd_firmware_lane_config.ForceNormalReach) { 273 PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NS_SET(*lane_config); 274 } 275 if (portmod_lane_config->pmd_firmware_lane_config.LpPrecoderEnabled) { 276 PORTMOD_PORT_PHY_LANE_CONFIG_LP_PREC_EN_SET(*lane_config); 277 } 278 if (portmod_lane_config->pmd_firmware_lane_config.ForcePAM4Mode) { 279 PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_PAM4_SET(*lane_config); 280 } 281 if (portmod_lane_config->pmd_firmware_lane_config.ForceNRZMode) { 282 PORTMOD_PORT_PHY_LANE_CONFIG_FORCE_NRZ_SET(*lane_config); 283 } 284 285 PORTMOD_PORT_PHY_LANE_CONFIG_PAM4_CHANNEL_LOSS_SET(*lane_config, 286 portmod_lane_config->pam4_channel_loss); 287 288 SOC_FUNC_RETURN; 289 290 } 291 292 293 294 295 /** 296 * @brief generic function for register write for PM4X25, 297 * PM4X10, PM 12X10 298 * @param reg_access_mem - the memory that used for access PHY 299 * registers. e.g: CLPORT_UCMEM_DATAm, 300 * XLPORT_UCMEM_DATA 301 * @param user_acc - user data. this function expect to get 302 * portmod_phy_op_data_t structure 303 * @param core_address - only 5 bits of PHY id used in case 304 * of sbus 305 * @param reg_addr - the reigister addrress 306 * @param val - the value to write to register. 16 bits value + 307 * 16 bits mask 308 309 */ 310 int 311 portmod_common_phy_sbus_reg_write(soc_mem_t reg_access_mem, void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 312 { 313 int rv= SOC_E_NONE; 314 soc_reg_above_64_val_t mem_data; 315 portmod_default_user_access_t *user_data = user_acc; 316 uint32 data, data_mask; 317 SOC_REG_ABOVE_64_CLEAR(mem_data); 318 319 if(user_data == NULL){ 320 return SOC_E_PARAM; 321 } 322 323 /* If write mask (upper 16 bits) is empty, add full mask */ 324 if ((val & 0xffff0000) == 0) { 325 val |= 0xffff0000; 326 } 327 328 /* assigning TSC register address to ucmem_data[31:0] and write the 329 * data/datamask to to ucmem_data[63:32] */ 330 mem_data[0] = (reg_addr & 0xffffffff) | ((core_addr & 0x1f) << 19); 331 /* data: ucmem_data[48:63] 332 datamask: ucmem_data[32:47] 333 */ 334 data = (val & 0xffff) << 16; 335 data_mask = (~val & 0xffff0000) >> 16; 336 mem_data[1] = data | data_mask; 337 mem_data[2] = 1; /* for TSC register write */ 338 339 #ifdef CRASH_RECOVERY_SUPPORT 340 if (BCM_UNIT_DO_HW_READ_WRITE(user_data->unit)){ 341 soc_dcmn_cr_suppress(user_data->unit, dcmn_cr_no_support_portmod); 342 } 343 #endif /* CRASH_RECOVERY_SUPPORT */ 344 345 rv = soc_mem_write(user_data->unit, reg_access_mem, user_data->blk_id, 0, mem_data); 346 347 LOG_DEBUG(BSL_LS_SOC_MII, 348 (BSL_META_U(user_data->unit, 349 "_portmod_utils_sbus_reg_write[%d]: " 350 "addr=0x%x reg=0x%08x data=0x%08x mask=0x%08x(%d/%d)\n"), 351 user_data->unit, core_addr, reg_addr, val , data_mask, user_data->blk_id, rv)); 352 353 return rv; 354 } 355 356 357 /** 358 * @brief generic function for register read for PM4X25, 359 * PM4X10, PM 12X10 360 * @param reg_access_mem - the memory that used for access PHY 361 * registers. e.g: CLPORT_UCMEM_DATAm, 362 * XLPORT_UCMEM_DATA 363 * @param user_acc - user data. this function expect to get 364 * portmod_phy_op_data_t structure 365 * @param core_address - only 5 bits of PHY id used in case 366 * of sbus 367 * @param reg_addr - the reigister addrress 368 * @param val - the value to write to register. no mask for 369 * read 370 */ 371 int 372 portmod_common_phy_sbus_reg_read(soc_mem_t reg_access_mem, void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 373 { 374 int rv = SOC_E_NONE, reg_val_offset; 375 soc_reg_above_64_val_t mem_data; 376 portmod_default_user_access_t *user_data = user_acc; 377 SOC_REG_ABOVE_64_CLEAR(mem_data); 378 379 if(user_data == NULL){ 380 return SOC_E_PARAM; 381 } 382 383 /* assigning TSC register address to ucmem_data[31:0] */ 384 mem_data[0] = (reg_addr & 0xffffffff) | ((core_addr & 0x1f) << 19); 385 mem_data[2] = 0; /* for TSC register READ */ 386 387 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) 388 #ifdef CRASH_RECOVERY_SUPPORT 389 soc_hw_set_immediate_hw_access(user_data->unit); 390 #endif /* CRASH_RECOVERY_SUPPORT */ 391 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */ 392 393 SOC_ALLOW_WB_WRITE(user_data->unit, soc_mem_write(user_data->unit, reg_access_mem, user_data->blk_id, 0, mem_data), rv); 394 395 /* read data back from ucmem_data[47:32] */ 396 if (SOC_SUCCESS(rv)) { 397 rv = soc_mem_read(user_data->unit, reg_access_mem, user_data->blk_id, 0, mem_data); 398 } 399 400 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) 401 #ifdef CRASH_RECOVERY_SUPPORT 402 soc_hw_restore_immediate_hw_access(user_data->unit); 403 #endif /* CRASH_RECOVERY_SUPPORT */ 404 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */ 405 406 if (PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_GET(user_data)) { 407 reg_val_offset = 0; 408 } else { 409 reg_val_offset = 1; /* default behaviour */ 410 } 411 412 *val = mem_data[reg_val_offset]; 413 414 LOG_DEBUG(BSL_LS_SOC_MII, (BSL_META_U(user_data->unit, 415 "_portmod_utils_sbus_reg_read[%d]: " 416 "addr=0x%x reg=0x%08x data=0x%08x (%d/%d)\n"), 417 user_data->unit, core_addr, reg_addr, *val, user_data->blk_id, rv)); 418 419 return rv; 420 } 421 422 int 423 portmod_common_mutex_take(void* user_acc) 424 { 425 portmod_default_user_access_t* user_data; 426 SOC_INIT_FUNC_DEFS; 427 428 user_data = (portmod_default_user_access_t*)user_acc; 429 430 if(user_data->mutex != NULL) { 431 _SOC_IF_ERR_EXIT(sal_mutex_take(user_data->mutex, sal_mutex_FOREVER)); 432 } 433 434 exit: 435 SOC_FUNC_RETURN; 436 } 437 438 int 439 portmod_common_mutex_give(void* user_acc) 440 { 441 portmod_default_user_access_t* user_data; 442 SOC_INIT_FUNC_DEFS; 443 444 user_data = (portmod_default_user_access_t*)user_acc; 445 446 if(user_data->mutex != NULL) { 447 _SOC_IF_ERR_EXIT(sal_mutex_give(user_data->mutex)); 448 } 449 450 exit: 451 SOC_FUNC_RETURN; 452 } 453 454 static 455 int _portmod_dma_buf_alloc(int unit, const uint8 *data, uint32 datalen, 456 portmod_ucode_buf_t *dmabuf, portmod_ucode_buf_order_t data_swap, 457 int endian, int entry_bytes) 458 { 459 int count, extra_bytes, i, j; 460 uint8 *dma_buf_ptr; 461 const uint8 *array_ptr; 462 int arr_pos_le[3] [16] 463 = {{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, 464 { 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}, 465 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; 466 int arr_pos_be[3] [16] 467 = {{12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3}, 468 {11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4}, 469 {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12}}; 470 int *arr_pos; 471 SOC_INIT_FUNC_DEFS; 472 473 if(endian) { 474 arr_pos = arr_pos_be[data_swap]; 475 } else { 476 arr_pos = arr_pos_le[data_swap]; 477 } 478 479 count = datalen / entry_bytes; 480 extra_bytes = datalen % entry_bytes; 481 dmabuf->ucode_alloc_size = datalen; 482 483 /* align to entry_bytes */ 484 if (extra_bytes != 0) { 485 dmabuf->ucode_alloc_size += entry_bytes - extra_bytes; 486 } 487 488 dmabuf->ucode_dma_buf = portmod_sys_dma_alloc(unit, dmabuf->ucode_alloc_size, 489 "WC ucode DMA buffer"); 490 if (dmabuf->ucode_dma_buf == NULL) { 491 _SOC_EXIT_WITH_ERR(SOC_E_MEMORY, ("Failed to alloc WC ucode DMA buffer")); 492 } 493 494 /* copy image into dma buffer */ 495 array_ptr = data; 496 dma_buf_ptr = dmabuf->ucode_dma_buf; 497 for (i = 0; i < count; i++) { 498 for (j = 0; j < 16; j++) { 499 dma_buf_ptr[arr_pos[j]] = array_ptr[j]; 500 } 501 array_ptr += entry_bytes; 502 dma_buf_ptr += entry_bytes; 503 } 504 if (extra_bytes != 0) { 505 sal_memset(dma_buf_ptr, 0, entry_bytes); 506 for (j = 0; j < extra_bytes; j++) { 507 dma_buf_ptr[arr_pos[j]] = array_ptr[j]; 508 } 509 } 510 511 exit: 512 SOC_FUNC_RETURN; 513 } 514 515 /** 516 * this function will download ucode through UCMEM, if ucode size exceeds UCMEM limitation, 517 * the second DMA buffer is required to download extra data 518 */ 519 int 520 portmod_firmware_set(int unit, 521 int blk_id, 522 const uint8 *array, 523 uint32 datalen, 524 portmod_ucode_buf_order_t data_swap, 525 int bcast_en, 526 portmod_ucode_buf_t* buf, 527 portmod_ucode_buf_t* buf_2nd, 528 soc_mem_t ucmem_data, 529 soc_reg_t ucmem_ctrl) 530 { 531 int entry_bytes, entry_num, ucmem_size, endian; 532 const uint8 *array_2nd; 533 uint32 datalen_2nd = 0; 534 int reg_access_idx = (blk_id | SOC_REG_ADDR_BLOCK_ID_MASK); 535 uint64 reg_val; 536 #ifdef FW_BCAST_DOWNLOAD 537 int flags = 0; 538 #endif 539 SOC_INIT_FUNC_DEFS; 540 541 entry_bytes = soc_mem_entry_bytes(unit, ucmem_data); 542 entry_num = soc_mem_index_count(unit, ucmem_data); 543 ucmem_size = entry_bytes * entry_num; 544 545 /* this is for PM8x50 16nm B0 UCMEM memory increase */ 546 if (ucmem_size > 65536) { 547 ucmem_size = 65536; 548 } 549 550 if (datalen > ucmem_size) { 551 if (buf_2nd==NULL || datalen>2*ucmem_size) { 552 _SOC_EXIT_WITH_ERR(SOC_E_RESOURCE, ("Can't fit all of the firmware into the device load table.")); 553 } 554 555 array_2nd = array + ucmem_size; 556 datalen_2nd = datalen - ucmem_size; 557 datalen = ucmem_size; 558 } else { 559 array_2nd = NULL; 560 } 561 562 portmod_sys_get_endian(unit, &endian); 563 564 if (buf->ucode_dma_buf == NULL) { 565 _SOC_IF_ERR_EXIT(_portmod_dma_buf_alloc(unit, array, datalen, buf, data_swap, endian, entry_bytes)); 566 } 567 568 if (datalen_2nd>0 && buf_2nd!=NULL && buf_2nd->ucode_dma_buf==NULL) { 569 _SOC_IF_ERR_EXIT(_portmod_dma_buf_alloc(unit, array_2nd, datalen_2nd, buf_2nd, data_swap, endian, entry_bytes)); 570 } 571 572 /* enable parallel bus access */ 573 _SOC_IF_ERR_EXIT(soc_reg_get(unit,ucmem_ctrl, reg_access_idx, 0, ®_val)); 574 soc_reg64_field32_set(unit, ucmem_ctrl, ®_val, ACCESS_MODEf, 1); 575 _SOC_IF_ERR_EXIT(soc_reg_set(unit,ucmem_ctrl, reg_access_idx, 0, reg_val)); 576 577 #ifdef FW_BCAST_DOWNLOAD 578 if (bcast_en) { 579 flags = SOC_MEM_WRITE_BCAST_OP; 580 } 581 582 _SOC_IF_ERR_EXIT 583 (soc_mem_array_write_range_multi_cmc(unit, flags, ucmem_data, 0, blk_id, 0, 584 buf->ucode_alloc_size / entry_bytes - 1, 585 buf->ucode_dma_buf, -1)); 586 587 /* if ucode size exceeds UCMEM limitation, the second buffer is used to download the extra data */ 588 if (datalen_2nd>0 && buf_2nd!=NULL) { 589 _SOC_IF_ERR_EXIT 590 (soc_mem_array_write_range_multi_cmc(unit, flags, ucmem_data, 0, blk_id, 0, 591 buf_2nd->ucode_alloc_size / entry_bytes - 1, 592 buf_2nd->ucode_dma_buf, -1)); 593 } 594 #else 595 /* coverity[stack_use_overflow] */ 596 _SOC_IF_ERR_EXIT 597 (soc_mem_write_range(unit, ucmem_data, blk_id, 0, 598 buf->ucode_alloc_size / entry_bytes - 1, 599 buf->ucode_dma_buf)); 600 601 /* if ucode size exceeds UCMEM limitation, the second buffer is used to download the extra data */ 602 if (datalen_2nd>0 && buf_2nd!=NULL) { 603 _SOC_IF_ERR_EXIT 604 (soc_mem_write_range(unit, ucmem_data, blk_id, 0, 605 buf_2nd->ucode_alloc_size / entry_bytes - 1, 606 buf_2nd->ucode_dma_buf)); 607 } 608 #endif 609 610 /* disable parallel bus access, and enable MDIO access */ 611 _SOC_IF_ERR_EXIT(soc_reg_get(unit,ucmem_ctrl, reg_access_idx, 0, ®_val)); 612 soc_reg64_field32_set(unit, ucmem_ctrl, ®_val, ACCESS_MODEf, 0); 613 _SOC_IF_ERR_EXIT(soc_reg_set(unit,ucmem_ctrl, reg_access_idx, 0, reg_val)); 614 615 exit: 616 SOC_FUNC_RETURN; 617 } 618 619 void portmod_common_phy_to_port_ability (phymod_autoneg_ability_t *anAbility, 620 portmod_port_ability_t *portAbility) 621 { 622 int abil37; 623 int abil73; 624 _shr_port_mode_t spd_fd = 0; /* Speed full duplex */ 625 int abil73bam; 626 627 /* retrieve CL73 abilities */ 628 abil73 = anAbility->an_cap; 629 spd_fd|= PHYMOD_AN_CAP_100G_CR10_GET(abil73) ?SOC_PA_SPEED_100GB:0; 630 spd_fd|= PHYMOD_AN_CAP_100G_CR4_GET(abil73) ?SOC_PA_SPEED_100GB:0; 631 spd_fd|= PHYMOD_AN_CAP_100G_KR4_GET(abil73) ?SOC_PA_SPEED_100GB:0; 632 spd_fd|= PHYMOD_AN_CAP_40G_CR4_GET(abil73) ?SOC_PA_SPEED_40GB:0; 633 spd_fd|= PHYMOD_AN_CAP_40G_KR4_GET(abil73) ?SOC_PA_SPEED_40GB:0; 634 spd_fd|= PHYMOD_AN_CAP_10G_KR_GET(abil73) ?SOC_PA_SPEED_10GB:0; 635 spd_fd|= PHYMOD_AN_CAP_10G_KX4_GET(abil73) ?SOC_PA_SPEED_10GB:0; 636 spd_fd|= PHYMOD_AN_CAP_1G_KX_GET(abil73) ?SOC_PA_SPEED_1000MB:0; 637 spd_fd|= PHYMOD_AN_CAP_100M_GET(abil73) ?SOC_PA_SPEED_100MB:0; 638 spd_fd|= PHYMOD_AN_CAP_25G_CR1_GET(abil73)? SOC_PA_SPEED_25GB:0; 639 spd_fd|= PHYMOD_AN_CAP_25G_KR1_GET(abil73)? SOC_PA_SPEED_25GB:0; 640 spd_fd|= PHYMOD_AN_CAP_25G_CRS1_GET(abil73)? SOC_PA_SPEED_25GB:0; 641 spd_fd|= PHYMOD_AN_CAP_25G_KRS1_GET(abil73)? SOC_PA_SPEED_25GB:0; 642 643 /* retrieve CL73bam abilities */ 644 abil73 = anAbility->cl73bam_cap; 645 spd_fd|= PHYMOD_BAM_CL73_CAP_50G_CR4_GET(abil73)? SOC_PA_SPEED_50GB:0; 646 spd_fd|= PHYMOD_BAM_CL73_CAP_50G_KR4_GET(abil73)? SOC_PA_SPEED_50GB:0; 647 spd_fd|= PHYMOD_BAM_CL73_CAP_50G_CR2_GET(abil73)? SOC_PA_SPEED_50GB:0; 648 spd_fd|= PHYMOD_BAM_CL73_CAP_50G_KR2_GET(abil73)? SOC_PA_SPEED_50GB:0; 649 spd_fd|= PHYMOD_BAM_CL73_CAP_40G_CR2_GET(abil73)? SOC_PA_SPEED_40GB:0; 650 spd_fd|= PHYMOD_BAM_CL73_CAP_40G_KR2_GET(abil73)? SOC_PA_SPEED_40GB:0; 651 spd_fd|= PHYMOD_BAM_CL73_CAP_25G_CR1_GET(abil73)? SOC_PA_SPEED_25GB:0; 652 spd_fd|= PHYMOD_BAM_CL73_CAP_25G_KR1_GET(abil73)? SOC_PA_SPEED_25GB:0; 653 spd_fd|= PHYMOD_BAM_CL73_CAP_20G_CR2_GET(abil73)? SOC_PA_SPEED_20GB:0; 654 spd_fd|= PHYMOD_BAM_CL73_CAP_20G_KR2_GET(abil73)? SOC_PA_SPEED_20GB:0; 655 spd_fd|= PHYMOD_BAM_CL73_CAP_20G_CR1_GET(abil73)? SOC_PA_SPEED_20GB:0; 656 spd_fd|= PHYMOD_BAM_CL73_CAP_20G_KR1_GET(abil73)? SOC_PA_SPEED_20GB:0; 657 658 /* retrieve CL37 abilities */ 659 abil37 = anAbility->cl37bam_cap; 660 spd_fd|= PHYMOD_BAM_CL37_CAP_40G_GET(abil37) ? SOC_PA_SPEED_40GB:0; 661 spd_fd|= PHYMOD_BAM_CL37_CAP_31P5G_GET(abil37)? SOC_PA_SPEED_30GB:0; 662 spd_fd|= PHYMOD_BAM_CL37_CAP_32P7G_GET(abil37)? SOC_PA_SPEED_32GB:0; 663 664 spd_fd|= PHYMOD_BAM_CL37_CAP_25P455G_GET(abil37) ? SOC_PA_SPEED_25GB:0; 665 spd_fd|= PHYMOD_BAM_CL37_CAP_21G_X4_GET(abil37) ? SOC_PA_SPEED_21GB:0; 666 spd_fd|= PHYMOD_BAM_CL37_CAP_20G_X2_CX4_GET(abil37)? SOC_PA_SPEED_20GB:0; 667 spd_fd|= PHYMOD_BAM_CL37_CAP_20G_X2_GET(abil37) ? SOC_PA_SPEED_20GB:0; 668 spd_fd|= PHYMOD_BAM_CL37_CAP_20G_X4_GET(abil37) ? SOC_PA_SPEED_20GB:0; 669 spd_fd|= PHYMOD_BAM_CL37_CAP_20G_X4_CX4_GET(abil37)? SOC_PA_SPEED_20GB:0; 670 spd_fd|= PHYMOD_BAM_CL37_CAP_16G_X4_GET(abil37) ? SOC_PA_SPEED_16GB:0; 671 spd_fd|= PHYMOD_BAM_CL37_CAP_15P75G_R2_GET(abil37) ? SOC_PA_SPEED_16GB:0; 672 spd_fd|= PHYMOD_BAM_CL37_CAP_15G_X4_GET(abil37)? SOC_PA_SPEED_15GB:0; 673 spd_fd|= PHYMOD_BAM_CL37_CAP_13G_X4_GET(abil37)? SOC_PA_SPEED_13GB:0; 674 spd_fd|= PHYMOD_BAM_CL37_CAP_12P7_DXGXS_GET(abil37)? SOC_PA_SPEED_13GB:0; 675 spd_fd|= PHYMOD_BAM_CL37_CAP_12P5_X4_GET(abil37)? SOC_PA_SPEED_12P5GB:0; 676 spd_fd|= PHYMOD_BAM_CL37_CAP_12G_X4_GET(abil37)? SOC_PA_SPEED_12GB:0; 677 spd_fd|= PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_GET(abil37)?SOC_PA_SPEED_11GB:0; 678 spd_fd|= PHYMOD_BAM_CL37_CAP_10G_X2_CX4_GET(abil37)? SOC_PA_SPEED_10GB:0; 679 spd_fd|= PHYMOD_BAM_CL37_CAP_10G_DXGXS_GET(abil37)? SOC_PA_SPEED_10GB:0; 680 spd_fd|= PHYMOD_BAM_CL37_CAP_10G_CX4_GET(abil37)? SOC_PA_SPEED_10GB:0; 681 spd_fd|= PHYMOD_BAM_CL37_CAP_10G_HIGIG_GET(abil37)? SOC_PA_SPEED_10GB:0; /* 4-lane */ 682 spd_fd|= PHYMOD_BAM_CL37_CAP_6G_X4_GET(abil37)? SOC_PA_SPEED_6000MB:0; 683 spd_fd|= PHYMOD_BAM_CL37_CAP_5G_X4_GET(abil37)? SOC_PA_SPEED_5000MB:0; 684 spd_fd|= PHYMOD_BAM_CL37_CAP_2P5G_GET(abil37)? SOC_PA_SPEED_2500MB:0; 685 686 if (PHYMOD_AN_CAP_CL37_GET(anAbility)){ 687 spd_fd|= SOC_PA_SPEED_1000MB; 688 } 689 690 if (PHYMOD_AN_CAP_SGMII_GET(anAbility)){ 691 switch (anAbility->sgmii_speed){ 692 case phymod_CL37_SGMII_10M: 693 spd_fd|= SOC_PA_SPEED_10MB; 694 break; 695 case phymod_CL37_SGMII_100M: 696 spd_fd|= SOC_PA_SPEED_100MB; 697 break; 698 case phymod_CL37_SGMII_1000M: 699 spd_fd|= SOC_PA_SPEED_1000MB; 700 break; 701 default: 702 break; 703 } 704 } 705 706 portAbility->pause = 0; 707 if (anAbility->capabilities & PHYMOD_AN_CAP_ASYM_PAUSE) { 708 if (anAbility->capabilities & PHYMOD_AN_CAP_SYMM_PAUSE) { 709 portAbility->pause = SOC_PA_PAUSE_RX; 710 } else { 711 portAbility->pause = SOC_PA_PAUSE_TX; 712 } 713 } else if (anAbility->capabilities & PHYMOD_AN_CAP_SYMM_PAUSE) { 714 portAbility->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 715 } 716 717 portAbility->speed_full_duplex = spd_fd; 718 719 abil73 = anAbility->an_cap; 720 abil73bam = anAbility->cl73bam_cap; 721 722 if (PHYMOD_AN_CAP_25G_KRS1_GET(abil73) || PHYMOD_AN_CAP_25G_CRS1_GET(abil73)) { 723 portAbility->channel = SOC_PA_CHANNEL_SHORT; 724 } else { 725 portAbility->channel = SOC_PA_CHANNEL_LONG; 726 } 727 728 if (PHYMOD_AN_CAP_100G_CR4_GET(abil73) || PHYMOD_AN_CAP_40G_CR4_GET(abil73) || 729 PHYMOD_AN_CAP_25G_CR1_GET(abil73) || PHYMOD_AN_CAP_25G_CRS1_GET(abil73) || 730 PHYMOD_BAM_CL73_CAP_20G_CR2_GET(abil73bam) || PHYMOD_BAM_CL73_CAP_40G_CR2_GET(abil73bam) || 731 PHYMOD_BAM_CL73_CAP_50G_CR2_GET(abil73bam) || PHYMOD_BAM_CL73_CAP_25G_CR1_GET(abil73bam) || 732 PHYMOD_BAM_CL73_CAP_50G_CR4_GET(abil73bam)) { 733 portAbility->medium = SOC_PA_MEDIUM_COPPER; 734 } else { 735 portAbility->medium = SOC_PA_MEDIUM_BACKPLANE; 736 } 737 738 portAbility->fec = 0; 739 if (PHYMOD_AN_FEC_OFF_GET(anAbility->an_fec)) { 740 portAbility->fec = SOC_PA_FEC_NONE; 741 } else { 742 if (PHYMOD_AN_FEC_CL74_GET(anAbility->an_fec)) { 743 portAbility->fec |= SOC_PA_FEC_CL74; 744 } 745 if (PHYMOD_AN_FEC_CL91_GET(anAbility->an_fec)) { 746 portAbility->fec |= SOC_PA_FEC_CL91; 747 } 748 } 749 750 if (anAbility->an_hg2) { 751 portAbility->encap = SOC_ENCAP_HIGIG2; 752 } else { 753 portAbility->encap = SOC_ENCAP_IEEE; 754 } 755 756 } 757 758 759 /* phy_tsce_ability_advert_set */ 760 #define PHYMOD_INTF_CR4 (1 << SOC_PORT_IF_CR4) 761 void portmod_common_port_to_phy_ability (portmod_port_ability_t *portAbility, 762 phymod_autoneg_ability_t *anAbility, 763 int port_num_lanes, 764 int line_interface, 765 int cx4_10g, 766 int an_cl72, 767 int an_fec, 768 int hg_mode) 769 { 770 uint32_t an_tech_ability = 0; 771 uint32_t an_bam37_ability = 0; 772 uint32_t an_bam73_ability = 0; 773 _shr_port_mode_t speed_full_duplex = portAbility->speed_full_duplex; 774 phymod_autoneg_ability_t_init(anAbility); 775 776 /* an_tech_ability */ 777 if (port_num_lanes == 4 || 778 port_num_lanes == 10 || 779 port_num_lanes == 12 ) { 780 if ((speed_full_duplex & SOC_PA_SPEED_100GB) || 781 (speed_full_duplex & SOC_PA_SPEED_106GB) || 782 (speed_full_duplex & SOC_PA_SPEED_120GB) || 783 (speed_full_duplex & SOC_PA_SPEED_127GB)) { 784 if (SOC_PORT_IF_CR4 == line_interface) { 785 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 786 } else if ((SOC_PORT_IF_KR4 == line_interface) 787 ||(SOC_PORT_IF_CAUI4 == line_interface)) { 788 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 789 } else { 790 if(port_num_lanes == 4){ 791 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 792 } else if (port_num_lanes == 10){ 793 PHYMOD_AN_CAP_100G_CR10_SET(an_tech_ability); 794 } else { 795 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 796 } 797 } 798 } 799 if (speed_full_duplex & SOC_PA_SPEED_50GB) { 800 if (SOC_PORT_IF_CR4 == line_interface) { 801 PHYMOD_BAM_CL73_CAP_50G_CR4_SET(an_bam73_ability); 802 } else { 803 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_bam73_ability); 804 } 805 } 806 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 807 if (SOC_PORT_IF_CR4 == line_interface) { 808 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 809 } else { 810 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 811 } 812 } 813 if(speed_full_duplex & SOC_PA_SPEED_20GB) { 814 if (SOC_PORT_IF_CR4 == line_interface) { 815 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 816 } else { 817 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 818 } 819 } 820 if(speed_full_duplex & SOC_PA_SPEED_10GB) { 821 PHYMOD_AN_CAP_10G_KX4_SET(an_tech_ability); 822 } 823 if (speed_full_duplex & SOC_PA_SPEED_1000MB) 824 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 825 } else if (port_num_lanes == 2) { 826 if(speed_full_duplex & SOC_PA_SPEED_50GB) { 827 if (SOC_PORT_IF_CR2 == line_interface) { 828 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_bam73_ability); 829 } else { 830 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability); 831 } 832 } 833 if(speed_full_duplex & SOC_PA_SPEED_40GB) { 834 if (SOC_PORT_IF_CR2 == line_interface) { 835 PHYMOD_BAM_CL73_CAP_40G_CR2_SET(an_bam73_ability); 836 /*support AN ability set for external PHY with Gearbox mode*/ 837 } else if (SOC_PORT_IF_CR4 == line_interface) { 838 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 839 } else if (SOC_PORT_IF_KR4 == line_interface) { 840 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 841 } else { 842 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_bam73_ability); 843 } 844 } 845 if(speed_full_duplex & SOC_PA_SPEED_20GB) { 846 if (SOC_PORT_IF_CR2 == line_interface) { 847 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_bam73_ability); 848 } else { 849 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_bam73_ability); 850 } 851 } 852 if (speed_full_duplex & SOC_PA_SPEED_10GB) 853 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 854 if (speed_full_duplex & SOC_PA_SPEED_1000MB) 855 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 856 } else { 857 if(speed_full_duplex & SOC_PA_SPEED_25GB) { 858 if (SOC_PORT_IF_CR == line_interface) { 859 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_bam73_ability); 860 PHYMOD_AN_CAP_25G_CR1_SET(an_tech_ability); 861 } else { 862 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability); 863 PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability); 864 } 865 } 866 if(speed_full_duplex & SOC_PA_SPEED_20GB) { 867 if (SOC_PORT_IF_CR == line_interface) { 868 PHYMOD_BAM_CL73_CAP_20G_CR1_SET(an_bam73_ability); 869 } else { 870 PHYMOD_BAM_CL73_CAP_20G_KR1_SET(an_bam73_ability); 871 } 872 } 873 if (speed_full_duplex & SOC_PA_SPEED_10GB) 874 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 875 if (speed_full_duplex & SOC_PA_SPEED_1000MB) 876 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 877 } 878 879 /* an_bam37_ability */ 880 if (port_num_lanes == 4 || 881 port_num_lanes == 10 || 882 port_num_lanes == 12) { 883 if(speed_full_duplex & SOC_PA_SPEED_40GB) 884 PHYMOD_BAM_CL37_CAP_40G_SET(an_bam37_ability); 885 /* if(speed_full_duplex & SOC_PA_SPEED_33GB) 886 an_bam37_ability |= (1<<PHYMOD_BAM37ABL_32P7G); */ 887 if(speed_full_duplex & SOC_PA_SPEED_30GB) 888 PHYMOD_BAM_CL37_CAP_31P5G_SET(an_bam37_ability); 889 if(speed_full_duplex & SOC_PA_SPEED_25GB) 890 PHYMOD_BAM_CL37_CAP_25P455G_SET(an_bam37_ability); 891 if(speed_full_duplex & SOC_PA_SPEED_21GB) 892 PHYMOD_BAM_CL37_CAP_21G_X4_SET(an_bam37_ability); 893 if(speed_full_duplex & SOC_PA_SPEED_20GB){ 894 PHYMOD_BAM_CL37_CAP_20G_X4_SET(an_bam37_ability); 895 PHYMOD_BAM_CL37_CAP_20G_X4_CX4_SET(an_bam37_ability); 896 } 897 if(speed_full_duplex & SOC_PA_SPEED_16GB) 898 PHYMOD_BAM_CL37_CAP_16G_X4_SET(an_bam37_ability); 899 if(speed_full_duplex & SOC_PA_SPEED_15GB) 900 PHYMOD_BAM_CL37_CAP_15G_X4_SET(an_bam37_ability); 901 if(speed_full_duplex & SOC_PA_SPEED_13GB) 902 PHYMOD_BAM_CL37_CAP_13G_X4_SET(an_bam37_ability); 903 if(speed_full_duplex & SOC_PA_SPEED_12P5GB) 904 PHYMOD_BAM_CL37_CAP_12P5_X4_SET(an_bam37_ability); 905 if(speed_full_duplex & SOC_PA_SPEED_12GB) 906 PHYMOD_BAM_CL37_CAP_12G_X4_SET(an_bam37_ability); 907 if(speed_full_duplex & SOC_PA_SPEED_10GB) { 908 if (cx4_10g) { 909 PHYMOD_BAM_CL37_CAP_10G_CX4_SET(an_bam37_ability); 910 } else { 911 PHYMOD_BAM_CL37_CAP_10G_HIGIG_SET(an_bam37_ability); 912 } 913 } 914 if(speed_full_duplex & SOC_PA_SPEED_6000MB) 915 PHYMOD_BAM_CL37_CAP_6G_X4_SET(an_bam37_ability); 916 if(speed_full_duplex & SOC_PA_SPEED_5000MB) 917 PHYMOD_BAM_CL37_CAP_5G_X4_SET(an_bam37_ability); 918 if(speed_full_duplex & SOC_PA_SPEED_2500MB) 919 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_bam37_ability); 920 if(speed_full_duplex & SOC_PA_SPEED_1000MB) 921 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 922 923 } else if (port_num_lanes == 2) { /* 2 lanes */ 924 925 if(speed_full_duplex & SOC_PA_SPEED_20GB){ 926 PHYMOD_BAM_CL37_CAP_20G_X2_SET(an_bam37_ability); 927 PHYMOD_BAM_CL37_CAP_20G_X2_CX4_SET(an_bam37_ability); 928 } 929 if (speed_full_duplex & SOC_PA_SPEED_16GB) 930 PHYMOD_BAM_CL37_CAP_15P75G_R2_SET(an_bam37_ability); 931 if (speed_full_duplex & SOC_PA_SPEED_13GB) 932 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_bam37_ability); 933 if (speed_full_duplex & SOC_PA_SPEED_11GB) 934 PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_SET(an_bam37_ability); 935 if (speed_full_duplex & SOC_PA_SPEED_10GB){ 936 PHYMOD_BAM_CL37_CAP_10G_X2_CX4_SET(an_bam37_ability); 937 PHYMOD_BAM_CL37_CAP_10G_DXGXS_SET(an_bam37_ability); 938 } 939 if (speed_full_duplex & SOC_PA_SPEED_2500MB) 940 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_bam37_ability); 941 if (speed_full_duplex & SOC_PA_SPEED_1000MB) 942 PHYMOD_AN_CAP_1G_KX_SET(an_tech_ability); 943 944 } else { /* 1 lane */ 945 if (speed_full_duplex & SOC_PA_SPEED_2500MB) 946 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_bam37_ability); 947 } 948 anAbility->an_cap = an_tech_ability; 949 anAbility->cl73bam_cap = an_bam73_ability; 950 anAbility->cl37bam_cap = an_bam37_ability; 951 952 953 954 switch (portAbility->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 955 case SOC_PA_PAUSE_TX: 956 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 957 break; 958 case SOC_PA_PAUSE_RX: 959 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 960 PHYMOD_AN_CAP_ASYM_PAUSE_SET(anAbility); 961 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 962 break; 963 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 964 PHYMOD_AN_CAP_SYMM_PAUSE_SET(anAbility); 965 break; 966 } 967 968 if ((speed_full_duplex & SOC_PA_SPEED_10MB) || 969 (speed_full_duplex & SOC_PA_SPEED_100MB) || 970 (speed_full_duplex & SOC_PA_SPEED_1000MB)) { 971 if (SOC_PORT_IF_SGMII == line_interface) { 972 /* also set the sgmii speed */ 973 if(portAbility->speed_full_duplex & SOC_PA_SPEED_1000MB) { 974 PHYMOD_AN_CAP_SGMII_SET(anAbility); 975 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 976 } else if(portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 977 PHYMOD_AN_CAP_SGMII_SET(anAbility); 978 anAbility->sgmii_speed = phymod_CL37_SGMII_100M; 979 } else if(portAbility->speed_full_duplex & SOC_PA_SPEED_10MB) { 980 PHYMOD_AN_CAP_SGMII_SET(anAbility); 981 anAbility->sgmii_speed = phymod_CL37_SGMII_10M; 982 } else { 983 PHYMOD_AN_CAP_SGMII_SET(anAbility); 984 anAbility->sgmii_speed = phymod_CL37_SGMII_1000M; 985 } 986 } else { 987 if(portAbility->speed_full_duplex & SOC_PA_SPEED_100MB) { 988 PHYMOD_AN_CAP_100M_SET(anAbility->an_cap); 989 } 990 } 991 } 992 993 /* next check if we need to set cl37 attribute */ 994 if (an_cl72) { 995 anAbility->an_cl72 = 1; 996 } 997 if (hg_mode) { 998 anAbility->an_hg2 = 1; 999 } 1000 1001 /* check if Cl74/CL91 fec is to be set */ 1002 if (portAbility->fec == SOC_PA_FEC_NONE) { 1003 PHYMOD_AN_FEC_OFF_SET(anAbility->an_fec); 1004 } else { 1005 if(portAbility->fec & SOC_PA_FEC_CL74) { 1006 PHYMOD_AN_FEC_CL74_SET(anAbility->an_fec); 1007 } 1008 if(portAbility->fec & SOC_PA_FEC_CL91) { 1009 PHYMOD_AN_FEC_CL91_SET(anAbility->an_fec); 1010 } 1011 } 1012 1013 if (an_fec) { 1014 PHYMOD_AN_FEC_CL74_SET(anAbility->an_fec); 1015 } 1016 1017 } 1018 1019 /*! 1020 * portmod_port_main_core_access_get 1021 * 1022 * @brief get port main cores' phymod access 1023 * 1024 * @param [in] unit - unit id 1025 * @param [in] port - logical port 1026 * @param [in] phyn - the number of hops from the internal phy. 0 - internal, 1- first external PHY, etc. 1027 * @param [out] core_access_arr - port phymod cores array 1028 * @param [out] nof_cores - number of core access structutres filled by the function 1029 */ 1030 int portmod_port_main_core_access_get(int unit, int port, int phyn, 1031 phymod_core_access_t *core_access, 1032 int *nof_cores) 1033 { 1034 int ncores = 0; 1035 if (IS_C_PORT(unit, port) || IS_CXX_PORT(unit, port)) { 1036 phymod_core_access_t core_acc_100g[3]; 1037 portmod_port_core_access_get(unit, port, phyn, 3, core_acc_100g, &ncores, NULL); 1038 sal_memcpy(core_access, &core_acc_100g[0], sizeof(phymod_core_access_t)); 1039 } else { 1040 phymod_core_access_t core_acc; 1041 portmod_port_core_access_get(unit, port, phyn, 1, &core_acc, &ncores, NULL); 1042 sal_memcpy(core_access, &core_acc, sizeof(phymod_core_access_t)); 1043 } 1044 *nof_cores = ncores; 1045 return SOC_E_NONE; 1046 } 1047 1048 /*! 1049 * portmod_port_to_phyaddr 1050 * 1051 * @brief Get Phy addr for a given port. 1052 * 1053 * @param [in] unit - unit id 1054 * @param [in] port - logical port 1055 */ 1056 int portmod_port_to_phyaddr(int unit, int port) 1057 { 1058 int nof_cores = 0, phyaddr; 1059 1060 phymod_core_access_t core_acc; 1061 portmod_port_main_core_access_get(unit, port, -1, &core_acc, &nof_cores); 1062 phyaddr = (nof_cores == 0)? -1 : core_acc.access.addr; 1063 1064 return (phyaddr); 1065 } 1066 1067 /*! 1068 * portmod_port_to_phyaddr_int 1069 * 1070 * @brief Get internal Phy addr for a given port. 1071 * 1072 * @param [in] unit - unit id 1073 * @param [in] port - logical port 1074 */ 1075 int portmod_port_to_phyaddr_int(int unit, int port) 1076 { 1077 phymod_core_access_t internal_core; 1078 int nof_cores = 0; 1079 1080 portmod_port_core_access_get(unit, port, 0, 1, &internal_core, &nof_cores, NULL); 1081 1082 return ((nof_cores == 0)? -1 : internal_core.access.addr); 1083 } 1084 1085 int portmod_intf_to_phymod_intf(int unit, int speed, soc_port_if_t interface, 1086 phymod_interface_t *phymod_interface) 1087 { 1088 return soc_phymod_phy_intf_from_port_intf(unit, speed, interface, phymod_interface); 1089 } 1090 1091 int portmod_intf_from_phymod_intf (int unit, 1092 phymod_interface_t phymod_interface, 1093 soc_port_if_t *interface) 1094 { 1095 return soc_phymod_phy_intf_to_port_intf(unit, phymod_interface, interface); 1096 } 1097 1098 int portmod_line_intf_from_config_get(const portmod_port_interface_config_t *config, soc_port_if_t *interface) 1099 { 1100 *interface = (config->line_interface != SOC_PORT_IF_NULL ? config->line_interface : config->interface); 1101 return SOC_E_NONE; 1102 } 1103 1104 int 1105 portmod_port_redirect_loopback_set(int unit, soc_port_t port, 1106 int phyn, int phy_lane, 1107 int sys_side, uint32 enable) 1108 { 1109 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1110 int nof_phys = 0; 1111 portmod_access_get_params_t params; 1112 SOC_INIT_FUNC_DEFS; 1113 1114 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 1115 params.lane = phy_lane; 1116 params.phyn = phyn; 1117 params.sys_side = (sys_side ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE); 1118 1119 _SOC_IF_ERR_EXIT(portmod_port_phy_lane_access_get(unit, port, ¶ms, 1120 PORT_MAX_PHY_ACCESS_STRUCTURES, 1121 phy_access, &nof_phys, NULL)); 1122 1123 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_set (unit, port, phy_access, nof_phys, portmodLoopbackPhyGloopPCS, enable)); 1124 1125 exit: 1126 SOC_FUNC_RETURN; 1127 1128 #if 0 1129 /* leave this code to look sys_side need to be taken care of. The comment need to delete before commit. tlwin*/ 1130 phymod_phy_access_t phy_access; 1131 int nof_phys; 1132 portmod_access_get_params_t params; 1133 1134 portmod_access_get_params_t_init(unit, ¶ms); 1135 params.lane = phy_lane; 1136 params.phyn = phyn; 1137 params.sys_side = (sys_side == 1) ? PORTMOD_SIDE_SYSTEM: PORTMOD_SIDE_LINE; 1138 1139 SOC_IF_ERROR_RETURN( 1140 portmod_port_phy_lane_access_get(unit, 1141 port, 1142 ¶ms, 1143 1, 1144 &phy_access, 1145 &nof_phys)); 1146 1147 SOC_IF_ERROR_RETURN(phymod_phy_loopback_set(&phy_access, 1148 portmodLoopbackPhyGloopPCS, enable)); 1149 1150 return SOC_E_NONE; 1151 #endif 1152 } 1153 1154 int 1155 portmod_port_redirect_loopback_get(int unit, soc_port_t port, 1156 int phyn, int phy_lane, 1157 int sys_side, uint32 *enable) 1158 { 1159 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1160 int nof_phys = 0; 1161 portmod_access_get_params_t params; 1162 SOC_INIT_FUNC_DEFS; 1163 1164 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 1165 params.lane = phy_lane; 1166 params.phyn = phyn; 1167 params.sys_side = (sys_side ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE); 1168 1169 _SOC_IF_ERR_EXIT(portmod_port_phy_lane_access_get(unit, port, ¶ms, 1170 PORT_MAX_PHY_ACCESS_STRUCTURES, 1171 phy_access, &nof_phys, NULL)); 1172 1173 _SOC_IF_ERR_EXIT(portmod_port_phychain_loopback_get (unit, port, phy_access, nof_phys, portmodLoopbackPhyGloopPCS, enable)); 1174 1175 exit: 1176 SOC_FUNC_RETURN; 1177 1178 #if 0 1179 /* need to review before deleting this */ 1180 phymod_phy_access_t phy_access; 1181 int nof_phys; 1182 portmod_access_get_params_t params; 1183 1184 portmod_access_get_params_t_init(unit, ¶ms); 1185 params.lane = phy_lane; 1186 params.phyn = phyn; 1187 params.sys_side = (sys_side == 1) ? PORTMOD_SIDE_SYSTEM: PORTMOD_SIDE_LINE; 1188 1189 SOC_IF_ERROR_RETURN( 1190 portmod_port_phy_lane_access_get(unit, 1191 port, 1192 ¶ms, 1193 1, 1194 &phy_access, 1195 &nof_phys)); 1196 1197 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&phy_access, 1198 portmodLoopbackPhyGloopPCS, enable)); 1199 1200 return SOC_E_NONE; 1201 #endif 1202 } 1203 1204 int 1205 portmod_port_redirect_autoneg_set (int unit, soc_port_t port, 1206 int phyn, int phy_lane, 1207 int sys_side, phymod_autoneg_control_t* an) 1208 { 1209 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1210 int nof_phys = 0, num_lanes = 0; 1211 portmod_access_get_params_t params; 1212 SOC_INIT_FUNC_DEFS; 1213 1214 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 1215 params.lane = phy_lane; 1216 params.phyn = phyn; 1217 params.sys_side = (sys_side ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE); 1218 1219 _SOC_IF_ERR_EXIT(portmod_port_lane_count_get(unit, port, !sys_side, &num_lanes)); 1220 an->num_lane_adv = num_lanes; 1221 1222 _SOC_IF_ERR_EXIT(portmod_port_phy_lane_access_get(unit, port, ¶ms, 1223 PORT_MAX_PHY_ACCESS_STRUCTURES, 1224 phy_access, &nof_phys, NULL)); 1225 1226 _SOC_IF_ERR_EXIT(portmod_port_phychain_autoneg_set(unit, port, phy_access, nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, an)); 1227 1228 exit: 1229 SOC_FUNC_RETURN; 1230 } 1231 1232 int 1233 portmod_port_redirect_autoneg_get (int unit, soc_port_t port, 1234 int phyn, int phy_lane, 1235 int sys_side, phymod_autoneg_control_t* an) 1236 { 1237 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1238 int nof_phys = 0; 1239 uint32_t an_done =0; 1240 portmod_access_get_params_t params; 1241 SOC_INIT_FUNC_DEFS; 1242 1243 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 1244 params.lane = phy_lane; 1245 params.phyn = phyn; 1246 params.sys_side = (sys_side ? PORTMOD_SIDE_SYSTEM : PORTMOD_SIDE_LINE); 1247 1248 _SOC_IF_ERR_EXIT(portmod_port_phy_lane_access_get(unit, port, ¶ms, 1249 PORT_MAX_PHY_ACCESS_STRUCTURES, 1250 phy_access, &nof_phys, NULL)); 1251 1252 _SOC_IF_ERR_EXIT(portmod_port_phychain_autoneg_get(unit, port, phy_access, nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, an, &an_done)); 1253 1254 exit: 1255 SOC_FUNC_RETURN; 1256 } 1257 1258 /* 1259 * This is a temporary fix for the PHY_FLAGS_TST code which 1260 * gets updated in linkscan. Proper code will be added 1261 */ 1262 int portmod_port_flags_test(int unit, soc_port_t port, int flag) 1263 { 1264 phymod_core_access_t core_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1265 phymod_autoneg_control_t an; 1266 portmod_port_interface_config_t cfg; 1267 phymod_operation_mode_t op_mode = 0; 1268 int is_legacy_present; 1269 1270 int nof_cores = 0, is_most_ext; 1271 1272 /* always get the MOST-EXT phy */ 1273 SOC_IF_ERROR_RETURN(portmod_port_core_access_get(unit, port, -1, PORT_MAX_PHY_ACCESS_STRUCTURES, 1274 core_access, &nof_cores, &is_most_ext)); 1275 SOC_IF_ERROR_RETURN( 1276 portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_present)); 1277 1278 if (is_legacy_present) { 1279 /* call legacy driver functions */ 1280 return portmod_port_legacy_phy_flags_test(unit, port, flag); 1281 } 1282 1283 if (nof_cores < 1) return (SOC_E_PARAM); 1284 1285 switch (flag) { 1286 case PHY_FLAGS_MEDIUM_CHANGE: 1287 return (0); 1288 break; 1289 1290 case PHY_FLAGS_C45: 1291 { 1292 return (PHYMOD_ACC_F_CLAUSE45_GET(&core_access[0].access)); 1293 } 1294 break; 1295 1296 case PHY_FLAGS_EXTERNAL_PHY: 1297 { 1298 /* whether exists ext-phy */ 1299 SOC_IF_ERROR_RETURN(portmod_port_core_access_get(unit, port, 1, PORT_MAX_PHY_ACCESS_STRUCTURES, 1300 core_access, &nof_cores, &is_most_ext)); 1301 return (nof_cores ? 1 : 0); 1302 } 1303 break; 1304 1305 case PHY_FLAGS_FORCED_SGMII: 1306 SOC_IF_ERROR_RETURN(portmod_port_autoneg_get(unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an)); 1307 if (an.enable) return (0); 1308 1309 SOC_IF_ERROR_RETURN(portmod_port_interface_config_get(unit, port, &cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 1310 return ((cfg.interface == SOC_PORT_IF_SGMII)? 1 : 0); 1311 break; 1312 1313 case PHY_FLAGS_REPEATER: 1314 SOC_IF_ERROR_RETURN(portmod_port_phy_op_mode_get(unit, port, &op_mode)); 1315 return ((op_mode == phymodOperationModeRetimer) ? 0 : 1); 1316 break; 1317 1318 default: 1319 break; 1320 } 1321 1322 return (SOC_E_UNAVAIL); 1323 } 1324 1325 int portmod_port_chain_core_access_get(int unit, int port, pm_info_t pm_info, phymod_core_access_t* core_access_arr, int max_buf, int* nof_cores) 1326 { 1327 int phyn = 0, is_most_ext = 0, core_count; 1328 int arr_idx = 0, rv; 1329 SOC_INIT_FUNC_DEFS; 1330 1331 while (!is_most_ext) { 1332 1333 if (max_buf <= 0) { /* buffer protection */ 1334 _SOC_EXIT_WITH_ERR(SOC_E_FULL, (_SOC_MSG("max buffer size exceeded."))); 1335 } 1336 1337 rv = __portmod__dispatch__[pm_info->type]->f_portmod_port_core_access_get(unit, port, pm_info, phyn, max_buf, &(core_access_arr[arr_idx]), &core_count, &is_most_ext); 1338 _SOC_IF_ERR_EXIT(rv); 1339 arr_idx += core_count; 1340 phyn++; 1341 max_buf -= core_count; 1342 } 1343 1344 *nof_cores = arr_idx; 1345 1346 exit: 1347 SOC_FUNC_RETURN; 1348 1349 } 1350 1351 int portmod_port_chain_phy_access_get(int unit, int port, pm_info_t pm_info, phymod_phy_access_t* core_access_arr, int max_buf, int* nof_cores) 1352 { 1353 int phyn = 0, is_most_ext = 0, core_count, arr_idx = 0, rv; 1354 portmod_access_get_params_t params; 1355 SOC_INIT_FUNC_DEFS; 1356 1357 while (!is_most_ext) { 1358 1359 if (max_buf <= 0) { /* buffer protection */ 1360 _SOC_EXIT_WITH_ERR(SOC_E_FULL, (_SOC_MSG("max buffer size exceeded."))); 1361 } 1362 1363 _SOC_IF_ERR_EXIT(portmod_access_get_params_t_init(unit, ¶ms)); 1364 params.phyn = phyn; 1365 rv = __portmod__dispatch__[pm_info->type]->f_portmod_port_phy_lane_access_get(unit, port, pm_info, ¶ms, max_buf, &(core_access_arr[arr_idx]), &core_count, &is_most_ext); 1366 _SOC_IF_ERR_EXIT(rv); 1367 1368 arr_idx += core_count; 1369 phyn++; 1370 max_buf -= core_count; 1371 } 1372 1373 *nof_cores = arr_idx; 1374 1375 exit: 1376 SOC_FUNC_RETURN; 1377 1378 } 1379 int portmod_ext_to_int_cmd_set(int unit, int port, portmod_ext_to_int_phy_ctrlcode_t cmd, void *data) { 1380 pm_info_t pm_info; 1381 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1382 int chain_length = 0, flags = 0, is_intf_valid = 0, spacing_value = 0; 1383 phymod_autoneg_control_t *an; 1384 portmod_port_ability_t *port_ability; 1385 1386 portmod_port_interface_config_t interface_config; 1387 1388 int *cmd_data = (int *)data; 1389 1390 SOC_INIT_FUNC_DEFS; 1391 1392 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, port, &pm_info)); 1393 1394 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 1395 PORT_MAX_PHY_ACCESS_STRUCTURES, 1396 &chain_length)); 1397 sal_memset(&interface_config, 0, sizeof(interface_config)); 1398 1399 /* call portmod_port_chain function */ 1400 switch(cmd) { 1401 case portmodExtToInt_CtrlCode_Link: 1402 break; 1403 case portmodExtToInt_CtrlCode_Enable: 1404 PORTMOD_PORT_ENABLE_PHY_SET(flags); 1405 PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_SET(flags); 1406 _SOC_IF_ERR_EXIT(portmod_port_enable_set(unit, port, flags, *cmd_data)); 1407 break; 1408 case portmodExtToInt_CtrlCode_Speed: 1409 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, port, &interface_config, 1410 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 1411 interface_config.speed = *cmd_data; 1412 _SOC_IF_ERR_EXIT(portmod_port_interface_config_set(unit, port, &interface_config, 1413 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1414 break; 1415 case portmodExtToInt_CtrlCode_Interface: 1416 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, port, &interface_config, 1417 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1418 interface_config.interface = *cmd_data; 1419 1420 /* 1421 * Some legacy external PHYs call portmod_ext_to_int_cmd_set() twice. First 1422 * with cmd portmodExtToInt_CtrlCode_Interface followed by cmd 1423 * portmodExtToInt_CtrlCode_Speed. During system init it is possible that 1424 * the internal PHY is still in its default state, so the speed fetched from 1425 * the above portmod_port_interface_config_get() call may not be compatible 1426 * with the new interface type (cmd_data). In this case the wrong speed + 1427 * interface config should not be provided to the internal PHY. 1428 */ 1429 _SOC_IF_ERR_EXIT(portmod_port_interface_check(unit, port, &interface_config, 1430 0, *cmd_data, &is_intf_valid)); 1431 if (!is_intf_valid) { 1432 return SOC_E_PARAM; 1433 } 1434 1435 _SOC_IF_ERR_EXIT(portmod_port_interface_config_set(unit, port, &interface_config, 1436 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1437 break; 1438 case portmodExtToInt_CtrlCode_AN: 1439 an = (phymod_autoneg_control_t *)data; 1440 _SOC_IF_ERR_EXIT(portmod_port_autoneg_set(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, an)); 1441 break; 1442 case portmodExtToInt_CtrlCode_AbilityAdvert: 1443 port_ability = (portmod_port_ability_t *)data; 1444 _SOC_IF_ERR_EXIT(portmod_port_ability_advert_set(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, port_ability)); 1445 break; 1446 case portmodExtToInt_CtrlCode_SpeedLine: 1447 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, port, &interface_config, 1448 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1449 if ((*cmd_data == 2500) && (interface_config.speed == 10000)) { 1450 spacing_value = MAC_WAN_MODE_THROTTLE_10G_TO_2P5G; 1451 } else if ((*cmd_data == 5000) && (interface_config.speed == 10000)) { 1452 spacing_value = MAC_WAN_MODE_THROTTLE_10G_TO_5G; 1453 } 1454 _SOC_IF_ERR_EXIT(portmod_port_frame_spacing_stretch_set(unit, port, spacing_value)); 1455 break; 1456 default: 1457 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("Invalid command input %d\n", cmd)); 1458 } 1459 1460 /* call portmod_port_chain function */ 1461 exit: 1462 SOC_FUNC_RETURN; 1463 1464 1465 } 1466 1467 1468 int portmod_ext_to_int_cmd_get(int unit, int port, portmod_ext_to_int_phy_ctrlcode_t cmd, void *data) { 1469 pm_info_t pm_info; 1470 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1471 int chain_length = 0; 1472 uint32 flags = 0; 1473 portmod_port_interface_config_t interface_config; 1474 phymod_autoneg_control_t *an; 1475 portmod_port_ability_t *port_ability; 1476 1477 int value; 1478 int *cmd_data = (int *)data; 1479 1480 SOC_INIT_FUNC_DEFS; 1481 1482 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, port, &pm_info)); 1483 1484 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 1485 PORT_MAX_PHY_ACCESS_STRUCTURES, 1486 &chain_length)); 1487 sal_memset(&interface_config, 0, sizeof(interface_config)); 1488 1489 /* call portmod_port_chain function */ 1490 switch(cmd) { 1491 case portmodExtToInt_CtrlCode_Link: 1492 _SOC_IF_ERR_EXIT(portmod_port_link_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, &value)); 1493 *cmd_data = value; 1494 break; 1495 case portmodExtToInt_CtrlCode_Enable: 1496 PORTMOD_PORT_ENABLE_INTERNAL_PHY_ONLY_SET(flags); 1497 _SOC_IF_ERR_EXIT(portmod_port_enable_get(unit, port, flags, &value)); 1498 *cmd_data = value; 1499 break; 1500 case portmodExtToInt_CtrlCode_Speed: 1501 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, port, &interface_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1502 *cmd_data = interface_config.speed; 1503 break; 1504 case portmodExtToInt_CtrlCode_Interface: 1505 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, port, &interface_config, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1506 *cmd_data = interface_config.interface; 1507 break; 1508 case portmodExtToInt_CtrlCode_AN: 1509 an = (phymod_autoneg_control_t *)data; 1510 _SOC_IF_ERR_EXIT(portmod_port_autoneg_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, an)); 1511 break; 1512 case portmodExtToInt_CtrlCode_AbilityAdvert: 1513 port_ability = (portmod_port_ability_t *)data; 1514 _SOC_IF_ERR_EXIT(portmod_port_ability_advert_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, port_ability)); 1515 break; 1516 case portmodExtToInt_CtrlCode_AbilityLocal: 1517 port_ability = (portmod_port_ability_t *)data; 1518 _SOC_IF_ERR_EXIT(portmod_port_ability_local_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, port_ability)); 1519 break; 1520 case portmodExtToInt_CtrlCode_AbilityRemote: 1521 port_ability = (portmod_port_ability_t *)data; 1522 _SOC_IF_ERR_EXIT(portmod_port_ability_remote_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, port_ability)); 1523 break; 1524 default: 1525 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("Invalid command input %d\n", cmd)); 1526 } 1527 1528 exit: 1529 SOC_FUNC_RETURN; 1530 1531 } 1532 1533 int portmod_port_is_legacy_ext_phy_present(int unit, int port, int *is_legacy_present) { 1534 pm_info_t pm_info; 1535 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1536 int chain_length = 0; 1537 portmod_dispatch_type_t __type__; 1538 int ext_phy_threshold = 1; 1539 1540 SOC_INIT_FUNC_DEFS; 1541 1542 *is_legacy_present = 0; 1543 1544 if (IS_IL_PORT(unit, port)) { 1545 /* ILKN does not support ext phy */ 1546 SOC_EXIT; 1547 } 1548 _SOC_IF_ERR_EXIT(portmod_port_pm_type_get(unit, port, &port, &__type__)); 1549 1550 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, port, &pm_info)); 1551 1552 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 1553 PORT_MAX_PHY_ACCESS_STRUCTURES, 1554 &chain_length)); 1555 1556 #ifdef PORTMOD_PM12X10_SUPPORT 1557 if (__type__ == portmodDispatchTypePm12x10) { 1558 ext_phy_threshold = 3; 1559 } 1560 #endif /*PORTMOD_PM12X10_SUPPORT */ 1561 1562 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 1563 if (__type__ == portmodDispatchTypePm12x10_xgs) { 1564 ext_phy_threshold = 3; 1565 } 1566 #endif /*PORTMOD_PM12X10_XGS_SUPPORT */ 1567 1568 if (chain_length > ext_phy_threshold) { 1569 /* external phy is present in this system */ 1570 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_get(unit, phy_access[chain_length - 1].access.addr, is_legacy_present)); 1571 } 1572 exit: 1573 SOC_FUNC_RETURN; 1574 1575 } 1576 1577 int portmod_port_ext_phy_control_set(int unit, int port, int phyn, int phy_lane, int sys_side, 1578 soc_phy_control_t control, uint32 value) { 1579 1580 portmod_dispatch_type_t __type__; 1581 1582 SOC_INIT_FUNC_DEFS; 1583 1584 _SOC_IF_ERR_EXIT(portmod_port_pm_type_get(unit, port, &port, &__type__)); 1585 1586 _SOC_IF_ERR_EXIT(portmod_port_legacy_phy_control_set(unit, port, phyn, phy_lane, sys_side, 1587 control, value)); 1588 1589 exit: 1590 SOC_FUNC_RETURN; 1591 } 1592 1593 int portmod_port_ext_phy_control_get(int unit, int port, int phyn, int phy_lane, int sys_side, 1594 soc_phy_control_t control, uint32* value) { 1595 1596 portmod_dispatch_type_t __type__; 1597 1598 SOC_INIT_FUNC_DEFS; 1599 1600 _SOC_IF_ERR_EXIT(portmod_port_pm_type_get(unit, port, &port, &__type__)); 1601 1602 /* 1603 * _SOC_IF_ERR_EXIT() could cause unwanted error message printings if it is used in 1604 * the following function call. 1605 */ 1606 return portmod_port_legacy_phy_control_get(unit, port, phyn, phy_lane, sys_side, 1607 control, value); 1608 1609 exit: 1610 SOC_FUNC_RETURN; 1611 } 1612 1613 int portmod_port_ext_phy_mdix_set(int unit, int port, soc_port_mdix_t mode) { 1614 return portmod_port_legacy_phy_mdix_set(unit, port, mode); 1615 } 1616 1617 int portmod_port_ext_phy_mdix_get(int unit, int port, soc_port_mdix_t *mode) { 1618 return portmod_port_legacy_phy_mdix_get(unit, port, mode); 1619 } 1620 1621 int portmod_port_ext_phy_mdix_status_get(int unit, soc_port_t port, 1622 soc_port_mdix_status_t *status) { 1623 return portmod_port_legacy_phy_mdix_status_get(unit, port, status); 1624 } 1625 1626 1627 int portmod_port_status_notify(int unit, int port, int link) 1628 { 1629 pm_info_t pm_info; 1630 phymod_phy_access_t phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES]; 1631 int chain_length = 0; 1632 portmod_port_interface_config_t interface_config; 1633 1634 SOC_INIT_FUNC_DEFS; 1635 1636 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, port, &pm_info)); 1637 1638 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 1639 PORT_MAX_PHY_ACCESS_STRUCTURES, 1640 &chain_length)); 1641 _SOC_IF_ERR_EXIT(portmod_port_chain_phy_access_get(unit, port, pm_info, phy_access, 1642 PORT_MAX_PHY_ACCESS_STRUCTURES, 1643 &chain_length)); 1644 1645 sal_memset(&interface_config, 0 , sizeof(interface_config)); 1646 1647 if (link) { 1648 if (chain_length > 1) { 1649 /* get the line side speed and program the internal phy 1650 * to the same speed */ 1651 _SOC_IF_ERR_EXIT(portmod_port_interface_config_get(unit, 1652 port, 1653 &interface_config, 1654 PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 1655 /* set the speed for internal phy */ 1656 _SOC_IF_ERR_EXIT(portmod_port_interface_config_set(unit, 1657 port, 1658 &interface_config, 1659 PORTMOD_INIT_F_INTERNAL_SERDES_ONLY)); 1660 } 1661 } else { 1662 /* TBD Disable the internal PHY */ 1663 } 1664 1665 exit: 1666 SOC_FUNC_RETURN; 1667 } 1668 #define PORTMOD_IF_ERROR_RETURN(_op) _SHR_E_IF_ERROR_RETURN(_op) 1669 1670 int portmod_common_timesync_config_set(const phymod_phy_access_t* phy_access, 1671 const portmod_phy_timesync_config_t* conf) 1672 { 1673 phymod_timesync_config_t ts_conf; 1674 1675 PORTMOD_IF_ERROR_RETURN( 1676 phymod_timesync_config_get(phy_access, &ts_conf)); 1677 1678 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 1679 1680 if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) { 1681 phymod_timesync_enable_set(phy_access, 0, TRUE); 1682 } else { 1683 phymod_timesync_enable_set(phy_access, 0, FALSE); 1684 } 1685 1686 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 1687 PHYMOD_TS_F_CAPTURE_TS_ENABLE_SET(ts_conf.flags); 1688 } else { 1689 PHYMOD_TS_F_CAPTURE_TS_ENABLE_CLR(ts_conf.flags); 1690 } 1691 1692 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 1693 PHYMOD_TS_F_HEARTBEAT_TS_ENABLE_SET(ts_conf.flags); 1694 } else { 1695 PHYMOD_TS_F_HEARTBEAT_TS_ENABLE_CLR(ts_conf.flags); 1696 } 1697 1698 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 1699 PHYMOD_TS_F_RX_CRC_ENABLE_SET(ts_conf.flags); 1700 } else { 1701 PHYMOD_TS_F_RX_CRC_ENABLE_CLR(ts_conf.flags); 1702 } 1703 1704 if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 1705 PHYMOD_TS_F_8021AS_ENABLE_SET(ts_conf.flags); 1706 } else { 1707 PHYMOD_TS_F_8021AS_ENABLE_CLR(ts_conf.flags); 1708 } 1709 1710 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 1711 PHYMOD_TS_F_L2_ENABLE_SET(ts_conf.flags); 1712 } else { 1713 PHYMOD_TS_F_L2_ENABLE_CLR(ts_conf.flags); 1714 } 1715 1716 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 1717 PHYMOD_TS_F_IP4_ENABLE_SET(ts_conf.flags); 1718 } else { 1719 PHYMOD_TS_F_IP4_ENABLE_CLR(ts_conf.flags); 1720 } 1721 1722 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 1723 PHYMOD_TS_F_IP6_ENABLE_SET(ts_conf.flags); 1724 } else { 1725 PHYMOD_TS_F_IP6_ENABLE_CLR(ts_conf.flags); 1726 } 1727 1728 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 1729 PHYMOD_TS_F_CLOCK_SRC_EXT_SET(ts_conf.flags); 1730 } else { 1731 PHYMOD_TS_F_CLOCK_SRC_EXT_CLR(ts_conf.flags); 1732 } 1733 1734 if (conf->flags & SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE) { 1735 PHYMOD_TS_F_64BIT_TIMESTAMP_ENABLE_SET(ts_conf.flags); 1736 } else { 1737 PHYMOD_TS_F_64BIT_TIMESTAMP_ENABLE_CLR(ts_conf.flags); 1738 } 1739 1740 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC) { 1741 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_SYNC_SET(ts_conf.flags); 1742 } 1743 1744 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ) { 1745 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_DELAY_REQ_SET(ts_conf.flags); 1746 } 1747 1748 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ) { 1749 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_PDELAY_REQ_SET(ts_conf.flags); 1750 } 1751 1752 if (conf-> 1753 flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP) { 1754 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_PDELAY_RESP_SET(ts_conf.flags); 1755 } 1756 1757 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC) { 1758 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_SYNC_SET(ts_conf.flags); 1759 } 1760 1761 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ) { 1762 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_DELAY_REQ_SET(ts_conf.flags); 1763 } 1764 1765 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ) { 1766 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_PDELAY_REQ_SET(ts_conf.flags); 1767 } 1768 1769 if (conf-> 1770 flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP) { 1771 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_PDELAY_RESP_SET(ts_conf.flags); 1772 } 1773 } 1774 1775 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 1776 ts_conf.itpid = conf->itpid; 1777 } 1778 1779 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 1780 ts_conf.otpid = conf->otpid; 1781 } 1782 1783 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 1784 ts_conf.otpid2 = conf->otpid2; 1785 } 1786 1787 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 1788 ts_conf.ts_divider= conf->ts_divider; 1789 } 1790 1791 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 1792 ts_conf.rx_link_delay= conf->rx_link_delay; 1793 } 1794 1795 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 1796 sal_memcpy(&ts_conf.original_timecode, &conf->original_timecode, 1797 sizeof(phymod_timesync_timespec_t)); 1798 } 1799 1800 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 1801 /* coverity[mixed_enums] */ 1802 ts_conf.gmode = conf->gmode; 1803 } 1804 1805 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 1806 PORTMOD_IF_ERROR_RETURN( 1807 phymod_timesync_framesync_mode_set(phy_access, 1808 (portmod_timesync_framesync_t*) &conf->framesync)); 1809 } 1810 1811 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 1812 sal_memcpy(&ts_conf.syncout, &conf->syncout, 1813 sizeof(phymod_timesync_syncout_t)); 1814 } 1815 1816 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 1817 PORTMOD_IF_ERROR_RETURN( 1818 phymod_timesync_rx_timestamp_offset_set(phy_access, 1819 conf->rx_timestamp_offset)); 1820 } 1821 1822 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 1823 PORTMOD_IF_ERROR_RETURN( 1824 phymod_timesync_tx_timestamp_offset_set(phy_access, 1825 conf->tx_timestamp_offset)); 1826 } 1827 1828 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 1829 /* coverity[mixed_enums] */ 1830 ts_conf.tx_sync_mode = conf->tx_sync_mode; 1831 } 1832 1833 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 1834 /* coverity[mixed_enums] */ 1835 ts_conf.tx_delay_req_mode = conf->tx_delay_request_mode; 1836 } 1837 1838 if (conf-> 1839 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 1840 /* coverity[mixed_enums] */ 1841 ts_conf.tx_pdelay_req_mode = conf->tx_pdelay_request_mode; 1842 } 1843 1844 if (conf-> 1845 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 1846 /* coverity[mixed_enums] */ 1847 ts_conf.tx_pdelay_resp_mode = conf->tx_pdelay_response_mode; 1848 } 1849 1850 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 1851 /* coverity[mixed_enums] */ 1852 ts_conf.rx_sync_mode = conf->rx_sync_mode; 1853 } 1854 1855 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 1856 /* coverity[mixed_enums] */ 1857 ts_conf.rx_delay_req_mode = conf->rx_delay_request_mode; 1858 } 1859 1860 if (conf-> 1861 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 1862 /* coverity[mixed_enums] */ 1863 ts_conf.rx_pdelay_req_mode = conf->rx_pdelay_request_mode; 1864 } 1865 1866 if (conf-> 1867 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 1868 /* coverity[mixed_enums] */ 1869 ts_conf.rx_pdelay_resp_mode = conf->rx_pdelay_response_mode; 1870 } 1871 1872 if (conf-> 1873 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 1874 ts_conf.phy_1588_dpll_ref_phase = conf->phy_1588_dpll_ref_phase; 1875 } 1876 1877 if (conf-> 1878 validity_mask & 1879 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 1880 ts_conf.phy_1588_dpll_ref_phase_delta = conf->phy_1588_dpll_ref_phase_delta; 1881 } 1882 1883 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 1884 ts_conf.phy_1588_dpll_k1 = conf->phy_1588_dpll_k1; 1885 } 1886 1887 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 1888 ts_conf.phy_1588_dpll_k2 = conf->phy_1588_dpll_k2; 1889 } 1890 1891 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 1892 ts_conf.phy_1588_dpll_k3 = conf->phy_1588_dpll_k3; 1893 } 1894 1895 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 1896 sal_memcpy(&ts_conf.mpls_ctrl, &conf->mpls_control, 1897 sizeof(phymod_timesync_mpls_ctrl_t)); 1898 } 1899 1900 PORTMOD_IF_ERROR_RETURN( 1901 phymod_timesync_config_set(phy_access, &ts_conf)); 1902 1903 return SOC_E_NONE; 1904 } 1905 1906 1907 int portmod_common_timesync_config_get(const phymod_phy_access_t* phy_access, 1908 portmod_phy_timesync_config_t* conf) 1909 { 1910 uint32 enable; 1911 phymod_timesync_config_t ts_conf; 1912 1913 PORTMOD_IF_ERROR_RETURN( 1914 phymod_timesync_config_get(phy_access, &ts_conf)); 1915 1916 conf->flags = 0; 1917 1918 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 1919 PORTMOD_IF_ERROR_RETURN( 1920 phymod_timesync_enable_get(phy_access, 0, &enable)); 1921 1922 if(enable) { 1923 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 1924 } else { 1925 conf->flags &= ~SOC_PORT_PHY_TIMESYNC_ENABLE; 1926 } 1927 1928 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 1929 PHYMOD_TS_F_CAPTURE_TS_ENABLE_SET(conf->flags); 1930 } else { 1931 PHYMOD_TS_F_CAPTURE_TS_ENABLE_CLR(conf->flags); 1932 } 1933 1934 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 1935 PHYMOD_TS_F_HEARTBEAT_TS_ENABLE_SET(conf->flags); 1936 } else { 1937 PHYMOD_TS_F_HEARTBEAT_TS_ENABLE_CLR(conf->flags); 1938 } 1939 1940 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 1941 PHYMOD_TS_F_RX_CRC_ENABLE_SET(conf->flags); 1942 } else { 1943 PHYMOD_TS_F_RX_CRC_ENABLE_CLR(conf->flags); 1944 } 1945 1946 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 1947 PHYMOD_TS_F_8021AS_ENABLE_SET(conf->flags); 1948 } else { 1949 PHYMOD_TS_F_8021AS_ENABLE_CLR(conf->flags); 1950 } 1951 1952 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 1953 PHYMOD_TS_F_L2_ENABLE_SET(conf->flags); 1954 } else { 1955 PHYMOD_TS_F_L2_ENABLE_CLR(conf->flags); 1956 } 1957 1958 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 1959 PHYMOD_TS_F_IP4_ENABLE_SET(conf->flags); 1960 } else { 1961 PHYMOD_TS_F_IP4_ENABLE_CLR(conf->flags); 1962 } 1963 1964 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 1965 PHYMOD_TS_F_IP6_ENABLE_SET(conf->flags); 1966 } else { 1967 PHYMOD_TS_F_IP6_ENABLE_CLR(conf->flags); 1968 } 1969 1970 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 1971 PHYMOD_TS_F_CLOCK_SRC_EXT_SET(conf->flags); 1972 } else { 1973 PHYMOD_TS_F_CLOCK_SRC_EXT_CLR(conf->flags); 1974 } 1975 1976 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE) { 1977 PHYMOD_TS_F_64BIT_TIMESTAMP_ENABLE_SET(conf->flags); 1978 } else { 1979 PHYMOD_TS_F_64BIT_TIMESTAMP_ENABLE_CLR(conf->flags); 1980 } 1981 1982 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC) { 1983 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_SYNC_SET(conf->flags); 1984 } 1985 1986 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ) { 1987 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_DELAY_REQ_SET(conf->flags); 1988 } 1989 1990 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ) { 1991 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_PDELAY_REQ_SET(conf->flags); 1992 } 1993 1994 if (ts_conf.flags 1995 & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP) { 1996 PHYMOD_TS_F_CAPTURE_TIMESTAMP_TX_PDELAY_RESP_SET(conf->flags); 1997 } 1998 1999 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC) { 2000 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_SYNC_SET(conf->flags); 2001 } 2002 2003 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ) { 2004 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_DELAY_REQ_SET(conf->flags); 2005 } 2006 2007 if (ts_conf.flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ) { 2008 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_PDELAY_REQ_SET(conf->flags); 2009 } 2010 2011 if (ts_conf.flags 2012 & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP) { 2013 PHYMOD_TS_F_CAPTURE_TIMESTAMP_RX_PDELAY_RESP_SET(conf->flags); 2014 } 2015 } 2016 2017 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 2018 conf->itpid = ts_conf.itpid; 2019 } 2020 2021 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 2022 conf->otpid = ts_conf.otpid; 2023 } 2024 2025 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 2026 conf->otpid2 = ts_conf.otpid2; 2027 } 2028 2029 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 2030 conf->ts_divider= ts_conf.ts_divider; 2031 } 2032 2033 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 2034 conf->rx_link_delay= ts_conf.rx_link_delay; 2035 } 2036 2037 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 2038 sal_memcpy(&conf->original_timecode, &ts_conf.original_timecode, 2039 sizeof(phymod_timesync_timespec_t)); 2040 } 2041 2042 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 2043 /* coverity[mixed_enums] */ 2044 conf->gmode = ts_conf.gmode; 2045 } 2046 2047 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 2048 PORTMOD_IF_ERROR_RETURN( 2049 phymod_timesync_framesync_mode_get(phy_access, 2050 (portmod_timesync_framesync_t*) &conf->framesync)); 2051 } 2052 2053 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 2054 sal_memcpy(&conf->syncout, &ts_conf.syncout, 2055 sizeof(phymod_timesync_syncout_t)); 2056 } 2057 2058 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 2059 PORTMOD_IF_ERROR_RETURN( 2060 phymod_timesync_rx_timestamp_offset_get(phy_access, 2061 &conf->rx_timestamp_offset)); 2062 } 2063 2064 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 2065 PORTMOD_IF_ERROR_RETURN( 2066 phymod_timesync_tx_timestamp_offset_get(phy_access, 2067 &conf->tx_timestamp_offset)); 2068 } 2069 2070 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 2071 /* coverity[mixed_enums] */ 2072 conf->tx_sync_mode = ts_conf.tx_sync_mode; 2073 } 2074 2075 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 2076 /* coverity[mixed_enums] */ 2077 conf->tx_delay_request_mode = ts_conf.tx_delay_req_mode; 2078 } 2079 2080 if (conf-> 2081 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 2082 /* coverity[mixed_enums] */ 2083 conf->tx_pdelay_request_mode = ts_conf.tx_pdelay_req_mode; 2084 } 2085 2086 if (conf-> 2087 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 2088 /* coverity[mixed_enums] */ 2089 conf->tx_pdelay_response_mode = ts_conf.tx_pdelay_resp_mode; 2090 } 2091 2092 2093 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 2094 /* coverity[mixed_enums] */ 2095 conf->rx_sync_mode = ts_conf.rx_sync_mode; 2096 } 2097 2098 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 2099 /* coverity[mixed_enums] */ 2100 conf->rx_delay_request_mode = ts_conf.rx_delay_req_mode; 2101 } 2102 2103 if (conf-> 2104 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 2105 /* coverity[mixed_enums] */ 2106 conf->rx_pdelay_request_mode = ts_conf.rx_pdelay_req_mode; 2107 } 2108 2109 if (conf-> 2110 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 2111 /* coverity[mixed_enums] */ 2112 conf->rx_pdelay_response_mode = ts_conf.rx_pdelay_resp_mode; 2113 } 2114 2115 if (conf-> 2116 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 2117 conf->phy_1588_dpll_ref_phase = ts_conf.phy_1588_dpll_ref_phase; 2118 } 2119 2120 if (conf-> 2121 validity_mask & 2122 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 2123 conf->phy_1588_dpll_ref_phase_delta = ts_conf.phy_1588_dpll_ref_phase_delta; 2124 } 2125 2126 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 2127 conf->phy_1588_dpll_k1 = ts_conf.phy_1588_dpll_k1; 2128 } 2129 2130 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 2131 conf->phy_1588_dpll_k2 = ts_conf.phy_1588_dpll_k2; 2132 } 2133 2134 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 2135 conf->phy_1588_dpll_k3 = ts_conf.phy_1588_dpll_k3; 2136 } 2137 2138 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 2139 sal_memcpy(&conf->mpls_control, &ts_conf.mpls_ctrl, 2140 sizeof(phymod_timesync_mpls_ctrl_t)); 2141 } 2142 2143 return SOC_E_NONE; 2144 } 2145 2146 int portmod_media_type_from_port_intf(int unit, soc_port_if_t interface, 2147 phymod_phy_inf_config_t *phy_interface_config) 2148 { 2149 return soc_phymod_media_type_from_port_intf(unit, interface, phy_interface_config); 2150 } 2151 2152 int portmod_intf_mode_from_phymod_intf(int unit, phymod_interface_t phymod_interface, 2153 phymod_phy_inf_config_t *phy_interface_config) 2154 { 2155 return soc_phymod_intf_mode_from_phymod_intf(unit, phymod_interface, phy_interface_config); 2156 } 2157 2158 2159 int portmod_common_control_phy_timesync_set(const phymod_phy_access_t* phy_access, 2160 const portmod_port_control_phy_timesync_t type, 2161 const uint64 value) 2162 { 2163 uint32 val_lo; 2164 uint32 once = 0, always = 0, flags = 0; 2165 uint32 value0; 2166 phymod_core_access_t core_access; 2167 phymod_timesync_compensation_mode_t timesync_am_norm_mode; 2168 2169 val_lo = COMPILER_64_LO(value); 2170 2171 switch (type) { 2172 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 2173 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 2174 return SOC_E_NONE; 2175 2176 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 2177 PORTMOD_IF_ERROR_RETURN(phymod_timesync_nco_addend_set(phy_access, val_lo)); 2178 PORTMOD_IF_ERROR_RETURN( 2179 phymod_timesync_nco_addend_set(phy_access, val_lo)); 2180 break; 2181 2182 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 2183 PORTMOD_IF_ERROR_RETURN( 2184 phymod_timesync_do_sync(phy_access)); 2185 break; 2186 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 2187 PORTMOD_IF_ERROR_RETURN( 2188 phymod_timesync_local_time_set(phy_access, value)); 2189 break; 2190 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 2191 if (val_lo & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 2192 PHYMOD_TS_LDCTL_TN_LOAD_SET(once); 2193 } 2194 if (val_lo & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 2195 PHYMOD_TS_LDCTL_TN_LOAD_SET(always); 2196 } 2197 if (val_lo & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 2198 PHYMOD_TS_LDCTL_TIMECODE_LOAD_SET(once); 2199 } 2200 if (val_lo & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 2201 PHYMOD_TS_LDCTL_TIMECODE_LOAD_SET(always); 2202 } 2203 if (val_lo & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 2204 PHYMOD_TS_LDCTL_SYNCOUT_LOAD_SET(once); 2205 } 2206 if (val_lo & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 2207 PHYMOD_TS_LDCTL_SYNCOUT_LOAD_SET(always); 2208 } 2209 if (val_lo & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 2210 PHYMOD_TS_LDCTL_NCO_DIVIDER_LOAD_SET(once); 2211 } 2212 if (val_lo & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 2213 PHYMOD_TS_LDCTL_NCO_DIVIDER_LOAD_SET(always); 2214 } 2215 if (val_lo & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 2216 PHYMOD_TS_LDCTL_LOCAL_TIME_LOAD_SET(once); 2217 } 2218 if (val_lo & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 2219 PHYMOD_TS_LDCTL_LOCAL_TIME_LOAD_SET(always); 2220 } 2221 if (val_lo & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 2222 PHYMOD_TS_LDCTL_NCO_ADDEND_LOAD_SET(once); 2223 } 2224 if (val_lo & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 2225 PHYMOD_TS_LDCTL_NCO_ADDEND_LOAD_SET(always); 2226 } 2227 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 2228 PHYMOD_TS_LDCTL_DPLL_LOOP_FILTER_LOAD_SET(once); 2229 } 2230 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 2231 PHYMOD_TS_LDCTL_DPLL_LOOP_FILTER_LOAD_SET(always); 2232 } 2233 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 2234 PHYMOD_TS_LDCTL_DPLL_REF_PHASE_LOAD_SET(once); 2235 } 2236 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 2237 PHYMOD_TS_LDCTL_DPLL_REF_PHASE_LOAD_SET(always); 2238 } 2239 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 2240 PHYMOD_TS_LDCTL_DPLL_REF_PHASE_DELTA_LOAD_SET(once); 2241 } 2242 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 2243 PHYMOD_TS_LDCTL_DPLL_REF_PHASE_DELTA_LOAD_SET(always); 2244 } 2245 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 2246 PHYMOD_TS_LDCTL_DPLL_K3_LOAD_SET(once); 2247 } 2248 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 2249 PHYMOD_TS_LDCTL_DPLL_K3_LOAD_SET(always); 2250 } 2251 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 2252 PHYMOD_TS_LDCTL_DPLL_K2_LOAD_SET(once); 2253 } 2254 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 2255 PHYMOD_TS_LDCTL_DPLL_K2_LOAD_SET(always); 2256 } 2257 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 2258 PHYMOD_TS_LDCTL_DPLL_K1_LOAD_SET(once); 2259 } 2260 if (val_lo & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 2261 PHYMOD_TS_LDCTL_DPLL_K1_LOAD_SET(always); 2262 } 2263 2264 PORTMOD_IF_ERROR_RETURN( 2265 phymod_timesync_load_ctrl_set(phy_access, once, always)); 2266 break; 2267 2268 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 2269 2270 if (val_lo & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) { 2271 PORTMOD_IF_ERROR_RETURN( 2272 phymod_phy_intr_status_clear(phy_access, 2273 PHYMOD_INTR_TIMESYNC_TIMESTAMP)); 2274 } 2275 if (val_lo & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) { 2276 PORTMOD_IF_ERROR_RETURN( 2277 phymod_phy_intr_status_clear(phy_access, 2278 PHYMOD_INTR_TIMESYNC_FRAMESYNC)); 2279 } 2280 break; 2281 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 2282 2283 PORTMOD_IF_ERROR_RETURN( 2284 phymod_phy_intr_enable_get(phy_access, &value0)); 2285 2286 if (val_lo & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT){ 2287 value0 |= PHYMOD_INTR_TIMESYNC_TIMESTAMP ; 2288 } else { 2289 value0 &= ~PHYMOD_INTR_TIMESYNC_TIMESTAMP ; 2290 } 2291 2292 if (val_lo & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT){ 2293 value0 |= PHYMOD_INTR_TIMESYNC_FRAMESYNC; 2294 } else { 2295 value0 &= ~PHYMOD_INTR_TIMESYNC_FRAMESYNC; 2296 } 2297 2298 PORTMOD_IF_ERROR_RETURN( 2299 phymod_phy_intr_enable_set(phy_access, value0)); 2300 2301 break; 2302 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 2303 val_lo = COMPILER_64_LO(value); 2304 2305 PORTMOD_IF_ERROR_RETURN( 2306 phymod_timesync_tx_timestamp_offset_set(phy_access, val_lo)); 2307 2308 break; 2309 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 2310 val_lo = COMPILER_64_LO(value); 2311 PORTMOD_IF_ERROR_RETURN( 2312 phymod_timesync_rx_timestamp_offset_set(phy_access, val_lo)); 2313 2314 break; 2315 case SOC_PORT_CONTROL_PHY_TIMESYNC_TIMESTAMP_OFFSET: 2316 val_lo = COMPILER_64_LO(value); 2317 sal_memcpy(&core_access, phy_access, sizeof(core_access)); 2318 PORTMOD_IF_ERROR_RETURN( 2319 phymod_timesync_offset_set(&core_access, val_lo)); 2320 break; 2321 case SOC_PORT_CONTROL_PHY_TIMESYNC_TIMESTAMP_ADJUST: 2322 timesync_am_norm_mode = COMPILER_64_LO(value); 2323 PORTMOD_IF_ERROR_RETURN( 2324 phymod_timesync_adjust_set(phy_access, timesync_am_norm_mode)); 2325 break; 2326 case SOC_PORT_CONTROL_PHY_TIMESYNC_ONE_STEP_ENABLE: 2327 val_lo = COMPILER_64_LO(value); 2328 PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags); 2329 PORTMOD_IF_ERROR_RETURN( 2330 phymod_timesync_enable_set(phy_access, flags, val_lo)); 2331 break; 2332 default: 2333 return SOC_E_UNAVAIL; 2334 } 2335 return SOC_E_NONE; 2336 } 2337 2338 int portmod_common_control_phy_timesync_get(const phymod_phy_access_t* phy_access, 2339 const portmod_port_control_phy_timesync_t type, 2340 uint64* value) 2341 { 2342 uint32 val_lo; 2343 uint32 once = 0, always = 0, flags = 0; 2344 uint32 value0; 2345 uint32 intr_status; 2346 2347 switch (type) { 2348 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 2349 PORTMOD_IF_ERROR_RETURN( 2350 phymod_timesync_heartbeat_timestamp_get(phy_access, value)); 2351 2352 break; 2353 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 2354 PORTMOD_IF_ERROR_RETURN( 2355 phymod_timesync_capture_timestamp_get(phy_access, value)); 2356 2357 break; 2358 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 2359 PORTMOD_IF_ERROR_RETURN( 2360 phymod_timesync_nco_addend_get(phy_access, &val_lo)); 2361 COMPILER_64_SET((*value), 0, val_lo); 2362 2363 break; 2364 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 2365 PORTMOD_IF_ERROR_RETURN( 2366 phymod_timesync_local_time_get(phy_access, value)); 2367 break; 2368 2369 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 2370 2371 PORTMOD_IF_ERROR_RETURN( 2372 phymod_timesync_load_ctrl_get(phy_access, &once, &always)); 2373 2374 val_lo = 0; 2375 2376 if (once & PHYMOD_TS_LDCTL_TN_LOAD) { 2377 val_lo |= SOC_PORT_PHY_TIMESYNC_TN_LOAD; 2378 } 2379 if (always & PHYMOD_TS_LDCTL_TN_LOAD) { 2380 val_lo |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 2381 } 2382 if (once & PHYMOD_TS_LDCTL_TIMECODE_LOAD) { 2383 val_lo |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 2384 } 2385 if (always & PHYMOD_TS_LDCTL_TIMECODE_LOAD) { 2386 val_lo |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 2387 } 2388 if (once & PHYMOD_TS_LDCTL_SYNCOUT_LOAD) { 2389 val_lo |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 2390 } 2391 if (always & PHYMOD_TS_LDCTL_SYNCOUT_LOAD) { 2392 val_lo |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 2393 } 2394 if (once & PHYMOD_TS_LDCTL_NCO_DIVIDER_LOAD) { 2395 val_lo |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 2396 } 2397 if (always & PHYMOD_TS_LDCTL_NCO_DIVIDER_LOAD) { 2398 val_lo |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 2399 } 2400 if (once & PHYMOD_TS_LDCTL_LOCAL_TIME_LOAD) { 2401 val_lo |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 2402 } 2403 if (always & PHYMOD_TS_LDCTL_LOCAL_TIME_LOAD) { 2404 val_lo |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 2405 } 2406 if (once & PHYMOD_TS_LDCTL_NCO_ADDEND_LOAD) { 2407 val_lo |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 2408 } 2409 if (always & PHYMOD_TS_LDCTL_NCO_ADDEND_LOAD) { 2410 val_lo |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 2411 } 2412 if (once & PHYMOD_TS_LDCTL_DPLL_LOOP_FILTER_LOAD) { 2413 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 2414 } 2415 if (always & PHYMOD_TS_LDCTL_DPLL_LOOP_FILTER_LOAD) { 2416 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 2417 } 2418 if (once & PHYMOD_TS_LDCTL_DPLL_REF_PHASE_LOAD) { 2419 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 2420 } 2421 if (always & PHYMOD_TS_LDCTL_DPLL_REF_PHASE_LOAD) { 2422 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 2423 } 2424 if (once & PHYMOD_TS_LDCTL_DPLL_REF_PHASE_DELTA_LOAD) { 2425 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 2426 } 2427 if (always & PHYMOD_TS_LDCTL_DPLL_REF_PHASE_DELTA_LOAD) { 2428 val_lo |= 2429 SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 2430 } 2431 if (once & PHYMOD_TS_LDCTL_DPLL_K3_LOAD) { 2432 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 2433 } 2434 if (always & PHYMOD_TS_LDCTL_DPLL_K3_LOAD) { 2435 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 2436 } 2437 if (once & PHYMOD_TS_LDCTL_DPLL_K2_LOAD) { 2438 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 2439 } 2440 if (always & PHYMOD_TS_LDCTL_DPLL_K2_LOAD) { 2441 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 2442 } 2443 if (once & PHYMOD_TS_LDCTL_DPLL_K1_LOAD) { 2444 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 2445 } 2446 if (always & PHYMOD_TS_LDCTL_DPLL_K1_LOAD) { 2447 val_lo |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 2448 } 2449 COMPILER_64_SET((*value), 0, val_lo); 2450 2451 break; 2452 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 2453 value0 = 0; 2454 2455 PORTMOD_IF_ERROR_RETURN( 2456 phymod_phy_intr_status_get(phy_access, &intr_status)); 2457 if (intr_status) { 2458 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 2459 } 2460 2461 PORTMOD_IF_ERROR_RETURN( 2462 phymod_phy_intr_status_get(phy_access, &intr_status)); 2463 if (intr_status) { 2464 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 2465 } 2466 2467 COMPILER_64_SET((*value), 0, (uint32) value0); 2468 break; 2469 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 2470 value0 = 0; 2471 2472 PORTMOD_IF_ERROR_RETURN( 2473 phymod_phy_intr_enable_get(phy_access, &intr_status)); 2474 if (intr_status) { 2475 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 2476 } 2477 2478 PORTMOD_IF_ERROR_RETURN( 2479 phymod_phy_intr_enable_get(phy_access, &intr_status)); 2480 if (intr_status) { 2481 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 2482 } 2483 2484 COMPILER_64_SET((*value), 0, (uint32) value0); 2485 break; 2486 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 2487 PORTMOD_IF_ERROR_RETURN( 2488 phymod_timesync_tx_timestamp_offset_get(phy_access, &val_lo)); 2489 COMPILER_64_SET((*value), 0, val_lo); 2490 2491 break; 2492 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 2493 PORTMOD_IF_ERROR_RETURN( 2494 phymod_timesync_rx_timestamp_offset_get(phy_access, &val_lo)); 2495 COMPILER_64_SET((*value), 0, val_lo); 2496 break; 2497 case SOC_PORT_CONTROL_PHY_TIMESYNC_ONE_STEP_ENABLE: 2498 PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_SET(flags); 2499 PORTMOD_IF_ERROR_RETURN( 2500 phymod_timesync_enable_get(phy_access, flags, &val_lo)); 2501 COMPILER_64_SET((*value), 0, val_lo); 2502 break; 2503 default: 2504 return SOC_E_UNAVAIL; 2505 } 2506 return SOC_E_NONE; 2507 } 2508 2509 STATIC 2510 int _portmod_common_ext_phy_addr_get(int unit, soc_port_t port, uint32 *xphy_id) 2511 { 2512 phymod_phy_access_t phy_access[1+MAX_PHYN]; 2513 int nof_phys = 0; 2514 portmod_access_get_params_t params; 2515 int is_most_ext; 2516 2517 *xphy_id = PORTMOD_XPHY_ID_INVALID; 2518 2519 SOC_IF_ERROR_RETURN 2520 (portmod_access_get_params_t_init(unit, ¶ms)); 2521 params.phyn = 0; 2522 SOC_IF_ERROR_RETURN 2523 (portmod_port_phy_lane_access_get(unit, port, 2524 ¶ms, (1+MAX_PHYN), phy_access, &nof_phys, &is_most_ext)); 2525 if(is_most_ext) 2526 { 2527 return SOC_E_NONE; 2528 } 2529 params.phyn = 1; 2530 SOC_IF_ERROR_RETURN 2531 (portmod_port_phy_lane_access_get(unit, port, 2532 ¶ms, (1+MAX_PHYN), phy_access, &nof_phys, NULL)); 2533 2534 *xphy_id = phy_access[0].access.addr; 2535 2536 return SOC_E_NONE; 2537 } 2538 2539 int portmod_common_ext_phy_fw_bcst(int unit, pbmp_t *pbmp) 2540 { 2541 phymod_core_status_t core_status; 2542 phymod_firmware_load_method_t fw_load_method; 2543 phymod_core_access_t core_access; 2544 int is_initialized; 2545 int force_fw_load, is_legacy_present; 2546 uint32 primary_core_num; 2547 2548 phymod_core_init_config_t core_config; 2549 2550 int rv=0, dev_type, mdio_bus; 2551 uint32 xphy_id, is_identify = 0; 2552 uint8 ext_phy_bcst_done[PM_MDIO_BUS_COUNT][phymodDispatchTypeCount]; 2553 soc_port_t port ; 2554 pbmp_t new_pbmp ; 2555 2556 sal_memset(ext_phy_bcst_done, 0, sizeof(ext_phy_bcst_done)); 2557 2558 for(dev_type = 0; dev_type < phymodDispatchTypeCount; dev_type++) { 2559 for(mdio_bus =0; mdio_bus < PM_MDIO_BUS_COUNT; mdio_bus++) { 2560 2561 /*set up new pbm of the same type in one mdio bus */ 2562 SOC_PBMP_CLEAR(new_pbmp); 2563 SOC_IF_ERROR_RETURN(phymod_core_init_config_t_init(&core_config)); 2564 PBMP_ITER(*pbmp, port){ 2565 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id); 2566 if (rv != SOC_E_NONE) continue; 2567 2568 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2569 continue; 2570 } 2571 2572 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2573 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2574 2575 rv = portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method); 2576 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2577 2578 if (fw_load_method != phymodFirmwareLoadMethodInternal) 2579 continue; 2580 2581 /* coverity[returned_value] */ 2582 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2583 /*skip if it is legacy PHY*/ 2584 rv = portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_present); 2585 if ((rv != SOC_E_NONE) || (is_legacy_present)) continue; 2586 2587 /* check if this is bcast capable */ 2588 SOC_IF_ERROR_RETURN(phymod_core_identify(&core_access, 0, &is_identify)); 2589 2590 /* if not broadcast capable - continue */ 2591 if (!(is_identify & 0x80000000)) continue; 2592 2593 if((dev_type == core_access.type) && 2594 (mdio_bus == PHY_ID_BUS_NUM(core_access.access.addr))){ 2595 SOC_PBMP_PORT_ADD(new_pbmp, port); 2596 } 2597 } 2598 2599 /*step1: reset core for firmware load if the external phy need*/ 2600 2601 PBMP_ITER(new_pbmp, port){ 2602 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id) ; 2603 if (rv != SOC_E_NONE) continue; 2604 2605 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2606 continue; 2607 } 2608 2609 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2610 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2611 /* skip if it is not sesto. */ 2612 if ( (core_access.type != phymodDispatchTypeSesto) 2613 && (core_access.type != phymodDispatchTypeDino)) { 2614 continue; 2615 } 2616 2617 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_get(unit, xphy_id, &core_config)); 2618 core_config.flags = 0; 2619 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 2620 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 2621 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 2622 2623 if(is_initialized & PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD) 2624 continue; 2625 PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_SET(&core_config); 2626 if (force_fw_load == phymodFirmwareLoadForce) { 2627 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config); 2628 } 2629 else if (force_fw_load == phymodFirmwareLoadAuto) { 2630 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config); 2631 } 2632 2633 core_config.firmware_load_method = fw_load_method; 2634 2635 core_status.pmd_active = 0; 2636 SOC_IF_ERROR_RETURN(phymod_core_init(&core_access, 2637 &core_config, &core_status)); 2638 is_initialized |= PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD; 2639 2640 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_set(unit, xphy_id, &core_config)); 2641 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2642 } 2643 2644 /*step2:enable broadcast*/ 2645 PBMP_ITER(new_pbmp, port){ 2646 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id) ; 2647 if (rv != SOC_E_NONE) continue; 2648 2649 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2650 continue; 2651 } 2652 2653 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2654 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2655 2656 SOC_IF_ERROR_RETURN(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 2657 if (primary_core_num == core_access.access.addr) { 2658 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 2659 if(is_initialized & PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD) 2660 continue; 2661 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 2662 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_get(unit, xphy_id, &core_config)); 2663 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 2664 2665 core_config.firmware_load_method = fw_load_method; 2666 core_config.flags = 0; 2667 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_SET(&core_config); 2668 if (force_fw_load == phymodFirmwareLoadForce) { 2669 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config); 2670 } 2671 else if (force_fw_load == phymodFirmwareLoadAuto) { 2672 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config); 2673 } 2674 2675 core_status.pmd_active = 0; 2676 SOC_IF_ERROR_RETURN(phymod_core_init(&core_access, 2677 &core_config, &core_status)); 2678 is_initialized |= PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD; 2679 2680 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_set(unit, xphy_id, &core_config)); 2681 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2682 } 2683 2684 } 2685 2686 /*step3:load firmware broadcast*/ 2687 PBMP_ITER(new_pbmp, port){ 2688 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id) ; 2689 if (rv != SOC_E_NONE) continue; 2690 2691 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2692 continue; 2693 } 2694 2695 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2696 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2697 2698 SOC_IF_ERROR_RETURN(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 2699 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 2700 2701 if (primary_core_num == core_access.access.addr) { 2702 if(is_initialized & PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD) 2703 continue; 2704 2705 if(!ext_phy_bcst_done[mdio_bus][dev_type]){ 2706 /* Do the broadcast*/ 2707 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_get(unit, xphy_id, &core_config)); 2708 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 2709 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 2710 2711 core_config.firmware_load_method = fw_load_method; 2712 core_config.flags = 0; 2713 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_SET(&core_config); 2714 if (force_fw_load == phymodFirmwareLoadForce) { 2715 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config); 2716 } 2717 else if (force_fw_load == phymodFirmwareLoadAuto) { 2718 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config); 2719 } 2720 2721 core_status.pmd_active = 0; 2722 SOC_IF_ERROR_RETURN(phymod_core_init(&core_access, 2723 &core_config, &core_status)); 2724 ext_phy_bcst_done[mdio_bus][dev_type] = 1; 2725 is_initialized |= PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD; 2726 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_set(unit, xphy_id, &core_config)); 2727 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2728 }else { 2729 /* if the download is already done, mark it as fw load executed. */ 2730 is_initialized |= PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD; 2731 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2732 break ; 2733 } 2734 } 2735 } 2736 2737 /*step4: resume and verify*/ 2738 PBMP_ITER(new_pbmp, port){ 2739 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id) ; 2740 if (rv != SOC_E_NONE) continue; 2741 2742 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2743 continue; 2744 } 2745 2746 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2747 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2748 2749 if (ext_phy_bcst_done[mdio_bus][dev_type]) { 2750 SOC_IF_ERROR_RETURN(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 2751 2752 if (primary_core_num == core_access.access.addr) { 2753 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 2754 if((is_initialized & PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD)&& 2755 (is_initialized & PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY)) 2756 { 2757 continue; 2758 } 2759 2760 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_get(unit, xphy_id, &core_config)); 2761 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 2762 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 2763 2764 core_config.firmware_load_method = fw_load_method; 2765 core_config.flags = 0; 2766 /* verify firmware download and resume init */ 2767 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_CLR(&core_config); 2768 PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_SET(&core_config); 2769 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&core_config); 2770 2771 if (force_fw_load == phymodFirmwareLoadForce) { 2772 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config); 2773 } 2774 else if (force_fw_load == phymodFirmwareLoadAuto) { 2775 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config); 2776 } 2777 2778 SOC_IF_ERROR_RETURN(phymod_core_init(&core_access, 2779 &core_config, &core_status)); 2780 is_initialized |= PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD; 2781 is_initialized |= PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 2782 2783 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_set(unit, xphy_id, &core_config)); 2784 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2785 } 2786 } 2787 } 2788 2789 /*step5: firmware load end*/ 2790 PBMP_ITER(new_pbmp, port){ 2791 rv = _portmod_common_ext_phy_addr_get(unit, port, &xphy_id) ; 2792 if (rv != SOC_E_NONE) continue; 2793 2794 if (xphy_id == PORTMOD_XPHY_ID_INVALID) { 2795 continue; 2796 } 2797 2798 rv = portmod_xphy_core_access_get(unit, xphy_id, &core_access, &is_legacy_present); 2799 if (rv == SOC_E_PARAM) continue; /* no external phy exists */ 2800 2801 if (ext_phy_bcst_done[mdio_bus][dev_type]) { 2802 2803 SOC_IF_ERROR_RETURN(portmod_xphy_primary_core_num_get(unit, xphy_id, &primary_core_num)); 2804 2805 if (primary_core_num == core_access.access.addr) { 2806 /* finish up the configuration */ 2807 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_get(unit, xphy_id, &is_initialized)); 2808 if(is_initialized & PHYMOD_CORE_INIT_F_FW_LOAD_END) 2809 continue; 2810 2811 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_get(unit, xphy_id, &core_config)); 2812 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, xphy_id, &force_fw_load)); 2813 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, xphy_id, &fw_load_method)); 2814 2815 core_config.firmware_load_method = fw_load_method; 2816 core_config.flags = 0; 2817 PHYMOD_CORE_INIT_F_FW_LOAD_END_SET(&core_config); 2818 if (force_fw_load == phymodFirmwareLoadForce) { 2819 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config); 2820 } 2821 else if (force_fw_load == phymodFirmwareLoadAuto) { 2822 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config); 2823 } 2824 2825 SOC_IF_ERROR_RETURN(phymod_core_init(&core_access, 2826 &core_config, &core_status)); 2827 is_initialized |= PHYMOD_CORE_INIT_F_FW_LOAD_END; 2828 SOC_IF_ERROR_RETURN(portmod_xphy_core_config_set(unit, xphy_id, &core_config)); 2829 SOC_IF_ERROR_RETURN(portmod_xphy_is_initialized_set(unit, xphy_id, is_initialized)); 2830 } 2831 } 2832 } 2833 } 2834 } 2835 return (SOC_E_NONE); 2836 2837 } 2838 2839 /*! 2840 * portmod_port_phy_drv_name_get 2841 * 2842 * @brief Get the phy driver name attached to the port 2843 * 2844 * @param [in] unit - unit id 2845 * @param [in] port - port num 2846 * @param [out] name - phy driver name. 2847 * @param [in] len - max length of the name buffer. 2848 */ 2849 int portmod_port_phy_drv_name_get(int unit, int port, char *name, int len) 2850 { 2851 int is_ext_legacy_phy = 0; 2852 phymod_core_access_t core_acc; 2853 phymod_core_info_t core_info; 2854 char *pname = NULL, namelen = 0; 2855 int nof_cores = 0; 2856 2857 SOC_IF_ERROR_RETURN( 2858 portmod_port_is_legacy_ext_phy_present(unit, port, &is_ext_legacy_phy)); 2859 2860 if (is_ext_legacy_phy) { 2861 SOC_IF_ERROR_RETURN( 2862 portmod_port_legacy_phy_drv_name_get(unit, port, name, len)); 2863 } else { 2864 phymod_core_access_t_init(&core_acc); 2865 phymod_core_info_t_init(&core_info); 2866 2867 SOC_IF_ERROR_RETURN( 2868 portmod_port_main_core_access_get(unit, port, -1, &core_acc, 2869 &nof_cores)); 2870 if (nof_cores == 0) { 2871 /*coverity[buffer_size]*/ 2872 strncpy(name, "<nophy>", strlen("<nophy>")); 2873 return SOC_E_NONE; 2874 } 2875 SOC_IF_ERROR_RETURN( 2876 phymod_core_info_get(&core_acc, &core_info)); 2877 /* 2878 * get the phy name string from the mapping. The format is 2879 * phymodCoreVersion"PhyName", only extract Phy Name from 2880 * the string. The Phy name is also appended with the version 2881 * version string as the last 2 characters. Skip it. 2882 */ 2883 pname = 2884 phymod_core_version_t_mapping[core_info.core_version].key; 2885 namelen = (len < (strlen(pname) - 2))? (len - 1) : strlen(pname) - 2; 2886 strncpy(name, pname, namelen); 2887 *(name + namelen) = '\0'; 2888 } 2889 return (SOC_E_NONE); 2890 } 2891 2892 /*! 2893 * portmod_common_default_interface_get 2894 * 2895 * @brief Get default interface type based on port speed, number of lanes, and medium 2896 * 2897 * @param [inout] interface_config - interface config, must contain following info: port speed, number of lanes and medium 2898 */ 2899 int portmod_common_default_interface_get(portmod_port_interface_config_t* interface_config) 2900 { 2901 int is_higig; 2902 int fiber_pref; 2903 2904 is_higig = ((interface_config->encap_mode == SOC_ENCAP_HIGIG2) || 2905 (interface_config->encap_mode == SOC_ENCAP_HIGIG) || 2906 PHYMOD_INTF_MODES_HIGIG_GET(interface_config)) ? 1 : 0; 2907 fiber_pref = PHYMOD_INTF_MODES_FIBER_GET(interface_config); 2908 2909 if (interface_config->port_num_lanes == 1) { 2910 if (interface_config->speed > 12000) { 2911 if (is_higig) { 2912 interface_config->interface = SOC_PORT_IF_CR; 2913 } else { 2914 interface_config->interface = fiber_pref ? 2915 SOC_PORT_IF_SR : SOC_PORT_IF_CR; 2916 } 2917 } else if (interface_config->speed >= 10000) { 2918 if (is_higig) { 2919 interface_config->interface = SOC_PORT_IF_XFI; 2920 } else { 2921 interface_config->interface = fiber_pref ? 2922 SOC_PORT_IF_SFI : SOC_PORT_IF_XFI; 2923 } 2924 } else if (interface_config->speed == 5000) { 2925 interface_config->interface = SOC_PORT_IF_GMII; 2926 } else { 2927 interface_config->interface = fiber_pref ? 2928 SOC_PORT_IF_GMII : SOC_PORT_IF_SGMII; 2929 } 2930 } else if (interface_config->port_num_lanes == 2) { 2931 if (interface_config->speed >= 40000) { 2932 if (is_higig){ 2933 interface_config->interface = SOC_PORT_IF_CR2; 2934 } else { 2935 interface_config->interface = fiber_pref ? 2936 SOC_PORT_IF_SR2 : SOC_PORT_IF_KR2; 2937 } 2938 } else if (interface_config->speed >=20000) { 2939 if (is_higig) { 2940 interface_config->interface = SOC_PORT_IF_CR2; 2941 } else { 2942 interface_config->interface = fiber_pref ? 2943 SOC_PORT_IF_SR2 : SOC_PORT_IF_CR2; 2944 } 2945 } else { 2946 /* 10G default interface type */ 2947 interface_config->interface = SOC_PORT_IF_RXAUI; 2948 } 2949 } else if (interface_config->port_num_lanes == 3) { 2950 /* Add the interface later (if valid )*/ 2951 } else if (interface_config->port_num_lanes == 4) { 2952 if (interface_config->speed >= 100000) { 2953 if (is_higig){ 2954 interface_config->interface = SOC_PORT_IF_CR4; 2955 } else{ 2956 interface_config->interface = fiber_pref ? 2957 SOC_PORT_IF_SR4 : SOC_PORT_IF_CAUI4; 2958 } 2959 } else if (interface_config->speed >= 50000) { 2960 if (is_higig){ 2961 interface_config->interface = SOC_PORT_IF_CR4; 2962 } else{ 2963 interface_config->interface = SOC_PORT_IF_KR4; 2964 } 2965 } else if (interface_config->speed >= 40000) { 2966 if (is_higig){ 2967 interface_config->interface = SOC_PORT_IF_CR4; 2968 } else{ 2969 interface_config->interface = fiber_pref ? 2970 SOC_PORT_IF_SR4 : SOC_PORT_IF_XLAUI; 2971 } 2972 } else if (interface_config->speed >= 20000) { 2973 if (is_higig){ 2974 interface_config->interface = SOC_PORT_IF_XGMII; 2975 } else{ 2976 interface_config->interface = fiber_pref ? 2977 SOC_PORT_IF_SR4 : SOC_PORT_IF_CR4; 2978 } 2979 } else if (interface_config->speed >= 10000) { 2980 if (is_higig){ 2981 interface_config->interface = SOC_PORT_IF_XGMII; 2982 } else{ 2983 interface_config->interface = SOC_PORT_IF_XAUI; 2984 } 2985 2986 } 2987 } else if (interface_config->port_num_lanes == 10) { /* 100G */ 2988 interface_config->interface = fiber_pref ? 2989 SOC_PORT_IF_SR10 : SOC_PORT_IF_CAUI; 2990 } else if (interface_config->port_num_lanes == 12) { /* 120G */ 2991 interface_config->interface = SOC_PORT_IF_CAUI; 2992 } else { 2993 /* Do Nothing - let it be default */ 2994 } 2995 2996 return SOC_E_NONE; 2997 } 2998 2999 STATIC 3000 int _portmod_common_phymod_identify(const phymod_dispatch_type_t* type_list, const phymod_access_t* access, 3001 phymod_dispatch_type_t* type, int* is_probed) 3002 { 3003 phymod_core_access_t core; 3004 uint32_t is_identified = 0; 3005 uint32_t core_id = 0; 3006 int rv = PHYMOD_E_NONE, i = 0; 3007 3008 phymod_core_access_t_init(&core); 3009 sal_memcpy(&core.access, access, sizeof(core.access)); 3010 3011 *is_probed = 0; 3012 while (type_list[i] != phymodDispatchTypeInvalid) { 3013 core.type = type_list[i]; 3014 3015 rv = phymod_core_identify(&core, core_id, &is_identified); 3016 if (rv == PHYMOD_E_NONE && is_identified) { 3017 *type = type_list[i]; 3018 *is_probed = 1; 3019 break; 3020 } 3021 3022 i++; 3023 } 3024 3025 return PHYMOD_E_NONE; 3026 } 3027 3028 int portmod_common_serdes_probe(const phymod_dispatch_type_t* type_list, phymod_core_access_t* core_access, int* probe) 3029 { 3030 int is_probed = 0; 3031 soc_error_t rv = SOC_E_NONE; 3032 SOC_INIT_FUNC_DEFS; 3033 3034 *probe = 0; 3035 if ((core_access->type == phymodDispatchTypeInvalid) || 3036 (core_access->type == phymodDispatchTypeCount)) { 3037 rv = _portmod_common_phymod_identify(type_list, &(core_access->access), &(core_access->type), &is_probed); 3038 if (SOC_FAILURE(rv)) { 3039 /* restore the old value */ 3040 core_access->type = phymodDispatchTypeInvalid; 3041 _SOC_IF_ERR_EXIT(rv); 3042 } 3043 3044 if (is_probed) { 3045 *probe = 1; 3046 } 3047 } 3048 3049 exit: 3050 SOC_FUNC_RETURN; 3051 } 3052 3053 phymod_dispatch_type_t portmod_ext_phy_list[] = 3054 { 3055 #ifdef PHYMOD_PHY8806X_SUPPORT 3056 phymodDispatchTypePhy8806x, 3057 #endif /*PHYMOD_PHY8806X_SUPPORT */ 3058 #ifdef PHYMOD_FURIA_SUPPORT 3059 phymodDispatchTypeFuria, 3060 #endif /*PHYMOD_FURIA_SUPPORT */ 3061 #ifdef PHYMOD_SESTO_SUPPORT 3062 phymodDispatchTypeSesto, 3063 #endif /*PHYMOD_SESTO_SUPPORT */ 3064 #ifdef PHYMOD_QUADRA28_SUPPORT 3065 phymodDispatchTypeQuadra28, 3066 #endif /*PHYMOD_QUADRA28_SUPPORT */ 3067 #ifdef PHYMOD_HURACAN_SUPPORT 3068 phymodDispatchTypeHuracan, 3069 #endif /*PHYMOD_HURACAN_SUPPORT */ 3070 #ifdef PHYMOD_MADURA_SUPPORT 3071 phymodDispatchTypeMadura, 3072 #endif /*PHYMOD_MADURA_SUPPORT */ 3073 #ifdef PHYMOD_FURIA_SUPPORT 3074 phymodDispatchTypeFuria_82212, 3075 #endif /*PHYMOD_FURIA_SUPPORT */ 3076 #ifdef PHYMOD_DINO_SUPPORT 3077 phymodDispatchTypeDino, 3078 #endif /*PHYMOD_DINO_SUPPORT */ 3079 phymodDispatchTypeInvalid 3080 }; 3081 3082 /* 3083 * Function: 3084 * portmod_common_ext_phy_probe 3085 * Purpose: 3086 * Probe for external PHY attached to the port and return probing result. 3087 * First, the Phymod EXT PHY driver list is searched. 3088 * Then, if PHY dirver isn't found in Phymod list, the legacy PHY driver list will be searched. 3089 * Parameters: 3090 * unit - SOC Unit #. 3091 * port - Port number. 3092 * core_access -Phymod core information. 3093 * probe -(OUT) Probe result: (1)-Found EXT PHY driver, (0)-Not found. 3094 * Returns: 3095 * SOC_E_XXX 3096 */ 3097 int portmod_common_ext_phy_probe(int unit, int port, phymod_core_access_t* core_access, int* probe) 3098 { 3099 int is_probed = 0, xphy_id; 3100 soc_error_t rv = SOC_E_NONE; 3101 SOC_INIT_FUNC_DEFS; 3102 3103 *probe = 0; 3104 if ((core_access->type == phymodDispatchTypeInvalid) || 3105 (core_access->type == phymodDispatchTypeCount)) { 3106 rv = _portmod_common_phymod_identify(portmod_ext_phy_list, &(core_access->access), &(core_access->type), &is_probed); 3107 if (SOC_FAILURE(rv)) { 3108 /* restore the old value */ 3109 core_access->type = phymodDispatchTypeInvalid; 3110 _SOC_IF_ERR_EXIT(rv); 3111 } 3112 3113 if (!is_probed) { 3114 /* Reset type */ 3115 core_access->type = phymodDispatchTypeInvalid; 3116 if (portmod_port_legacy_phy_probe(unit, port)) { 3117 xphy_id = core_access->access.addr; 3118 _SOC_IF_ERR_EXIT(portmod_xphy_is_legacy_phy_set(unit, xphy_id, 1)); 3119 *probe = 1; 3120 } 3121 } 3122 else { 3123 *probe = 1; 3124 } 3125 } 3126 3127 exit: 3128 SOC_FUNC_RETURN; 3129 } 3130 3131 /*! 3132 * Function: 3133 * portmod_pm_capability_get 3134 * Purpose: 3135 * Get PortMacro specific capabilites. 3136 * Parameters: 3137 * unit - SOC Unit #. 3138 * pm_type - Port macro type. 3139 * pm_cap -(OUT) PM specific capabilities. 3140 * Returns: 3141 * SOC_E_XXX 3142 */ 3143 int portmod_pm_capability_get(int unit, 3144 portmod_dispatch_type_t pm_type, 3145 portmod_pm_capability_t* pm_cap) 3146 { 3147 SOC_INIT_FUNC_DEFS; 3148 3149 if(pm_cap == NULL){ 3150 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("pm_cap NULL paramaeter"))); 3151 } 3152 3153 switch (pm_type) { 3154 #ifdef PORTMOD_PM8X50_SUPPORT 3155 case portmodDispatchTypePm8x50: 3156 pm_cap->type = pm_type; 3157 portmod_pm8x50_capability_t_init(unit, 3158 &pm_cap->pm_capability.pm8x50_cap); 3159 pm_cap->pm_capability.pm8x50_cap.vcos[0] = portmodVCO20P625G; 3160 pm_cap->pm_capability.pm8x50_cap.vcos[1] = portmodVCO25P781G; 3161 pm_cap->pm_capability.pm8x50_cap.vcos[2] = portmodVCO26P562G; 3162 break; 3163 #endif /*PORTMOD_PM8X50_SUPPORT */ 3164 default: 3165 return SOC_E_UNAVAIL; 3166 } 3167 3168 exit: 3169 SOC_FUNC_RETURN; 3170 } 3171 3172 #ifdef FW_BCAST_DOWNLOAD 3173 static int _portmod_pm_id_find(const int* pm_array, int array_len, int pm_id) 3174 { 3175 int i; 3176 3177 for (i=0; i<array_len; i++) { 3178 if (pm_array[i] == pm_id) { 3179 return 1; 3180 } 3181 } 3182 3183 return 0; 3184 } 3185 3186 /* 3187 * This function is used to execute SerDes broadcast on all PMs 3188 * which belongs to the same broadcast ring 3189 */ 3190 static int _portmod_sbus_ring_bcast(int unit, 3191 int* pm_array, 3192 int array_len, 3193 int bcast_id, 3194 int last_pm, 3195 int crc_enable) 3196 { 3197 pm_info_t pm_info; 3198 portmod_sbus_bcast_config_t bcast_cfg; 3199 int i; 3200 3201 bcast_cfg.bcast_id = bcast_id; 3202 3203 /* step 1: call RESET_CORE_FOR_FW_LOAD per core */ 3204 bcast_cfg.flag = PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD; 3205 for (i=0; i<array_len; i++) { 3206 portmod_pm_info_from_pm_id_get(unit, pm_array[i], &pm_info); 3207 bcast_cfg.chain_last = (pm_array[i]==last_pm ? 1 : 0); 3208 3209 portmod_fw_bcast(unit, pm_info, &bcast_cfg); 3210 } 3211 3212 /* step 2: call UNTIL_FW_LOAD per core */ 3213 bcast_cfg.flag = PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD; 3214 for (i=0; i<array_len; i++) { 3215 portmod_pm_info_from_pm_id_get(unit, pm_array[i], &pm_info); 3216 bcast_cfg.chain_last = (pm_array[i]==last_pm ? 1 : 0); 3217 3218 portmod_fw_bcast(unit, pm_info, &bcast_cfg); 3219 } 3220 3221 /* step 3: download ucode per ring */ 3222 bcast_cfg.flag = PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD; 3223 portmod_pm_info_from_pm_id_get(unit, pm_array[0], &pm_info); 3224 bcast_cfg.chain_last = (pm_array[0]==last_pm ? 1 : 0); 3225 3226 portmod_fw_bcast(unit, pm_info, &bcast_cfg); 3227 3228 /* step 4: call RESUME_AFTER_FW_LOAD per core */ 3229 bcast_cfg.flag = PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD; 3230 for (i=0; i<array_len; i++) { 3231 portmod_pm_info_from_pm_id_get(unit, pm_array[i], &pm_info); 3232 bcast_cfg.chain_last = (pm_array[i]==last_pm ? 1 : 0); 3233 3234 portmod_fw_bcast(unit, pm_info, &bcast_cfg); 3235 } 3236 3237 /* step 5: call FW_LOAD_END per core */ 3238 bcast_cfg.flag = PHYMOD_CORE_INIT_F_FW_LOAD_END; 3239 if (crc_enable) { 3240 bcast_cfg.flag |= PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 3241 } 3242 for (i=0; i<array_len; i++) { 3243 portmod_pm_info_from_pm_id_get(unit, pm_array[i], &pm_info); 3244 bcast_cfg.chain_last = (pm_array[i]==last_pm ? 1 : 0); 3245 3246 portmod_fw_bcast(unit, pm_info, &bcast_cfg); 3247 } 3248 3249 return SOC_E_NONE; 3250 } 3251 3252 #define PORTMOD_SBUS_BCAST_PM_MAX_NUM 32 3253 3254 /* 3255 * This function is SerDes broadcast entry 3256 * It's called between INIT_PASS1 and INIT_PASS2 3257 */ 3258 int portmod_common_serdes_fw_bcst(int unit, pbmp_t pbmp, int crc_enable) 3259 { 3260 soc_port_t port; 3261 int pm_array[PORTMOD_SBUS_BCAST_PM_MAX_NUM], pm_num, ring_bcast_id, ring_last_pm; 3262 int pm_id, port_bcast_id, port_pos, rv, last_pos; 3263 3264 if ((SOC_PORTCTRL_FUNCTIONS(unit) == NULL) 3265 || (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_sbus_ring_info_get == NULL)) { 3266 return SOC_E_UNAVAIL; 3267 } 3268 3269 do { 3270 pm_num = 0; 3271 ring_bcast_id = -1; 3272 ring_last_pm = 0; 3273 last_pos = -1; 3274 3275 /* 3276 * find all PMs belongs to the same broadcast ring and put them into a PM list 3277 */ 3278 PBMP_ITER(pbmp, port) { 3279 rv= SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_sbus_ring_info_get(unit, port, &port_bcast_id, &port_pos); 3280 if (SOC_FAILURE(rv)) { 3281 /* this port doesn't exist in any broadcast ring */ 3282 SOC_PBMP_PORT_REMOVE(pbmp, port); 3283 continue; 3284 } 3285 3286 if (ring_bcast_id != -1 && port_bcast_id != ring_bcast_id) { 3287 /* this port doesn't belong to current broadcast ring */ 3288 continue; 3289 } 3290 3291 if (ring_bcast_id == -1) { 3292 /* this port is the first element of current broadcast ring */ 3293 ring_bcast_id = port_bcast_id; 3294 } 3295 3296 SOC_PBMP_PORT_REMOVE(pbmp, port); 3297 3298 portmod_port_pm_id_get(unit, port, &pm_id); 3299 3300 if (_portmod_pm_id_find(pm_array, pm_num, pm_id)) { 3301 /* this port has been already put into broadcast ring */ 3302 continue; 3303 } 3304 3305 pm_array[pm_num] = pm_id; 3306 if (port_pos > last_pos) { 3307 last_pos = port_pos; 3308 ring_last_pm = pm_id; 3309 } 3310 pm_num++; 3311 } 3312 3313 /* broadcast on PM list */ 3314 if (pm_num > 0) { 3315 _portmod_sbus_ring_bcast(unit, pm_array, pm_num, ring_bcast_id, ring_last_pm, crc_enable); 3316 } 3317 } while (SOC_PBMP_NOT_NULL(pbmp)); 3318 3319 return SOC_E_NONE; 3320 } 3321 #endif 3322 3323 #undef _ERR_MSG_MODULE_NAME