portctrl.c (26259B)
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/maverick2.h> 21 22 #ifdef BCM_MAVERICK2_SUPPORT 23 24 #define SOC_MV2_PM4X10_COUNT 1 25 static uint32_t _mv2_pm4x10_addr[SOC_MV2_PM4X10_COUNT] = { 0x1c1 }; 26 27 #define SOC_MV2_PM4X25_COUNT 20 28 #define SOC_MV2_MAX_PHYS 87 /* 20*4 CLMAC's + 4 XLMAC */ 29 30 static uint32_t _mv2_pm4x25_addr[SOC_MV2_PM4X25_COUNT] = { 31 0x81, 0x85, 0x89, 0x8D, 0x91, 32 0xA1, 0xA5, 0xA9, 0xAD, 0xB1, 33 0xC1, 0xC5, 0xC9, 0xCD, 0xD1, 34 0xE1, 0xE5, 0xE9, 0xED, 0xF1, 35 }; 36 37 38 static portmod_pm_instances_t mv2_pm_types[] = { 39 #ifdef PORTMOD_PM4X25_SUPPORT 40 {portmodDispatchTypePm4x25, SOC_MV2_PM4X25_COUNT}, 41 #endif 42 #ifdef PORTMOD_PM4X10_SUPPORT 43 {portmodDispatchTypePm4x10, SOC_MV2_PM4X10_COUNT}, 44 #endif 45 }; 46 47 #ifdef PORTMOD_PM4X25_SUPPORT 48 static portmod_default_user_access_t *pm4x25_mv2_user_acc[SOC_MAX_NUM_DEVICES]; 49 #endif /* PORTMOD_PM4X25_SUPPORT */ 50 51 #ifdef PORTMOD_PM4X10_SUPPORT 52 static portmod_default_user_access_t *pm4x10_mv2_user_acc[SOC_MAX_NUM_DEVICES]; 53 #endif /* PORTMOD_PM4X25_SUPPORT */ 54 55 56 57 /* 58 * Polarity get looks for physical port based config first. This will enable 59 * the user to define the polarity for all ports weather mapped to logical 60 * port or not. 61 * 62 * For legacy compatibility - we still look for the logical port 63 * config setup. 64 */ 65 STATIC void 66 mv2_pm_port_polarity_get (int unit, int logical_port, int physical_port, 67 int lane, uint32 *tx_pol, uint32* rx_pol) 68 { 69 uint32 rx_polarity, tx_polarity; 70 71 rx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane, 72 spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0x0); 73 *rx_pol = (rx_polarity & 0x1) << lane; 74 75 tx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane, 76 spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0x0); 77 *tx_pol = (tx_polarity & 0x1) << lane; 78 } 79 80 /* 81 * lanemap get looks for physical port based config first. This will enable 82 * the user to define the lanemap for all ports weather mapped to logical 83 * port or not. 84 * 85 * For legacy compatibility - we still look for the logical port 86 * config setup. 87 */ 88 STATIC 89 void mv2_pm_port_lanemap_get (int unit, int logical_port, int physical_port, 90 uint32 *txlane_map, uint32* rxlane_map) 91 { 92 *rxlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0, 93 spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0x3210); 94 95 *txlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0, 96 spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0x3210); 97 } 98 99 100 STATIC int 101 _soc_mv2_portctrl_pm4x25_portmod_init(int unit, int second_mgmt_port) 102 { 103 #ifdef PORTMOD_PM4X25_SUPPORT 104 int rv = SOC_E_NONE; 105 portmod_pm_create_info_t pm_create_info; 106 int pmid = 0, blk, is_sim, lane, phy, found, logical_port; 107 int first_port, idx, ref_clk_prop; 108 uint32 txlane_map, rxlane_map; 109 uint32 tx_polarity, rx_polarity; 110 111 /* Allocate user access for all PMs */ 112 SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 113 SOC_MV2_PM4X25_COUNT, &pm4x25_mv2_user_acc[unit])); 114 115 116 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_MV2_PM4X25_COUNT); pmid++) { 117 118 rv = portmod_pm_create_info_t_init(unit, &pm_create_info); 119 if (PORTMOD_FAILURE(rv)) { 120 break; 121 } 122 123 pm_create_info.type = portmodDispatchTypePm4x25; 124 125 /* 1 based port number */ 126 first_port = 1 + (pmid << 2); 127 128 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port); 129 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+1); 130 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+2); 131 SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+3); 132 133 /* Identify the block for this particular port */ 134 found = 0; 135 136 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 137 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 138 if (SOC_BLOCK_INFO(unit, blk).type == 139 (soc_feature(unit, soc_feature_clport_gen2) ? SOC_BLK_CLG2PORT : SOC_BLK_CLPORT)){ 140 found = 1; 141 break; 142 } 143 } 144 145 if (!found) { 146 rv = SOC_E_INTERNAL; 147 break; 148 } 149 150 151 /* Init user_acc for phymod access struct */ 152 rv = portmod_default_user_access_t_init(unit, 153 &(pm4x25_mv2_user_acc[unit][pmid])); 154 if (PORTMOD_FAILURE(rv)) { 155 break; 156 } 157 158 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_mv2_user_acc[unit][pmid]))); 159 pm4x25_mv2_user_acc[unit][pmid].unit = unit; 160 pm4x25_mv2_user_acc[unit][pmid].blk_id = blk; 161 pm4x25_mv2_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 162 163 if (pm4x25_mv2_user_acc[unit][pmid].mutex == NULL) { 164 rv = SOC_E_MEMORY; 165 break; 166 } 167 168 /* Specific info for PM4x25 */ 169 rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x25.access); 170 if (PORTMOD_FAILURE(rv)) { 171 break; 172 } 173 174 pm_create_info.pm_specific_info.pm4x25.access.user_acc = &(pm4x25_mv2_user_acc[unit][pmid]); 175 pm_create_info.pm_specific_info.pm4x25.access.addr = _mv2_pm4x25_addr[pmid]; 176 pm_create_info.pm_specific_info.pm4x25.access.bus = NULL; /* Use default bus */ 177 pm_create_info.pm_specific_info.pm4x25.rescal = -1; 178 179 rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 180 &(pm_create_info.pm_specific_info.pm4x25.access), 181 0, &is_sim); 182 183 if (PORTMOD_FAILURE(rv)) { 184 break; 185 } 186 187 if (is_sim) { 188 pm_create_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 189 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 190 191 /* Firmward loader : Don't allow FW load on sim enviroment */ 192 pm_create_info.pm_specific_info.pm4x25.fw_load_method = 193 phymodFirmwareLoadMethodNone; 194 } else { 195 pm_create_info.pm_specific_info.pm4x25.fw_load_method = 196 soc_property_suffix_num_get(unit, pmid, 197 spn_LOAD_FIRMWARE, "quad", 198 phymodFirmwareLoadMethodExternal); 199 pm_create_info.pm_specific_info.pm4x25.fw_load_method &= 0xff; 200 } 201 202 /* Use default external loader if NULL */ 203 pm_create_info.pm_specific_info.pm4x25.external_fw_loader = NULL; 204 205 /* Polarity */ 206 rv = phymod_polarity_t_init (&(pm_create_info.pm_specific_info.pm4x25.polarity)); 207 if (PORTMOD_FAILURE(rv)) { 208 break; 209 } 210 211 for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) { 212 phy = first_port+lane; 213 214 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 215 216 mv2_pm_port_polarity_get (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity); 217 218 pm_create_info.pm_specific_info.pm4x25.polarity.rx_polarity |= rx_polarity; 219 pm_create_info.pm_specific_info.pm4x25.polarity.tx_polarity |= tx_polarity; 220 } 221 222 /* Lane map */ 223 rv = phymod_lane_map_t_init 224 (&(pm_create_info.pm_specific_info.pm4x25.lane_map)); 225 if (PORTMOD_FAILURE(rv)) { 226 break; 227 } 228 229 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 230 231 mv2_pm_port_lanemap_get (unit, logical_port, first_port, &txlane_map, &rxlane_map); 232 233 pm_create_info.pm_specific_info.pm4x25.lane_map.num_of_lanes = SOC_PM4X25_NUM_LANES; 234 pm_create_info.pm_specific_info.pm4x25.core_num = pmid; 235 pm_create_info.pm_specific_info.pm4x25.core_num_int = 0; 236 237 for(lane=0 ; lane<SOC_PM4X25_NUM_LANES; lane++) { 238 239 pm_create_info.pm_specific_info.pm4x25.lane_map.lane_map_tx[lane] = 240 (txlane_map >> (lane * SOC_PM4X25_NUM_LANES)) & 241 SOC_PM4X25_LANE_MASK; 242 243 pm_create_info.pm_specific_info.pm4x25.lane_map.lane_map_rx[lane] = 244 (rxlane_map >> (lane * SOC_PM4X25_NUM_LANES)) & 245 SOC_PM4X25_LANE_MASK; 246 } 247 248 ref_clk_prop = soc_property_port_get(unit, first_port, 249 spn_XGXS_LCPLL_XTAL_REFCLK, 156); 250 251 252 if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)) { 253 pm_create_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk156Mhz; 254 } else if (ref_clk_prop == 125) { 255 pm_create_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk125Mhz; 256 } else { 257 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_UP(unit, first_port, 258 "ERROR: This %d MHz clk freq is not supported. Use 156MHz / 125MHz.\n"),ref_clk_prop)); 259 return SOC_E_PARAM ; 260 } 261 262 /* Add PM to PortMod */ 263 rv = portmod_port_macro_add(unit, &pm_create_info); 264 } 265 266 if (PORTMOD_FAILURE(rv)) { 267 for (pmid=0; pmid < SOC_MV2_PM4X25_COUNT; pmid++) { 268 if (pm4x25_mv2_user_acc[unit][pmid].mutex) { 269 sal_mutex_destroy(pm4x25_mv2_user_acc[unit][pmid].mutex); 270 pm4x25_mv2_user_acc[unit][pmid].mutex = NULL; 271 } 272 } 273 } 274 275 return rv; 276 #else /* PORTMOD_PM4X25_SUPPORT */ 277 return SOC_E_UNAVAIL; 278 #endif /* PORTMOD_PM4X25_SUPPORT */ 279 } 280 281 #define MAVERICK2_FIRST_MGMT_PHYSICAL_PORT_NUM 81 282 /* #define MAVERICK2_SECOND_MGMT_PHYSICAL_PORT_NUM 131 */ 283 STATIC int 284 _soc_mv2_portctrl_pm4x10_portmod_init(int unit, int second_mgmt_port) 285 { 286 #ifdef PORTMOD_PM4X10_SUPPORT 287 int rv = SOC_E_NONE; 288 portmod_pm_create_info_t pm_create_info; 289 int pmid = 0, blk, is_sim, lane, phy, found, logical_port; 290 int idx, ref_clk_prop; 291 uint32 txlane_map = 0x3210, rxlane_map = 0x3210; 292 uint32 tx_polarity, rx_polarity; 293 uint8_t pPort[] = {MAVERICK2_FIRST_MGMT_PHYSICAL_PORT_NUM, 0 /* unused */} ; 294 295 /* Allocate user access for all PMs */ 296 SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 297 SOC_MV2_PM4X10_COUNT, &pm4x10_mv2_user_acc[unit])); 298 299 300 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_MV2_PM4X10_COUNT); pmid++) { 301 302 rv = portmod_pm_create_info_t_init(unit, &pm_create_info); 303 if (PORTMOD_FAILURE(rv)) { 304 break; 305 } 306 307 pm_create_info.type = portmodDispatchTypePm4x10; 308 309 SOC_PBMP_PORT_ADD(pm_create_info.phys, pPort[0]); /* first mgmt port */ 310 SOC_PBMP_PORT_ADD(pm_create_info.phys, pPort[0]+1); 311 SOC_PBMP_PORT_ADD(pm_create_info.phys, pPort[0]+2); 312 SOC_PBMP_PORT_ADD(pm_create_info.phys, pPort[0]+3); 313 if (second_mgmt_port) { 314 SOC_PBMP_PORT_ADD(pm_create_info.phys, pPort[1]); /* second mgmt port */ 315 } 316 317 /* Identify the block for this particular port */ 318 found = 0; 319 320 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 321 blk = SOC_PORT_IDX_INFO(unit, pPort[0], idx).blk; 322 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){ 323 found = 1; 324 break; 325 } 326 } 327 328 if (!found) { 329 rv = SOC_E_INTERNAL; 330 break; 331 } 332 333 334 /* Init user_acc for phymod access struct */ 335 rv = portmod_default_user_access_t_init(unit, 336 &(pm4x10_mv2_user_acc[unit][pmid])); 337 if (PORTMOD_FAILURE(rv)) { 338 break; 339 } 340 341 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10_mv2_user_acc[unit][pmid]))); 342 pm4x10_mv2_user_acc[unit][pmid].unit = unit; 343 pm4x10_mv2_user_acc[unit][pmid].blk_id = blk; 344 pm4x10_mv2_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 345 346 if (pm4x10_mv2_user_acc[unit][pmid].mutex == NULL) { 347 rv = SOC_E_MEMORY; 348 break; 349 } 350 351 /* Specific info for PM4x10 */ 352 rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x10.access); 353 if (PORTMOD_FAILURE(rv)) { 354 break; 355 } 356 357 pm_create_info.pm_specific_info.pm4x10.access.user_acc = &(pm4x10_mv2_user_acc[unit][pmid]); 358 pm_create_info.pm_specific_info.pm4x10.access.addr = _mv2_pm4x10_addr[pmid]; 359 pm_create_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 360 pm_create_info.pm_specific_info.pm4x10.rescal = -1; 361 362 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 363 &(pm_create_info.pm_specific_info.pm4x10.access), 364 0, &is_sim); 365 366 if (PORTMOD_FAILURE(rv)) { 367 break; 368 } 369 370 if (is_sim) { 371 pm_create_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |= 372 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 373 374 /* Firmward loader : Don't allow FW load on sim enviroment */ 375 pm_create_info.pm_specific_info.pm4x10.fw_load_method = 376 phymodFirmwareLoadMethodNone; 377 } else { 378 pm_create_info.pm_specific_info.pm4x10.fw_load_method = 379 soc_property_suffix_num_get(unit, pmid, 380 spn_LOAD_FIRMWARE, "quad", 381 phymodFirmwareLoadMethodExternal); 382 pm_create_info.pm_specific_info.pm4x10.fw_load_method &= 0xff; 383 } 384 385 /* Use default external loader if NULL */ 386 pm_create_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 387 388 /* Polarity */ 389 rv = phymod_polarity_t_init (&(pm_create_info.pm_specific_info.pm4x10.polarity)); 390 if (PORTMOD_FAILURE(rv)) { 391 break; 392 } 393 394 for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) { 395 396 if ((lane == 1) || (lane == 3)) continue; 397 if ((lane == 2) && (!second_mgmt_port)) continue; 398 399 if (lane > 1) { 400 rv = SOC_E_INTERNAL; 401 break; 402 } 403 404 phy = pPort[lane]; 405 406 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 407 408 mv2_pm_port_polarity_get (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity); 409 410 pm_create_info.pm_specific_info.pm4x10.polarity.rx_polarity |= rx_polarity; 411 pm_create_info.pm_specific_info.pm4x10.polarity.tx_polarity |= tx_polarity; 412 } 413 414 if (PORTMOD_FAILURE(rv)) { 415 break; 416 } 417 418 /* Lane map */ 419 rv = phymod_lane_map_t_init 420 (&(pm_create_info.pm_specific_info.pm4x10.lane_map)); 421 if (PORTMOD_FAILURE(rv)) { 422 break; 423 } 424 425 logical_port = SOC_INFO(unit).port_p2l_mapping[pPort[0]]; 426 427 if (logical_port != -1) { 428 mv2_pm_port_lanemap_get (unit, logical_port, pPort[0], &txlane_map, &rxlane_map); 429 } 430 431 pm_create_info.pm_specific_info.pm4x10.lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 432 pm_create_info.pm_specific_info.pm4x10.core_num = pmid; 433 pm_create_info.pm_specific_info.pm4x10.core_num_int = 0; 434 435 for(lane=0 ; lane<SOC_PM4X10_NUM_LANES; lane++) { 436 /*if ((lane == 1) || (lane == 3)) continue; only 2 lanes connected 437 if ((lane == 2) && (!second_mgmt_port)) continue; lane 2 for mgmt only. **/ 438 439 pm_create_info.pm_specific_info.pm4x10.lane_map.lane_map_tx[lane] = 440 (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 441 SOC_PM4X10_LANE_MASK; 442 443 pm_create_info.pm_specific_info.pm4x10.lane_map.lane_map_rx[lane] = 444 (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 445 SOC_PM4X10_LANE_MASK; 446 } 447 448 ref_clk_prop = soc_property_port_get(unit, pPort[0], 449 spn_XGXS_LCPLL_XTAL_REFCLK, 156); 450 451 452 if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)) { 453 pm_create_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk156Mhz; 454 } else if (ref_clk_prop == 125) { 455 pm_create_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk125Mhz; 456 } else { 457 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_UP(unit, pPort[0], 458 "ERROR: %d MHz clk not valid. Use 156/125 MHz.\n"),ref_clk_prop)); 459 return SOC_E_PARAM ; 460 } 461 462 /* shim code for Mgmt port doesn't support single port mode 463 * As a WAR, set 4-lanes port as dual-port mode 464 */ 465 logical_port = SOC_INFO(unit).port_p2l_mapping[pPort[0]]; 466 if (SOC_INFO(unit).port_num_lanes[logical_port] == 4) { 467 pm_create_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoTwoDualModePorts; 468 } 469 470 /* Add PM to PortMod */ 471 rv = portmod_port_macro_add(unit, &pm_create_info); 472 } 473 474 if (PORTMOD_FAILURE(rv)) { 475 for (pmid=0; pmid < SOC_MV2_PM4X10_COUNT; pmid++) { 476 if (pm4x10_mv2_user_acc[unit][pmid].mutex) { 477 sal_mutex_destroy(pm4x10_mv2_user_acc[unit][pmid].mutex); 478 pm4x10_mv2_user_acc[unit][pmid].mutex = NULL; 479 } 480 } 481 } 482 483 return rv; 484 #else /* PORTMOD_PM4X10_SUPPORT */ 485 return SOC_E_UNAVAIL; 486 #endif /* PORTMOD_PM4X10_SUPPORT */ 487 } 488 489 /* 490 * Function: 491 * soc_mv2_portctrl_pm_portmod_init 492 * Purpose: 493 * Initialize PortMod and PortMacro for Trident2Plus 494 * Add port macros (PM) to the unit's PortMod Manager (PMM). 495 * Parameters: 496 * unit - (IN) Unit number. 497 * Returns: 498 * SOC_E_XXX 499 */ 500 int 501 soc_mv2_portctrl_pm_portmod_init(int unit) 502 { 503 int rv = SOC_E_NONE; 504 uint32 flags = 0, mgmt_port_count = 0; 505 506 /* 507 * If portmod was create - destroy and create again 508 * Better way would be to create once and leave it. 509 */ 510 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 511 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 512 } 513 514 PORTMOD_CREATE_F_PM_NULL_SET(flags); 515 516 SOC_IF_ERROR_RETURN 517 (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, SOC_MV2_MAX_PHYS, 518 sizeof(mv2_pm_types)/sizeof(portmod_pm_instances_t), mv2_pm_types)); 519 520 SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, mgmt_port_count); 521 522 rv = _soc_mv2_portctrl_pm4x25_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0); 523 if (rv) return (rv); 524 525 return(_soc_mv2_portctrl_pm4x10_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0)); 526 } 527 528 /* 529 * Function: 530 * soc_mv2_portctrl_pm_portmod_deinit 531 * Purpose: 532 * Deinitialize PortMod and PortMacro for Trident2Plus. 533 * Free pm user access data. 534 * Parameters: 535 * unit - (IN) Unit number. 536 * Returns: 537 * SOC_E_NONE 538 */ 539 int 540 soc_mv2_portctrl_pm_portmod_deinit(int unit) 541 { 542 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 543 return SOC_E_NONE; 544 } 545 546 /* Free PMs structures */ 547 #ifdef PORTMOD_PM4X25_SUPPORT 548 if (pm4x25_mv2_user_acc[unit] != NULL) { 549 sal_free(pm4x25_mv2_user_acc[unit]); 550 pm4x25_mv2_user_acc[unit] = NULL; 551 } 552 #endif /* PORTMOD_PM4X25_SUPPORT */ 553 554 #ifdef PORTMOD_PM4X10_SUPPORT 555 if (pm4x10_mv2_user_acc[unit] != NULL) { 556 sal_free(pm4x10_mv2_user_acc[unit]); 557 pm4x10_mv2_user_acc[unit] = NULL; 558 } 559 #endif /* PORTMOD_PM4X10_SUPPORT */ 560 561 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 562 563 return SOC_E_NONE; 564 } 565 566 int 567 soc_mv2_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config) 568 { 569 #ifdef PORTMOD_PM4X25_SUPPORT 570 int rv = SOC_E_NONE; 571 int pmid = 0, lane, phy, phy_port, logical_port; 572 int first_port = 0, core_num, core_count = 0, core_index, is_sim, type; 573 uint32 txlane_map, rxlane_map, i; 574 uint32 tx_polarity, rx_polarity; 575 portmod_port_init_config_t *port_config_info; 576 phymod_firmware_load_method_t fw_load_method; 577 phymod_polarity_t polarity; /**< Lanes Polarity */ 578 phymod_lane_map_t lane_map; 579 580 port_config_info = (portmod_port_init_config_t *)port_config; 581 582 phy = SOC_INFO(unit).port_l2p_mapping[port]; 583 584 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 585 core_num = (phy - 1) / SOC_PM4X25_NUM_LANES; 586 587 for (i=0; i<SOC_MV2_PM4X25_COUNT; i++) { 588 if (core_num == i) { 589 type = portmodDispatchTypePm4x25; 590 pmid = i; 591 first_port = 1 + (pmid << 2); 592 core_count = 1; 593 break; 594 } 595 } 596 /* When port dones't find PM4x25, find PM4x10 again. */ 597 if (i == SOC_MV2_PM4X25_COUNT) { 598 for (i=0; i<SOC_MV2_PM4X10_COUNT; i++) { 599 if (core_num == (31+i)) { 600 type = portmodDispatchTypePm4x10; 601 pmid = i; 602 core_count = 1; 603 first_port = 128 + pmid; 604 break; 605 } 606 } 607 } 608 609 for (core_index = 0; core_index < core_count; core_index++) { 610 fw_load_method = phymodFirmwareLoadMethodExternal; 611 612 soc_physim_enable_get(unit, &is_sim); 613 614 if (is_sim) { 615 /* Firmward loader : Don't allow FW load on sim enviroment */ 616 fw_load_method = phymodFirmwareLoadMethodNone; 617 } else { 618 fw_load_method = soc_property_suffix_num_get(unit, pmid, 619 spn_LOAD_FIRMWARE, "quad", 620 phymodFirmwareLoadMethodExternal); 621 fw_load_method &= 0xff; 622 } 623 624 rv = phymod_polarity_t_init(&polarity); 625 if (PORTMOD_FAILURE(rv)) { 626 break; 627 } 628 629 /* Polarity */ 630 for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) { 631 phy_port = first_port + lane + (core_index*4); 632 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 633 634 mv2_pm_port_polarity_get (unit, logical_port, phy_port, lane, &tx_polarity, &rx_polarity); 635 636 polarity.rx_polarity |= rx_polarity; 637 polarity.tx_polarity |= tx_polarity; 638 } 639 640 /* Lane map */ 641 rv = phymod_lane_map_t_init(&lane_map); 642 if (PORTMOD_FAILURE(rv)) { 643 break; 644 } 645 646 phy_port = first_port + (core_index*4); 647 logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 648 649 mv2_pm_port_lanemap_get (unit, logical_port, first_port, &txlane_map, &rxlane_map); 650 651 lane_map.num_of_lanes = (type == portmodDispatchTypePm4x25) ? 652 SOC_PM4X25_NUM_LANES : SOC_PM4X10_NUM_LANES; 653 654 for(lane = 0 ; lane < lane_map.num_of_lanes; lane++) { 655 lane_map.lane_map_tx[lane] = 656 (txlane_map >> (lane * lane_map.num_of_lanes)) & 657 SOC_PM4X25_LANE_MASK; 658 lane_map.lane_map_rx[lane] = 659 (rxlane_map >> (lane * lane_map.num_of_lanes)) & 660 SOC_PM4X25_LANE_MASK; 661 } 662 663 sal_memcpy(&port_config_info->fw_load_method[core_index], &fw_load_method, 664 sizeof(phymod_firmware_load_method_t)); 665 port_config_info->fw_load_method_overwrite = 1; 666 sal_memcpy(&port_config_info->polarity[core_index], &polarity, 667 sizeof(phymod_polarity_t)); 668 port_config_info->polarity_overwrite = 1; 669 sal_memcpy(&port_config_info->lane_map[core_index], &lane_map, 670 sizeof(phymod_lane_map_t)); 671 port_config_info->lane_map_overwrite = 1; 672 } 673 674 return rv; 675 #else /* PORTMOD_PM4X25_SUPPORT */ 676 return SOC_E_UNAVAIL; 677 #endif /* PORTMOD_PM4X25_SUPPORT */ 678 } 679 680 int 681 soc_mv2_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port) 682 { 683 int phy, core_index; 684 uint32 pmid; 685 686 phy = SOC_INFO(unit).port_l2p_mapping[port]; 687 688 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 689 core_index = (phy - 1) / SOC_PM4X25_NUM_LANES; 690 691 #ifdef PORTMOD_PM4X25_SUPPORT 692 /* When port dones't find PM4x10, find PM4x25 again. */ 693 for (pmid=0; pmid<SOC_MV2_PM4X25_COUNT; pmid++) { 694 if (core_index == pmid) { 695 return _mv2_pm4x25_addr[pmid]; 696 } 697 } 698 #endif /* PORTMOD_PM4X25_SUPPORT */ 699 700 #ifdef PORTMOD_PM4X10_SUPPORT 701 for (pmid=0; pmid<SOC_MV2_PM4X10_COUNT; pmid++) { 702 if (core_index == (31+pmid)) { 703 return _mv2_pm4x10_addr[pmid]; 704 } 705 } 706 #endif /* PORTMOD_PM4X10_SUPPORT */ 707 return -1; 708 } 709 710 #define _MV2_PHY_PORT_MNG0 129 711 int 712 soc_mv2_portctrl_pm_type_get(int unit, soc_port_t phy_port, int* pm_type) 713 { 714 *pm_type = -1; 715 716 if (phy_port >= 1 && phy_port <= 128) { 717 #ifdef PORTMOD_PM4X25_SUPPORT 718 *pm_type = portmodDispatchTypePm4x25; 719 return (SOC_E_NONE); 720 #endif 721 } else if (phy_port == _MV2_PHY_PORT_MNG0) { 722 #ifdef PORTMOD_PM4X10_SUPPORT 723 *pm_type = portmodDispatchTypePm4x10; 724 return (SOC_E_NONE); 725 #endif 726 } else { 727 return(SOC_E_PARAM); 728 } 729 730 return SOC_E_UNAVAIL; 731 } 732 733 STATIC int 734 _soc_mv2_portctrl_port_ability_update(int unit, soc_port_t port, soc_port_ability_t *ability) 735 { 736 uint32 max_lane_speed = 0; 737 738 if (!soc_feature(unit, soc_feature_untethered_otp)) { 739 return SOC_E_NONE; 740 } 741 742 SHR_BITCOPY_RANGE(&max_lane_speed, 0, SOC_BOND_INFO(unit)->tsc_max_speed, 743 SOC_INFO(unit).port_serdes[port] * 2, 2); 744 745 /* Each PM4x25 TSC has two bit. 746 * 00= no restrcition, 01= 27.9525G, 10=10.9375G, 11=reserved 747 */ 748 if (max_lane_speed == 2) { 749 ability->speed_full_duplex &= (SOC_PA_SPEED_1000MB | SOC_PA_SPEED_10GB | 750 SOC_PA_SPEED_11GB); 751 } 752 return SOC_E_NONE; 753 } 754 755 soc_portctrl_functions_t soc_mv2_portctrl_func = { 756 soc_mv2_portctrl_pm_portmod_init, 757 soc_mv2_portctrl_pm_portmod_deinit, 758 soc_mv2_portctrl_pm_port_config_get, 759 soc_mv2_portctrl_pm_port_phyaddr_get, 760 _soc_mv2_portctrl_port_ability_update, 761 soc_mv2_portctrl_pm_type_get, 762 NULL, 763 NULL 764 }; 765 766 #endif /* BCM_MAVERICK2_SUPPORT */