portctrl.c (45977B)
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 <soc/esw/portctrl_internal.h> 18 #include <soc/apache.h> 19 #include <shared/bsl.h> 20 #include <soc/phy/phymod_sim.h> 21 #include <soc/portmod/portmod.h> 22 23 #ifdef BCM_APACHE_SUPPORT 24 25 #define SOC_AP_PM4X10_COUNT 8 26 #define SOC_AP_PM4X25_COUNT 4 27 #define SOC_AP_PM12X10_COUNT 2 28 29 #define SOC_AP_MAX_PORTS_PER_TSC 4 30 31 #define SOC_AP_PM4X10_PORT_1 1 32 #define SOC_AP_PM4X10_PORT_2 5 33 #define SOC_AP_PM4X10_PORT_3 9 34 #define SOC_AP_PM4X10_PORT_4 13 35 #define SOC_AP_PM4X10_PORT_5 37 36 #define SOC_AP_PM4X10_PORT_6 41 37 #define SOC_AP_PM4X10_PORT_7 45 38 #define SOC_AP_PM4X10_PORT_8 49 39 40 #define SOC_AP_PM12X10_PORT_1 17 41 #define SOC_AP_PM12X10_PORT_2 53 42 43 #define SOC_AP_PM4X25_PORT_1 29 44 #define SOC_AP_PM4X25_PORT_2 33 45 #define SOC_AP_PM4X25_PORT_3 65 46 #define SOC_AP_PM4X25_PORT_4 69 47 48 static uint32_t _ap_pm4x10_addr[SOC_AP_PM4X10_COUNT] = { 49 0x81, 0x85, 0x89, 0x8D, 0xA9, 0xAD, 0xB1, 0xC1 50 }; 51 52 static uint32_t _ap_pm4x10_core_num[SOC_AP_PM4X10_COUNT] = { 53 0, 1, 2, 3, 9, 10, 11, 12 54 }; 55 56 static uint32_t _ap_pm4x10_port[SOC_AP_PM4X10_COUNT] = { 57 SOC_AP_PM4X10_PORT_1, 58 SOC_AP_PM4X10_PORT_2, 59 SOC_AP_PM4X10_PORT_3, 60 SOC_AP_PM4X10_PORT_4, 61 SOC_AP_PM4X10_PORT_5, 62 SOC_AP_PM4X10_PORT_6, 63 SOC_AP_PM4X10_PORT_7, 64 SOC_AP_PM4X10_PORT_8 65 }; 66 67 static uint32_t _ap_pm12x10_addr[SOC_AP_PM12X10_COUNT * SOC_PM12X10_PM4X10_COUNT] = { 68 0x91, 0x95, 0x99, /* PM12X10 Inst 0, Core 4-6 */ 69 0xC5, 0xC9, 0xCD /* PM12X10 Inst 1, Core 12-14 */ 70 }; 71 static uint32_t _ap_pm12x10_core_num[SOC_AP_PM12X10_COUNT * SOC_PM12X10_PM4X10_COUNT] = { 72 4, 5, 6, 13, 14, 15 73 }; 74 75 static uint32_t _ap_pm12x10_port[SOC_AP_PM12X10_COUNT] = { 76 SOC_AP_PM12X10_PORT_1, 77 SOC_AP_PM12X10_PORT_2 78 }; 79 80 static uint32_t _ap_pm4x25_addr[SOC_AP_PM4X25_COUNT] = { 81 0xA1, 0xA5, 0xD1, 0xD5 82 }; 83 84 static uint32_t _ap_pm4x25_core_num[SOC_AP_PM4X25_COUNT] = { 85 7, 8, 16, 17 86 }; 87 88 static uint32_t _ap_pm4x25_port[SOC_AP_PM4X25_COUNT] = { 89 SOC_AP_PM4X25_PORT_1, 90 SOC_AP_PM4X25_PORT_2, 91 SOC_AP_PM4X25_PORT_3, 92 SOC_AP_PM4X25_PORT_4 93 }; 94 95 96 #define SOC_AP_MAX_PHYS 80 /* ?? 56 XLMACS, 24 CLMAC's */ 97 98 99 static portmod_pm_instances_t ap_pm_types[] = { 100 #ifdef PORTMOD_PM4X10_SUPPORT 101 {portmodDispatchTypePm4x10, SOC_AP_PM4X10_COUNT}, 102 #endif 103 #ifdef PORTMOD_PM4X25_SUPPORT 104 {portmodDispatchTypePm4x25, SOC_AP_PM4X25_COUNT}, 105 #endif 106 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 107 {portmodDispatchTypePm12x10_xgs, SOC_AP_PM12X10_COUNT}, 108 #endif 109 }; 110 111 112 #ifdef PORTMOD_PM4X10_SUPPORT 113 static portmod_default_user_access_t *pm4x10_ap_user_acc[SOC_MAX_NUM_DEVICES]; 114 #endif /* PORTMOD_PM4X10_SUPPORT */ 115 116 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 117 static portmod_default_user_access_t *pm12x10_ap_user_acc[SOC_MAX_NUM_DEVICES]; 118 static portmod_default_user_access_t *pm12_4x10_ap_user_acc[SOC_MAX_NUM_DEVICES]; 119 static portmod_default_user_access_t *pm12_4x25_ap_user_acc[SOC_MAX_NUM_DEVICES]; 120 #endif /* PORTMOD_PM12X10_XGS_SUPPORT */ 121 122 #ifdef PORTMOD_PM4X25_SUPPORT 123 static portmod_default_user_access_t *pm4x25_ap_user_acc[SOC_MAX_NUM_DEVICES]; 124 #endif /* PORTMOD_PM4X25_SUPPORT */ 125 126 127 soc_portctrl_functions_t soc_ap_portctrl_func = { 128 soc_ap_portctrl_pm_portmod_init, 129 soc_ap_portctrl_pm_portmod_deinit, 130 soc_ap_portctrl_pm_port_config_get, 131 soc_ap_portctrl_pm_port_phyaddr_get, 132 soc_ap_portctrl_port_ability_update, 133 soc_ap_portctrl_pm_type_get, 134 NULL, 135 NULL 136 }; 137 138 STATIC int 139 _soc_ap_portctrl_pm_init(int unit, int *max_phys, 140 portmod_pm_instances_t **pm_types, 141 int *pms_arr_len) 142 { 143 *max_phys = SOC_AP_MAX_PHYS; 144 *pm_types = ap_pm_types; 145 *pms_arr_len = (sizeof(ap_pm_types) / sizeof(portmod_pm_instances_t)); 146 147 return SOC_E_NONE; 148 } 149 150 STATIC int 151 _soc_ap_portctrl_device_addr_port_get(int unit, int pm_type, 152 uint32_t **addr, 153 uint32_t **port, 154 uint32_t **core_num) 155 { 156 *addr = NULL; 157 *port = NULL; 158 *core_num = NULL; 159 160 if (pm_type == portmodDispatchTypePm4x10) { 161 *addr = _ap_pm4x10_addr; 162 *port = _ap_pm4x10_port; 163 *core_num = _ap_pm4x10_core_num; 164 } else if (pm_type == portmodDispatchTypePm4x25){ 165 *addr = _ap_pm4x25_addr; 166 *port = _ap_pm4x25_port; 167 *core_num = _ap_pm4x25_core_num; 168 } else if (pm_type == portmodDispatchTypePm12x10_xgs){ 169 *addr = _ap_pm12x10_addr; 170 *port = _ap_pm12x10_port; 171 *core_num = _ap_pm12x10_core_num; 172 } 173 174 return SOC_E_NONE; 175 } 176 177 STATIC int 178 _soc_ap_portctrl_pm_user_acc_flag_set(int unit, 179 portmod_default_user_access_t* pm_user_access) 180 { 181 return SOC_E_NONE; 182 } 183 184 185 #define NIBBLE_SWAP(data) (\ 186 (((data) & 0x0f) << 12) | \ 187 (((data) & 0xf0) << 4 ) | \ 188 (((data) >> 4) & 0xf0 ) | \ 189 (((data) >> 12) & 0x0f )) 190 191 #define LANE_SWAP(data) \ 192 ((0x3-(data&0x0f)) | (0x30-(data&0xf0)) | \ 193 (0x300-(data&0xf00)) | (0x3000-(data&0xf000))) 194 195 #define NIBBLE_GET(data, num) \ 196 (num == 0) ? (data & 0x0f) : \ 197 (num == 1) ? ((data & 0xf0) >> 4) : \ 198 (num == 2) ? ((data & 0xf00) >> 8) : \ 199 (num == 3) ? ((data & 0xf000) >> 12): \ 200 -1 201 202 /* Indexed by direction (rx=0; tx=1) and physical port number */ 203 static int apache_def_pkg_rx_polarity_flip[73] = {0}; 204 static int apache_def_pkg_tx_polarity_flip[73] = {0}; 205 static int apache_tdp_pkg_rx_polarity_flip[73] = {0}; 206 static int apache_tdp_pkg_tx_polarity_flip[73] = {0}; 207 static int apache_td2_pkg_rx_polarity_flip[73] = { 208 -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 /* Only TSC2 lanes 2 & 3 needs polarity inversion */ 209 }; 210 static int apache_td2_pkg_tx_polarity_flip[73] = { 211 -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 /* Only TSC2 lanes 2 & 3 needs polarity inversion */ 212 }; 213 214 /* Indexed by direction (rx=0; tx=1) and TSC instance */ 215 static int apache_def_pkg_rx_lane_swap[18] = {0}; 216 static int apache_def_pkg_tx_lane_swap[18] = {0}; 217 static int apache_tdp_pkg_rx_lane_swap[18] = { 218 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1 219 }; 220 static int apache_tdp_pkg_tx_lane_swap[18] = { 221 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0 222 }; 223 static int apache_td2_pkg_rx_lane_swap[18] = { 224 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0 225 }; 226 static int apache_td2_pkg_tx_lane_swap[18] = { 227 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1 228 }; 229 230 STATIC void 231 _soc_apache_portctrl_pkg_config_set(int unit, int phy_port, uint32 *rx_pol, uint32 *tx_pol, 232 uint32 *rxlane_map, uint32 *txlane_map) 233 { 234 int *pkg_rx_lane_swap, *pkg_tx_lane_swap; 235 int *pkg_rx_polarity_flip, *pkg_tx_polarity_flip; 236 int tsc_num, lane, i; 237 238 tsc_num = (phy_port - 1) / SOC_PM4X10_NUM_LANES; 239 240 if (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureApachePkg50mmTDpCompat)) { 241 /* socBondInfoFeatureApachePkg50mmTDpCompat 242 * 50mm x 50mm TD+ compatible package */ 243 pkg_rx_lane_swap = &(apache_tdp_pkg_rx_lane_swap[0]); 244 pkg_tx_lane_swap = &(apache_tdp_pkg_tx_lane_swap[0]); 245 pkg_rx_polarity_flip = &(apache_tdp_pkg_rx_polarity_flip[0]); 246 pkg_tx_polarity_flip = &(apache_tdp_pkg_tx_polarity_flip[0]); 247 } else if ((SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureApachePkg50mmTD2pCompat)) || 248 (SOC_BOND_INFO(unit)->dev_id == BCM56765_DEVICE_ID)) { 249 /* socBondInfoFeatureApachePkg50mmTD2pCompat 250 * 50mm x 50mm TD2 compatible package */ 251 pkg_rx_lane_swap = &(apache_td2_pkg_rx_lane_swap[0]); 252 pkg_tx_lane_swap = &(apache_td2_pkg_tx_lane_swap[0]); 253 pkg_rx_polarity_flip = &(apache_td2_pkg_rx_polarity_flip[0]); 254 pkg_tx_polarity_flip = &(apache_td2_pkg_tx_polarity_flip[0]); 255 } else { 256 /* socBondInfoFeatureApachePkg42p5mm 257 * 42.5mm x 42.5mm original/base package */ 258 pkg_rx_lane_swap = &(apache_def_pkg_rx_lane_swap[0]); 259 pkg_tx_lane_swap = &(apache_def_pkg_tx_lane_swap[0]); 260 pkg_rx_polarity_flip = &(apache_def_pkg_rx_polarity_flip[0]); 261 pkg_tx_polarity_flip = &(apache_def_pkg_tx_polarity_flip[0]); 262 } 263 264 for (i = 0; i < SOC_PM4X10_NUM_LANES; i++) { 265 if (pkg_rx_polarity_flip[phy_port + i]) { 266 if (pkg_rx_lane_swap[tsc_num] == 0) { 267 lane = NIBBLE_GET(*rxlane_map, i); 268 *rx_pol = (*rx_pol) ^ (0x1 << lane); 269 } 270 } 271 if (pkg_tx_polarity_flip[phy_port + i]) { 272 if (pkg_tx_lane_swap[tsc_num] == 0) { 273 lane = NIBBLE_GET(*txlane_map, i); 274 *tx_pol = (*tx_pol) ^ (0x1 << lane); 275 } 276 } 277 } 278 279 if (pkg_rx_lane_swap[tsc_num] == 1) { 280 for (i = 0; i < SOC_PM4X10_NUM_LANES; i++) { 281 if (pkg_rx_polarity_flip[phy_port + i]) { 282 lane = NIBBLE_GET(*rxlane_map, ((SOC_PM4X10_NUM_LANES - 1) - i)); 283 *rx_pol = (*rx_pol) ^ (0x1 << lane); 284 } 285 } 286 *rxlane_map = LANE_SWAP(*rxlane_map); 287 } 288 if (pkg_tx_lane_swap[tsc_num] == 1) { 289 for (i = 0; i < SOC_PM4X10_NUM_LANES; i++) { 290 if (pkg_tx_polarity_flip[phy_port + i]) { 291 lane = NIBBLE_GET(*txlane_map, ((SOC_PM4X10_NUM_LANES - 1) - i)); 292 *tx_pol = (*tx_pol) ^ (0x1 << lane); 293 } 294 } 295 *txlane_map = LANE_SWAP(*txlane_map); 296 } 297 298 return; 299 } 300 /* 301 * Polarity get looks for physical port based config first. This will enable 302 * the user to define the polarity for all ports weather mapped to logical 303 * port or not. 304 * 305 * For legacy compatibility - we still look for the logical port 306 * config setup. 307 */ 308 STATIC 309 void apache_pm_port_polarity_get(int unit, int logical_port, int physical_port, int lane, 310 int core_num, uint32 *tx_pol, uint32* rx_pol) 311 { 312 uint32 rx_polarity, tx_polarity, num_lanes=1; 313 314 if (logical_port != -1) { 315 num_lanes = SOC_INFO(unit).port_num_lanes[logical_port]; 316 } 317 rx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 318 spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF); 319 if (rx_polarity == 0xFFFFFFFF) { 320 rx_polarity = soc_property_port_get(unit, logical_port, 321 spn_PHY_XAUI_RX_POLARITY_FLIP, 0); 322 *rx_pol = (num_lanes == 1) ? ((rx_polarity & 0x1) << lane): rx_polarity; 323 if (SOC_PORT_VALID(unit, logical_port) && 324 IS_CXX_PORT(unit, logical_port) && IS_CL_PORT(unit, logical_port)) { 325 *rx_pol = ((rx_polarity >> (core_num * SOC_PM4X10_NUM_LANES)) & 0xf); 326 } 327 } else { 328 *rx_pol = (rx_polarity & 0x1) << lane; 329 } 330 331 tx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 332 spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF); 333 if (tx_polarity == 0xFFFFFFFF) { 334 tx_polarity = soc_property_port_get(unit, logical_port, 335 spn_PHY_XAUI_TX_POLARITY_FLIP, 0); 336 *tx_pol = (num_lanes == 1) ? ((tx_polarity & 0x1) << lane) : tx_polarity; 337 if (SOC_PORT_VALID(unit, logical_port) && 338 IS_CXX_PORT(unit, logical_port) && IS_CL_PORT(unit, logical_port)) { 339 *tx_pol = ((tx_polarity >> (core_num * SOC_PM4X10_NUM_LANES)) & 0xf); 340 } 341 } else { 342 *tx_pol = (tx_polarity & 0x1) << lane; 343 } 344 } 345 346 /* 347 * lanemap get looks for physical port based config first. This will enable 348 * the user to define the lanemap for all ports weather mapped to logical 349 * port or not. 350 * 351 * For legacy compatibility - we still look for the logical port 352 * config setup. 353 */ 354 STATIC 355 void apache_pm_port_lanemap_get (int unit, int logical_port, int physical_port, 356 int core_num, uint32 *txlane_map, uint32* rxlane_map) 357 { 358 359 *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 360 spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0xFFFFFFFF); 361 362 if (*rxlane_map == 0xFFFFFFFF) { 363 *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 364 spn_PHY_RX_LANE_MAP, 0xFFFFFFFF); 365 } 366 if (*rxlane_map == 0xFFFFFFFF) { 367 *rxlane_map = soc_property_port_suffix_num_get(unit, logical_port, core_num, 368 spn_XGXS_RX_LANE_MAP, 369 "core", 0x3210); 370 } 371 372 *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 373 spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0xFFFFFFFF); 374 375 if (*txlane_map == 0xFFFFFFFF) { 376 *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 377 spn_PHY_TX_LANE_MAP, 0xFFFFFFFF); 378 } 379 if (*txlane_map == 0xFFFFFFFF) { 380 *txlane_map = soc_property_port_suffix_num_get(unit, logical_port, core_num, 381 spn_XGXS_TX_LANE_MAP, 382 "core", 0x3210); 383 } 384 } 385 386 387 STATIC int 388 _soc_ap_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 389 { 390 #ifdef PORTMOD_PM4X10_SUPPORT 391 int rv = SOC_E_NONE; 392 portmod_pm_create_info_t pm_info; 393 int pmid = 0, blk, is_sim, found, logical_port; 394 int first_port, idx, core_num, core_cnt; 395 uint32 *pAddr, *pPort, *pCoreNum; 396 int mode; 397 398 SOC_IF_ERROR_RETURN 399 (_soc_ap_portctrl_device_addr_port_get(unit, 400 portmodDispatchTypePm4x10, 401 &pAddr, &pPort, &pCoreNum)); 402 if (!pAddr || !pPort) { 403 return SOC_E_INTERNAL; 404 } 405 406 /* Allocate PMs */ 407 SOC_IF_ERROR_RETURN 408 (soc_esw_portctrl_pm_user_access_alloc(unit, 409 num_of_instances, 410 &pm4x10_ap_user_acc[unit])); 411 412 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 413 414 rv = portmod_pm_create_info_t_init(unit, &pm_info); 415 if (PORTMOD_FAILURE(rv)) { 416 break; 417 } 418 /* PM info */ 419 first_port = pPort[pmid]; 420 421 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 422 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 423 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 424 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 425 426 found = 0; 427 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 428 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 429 if (SOC_BLOCK_INFO(unit, blk).type == 430 (soc_feature(unit, soc_feature_xlportb0) ? SOC_BLK_XLPORTB0 : SOC_BLK_XLPORT)){ 431 found = 1; 432 break; 433 } 434 435 } 436 if (!found) { 437 rv = SOC_E_INTERNAL; 438 break; 439 } 440 441 pm_info.type = portmodDispatchTypePm4x10; 442 443 /* Init user_acc for phymod access struct */ 444 rv = portmod_default_user_access_t_init(unit, 445 &(pm4x10_ap_user_acc[unit][pmid])); 446 if (PORTMOD_FAILURE(rv)) { 447 break; 448 } 449 450 SOC_IF_ERROR_RETURN( 451 _soc_ap_portctrl_pm_user_acc_flag_set(unit, 452 &(pm4x10_ap_user_acc[unit][pmid]))); 453 454 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10_ap_user_acc[unit][pmid]))); 455 pm4x10_ap_user_acc[unit][pmid].unit = unit; 456 pm4x10_ap_user_acc[unit][pmid].blk_id = blk; 457 pm4x10_ap_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 458 if (pm4x10_ap_user_acc[unit][pmid].mutex == NULL) { 459 rv = SOC_E_MEMORY; 460 break; 461 } 462 463 /* Specific info for PM4x10 */ 464 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access); 465 if (PORTMOD_FAILURE(rv)) { 466 break; 467 } 468 469 pm_info.pm_specific_info.pm4x10.access.user_acc = 470 &(pm4x10_ap_user_acc[unit][pmid]); 471 pm_info.pm_specific_info.pm4x10.access.addr = pAddr[pmid]; 472 pm_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 473 474 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 475 &(pm_info.pm_specific_info.pm4x10.access), 476 0, &is_sim); 477 if (PORTMOD_FAILURE(rv)) { 478 break; 479 } 480 481 if (is_sim) { 482 pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |= 483 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 484 485 /* Firmward loader : Don't allow FW load on sim enviroment */ 486 pm_info.pm_specific_info.pm4x10.fw_load_method = 487 phymodFirmwareLoadMethodNone; 488 } 489 490 /* Use default external loader if NULL */ 491 pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 492 493 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 494 core_cnt = 1; 495 496 for (core_num = 0; core_num < core_cnt; core_num++) { 497 pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid; 498 pm_info.pm_specific_info.pm4x10.core_num_int = 0; 499 pm_info.pm_specific_info.pm4x10.rescal = -1; 500 } 501 502 SOC_IF_ERROR_RETURN(soc_apache_port_mode_get(unit, logical_port, &mode)); 503 if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) { 504 pm_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoThreePorts; 505 } 506 507 /* Add PM to PortMod */ 508 rv = portmod_port_macro_add(unit, &pm_info); 509 } 510 511 if (PORTMOD_FAILURE(rv)) { 512 for (pmid=0; pmid < num_of_instances; pmid++) { 513 if (pm4x10_ap_user_acc[unit][pmid].mutex) { 514 sal_mutex_destroy(pm4x10_ap_user_acc[unit][pmid].mutex); 515 pm4x10_ap_user_acc[unit][pmid].mutex = NULL; 516 } 517 } 518 } 519 520 return rv; 521 #else /* PORTMOD_PM4X10_SUPPORT */ 522 return SOC_E_UNAVAIL; 523 #endif /* PORTMOD_PM4X10_SUPPORT */ 524 } 525 526 STATIC int 527 _soc_ap_portctrl_pm4x25_portmod_init(int unit, int num_of_instances) 528 { 529 #ifdef PORTMOD_PM4X25_SUPPORT 530 int rv = SOC_E_NONE; 531 portmod_pm_create_info_t pm_info; 532 int pmid = 0, blk, is_sim, found, logical_port; 533 int first_port, idx, core_num, core_cnt; 534 uint32 *pAddr, *pPort,*pCoreNum; 535 int mode; 536 537 SOC_IF_ERROR_RETURN 538 (_soc_ap_portctrl_device_addr_port_get(unit, 539 portmodDispatchTypePm4x25, 540 &pAddr, &pPort,&pCoreNum)); 541 if (!pAddr || !pPort) { 542 return SOC_E_INTERNAL; 543 } 544 545 /* Allocate PMs */ 546 SOC_IF_ERROR_RETURN 547 (soc_esw_portctrl_pm_user_access_alloc(unit, 548 num_of_instances, 549 &pm4x25_ap_user_acc[unit])); 550 551 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 552 553 rv = portmod_pm_create_info_t_init(unit, &pm_info); 554 if (PORTMOD_FAILURE(rv)) { 555 break; 556 } 557 /* PM info */ 558 first_port = pPort[pmid]; 559 560 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 561 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 562 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 563 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 564 565 found = 0; 566 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 567 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 568 if (SOC_BLOCK_INFO(unit, blk).type == 569 (soc_feature(unit, soc_feature_clport_gen2) ? SOC_BLK_CLG2PORT : SOC_BLK_CLPORT)){ 570 found = 1; 571 break; 572 } 573 } 574 if (!found) { 575 rv = SOC_E_INTERNAL; 576 break; 577 } 578 579 pm_info.type = portmodDispatchTypePm4x25; 580 581 /* Init user_acc for phymod access struct */ 582 rv = portmod_default_user_access_t_init(unit, 583 &(pm4x25_ap_user_acc[unit][pmid])); 584 if (PORTMOD_FAILURE(rv)) { 585 break; 586 } 587 588 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_ap_user_acc[unit][pmid]))); 589 pm4x25_ap_user_acc[unit][pmid].unit = unit; 590 pm4x25_ap_user_acc[unit][pmid].blk_id = blk; 591 pm4x25_ap_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 592 if (pm4x25_ap_user_acc[unit][pmid].mutex == NULL) { 593 rv = SOC_E_MEMORY; 594 break; 595 } 596 597 /* Specific info for PM4x25 */ 598 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x25.access); 599 if (PORTMOD_FAILURE(rv)) { 600 break; 601 } 602 603 pm_info.pm_specific_info.pm4x25.access.user_acc = 604 &(pm4x25_ap_user_acc[unit][pmid]); 605 pm_info.pm_specific_info.pm4x25.access.addr = pAddr[pmid]; 606 pm_info.pm_specific_info.pm4x25.access.bus = NULL; /* Use default bus */ 607 608 rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 609 &(pm_info.pm_specific_info.pm4x25.access), 610 0, &is_sim); 611 612 if (PORTMOD_FAILURE(rv)) { 613 break; 614 } 615 616 if (is_sim) { 617 pm_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 618 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 619 620 /* Firmward loader : Don't allow FW load on sim enviroment */ 621 pm_info.pm_specific_info.pm4x25.fw_load_method = 622 phymodFirmwareLoadMethodNone; 623 } 624 625 /* Use default external loader if NULL */ 626 pm_info.pm_specific_info.pm4x25.external_fw_loader = NULL; 627 628 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 629 core_cnt = 1; 630 631 for (core_num = 0; core_num < core_cnt; core_num++) { 632 pm_info.pm_specific_info.pm4x25.core_num = pCoreNum? pCoreNum[pmid] : pmid; 633 pm_info.pm_specific_info.pm4x25.core_num_int = 0; 634 pm_info.pm_specific_info.pm4x25.rescal = -1; 635 } 636 637 SOC_IF_ERROR_RETURN(soc_apache_port_mode_get(unit, logical_port, &mode)); 638 if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) { 639 pm_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoThreePorts; 640 } 641 642 /* Add PM to PortMod */ 643 rv = portmod_port_macro_add(unit, &pm_info); 644 } 645 646 if (PORTMOD_FAILURE(rv)) { 647 for (pmid=0; pmid < num_of_instances; pmid++) { 648 if (pm4x25_ap_user_acc[unit][pmid].mutex) { 649 sal_mutex_destroy(pm4x25_ap_user_acc[unit][pmid].mutex); 650 pm4x25_ap_user_acc[unit][pmid].mutex = NULL; 651 } 652 } 653 } 654 655 return rv; 656 #else /* PORTMOD_PM4X25_SUPPORT */ 657 return SOC_E_UNAVAIL; 658 #endif /* PORTMOD_PM4X25_SUPPORT */ 659 } 660 661 662 STATIC int 663 _soc_ap_portctrl_pm12x10_portmod_init(int unit, int num_of_instances) 664 { 665 #if defined(PORTMOD_PM12X10_XGS_SUPPORT) 666 int rv = SOC_E_NONE; 667 portmod_pm_create_info_t pm_info; 668 portmod_pm4x10_create_info_t *pm4x10_info; 669 portmod_pm4x25_create_info_t *pm4x25_info; 670 int pmid = 0, blk, is_sim, phy, found, logical_port, f_logical_port; 671 int first_port, idx, core_num; 672 uint32 *pAddr, *pPort, *pCoreNum; 673 int mode; 674 675 SOC_IF_ERROR_RETURN 676 (_soc_ap_portctrl_device_addr_port_get(unit, 677 portmodDispatchTypePm12x10_xgs, 678 &pAddr, &pPort, &pCoreNum)); 679 if (!pAddr || !pPort) { 680 return SOC_E_INTERNAL; 681 } 682 683 SOC_IF_ERROR_RETURN 684 (soc_esw_portctrl_pm_user_access_alloc(unit, 685 num_of_instances, 686 &pm12x10_ap_user_acc[unit])); 687 688 SOC_IF_ERROR_RETURN 689 (soc_esw_portctrl_pm_user_access_alloc(unit, 690 num_of_instances*SOC_PM12X10_PM4X10_COUNT, 691 &pm12_4x10_ap_user_acc[unit])); 692 693 SOC_IF_ERROR_RETURN 694 (soc_esw_portctrl_pm_user_access_alloc(unit, 695 num_of_instances, 696 &pm12_4x25_ap_user_acc[unit])); 697 698 699 /* Register PM12x10 */ 700 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 701 int core_idx, core_blk; 702 703 rv = portmod_pm_create_info_t_init(unit, &pm_info); 704 if (PORTMOD_FAILURE(rv)) { 705 break; 706 } 707 708 pm_info.pm_specific_info.pm12x10.refclk_source = 0; 709 710 /* PM info */ 711 first_port = pPort[pmid]; 712 713 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 714 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 715 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 716 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 717 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+4); 718 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+5); 719 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+6); 720 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+7); 721 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+8); 722 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+9); 723 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+10); 724 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+11); 725 726 found = 0; 727 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 728 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 729 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CXXPORT) { 730 found = 1; 731 break; 732 } 733 } 734 735 if (!found) { 736 rv = SOC_E_INTERNAL; 737 break; 738 } 739 pm_info.type = portmodDispatchTypePm12x10_xgs; 740 PORTMOD_PM12x10_F_USE_PM_XGS_SET(pm_info.pm_specific_info.pm12x10.flags); 741 742 743 /* init user_acc for phymod access struct */ 744 rv = portmod_default_user_access_t_init(unit, 745 &(pm12x10_ap_user_acc[unit][pmid])); 746 if (PORTMOD_FAILURE(rv)) { 747 break; 748 } 749 750 pm12x10_ap_user_acc[unit][pmid].unit = unit; 751 pm12x10_ap_user_acc[unit][pmid].blk_id = blk; 752 pm_info.pm_specific_info.pm12x10.blk_id = blk; 753 pm12x10_ap_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 754 if (pm12x10_ap_user_acc[unit][pmid].mutex == NULL) { 755 rv = SOC_E_MEMORY; 756 break; 757 } 758 759 for (core_num = 0; 760 PORTMOD_SUCCESS(rv) && (core_num < SOC_PM12X10_PM4X10_COUNT); 761 core_num++) { 762 763 /* PM4X10 INFO UPDATE */ 764 pm4x10_info = &pm_info.pm_specific_info.pm12x10.pm4x10_infos[core_num]; 765 766 /* Specific info for PM12x10 */ 767 rv = phymod_access_t_init(&pm4x10_info->access); 768 if (PORTMOD_FAILURE(rv)) { 769 break; 770 } 771 pm12_4x10_ap_user_acc[unit][(pmid*3)+core_num] = pm12x10_ap_user_acc[unit][pmid]; 772 773 found = 0; 774 for(core_idx = 0; core_idx < SOC_DRIVER(unit)->port_num_blktype; core_idx++){ 775 core_blk = SOC_PORT_IDX_INFO(unit, (first_port+(4*core_num)), core_idx).blk; 776 if (SOC_BLOCK_INFO(unit, core_blk).type == SOC_BLK_XLPORT){ 777 found = 1; 778 break; 779 } 780 } 781 782 if (!found) { 783 /* Internal Error */ 784 break; 785 } 786 787 pm12_4x10_ap_user_acc[unit][(pmid*3)+core_num].blk_id = core_blk; 788 pm4x10_info->access.user_acc = &(pm12_4x10_ap_user_acc[unit][(pmid*3)+core_num]); 789 pm4x10_info->access.addr = pAddr[(pmid*3) + core_num]; 790 pm4x10_info->access.bus = NULL; 791 pm4x10_info->core_num = pCoreNum? pCoreNum[(pmid*3)+core_num] : ((pmid*3)+core_num); 792 pm4x10_info->core_num_int = core_num; 793 pm4x10_info->in_pm_12x10 = TRUE; 794 pm4x10_info->rescal = -1; 795 796 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 797 &(pm4x10_info->access), 0, &is_sim); 798 if (PORTMOD_FAILURE(rv)) { 799 break; 800 } 801 802 if (is_sim) { 803 pm4x10_info->access.bus->bus_capabilities |= 804 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 805 806 /* Firmward loader : Don't allow FW load on sim enviroment */ 807 pm4x10_info->fw_load_method = phymodFirmwareLoadMethodNone; 808 } 809 810 /* Use default external loader */ 811 pm4x10_info->external_fw_loader = NULL; 812 813 f_logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 814 815 /* Three Port Mode */ 816 { 817 phy = first_port+(core_num*4); 818 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 819 820 if (-1 != logical_port) { 821 SOC_IF_ERROR_RETURN(soc_apache_port_mode_get(unit, logical_port, &mode)); 822 if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) { 823 pm4x10_info->port_mode_aux_info = portmodModeInfoThreePorts; 824 } 825 } 826 } 827 828 if (core_num && (logical_port == -1)) { 829 if (IS_CXX_PORT(unit, f_logical_port) && IS_CL_PORT(unit, f_logical_port)) { 830 logical_port = f_logical_port; 831 } 832 } 833 } 834 835 836 /* PM4X25 INFO UPDATE */ 837 pm4x25_info = &pm_info.pm_specific_info.pm12x10.pm4x25_info; 838 839 /* Specific info for PM12x10 */ 840 rv = phymod_access_t_init(&pm4x25_info->access); 841 if (PORTMOD_FAILURE(rv)) { 842 break; 843 } 844 pm12_4x25_ap_user_acc[unit][pmid] = pm12x10_ap_user_acc[unit][pmid]; 845 found = 0; 846 first_port = pPort[pmid]; 847 for(core_idx = 0; core_idx < SOC_DRIVER(unit)->port_num_blktype; core_idx++){ 848 core_blk = SOC_PORT_IDX_INFO(unit, first_port, core_idx).blk; 849 if (SOC_BLOCK_INFO(unit, core_blk).type == SOC_BLK_CLPORT){ 850 found = 1; 851 break; 852 } 853 } 854 855 if (!found) { 856 rv = SOC_E_INTERNAL; 857 break; 858 } 859 860 pm12_4x25_ap_user_acc[unit][pmid].blk_id = core_blk; 861 pm4x25_info->lane_map.num_of_lanes = SOC_PM4X25_NUM_LANES; 862 pm4x25_info->access.user_acc = &(pm12_4x25_ap_user_acc[unit][pmid]); 863 pm4x25_info->access.addr = pAddr[pmid]; 864 pm4x25_info->access.bus = NULL; 865 pm4x25_info->core_num = pmid; 866 pm4x25_info->external_fw_loader = NULL; 867 pm4x25_info->fw_load_method = phymodFirmwareLoadMethodNone; 868 pm4x25_info->in_pm_12x10 = TRUE; 869 pm4x25_info->rescal = -1; 870 871 872 rv = portmod_port_macro_add(unit, &pm_info); 873 } 874 875 if (PORTMOD_FAILURE(rv)) { 876 for (pmid=0; pmid < num_of_instances; pmid++) { 877 if (pm12x10_ap_user_acc[unit][pmid].mutex) { 878 sal_mutex_destroy(pm12x10_ap_user_acc[unit][pmid].mutex); 879 pm12x10_ap_user_acc[unit][pmid].mutex = NULL; 880 } 881 } 882 } 883 return rv; 884 #else /* PORTMOD_PM12X10_XGS_SUPPORT */ 885 return SOC_E_UNAVAIL; 886 #endif /* PORTMOD_PM12X10_XGS_SUPPORT */ 887 } 888 889 /* 890 * Function: 891 * soc_ap_portctrl_pm_portmod_init 892 * Purpose: 893 * Initialize PortMod and PortMacro for Trident2Plus 894 * Add port macros (PM) to the unit's PortMod Manager (PMM). 895 * Parameters: 896 * unit - (IN) Unit number. 897 * Returns: 898 * SOC_E_XXX 899 */ 900 int 901 soc_ap_portctrl_pm_portmod_init(int unit) 902 { 903 uint32 flags = 0; 904 int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0; 905 portmod_pm_instances_t *pm_types = NULL; 906 907 /* Call PortMod library initialization */ 908 SOC_IF_ERROR_RETURN( 909 _soc_ap_portctrl_pm_init(unit, &max_phys, 910 &pm_types, &pms_arr_len)); 911 if (pms_arr_len == 0) { 912 return SOC_E_UNAVAIL; 913 } 914 915 /* 916 * If portmod was create - destroy and create again 917 * Better way would be to create once and leave it. 918 */ 919 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 920 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 921 } 922 923 PORTMOD_CREATE_F_PM_NULL_SET(flags); 924 925 SOC_IF_ERROR_RETURN 926 (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, max_phys, 927 pms_arr_len, pm_types)); 928 929 for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) { 930 #ifdef PORTMOD_PM4X10_SUPPORT 931 if (pm_types[count].type == portmodDispatchTypePm4x10) { 932 rv = _soc_ap_portctrl_pm4x10_portmod_init 933 (unit, pm_types[count].instances); 934 } else 935 #endif /* PORTMOD_PM4X10_SUPPORT */ 936 #ifdef PORTMOD_PM4X25_SUPPORT 937 if (pm_types[count].type == portmodDispatchTypePm4x25) { 938 rv = _soc_ap_portctrl_pm4x25_portmod_init 939 (unit, pm_types[count].instances); 940 } else 941 #endif /* PORTMOD_PM4X25_SUPPORT */ 942 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 943 if (pm_types[count].type == portmodDispatchTypePm12x10_xgs) { 944 rv = _soc_ap_portctrl_pm12x10_portmod_init 945 (unit, pm_types[count].instances); 946 } else 947 #endif /* PORTMOD_PM12X10_XGS_SUPPORT */ 948 { 949 rv = SOC_E_INTERNAL; 950 } 951 } 952 953 return rv; 954 } 955 956 /* 957 * Function: 958 * soc_ap_portctrl_pm_portmod_deinit 959 * Purpose: 960 * Deinitialize PortMod and PortMacro for Trident2Plus. 961 * Free pm user access data. 962 * Parameters: 963 * unit - (IN) Unit number. 964 * Returns: 965 * SOC_E_NONE 966 */ 967 int 968 soc_ap_portctrl_pm_portmod_deinit(int unit) 969 { 970 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 971 return SOC_E_NONE; 972 } 973 974 /* Free PMs structures */ 975 #ifdef PORTMOD_PM4X10_SUPPORT 976 if (pm4x10_ap_user_acc[unit] != NULL) { 977 sal_free(pm4x10_ap_user_acc[unit]); 978 pm4x10_ap_user_acc[unit] = NULL; 979 } 980 #endif /* PORTMOD_PM4X10_SUPPORT */ 981 982 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 983 if (pm12x10_ap_user_acc[unit] != NULL) { 984 sal_free(pm12x10_ap_user_acc[unit]); 985 pm12x10_ap_user_acc[unit] = NULL; 986 } 987 #endif /* PORTMOD_PM12X10_XGS_SUPPORT */ 988 989 #ifdef PORTMOD_PM4X25_SUPPORT 990 if (pm4x25_ap_user_acc[unit] != NULL) { 991 sal_free(pm4x25_ap_user_acc[unit]); 992 pm4x25_ap_user_acc[unit] = NULL; 993 } 994 #endif /* PORTMOD_PM4X25_SUPPORT */ 995 996 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 997 998 return SOC_E_NONE; 999 } 1000 1001 int 1002 soc_ap_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config) 1003 { 1004 #ifdef PORTMOD_PM4X10_SUPPORT 1005 int rv = SOC_E_NONE; 1006 int pmid = 0, lane, phy, phy_port, logical_port, f_logical_port, port_mode; 1007 int first_port, core_num = 0, core_index, is_sim, type; 1008 uint32 txlane_map, rxlane_map, rxlane_map_l, i; 1009 uint32 *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL; 1010 uint32 tx_polarity, rx_polarity; 1011 portmod_port_init_config_t *port_config_info; 1012 phymod_firmware_load_method_t fw_load_method; 1013 phymod_polarity_t polarity; /**< Lanes Polarity */ 1014 phymod_lane_map_t lane_map; 1015 uint8_t pm_found=0; 1016 1017 port_config_info = (portmod_port_init_config_t *)port_config; 1018 1019 SOC_IF_ERROR_RETURN(soc_apache_port_mode_get(unit, port, &port_mode)); 1020 if (port_mode == portmodPortModeTri012 || port_mode == portmodPortModeTri023) { 1021 port_config_info->port_mode_aux_info = portmodModeInfoThreePorts; 1022 } 1023 1024 phy = SOC_INFO(unit).port_l2p_mapping[port]; 1025 1026 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 1027 pm_found = 0; 1028 core_index = (phy - 1) / SOC_PM4X10_NUM_LANES; 1029 for (i=0; i<SOC_AP_PM4X10_COUNT; i++) { 1030 if (core_index == _ap_pm4x10_core_num[i]) { 1031 type = portmodDispatchTypePm4x10; 1032 SOC_IF_ERROR_RETURN 1033 (_soc_ap_portctrl_device_addr_port_get(unit, 1034 portmodDispatchTypePm4x10, 1035 &pAddr, &pPort, &pCoreNum)); 1036 pmid = i; 1037 core_num = 1; 1038 pm_found = 1; 1039 break; 1040 } 1041 } 1042 /* When port dones't find PM4x10, find PM4x25 again. */ 1043 if (!pm_found) { 1044 for (i=0; i<SOC_AP_PM4X25_COUNT; i++) { 1045 if (core_index == _ap_pm4x25_core_num[i]) { 1046 type = portmodDispatchTypePm4x25; 1047 SOC_IF_ERROR_RETURN 1048 (_soc_ap_portctrl_device_addr_port_get(unit, 1049 portmodDispatchTypePm4x25, 1050 &pAddr, &pPort, &pCoreNum)); 1051 /* Because one PM4x25 has three cores and one corresponding pmid. */ 1052 pmid = i; 1053 core_num = 1; 1054 pm_found = 1; 1055 break; 1056 } 1057 } 1058 } 1059 1060 /* When port dones't find PM4x25, find PM12x10 again. */ 1061 if (!pm_found) { 1062 for (i=0; i<SOC_AP_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT; i++) { 1063 if (core_index == _ap_pm12x10_core_num[i]) { 1064 type = portmodDispatchTypePm12x10_xgs; 1065 SOC_IF_ERROR_RETURN 1066 (_soc_ap_portctrl_device_addr_port_get(unit, 1067 portmodDispatchTypePm12x10_xgs, 1068 &pAddr, &pPort, &pCoreNum)); 1069 /* Because one PM12x10 has three cores and one corresponding pmid. */ 1070 pmid = i / SOC_PM12X10_PM4X10_COUNT; 1071 core_num = SOC_PM12X10_PM4X10_COUNT; 1072 pm_found = 1; 1073 break; 1074 } 1075 } 1076 } 1077 1078 if (!pAddr || !pPort) { 1079 return SOC_E_INTERNAL; 1080 } 1081 1082 /* PM info */ 1083 first_port = pPort[pmid]; 1084 1085 for (core_index = 0; core_index < core_num; core_index++) { 1086 fw_load_method = phymodFirmwareLoadMethodExternal; 1087 1088 soc_physim_enable_get(unit, &is_sim); 1089 1090 if (is_sim) { 1091 /* Firmward loader : Don't allow FW load on sim enviroment */ 1092 fw_load_method = phymodFirmwareLoadMethodNone; 1093 } else { 1094 fw_load_method = soc_property_suffix_num_get(unit, pmid, 1095 spn_LOAD_FIRMWARE, "quad", 1096 phymodFirmwareLoadMethodExternal); 1097 fw_load_method &= 0xff; 1098 } 1099 1100 rv = phymod_polarity_t_init(&polarity); 1101 if (PORTMOD_FAILURE(rv)) { 1102 break; 1103 } 1104 1105 f_logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 1106 1107 /* Polarity */ 1108 for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) { 1109 phy_port = first_port + lane + (core_index*4); 1110 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1111 1112 /* in case of 100G - there is no logical port for core1, core2 */ 1113 /* so if the logical port is -1, check 100G and use core0 */ 1114 /* This could be a 100G port. so mapping is available for core0 only */ 1115 if (core_index && (logical_port == -1)) { 1116 if (IS_CXX_PORT(unit, f_logical_port) && IS_CL_PORT(unit, f_logical_port)) { 1117 logical_port = f_logical_port; 1118 } 1119 } 1120 1121 apache_pm_port_polarity_get(unit, logical_port, phy_port, lane, core_index, &tx_polarity, &rx_polarity); 1122 1123 polarity.rx_polarity |= rx_polarity; 1124 polarity.tx_polarity |= tx_polarity; 1125 } 1126 1127 /* Lane map */ 1128 rv = phymod_lane_map_t_init(&lane_map); 1129 if (PORTMOD_FAILURE(rv)) { 1130 break; 1131 } 1132 1133 phy_port = first_port + (core_index*4); 1134 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1135 1136 if (core_index && (logical_port == -1)) { 1137 if (IS_CXX_PORT(unit, f_logical_port) && IS_CL_PORT(unit, f_logical_port)) { 1138 logical_port = f_logical_port; 1139 } 1140 } 1141 1142 apache_pm_port_lanemap_get(unit, logical_port, phy_port, core_index, &txlane_map, &rxlane_map); 1143 /* Handle package level polarity flips and lane swaps */ 1144 if (!SAL_BOOT_SIMULATION) { 1145 _soc_apache_portctrl_pkg_config_set(unit, phy_port, &rx_polarity, &tx_polarity, 1146 &rxlane_map, &txlane_map); 1147 } 1148 1149 polarity.rx_polarity |= rx_polarity; 1150 polarity.tx_polarity |= tx_polarity; 1151 1152 rxlane_map_l = rxlane_map ; 1153 /* For TSC-E/F family, both lane_map_rx and lane_map_tx are logic lane base */ 1154 /* TD2/TD2+ xgxs_rx_lane_map is phy-lane base */ 1155 if(SOC_IS_APACHE(unit)) { /* use TD2 legacy notion system */ 1156 rxlane_map_l = 0 ; 1157 for (i=0; i<SOC_PM4X10_NUM_LANES; i++) { 1158 rxlane_map_l |= i << SOC_PM4X10_NUM_LANES *((rxlane_map >> (i*SOC_PM4X10_NUM_LANES))& SOC_PM4X10_LANE_MASK) ; 1159 } 1160 } 1161 1162 if (type == portmodDispatchTypePm4x25) { 1163 lane_map.num_of_lanes = SOC_PM4X25_NUM_LANES; 1164 } else { 1165 lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 1166 } 1167 1168 for(lane = 0 ; lane < SOC_PM4X10_NUM_LANES; lane++) { 1169 lane_map.lane_map_tx[lane] = 1170 (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 1171 SOC_PM4X10_LANE_MASK; 1172 lane_map.lane_map_rx[lane] = 1173 (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 1174 SOC_PM4X10_LANE_MASK; 1175 } 1176 1177 sal_memcpy(&port_config_info->fw_load_method[core_index], &fw_load_method, 1178 sizeof(phymod_firmware_load_method_t)); 1179 port_config_info->fw_load_method_overwrite = 1; 1180 sal_memcpy(&port_config_info->polarity[core_index], &polarity, 1181 sizeof(phymod_polarity_t)); 1182 port_config_info->polarity_overwrite = 1; 1183 sal_memcpy(&port_config_info->lane_map[core_index], &lane_map, 1184 sizeof(phymod_lane_map_t)); 1185 port_config_info->lane_map_overwrite = 1; 1186 } 1187 1188 return rv; 1189 #else /* PORTMOD_PM4X10_SUPPORT */ 1190 return SOC_E_UNAVAIL; 1191 #endif /* PORTMOD_PM4X10_SUPPORT */ 1192 } 1193 1194 int 1195 soc_ap_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port) 1196 { 1197 int phy, core_index; 1198 uint32 i, *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL; 1199 1200 phy = SOC_INFO(unit).port_l2p_mapping[port]; 1201 1202 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 1203 core_index = (phy - 1) / SOC_PM4X10_NUM_LANES; 1204 #ifdef PORTMOD_PM4X10_SUPPORT 1205 for (i=0; i<SOC_AP_PM4X10_COUNT; i++) { 1206 if (core_index == _ap_pm4x10_core_num[i]) { 1207 SOC_IF_ERROR_RETURN 1208 (_soc_ap_portctrl_device_addr_port_get(unit, 1209 portmodDispatchTypePm4x10, 1210 &pAddr, &pPort, &pCoreNum)); 1211 return pAddr[i]; 1212 } 1213 } 1214 #endif /* PORTMOD_PM4X10_SUPPORT */ 1215 1216 #ifdef PORTMOD_PM4X25_SUPPORT 1217 /* When port dones't find PM4x10, find PM4x25 again. */ 1218 for (i=0; i<SOC_AP_PM4X25_COUNT; i++) { 1219 if (core_index == _ap_pm4x25_core_num[i]) { 1220 SOC_IF_ERROR_RETURN 1221 (_soc_ap_portctrl_device_addr_port_get(unit, 1222 portmodDispatchTypePm4x25, 1223 &pAddr, &pPort, &pCoreNum)); 1224 return pAddr[i]; 1225 } 1226 } 1227 #endif /* PORTMOD_PM4X25_SUPPORT */ 1228 1229 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 1230 /* When port dones't find PM4x25, find PM12x10 again. */ 1231 for (i=0; i<SOC_AP_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT; i++) { 1232 if (core_index == _ap_pm12x10_core_num[i]) { 1233 SOC_IF_ERROR_RETURN 1234 (_soc_ap_portctrl_device_addr_port_get(unit, 1235 portmodDispatchTypePm12x10_xgs, 1236 &pAddr, &pPort, &pCoreNum)); 1237 return pAddr[i]; 1238 } 1239 } 1240 #endif /* PORTMOD_PM12X10_XGS_SUPPORT */ 1241 1242 return -1; 1243 } 1244 1245 int 1246 soc_ap_portctrl_port_ability_update(int unit, soc_port_t port, soc_port_ability_t *ability) 1247 { 1248 int phy_port, tsc_id; 1249 uint32 force_hg; 1250 1251 if (!soc_feature(unit, soc_feature_untethered_otp)) { 1252 return SOC_E_NONE; 1253 } 1254 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1255 /* Each bit in FORCE_HG bond option represents one TSC/Port Macro 1256 * 1 - All ports in specified TSC are Higig only. 1257 * 0 - No restrictions 1258 */ 1259 force_hg = SOC_BOND_INFO(unit)->tsc_force_hg; 1260 tsc_id = (phy_port - 1) / SOC_AP_MAX_PORTS_PER_TSC; 1261 1262 if (force_hg & (1 << tsc_id)) { 1263 ability->encap &= ~SOC_PA_ENCAP_IEEE; 1264 } 1265 return SOC_E_NONE; 1266 } 1267 1268 int 1269 soc_ap_portctrl_pm_type_get(int unit, soc_port_t phy_port, 1270 int* pm_type) 1271 { 1272 if ((phy_port < 0) || (phy_port > 72)) { 1273 return SOC_E_PARAM; 1274 } 1275 1276 #if defined(PORTMOD_PM4X10_SUPPORT) && defined (PORTMOD_PM4X25_SUPPORT) 1277 if (PORT_IS_PM4x25_PORT_PHY(unit, phy_port)) { 1278 *pm_type = portmodDispatchTypePm4x25; 1279 } else { 1280 *pm_type = portmodDispatchTypePm4x10; 1281 } 1282 #else 1283 *pm_type = -1; 1284 #endif 1285 1286 return ((*pm_type == -1) ? SOC_E_UNAVAIL : SOC_E_NONE); 1287 } 1288 1289 #endif /* BCM_APACHE_SUPPORT */