portctrl.c (22092B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * portctrl soc routines 8 */ 9 10 #include <sal/core/libc.h> 11 12 #include <soc/debug.h> 13 #include <soc/util.h> 14 #include <soc/bondoptions.h> 15 #include <soc/mem.h> 16 #include <soc/esw/portctrl.h> 17 #include <shared/bsl.h> 18 #include <soc/phy/phymod_sim.h> 19 #include <soc/portmod/portmod.h> 20 #include <soc/trident3.h> 21 22 #ifdef BCM_TRIDENT3_SUPPORT 23 24 #define SOC_TD3_PM4X10_COUNT 1 25 static uint32_t _td3_pm4x10_addr[SOC_TD3_PM4X10_COUNT] = { 0x1c1 }; 26 27 #define SOC_TD3_PM4X25_COUNT 32 28 #define SOC_TD3_MAX_PHYS 137 /* 32*4 CLMAC's + 4 XLMAC */ 29 30 static uint32_t _td3_pm4x25_addr[SOC_TD3_PM4X25_COUNT] = { 31 0x81, 0x85, 0x89, 0x8D, 32 0x91, 0x95, 0xA1, 0xA5, 33 0xA9, 0xAD, 0xc1, 0xC5, 34 0xC9, 0xCD, 0xD1, 0xD5, 35 0xE1, 0xE5, 0xE9, 0xED, 36 0xF1, 0xF5, 0x181, 0x185, 37 0x189, 0x18D, 0x1A1, 0x1A5, 38 0x1A9, 0x1AD, 0x1B1, 0x1B5 39 }; 40 41 42 static portmod_pm_instances_t td3_pm_types[] = { 43 #ifdef PORTMOD_PM4X25_SUPPORT 44 {portmodDispatchTypePm4x25, SOC_TD3_PM4X25_COUNT}, 45 #endif 46 #ifdef PORTMOD_PM4X10_SUPPORT 47 {portmodDispatchTypePm4x10, SOC_TD3_PM4X10_COUNT}, 48 #endif 49 }; 50 51 #ifdef PORTMOD_PM4X25_SUPPORT 52 static portmod_default_user_access_t *pm4x25_td3_user_acc[SOC_MAX_NUM_DEVICES]; 53 #endif /* PORTMOD_PM4X25_SUPPORT */ 54 55 #ifdef PORTMOD_PM4X10_SUPPORT 56 static portmod_default_user_access_t *pm4x10_td3_user_acc[SOC_MAX_NUM_DEVICES]; 57 #endif /* PORTMOD_PM4X25_SUPPORT */ 58 59 60 61 /* 62 * Polarity get looks for physical port based config first. This will enable 63 * the user to define the polarity for all ports weather mapped to logical 64 * port or not. 65 * 66 * For legacy compatibility - we still look for the logical port 67 * config setup. 68 */ 69 STATIC void 70 td3_pm_port_polarity_get (int unit, int logical_port, int physical_port, 71 int lane, uint32 *tx_pol, uint32* rx_pol) 72 { 73 uint32 rx_polarity, tx_polarity; 74 75 rx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane, 76 spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0x0); 77 *rx_pol = (rx_polarity & 0x1) << lane; 78 79 tx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane, 80 spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0x0); 81 *tx_pol = (tx_polarity & 0x1) << lane; 82 } 83 84 /* 85 * lanemap get looks for physical port based config first. This will enable 86 * the user to define the lanemap for all ports weather mapped to logical 87 * port or not. 88 * 89 * For legacy compatibility - we still look for the logical port 90 * config setup. 91 */ 92 STATIC 93 void td3_pm_port_lanemap_get (int unit, int logical_port, int physical_port, 94 uint32 *txlane_map, uint32* rxlane_map) 95 { 96 *rxlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0, 97 spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0x3210); 98 99 *txlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0, 100 spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0x3210); 101 } 102 103 104 STATIC int 105 _soc_td3_portctrl_pm4x25_portmod_init(int unit, int second_mgmt_port) 106 { 107 #ifdef PORTMOD_PM4X25_SUPPORT 108 int rv = SOC_E_NONE; 109 portmod_pm_create_info_t pm_create_info; 110 int pmid = 0, blk, is_sim, found, logical_port; 111 int first_port, idx, mode; 112 uint32 pm_mask = 0xFFFFFFFF; 113 114 /* Allocate user access for all PMs */ 115 SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 116 SOC_TD3_PM4X25_COUNT, &pm4x25_td3_user_acc[unit])); 117 118 /* 119 * in 2T SKU, the following PM's are removed between PM0-PM31 120 * PM2, PM4, PM6, ---- PM9, PM11, PM13, 121 * PM18, PM20, PM22, --- PM25, PM27, PM29, 122 * These PM's correspond to the bit mask (cleared bits) below. 123 */ 124 if (soc_feature(unit, soc_feature_td3_reduced_pm)) { 125 pm_mask = 0xD5AFD5AF; 126 } 127 128 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_TD3_PM4X25_COUNT); pmid++) { 129 130 if (!((0x01 << pmid) & pm_mask)) { 131 continue; 132 } 133 134 rv = portmod_pm_create_info_t_init(unit, &pm_create_info); 135 if (PORTMOD_FAILURE(rv)) { 136 break; 137 } 138 139 pm_create_info.type = portmodDispatchTypePm4x25; 140 141 /* 1 based port number */ 142 first_port = 1 + (pmid << 2); 143 144 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port); 145 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+1); 146 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+2); 147 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+3); 148 149 /* Identify the block for this particular port */ 150 found = 0; 151 152 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 153 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 154 if (SOC_BLOCK_INFO(unit, blk).type == 155 (soc_feature(unit, soc_feature_clport_gen2) ? SOC_BLK_CLG2PORT : SOC_BLK_CLPORT)){ 156 found = 1; 157 break; 158 } 159 } 160 161 if (!found) { 162 rv = SOC_E_INTERNAL; 163 break; 164 } 165 166 167 /* Init user_acc for phymod access struct */ 168 rv = portmod_default_user_access_t_init(unit, 169 &(pm4x25_td3_user_acc[unit][pmid])); 170 if (PORTMOD_FAILURE(rv)) { 171 break; 172 } 173 174 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_td3_user_acc[unit][pmid]))); 175 PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x25_td3_user_acc[unit][pmid]))); 176 pm4x25_td3_user_acc[unit][pmid].unit = unit; 177 pm4x25_td3_user_acc[unit][pmid].blk_id = blk; 178 pm4x25_td3_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 179 180 if (pm4x25_td3_user_acc[unit][pmid].mutex == NULL) { 181 rv = SOC_E_MEMORY; 182 break; 183 } 184 185 /* Specific info for PM4x25 */ 186 rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x25.access); 187 if (PORTMOD_FAILURE(rv)) { 188 break; 189 } 190 191 pm_create_info.pm_specific_info.pm4x25.access.user_acc = &(pm4x25_td3_user_acc[unit][pmid]); 192 pm_create_info.pm_specific_info.pm4x25.access.addr = _td3_pm4x25_addr[pmid]; 193 pm_create_info.pm_specific_info.pm4x25.access.bus = NULL; /* Use default bus */ 194 pm_create_info.pm_specific_info.pm4x25.rescal = -1; 195 196 rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 197 &(pm_create_info.pm_specific_info.pm4x25.access), 198 0, &is_sim); 199 200 if (PORTMOD_FAILURE(rv)) { 201 break; 202 } 203 204 if (is_sim) { 205 /* Firmward loader : Don't allow FW load on sim enviroment */ 206 pm_create_info.pm_specific_info.pm4x25.fw_load_method = 207 phymodFirmwareLoadMethodNone; 208 209 PHYMOD_ACC_F_CLAUSE45_SET(&pm_create_info.pm_specific_info.pm4x25.access); 210 } 211 212 /* Use default external loader if NULL */ 213 pm_create_info.pm_specific_info.pm4x25.external_fw_loader = NULL; 214 215 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 216 217 pm_create_info.pm_specific_info.pm4x25.core_num = pmid; 218 pm_create_info.pm_specific_info.pm4x25.core_num_int = 0; 219 220 /* Figure out the port mode */ 221 SOC_IF_ERROR_RETURN(soc_td3_port_mode_get(unit, logical_port, &mode)); 222 if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) { 223 pm_create_info.pm_specific_info.pm4x25.port_mode_aux_info = portmodModeInfoThreePorts; 224 } 225 226 /* Add PM to PortMod */ 227 rv = portmod_port_macro_add(unit, &pm_create_info); 228 } 229 230 if (PORTMOD_FAILURE(rv)) { 231 for (pmid=0; pmid < SOC_TD3_PM4X25_COUNT; pmid++) { 232 if (pm4x25_td3_user_acc[unit][pmid].mutex) { 233 sal_mutex_destroy(pm4x25_td3_user_acc[unit][pmid].mutex); 234 pm4x25_td3_user_acc[unit][pmid].mutex = NULL; 235 } 236 } 237 } 238 239 return rv; 240 #else /* PORTMOD_PM4X25_SUPPORT */ 241 return SOC_E_UNAVAIL; 242 #endif /* PORTMOD_PM4X25_SUPPORT */ 243 } 244 245 #define TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM 129 246 #define TRIDENT3_SECOND_MGMT_PHYSICAL_PORT_NUM 131 247 STATIC int 248 _soc_td3_portctrl_pm4x10_portmod_init(int unit, int second_mgmt_port) 249 { 250 #if defined PORTMOD_PM4X10_SUPPORT && defined BCM_56870_A0 251 int rv = SOC_E_NONE; 252 portmod_pm_create_info_t pm_create_info; 253 int pmid = 0, blk, is_sim, found; 254 int idx, first_port; 255 int port_num_lanes = 0; 256 soc_info_t *si; 257 258 si = &SOC_INFO(unit); 259 /* Allocate user access for all PMs */ 260 SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 261 SOC_TD3_PM4X10_COUNT, &pm4x10_td3_user_acc[unit])); 262 263 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_TD3_PM4X10_COUNT); pmid++) { 264 265 rv = portmod_pm_create_info_t_init(unit, &pm_create_info); 266 if (PORTMOD_FAILURE(rv)) { 267 break; 268 } 269 270 pm_create_info.type = portmodDispatchTypePm4x10; 271 first_port = TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM; 272 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port); /* first mgmt port */ 273 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 1); /* SW Workaround: Need to add. 274 the dummy port so that lane_index 275 is incremented to 2 for the second 276 management port to detect ext PHY */ 277 278 if (second_mgmt_port) { 279 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 2); 280 /* Second mgmt reuse physical port number 128 */ 281 port_num_lanes = si->port_num_lanes[si->port_p2l_mapping[128]]; 282 if (port_num_lanes == 2) { 283 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 3); 284 } 285 } 286 /* Check if mgmt ports is configured as 4 lanes */ 287 port_num_lanes = si->port_num_lanes[si->port_p2l_mapping[TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM]]; 288 if (port_num_lanes == 4) { 289 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 2); 290 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 3); 291 } 292 293 /* Identify the block for this particular port */ 294 found = 0; 295 296 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 297 blk = SOC_PORT_IDX_INFO(unit, TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM, idx).blk; 298 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){ 299 found = 1; 300 break; 301 } 302 } 303 304 if (!found) { 305 rv = SOC_E_INTERNAL; 306 break; 307 } 308 309 310 /* Init user_acc for phymod access struct */ 311 rv = portmod_default_user_access_t_init(unit, 312 &(pm4x10_td3_user_acc[unit][pmid])); 313 if (PORTMOD_FAILURE(rv)) { 314 break; 315 } 316 317 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10_td3_user_acc[unit][pmid]))); 318 PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x10_td3_user_acc[unit][pmid]))); 319 320 pm4x10_td3_user_acc[unit][pmid].unit = unit; 321 pm4x10_td3_user_acc[unit][pmid].blk_id = blk; 322 pm4x10_td3_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 323 324 if (pm4x10_td3_user_acc[unit][pmid].mutex == NULL) { 325 rv = SOC_E_MEMORY; 326 break; 327 } 328 329 /* Specific info for PM4x10 */ 330 rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x10.access); 331 if (PORTMOD_FAILURE(rv)) { 332 break; 333 } 334 335 pm_create_info.pm_specific_info.pm4x10.access.user_acc = &(pm4x10_td3_user_acc[unit][pmid]); 336 pm_create_info.pm_specific_info.pm4x10.access.addr = _td3_pm4x10_addr[pmid]; 337 pm_create_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 338 pm_create_info.pm_specific_info.pm4x10.rescal = -1; 339 340 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce16, 341 &(pm_create_info.pm_specific_info.pm4x10.access), 342 0, &is_sim); 343 344 if (PORTMOD_FAILURE(rv)) { 345 break; 346 } 347 348 if (is_sim) { 349 /* Firmward loader : Don't allow FW load on sim enviroment */ 350 pm_create_info.pm_specific_info.pm4x10.fw_load_method = 351 phymodFirmwareLoadMethodNone; 352 353 /* TSCE sim supports CL45 mode to read/write registers. */ 354 PHYMOD_ACC_F_CLAUSE45_SET(&pm_create_info.pm_specific_info.pm4x10.access); 355 } 356 357 /* Use default external loader if NULL */ 358 pm_create_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 359 360 pm_create_info.pm_specific_info.pm4x10.core_num = pmid; 361 pm_create_info.pm_specific_info.pm4x10.core_num_int = 0; 362 363 /* 364 * Set port mode as dual-port mode for all speed modes(XFI/RXAUI/XAUI), 365 * it is WAR for shim issue on Merlin16 MGMT port 366 */ 367 pm_create_info.pm_specific_info.pm4x10.port_mode_aux_info 368 = portmodModeInfoTwoDualModePorts; 369 pm_create_info.pm_specific_info.pm4x10.portmod_phy_external_reset 370 = soc_esw_portctrl_reset_tsc3_cb; 371 372 /* Add PM to PortMod */ 373 rv = portmod_port_macro_add(unit, &pm_create_info); 374 } 375 376 if (PORTMOD_FAILURE(rv)) { 377 for (pmid=0; pmid < SOC_TD3_PM4X10_COUNT; pmid++) { 378 if (pm4x10_td3_user_acc[unit][pmid].mutex) { 379 sal_mutex_destroy(pm4x10_td3_user_acc[unit][pmid].mutex); 380 pm4x10_td3_user_acc[unit][pmid].mutex = NULL; 381 } 382 } 383 } 384 385 return rv; 386 #else /* PORTMOD_PM4X10_SUPPORT */ 387 return SOC_E_UNAVAIL; 388 #endif /* PORTMOD_PM4X10_SUPPORT */ 389 } 390 391 /* 392 * Function: 393 * soc_td3_portctrl_pm_portmod_init 394 * Purpose: 395 * Initialize PortMod and PortMacro for Trident2Plus 396 * Add port macros (PM) to the unit's PortMod Manager (PMM). 397 * Parameters: 398 * unit - (IN) Unit number. 399 * Returns: 400 * SOC_E_XXX 401 */ 402 int 403 soc_td3_portctrl_pm_portmod_init(int unit) 404 { 405 int rv = SOC_E_NONE; 406 uint32 flags = 0, mgmt_port_count = 0; 407 408 /* 409 * If portmod was create - destroy and create again 410 * Better way would be to create once and leave it. 411 */ 412 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 413 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 414 } 415 416 PORTMOD_CREATE_F_PM_NULL_SET(flags); 417 418 SOC_IF_ERROR_RETURN 419 (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, SOC_TD3_MAX_PHYS, 420 sizeof(td3_pm_types)/sizeof(portmod_pm_instances_t), td3_pm_types)); 421 422 SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, mgmt_port_count); 423 424 rv = _soc_td3_portctrl_pm4x25_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0); 425 if (rv) return (rv); 426 427 return(_soc_td3_portctrl_pm4x10_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0)); 428 } 429 430 /* 431 * Function: 432 * soc_td3_portctrl_pm_portmod_deinit 433 * Purpose: 434 * Deinitialize PortMod and PortMacro for Trident2Plus. 435 * Free pm user access data. 436 * Parameters: 437 * unit - (IN) Unit number. 438 * Returns: 439 * SOC_E_NONE 440 */ 441 int 442 soc_td3_portctrl_pm_portmod_deinit(int unit) 443 { 444 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 445 return SOC_E_NONE; 446 } 447 448 /* Free PMs structures */ 449 #ifdef PORTMOD_PM4X25_SUPPORT 450 if (pm4x25_td3_user_acc[unit] != NULL) { 451 sal_free(pm4x25_td3_user_acc[unit]); 452 pm4x25_td3_user_acc[unit] = NULL; 453 } 454 #endif /* PORTMOD_PM4X25_SUPPORT */ 455 456 #ifdef PORTMOD_PM4X10_SUPPORT 457 if (pm4x10_td3_user_acc[unit] != NULL) { 458 sal_free(pm4x10_td3_user_acc[unit]); 459 pm4x10_td3_user_acc[unit] = NULL; 460 } 461 #endif /* PORTMOD_PM4X10_SUPPORT */ 462 463 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 464 465 return SOC_E_NONE; 466 } 467 468 int 469 soc_td3_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config) 470 { 471 #ifdef PORTMOD_PM4X25_SUPPORT 472 int rv = SOC_E_NONE; 473 int pmid = 0, lane, phy, phy_port, logical_port, port_mode; 474 int first_port = 0, core_num, core_count = 0, core_index, is_sim, type; 475 uint32 txlane_map, rxlane_map, i; 476 uint32 tx_polarity, rx_polarity; 477 uint32 mgmt_port_count; 478 portmod_port_init_config_t *port_config_info; 479 phymod_firmware_load_method_t fw_load_method; 480 phymod_polarity_t polarity; /**< Lanes Polarity */ 481 phymod_lane_map_t lane_map; 482 483 port_config_info = (portmod_port_init_config_t *)port_config; 484 SOC_IF_ERROR_RETURN(soc_td3_port_mode_get(unit, port, &port_mode)); 485 if (port_mode == portmodPortModeTri012 || port_mode == portmodPortModeTri023) { 486 port_config_info->port_mode_aux_info = portmodModeInfoThreePorts; 487 } 488 489 phy = SOC_INFO(unit).port_l2p_mapping[port]; 490 491 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 492 core_num = (phy - 1) / SOC_PM4X25_NUM_LANES; 493 494 for (i=0; i<SOC_TD3_PM4X25_COUNT; i++) { 495 if (core_num == i) { 496 type = portmodDispatchTypePm4x25; 497 pmid = i; 498 first_port = 1 + (pmid << 2); 499 core_count = 1; 500 break; 501 } 502 } 503 504 /* When port doesn't find PM4x25, find PM4x10 again. */ 505 SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, mgmt_port_count); 506 507 if ((i == SOC_TD3_PM4X25_COUNT) || 508 ((mgmt_port_count == 2) && (phy == 128))) { 509 type = portmodDispatchTypePm4x10; 510 pmid = 0; 511 core_count = 1; 512 first_port = 129; 513 } 514 515 for (core_index = 0; core_index < core_count; core_index++) { 516 fw_load_method = phymodFirmwareLoadMethodExternal; 517 518 soc_physim_enable_get(unit, &is_sim); 519 520 if (is_sim) { 521 /* Firmward loader : Don't allow FW load on sim enviroment */ 522 fw_load_method = phymodFirmwareLoadMethodNone; 523 } else { 524 fw_load_method = soc_property_suffix_num_get(unit, pmid, 525 spn_LOAD_FIRMWARE, "quad", 526 phymodFirmwareLoadMethodExternal); 527 fw_load_method &= 0xff; 528 } 529 530 rv = phymod_polarity_t_init(&polarity); 531 if (PORTMOD_FAILURE(rv)) { 532 break; 533 } 534 535 /* Polarity */ 536 for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) { 537 phy_port = first_port + lane + (core_index*4); 538 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 539 540 td3_pm_port_polarity_get (unit, logical_port, phy_port, lane, 541 &tx_polarity, &rx_polarity); 542 543 polarity.rx_polarity |= rx_polarity; 544 polarity.tx_polarity |= tx_polarity; 545 } 546 547 /* Lane map */ 548 rv = phymod_lane_map_t_init(&lane_map); 549 if (PORTMOD_FAILURE(rv)) { 550 break; 551 } 552 553 phy_port = first_port + (core_index*4); 554 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 555 556 td3_pm_port_lanemap_get (unit, logical_port, phy_port, 557 &txlane_map, &rxlane_map); 558 559 lane_map.num_of_lanes = (type == portmodDispatchTypePm4x25) ? 560 SOC_PM4X25_NUM_LANES : SOC_PM4X10_NUM_LANES; 561 562 for(lane = 0 ; lane < lane_map.num_of_lanes; lane++) { 563 lane_map.lane_map_tx[lane] = 564 (txlane_map >> (lane * lane_map.num_of_lanes)) & 565 SOC_PM4X25_LANE_MASK; 566 lane_map.lane_map_rx[lane] = 567 (rxlane_map >> (lane * lane_map.num_of_lanes)) & 568 SOC_PM4X25_LANE_MASK; 569 } 570 571 sal_memcpy(&port_config_info->fw_load_method[core_index], &fw_load_method, 572 sizeof(phymod_firmware_load_method_t)); 573 port_config_info->fw_load_method_overwrite = 1; 574 sal_memcpy(&port_config_info->polarity[core_index], &polarity, 575 sizeof(phymod_polarity_t)); 576 port_config_info->polarity_overwrite = 1; 577 sal_memcpy(&port_config_info->lane_map[core_index], &lane_map, 578 sizeof(phymod_lane_map_t)); 579 port_config_info->lane_map_overwrite = 1; 580 } 581 582 return rv; 583 #else /* PORTMOD_PM4X25_SUPPORT */ 584 return SOC_E_UNAVAIL; 585 #endif /* PORTMOD_PM4X25_SUPPORT */ 586 } 587 588 int 589 soc_td3_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port) 590 { 591 int phy, core_index; 592 uint32 pmid; 593 594 phy = SOC_INFO(unit).port_l2p_mapping[port]; 595 596 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 597 core_index = (phy - 1) / SOC_PM4X25_NUM_LANES; 598 599 #ifdef PORTMOD_PM4X25_SUPPORT 600 /* When port dones't find PM4x10, find PM4x25 again. */ 601 for (pmid=0; pmid<SOC_TD3_PM4X25_COUNT; pmid++) { 602 if (core_index == pmid) { 603 return _td3_pm4x25_addr[pmid]; 604 } 605 } 606 #endif /* PORTMOD_PM4X25_SUPPORT */ 607 608 #ifdef PORTMOD_PM4X10_SUPPORT 609 for (pmid=0; pmid<SOC_TD3_PM4X10_COUNT; pmid++) { 610 if (core_index == (31+pmid)) { 611 return _td3_pm4x10_addr[pmid]; 612 } 613 } 614 #endif /* PORTMOD_PM4X10_SUPPORT */ 615 return -1; 616 } 617 618 #define _TD3_PHY_PORT_MNG0 129 619 int 620 soc_td3_portctrl_pm_type_get(int unit, soc_port_t phy_port, int* pm_type) 621 { 622 *pm_type = -1; 623 624 if (phy_port >= 1 && phy_port <= 128) { 625 #ifdef PORTMOD_PM4X25_SUPPORT 626 *pm_type = portmodDispatchTypePm4x25; 627 return (SOC_E_NONE); 628 #endif 629 } else if (phy_port == _TD3_PHY_PORT_MNG0) { 630 #ifdef PORTMOD_PM4X10_SUPPORT 631 *pm_type = portmodDispatchTypePm4x10; 632 return (SOC_E_NONE); 633 #endif 634 } else { 635 return(SOC_E_PARAM); 636 } 637 638 return SOC_E_UNAVAIL; 639 } 640 641 soc_portctrl_functions_t soc_td3_portctrl_func = { 642 soc_td3_portctrl_pm_portmod_init, 643 soc_td3_portctrl_pm_portmod_deinit, 644 soc_td3_portctrl_pm_port_config_get, 645 soc_td3_portctrl_pm_port_phyaddr_get, 646 NULL, 647 soc_td3_portctrl_pm_type_get, 648 NULL, 649 NULL 650 }; 651 652 #endif /* BCM_TRIDENT3_SUPPORT */