portctrl.c (35140B)
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/helix5.h> 19 #include <shared/bsl.h> 20 #include <soc/phy/phymod_sim.h> 21 #include <soc/portmod/portmod.h> 22 23 #ifdef BCM_HELIX5_SUPPORT 24 25 #define SOC_HX5_PM4X10_COUNT 4 26 #define SOC_HX5_PM4X10_QTC_COUNT 3 27 #define SOC_HX5_PM4X25_COUNT 3 28 29 static uint32_t _hx5_pm4x10_addr[SOC_HX5_PM4X10_COUNT] = { 30 0xA1, 0xA5, 0xA9, 0xAD 31 }; 32 33 static uint32_t _hx5_pm4x10_core_num[SOC_HX5_PM4X10_COUNT] = { 34 3, 4, 5, 6 35 }; 36 37 static uint32_t _hx5_pm4x10_port[SOC_HX5_PM4X10_COUNT] = { 38 49, 53, 57, 61 39 }; 40 41 static uint32_t _hx5_pm4x10q_addr[SOC_HX5_PM4X10_QTC_COUNT] = { 42 0x81, /* PM4x10Q Inst 0 */ 43 0x85, /* PM4x10Q Inst 1 */ 44 0x89 /* PM4x10Q Inst 2 */ 45 }; 46 47 static uint32_t _hx5_pm4x10q_core_num[SOC_HX5_PM4X10_QTC_COUNT] = { 48 0, 1, 2 49 }; 50 51 static uint32_t _hx5_pm4x10q_port[SOC_HX5_PM4X10_QTC_COUNT] = { 52 1, 17, 33 53 }; 54 55 static uint32_t _hx5_pm4x25_addr[SOC_HX5_PM4X25_COUNT] = { 56 0xC1, 0xC5, 0xC9 57 }; 58 59 static uint32_t _hx5_pm4x25_core_num[SOC_HX5_PM4X25_COUNT] = { 60 7, 8, 9 61 }; 62 63 static uint32_t _hx5_pm4x25_port[SOC_HX5_PM4X25_COUNT] = { 64 65, 69, 73 65 }; 66 67 68 #define SOC_HX5_MAX_PHYS 88 /* 48 GXPORTS + 28 XLPORTS + 12 CLPORTS */ 69 #define SOC_HX5_SUB_PHYS_IN_QSGMII 4 70 71 static portmod_pm_instances_t hx5_pm_types[] = { 72 #ifdef PORTMOD_PM4X10_SUPPORT 73 {portmodDispatchTypePm4x10, SOC_HX5_PM4X10_COUNT}, 74 #endif 75 #ifdef PORTMOD_PM4X25_SUPPORT 76 {portmodDispatchTypePm4x25, SOC_HX5_PM4X25_COUNT}, 77 #endif 78 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 79 {portmodDispatchTypePm4x10_qtc, SOC_HX5_PM4X10_QTC_COUNT}, 80 #endif 81 }; 82 83 #ifdef PORTMOD_PM4X10_SUPPORT 84 static portmod_default_user_access_t *pm4x10_hx5_user_acc[SOC_MAX_NUM_DEVICES]; 85 #endif /* PORTMOD_PM4X10_SUPPORT */ 86 87 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 88 static portmod_default_user_access_t *pm4x10q_hx5_user_acc[SOC_MAX_NUM_DEVICES]; 89 static portmod_default_user_access_t *pm4x10q_4x10_hx5_user_acc[SOC_MAX_NUM_DEVICES]; 90 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 91 92 #ifdef PORTMOD_PM4X25_SUPPORT 93 static portmod_default_user_access_t *pm4x25_hx5_user_acc[SOC_MAX_NUM_DEVICES]; 94 #endif /* PORTMOD_PM4X25_SUPPORT */ 95 96 #define SOC_HX5_CORE_FREQ_KHZ_DEFAULT 50000 /* HX5 default core freq is 50MHz*/ 97 98 extern int soc_hx5_portctrl_pm_portmod_init(int unit); 99 extern int soc_hx5_portctrl_pm_portmod_deinit(int unit); 100 extern int soc_hx5_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config_info); 101 extern int soc_hx5_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port); 102 extern int soc_hx5_portctrl_pm_type_get(int unit, soc_port_t phy_port, int* pm_type); 103 104 soc_portctrl_functions_t soc_hx5_portctrl_func = { 105 soc_hx5_portctrl_pm_portmod_init, 106 soc_hx5_portctrl_pm_portmod_deinit, 107 soc_hx5_portctrl_pm_port_config_get, 108 soc_hx5_portctrl_pm_port_phyaddr_get, 109 NULL /* soc_hx5_portctrl_port_ability_update*/, 110 soc_hx5_portctrl_pm_type_get, 111 NULL, 112 NULL 113 }; 114 115 STATIC int 116 _soc_hx5_portctrl_pm_init(int unit, int *max_phys, 117 portmod_pm_instances_t **pm_types, 118 int *pms_arr_len) 119 { 120 *max_phys = SOC_HX5_MAX_PHYS; 121 *pm_types = hx5_pm_types; 122 *pms_arr_len = (sizeof(hx5_pm_types) / sizeof(portmod_pm_instances_t)); 123 124 return SOC_E_NONE; 125 } 126 127 STATIC int 128 _soc_hx5_portctrl_device_addr_port_get(int unit, int pm_type, 129 uint32_t **addr, 130 uint32_t **port, 131 uint32_t **core_num) 132 { 133 *addr = NULL; 134 *port = NULL; 135 *core_num = NULL; 136 137 if (pm_type == portmodDispatchTypePm4x10) { 138 *addr = _hx5_pm4x10_addr; 139 *port = _hx5_pm4x10_port; 140 *core_num = _hx5_pm4x10_core_num; 141 } else if (pm_type == portmodDispatchTypePm4x25){ 142 *addr = _hx5_pm4x25_addr; 143 *port = _hx5_pm4x25_port; 144 *core_num = _hx5_pm4x25_core_num; 145 } else if (pm_type == portmodDispatchTypePm4x10_qtc){ 146 *addr = _hx5_pm4x10q_addr; 147 *port = _hx5_pm4x10q_port; 148 *core_num = _hx5_pm4x10q_core_num; 149 } 150 151 return SOC_E_NONE; 152 } 153 154 STATIC int 155 _soc_hx5_portctrl_pm_user_acc_flag_set(int unit, 156 portmod_default_user_access_t* pm_user_access) 157 { 158 return SOC_E_NONE; 159 } 160 161 /* 162 * Polarity get looks for physical port based config first. This will enable 163 * the user to define the polarity for all ports weather mapped to logical 164 * port or not. 165 */ 166 STATIC 167 void helix5_pm_port_polarity_get(int unit, int physical_port, int lane, 168 uint32 *tx_pol, uint32* rx_pol) 169 { 170 uint32 rx_polarity, tx_polarity; 171 172 rx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 173 spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0x0); 174 *rx_pol = (rx_polarity & 0x1) << lane; 175 176 tx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 177 spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0x0); 178 *tx_pol = (tx_polarity & 0x1) << lane; 179 } 180 181 /* 182 * lanemap get looks for physical port based config first. This will enable 183 * the user to define the lanemap for all ports weather mapped to logical 184 * port or not. 185 */ 186 STATIC 187 void helix5_pm_port_lanemap_get (int unit, int physical_port, 188 uint32 *txlane_map, uint32* rxlane_map) 189 { 190 191 *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 192 spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0x3210); 193 194 195 *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 196 spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0x3210); 197 198 } 199 200 201 STATIC int 202 _soc_hx5_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 203 { 204 #ifdef PORTMOD_PM4X10_SUPPORT 205 int rv = SOC_E_NONE; 206 portmod_pm_create_info_t pm_info; 207 int pmid = 0, blk, is_sim, found; 208 int first_port, idx, core_num, core_cnt; 209 uint32 *pAddr, *pPort, *pCoreNum; 210 211 212 SOC_IF_ERROR_RETURN 213 (_soc_hx5_portctrl_device_addr_port_get(unit, 214 portmodDispatchTypePm4x10, 215 &pAddr, &pPort, &pCoreNum)); 216 if (!pAddr || !pPort) { 217 return SOC_E_INTERNAL; 218 } 219 220 /* Allocate PMs */ 221 SOC_IF_ERROR_RETURN 222 (soc_esw_portctrl_pm_user_access_alloc(unit, 223 num_of_instances, 224 &pm4x10_hx5_user_acc[unit])); 225 226 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 227 228 rv = portmod_pm_create_info_t_init(unit, &pm_info); 229 if (PORTMOD_FAILURE(rv)) { 230 break; 231 } 232 /* PM info */ 233 first_port = pPort[pmid]; 234 235 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 236 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 237 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 238 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 239 240 found = 0; 241 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 242 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 243 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) { 244 found = 1; 245 break; 246 } 247 248 } 249 if (!found) { 250 rv = SOC_E_INTERNAL; 251 break; 252 } 253 254 pm_info.type = portmodDispatchTypePm4x10; 255 256 /* Init user_acc for phymod access struct */ 257 rv = portmod_default_user_access_t_init(unit, 258 &(pm4x10_hx5_user_acc[unit][pmid])); 259 if (PORTMOD_FAILURE(rv)) { 260 break; 261 } 262 263 SOC_IF_ERROR_RETURN( 264 _soc_hx5_portctrl_pm_user_acc_flag_set(unit, 265 &(pm4x10_hx5_user_acc[unit][pmid]))); 266 267 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10_hx5_user_acc[unit][pmid]))); 268 pm4x10_hx5_user_acc[unit][pmid].unit = unit; 269 pm4x10_hx5_user_acc[unit][pmid].blk_id = blk; 270 pm4x10_hx5_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 271 if (pm4x10_hx5_user_acc[unit][pmid].mutex == NULL) { 272 rv = SOC_E_MEMORY; 273 break; 274 } 275 276 /* Specific info for PM4x10 */ 277 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access); 278 if (PORTMOD_FAILURE(rv)) { 279 break; 280 } 281 282 pm_info.pm_specific_info.pm4x10.access.user_acc = 283 &(pm4x10_hx5_user_acc[unit][pmid]); 284 pm_info.pm_specific_info.pm4x10.access.addr = pAddr[pmid]; 285 pm_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 286 pm_info.pm_specific_info.pm4x10.lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 287 pm_info.pm_specific_info.pm4x10.rescal = -1; 288 289 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce16, 290 &(pm_info.pm_specific_info.pm4x10.access), 291 0, &is_sim); 292 if (PORTMOD_FAILURE(rv)) { 293 break; 294 } 295 296 if (is_sim) { 297 pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |= 298 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 299 300 /* Firmward loader : Don't allow FW load on sim enviroment */ 301 pm_info.pm_specific_info.pm4x10.fw_load_method = 302 phymodFirmwareLoadMethodNone; 303 } 304 305 /* Use default external loader if NULL */ 306 pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 307 308 core_cnt = 1; 309 310 for (core_num = 0; core_num < core_cnt; core_num++) { 311 pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid; 312 pm_info.pm_specific_info.pm4x10.core_num_int = 0; 313 } 314 315 /* Add PM to PortMod */ 316 rv = portmod_port_macro_add(unit, &pm_info); 317 } 318 319 if (PORTMOD_FAILURE(rv)) { 320 for (pmid=0; pmid < num_of_instances; pmid++) { 321 if (pm4x10_hx5_user_acc[unit][pmid].mutex) { 322 sal_mutex_destroy(pm4x10_hx5_user_acc[unit][pmid].mutex); 323 pm4x10_hx5_user_acc[unit][pmid].mutex = NULL; 324 } 325 } 326 } 327 328 return rv; 329 #else /* PORTMOD_PM4X10_SUPPORT */ 330 return SOC_E_UNAVAIL; 331 #endif /* PORTMOD_PM4X10_SUPPORT */ 332 } 333 334 STATIC int 335 _soc_hx5_portctrl_pm4x10_qtc_pm_qtc_init(int unit, int instance_id, portmod_pm_qtc_create_info_t *pm_qtc_info) 336 { 337 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 338 int rv = SOC_E_NONE; 339 int blk, is_sim, found; 340 int blktype; 341 uint32 *pAddr, *pPort, *pCoreNum; 342 343 SOC_IF_ERROR_RETURN 344 (_soc_hx5_portctrl_device_addr_port_get(unit, 345 portmodDispatchTypePm4x10_qtc, 346 &pAddr, &pPort, &pCoreNum)); 347 if (!pAddr || !pPort) { 348 return SOC_E_INTERNAL; 349 } 350 351 /* Pm_qtc information */ 352 found = 0; 353 for (blk = 0; SOC_BLOCK_INFO(unit, blk).type >= 0; blk++) { 354 blktype = SOC_BLOCK_INFO(unit, blk).type; 355 if ((blktype == SOC_BLK_PMQPORT) && (SOC_BLOCK_INFO(unit, blk).number == instance_id)) { 356 found = 1; 357 break; 358 } 359 } 360 361 if (!found) { 362 return SOC_E_INTERNAL; 363 } 364 365 /* Init user_acc for phymod access struct */ 366 rv = portmod_default_user_access_t_init(unit, 367 &(pm4x10q_hx5_user_acc[unit][instance_id])); 368 if (PORTMOD_FAILURE(rv)) { 369 return rv; 370 } 371 372 /* for Qmode. */ 373 pm4x10q_hx5_user_acc[unit][instance_id].unit = unit; 374 pm4x10q_hx5_user_acc[unit][instance_id].blk_id = blk; 375 pm4x10q_hx5_user_acc[unit][instance_id].mutex = sal_mutex_create("core mutex"); 376 if (pm4x10q_hx5_user_acc[unit][instance_id].mutex == NULL) { 377 return SOC_E_MEMORY; 378 } 379 380 /* Specific info for PM_QTC */ 381 rv = phymod_access_t_init(&pm_qtc_info->access); 382 if (PORTMOD_FAILURE(rv)) { 383 return rv; 384 } 385 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10q_hx5_user_acc[unit][instance_id]))); 386 pm_qtc_info->access.user_acc = &pm4x10q_hx5_user_acc[unit][instance_id]; 387 pm_qtc_info->access.addr = pAddr[instance_id]; 388 pm_qtc_info->access.bus = NULL; 389 pm_qtc_info->lane_map.num_of_lanes = SOC_PM4X10_QTC_NUM_LANES; 390 pm_qtc_info->core_num = pCoreNum[instance_id]; 391 pm_qtc_info->core_clock_khz = SOC_HX5_CORE_FREQ_KHZ_DEFAULT; 392 393 rv = soc_physim_check_sim(unit, phymodDispatchTypeQtce16, 394 &(pm_qtc_info->access), 395 0, &is_sim); 396 if (PORTMOD_FAILURE(rv)) { 397 return rv; 398 } 399 400 if (is_sim) { 401 pm_qtc_info->access.bus->bus_capabilities |= 402 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 403 404 /* Firmward loader : Don't allow FW load on sim enviroment */ 405 pm_qtc_info->fw_load_method = phymodFirmwareLoadMethodNone; 406 } 407 408 /* Use default external loader */ 409 pm_qtc_info->external_fw_loader = NULL; 410 411 return rv; 412 #else /* PORTMOD_PM4X10_QTC_SUPPORT */ 413 return SOC_E_UNAVAIL; 414 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 415 } 416 417 STATIC int 418 _soc_hx5_portctrl_pm4x10_qtc_pm4x10_init(int unit, int instance_id, portmod_pm4x10_create_info_t *pm4x10_info) 419 { 420 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 421 int rv = SOC_E_NONE; 422 int blk, is_sim, found; 423 int first_port, idx; 424 uint32 *pAddr, *pPort, *pCoreNum; 425 426 SOC_IF_ERROR_RETURN 427 (_soc_hx5_portctrl_device_addr_port_get(unit, 428 portmodDispatchTypePm4x10_qtc, 429 &pAddr, &pPort, &pCoreNum)); 430 if (!pAddr || !pPort) { 431 return SOC_E_INTERNAL; 432 } 433 434 first_port = pPort[instance_id]; 435 436 /* Pm4x10 information */ 437 found = 0; 438 for (idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++) { 439 blk = SOC_PORT_IDX_INFO(unit, first_port , idx).blk; 440 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) { 441 found = 1; 442 break; 443 } 444 } 445 446 if (!found) { 447 return SOC_E_INTERNAL; 448 } 449 450 /* Init user_acc for phymod access struct */ 451 rv = portmod_default_user_access_t_init(unit, 452 &(pm4x10q_4x10_hx5_user_acc[unit][instance_id])); 453 if (PORTMOD_FAILURE(rv)) { 454 return rv; 455 } 456 pm4x10q_4x10_hx5_user_acc[unit][instance_id].unit = unit; 457 pm4x10q_4x10_hx5_user_acc[unit][instance_id].blk_id = blk; 458 pm4x10q_4x10_hx5_user_acc[unit][instance_id].mutex = sal_mutex_create("core mutex"); 459 if (pm4x10q_4x10_hx5_user_acc[unit][instance_id].mutex == NULL) { 460 return SOC_E_MEMORY; 461 } 462 463 /* Specific info for PM4x10 */ 464 rv = phymod_access_t_init(&pm4x10_info->access); 465 if (PORTMOD_FAILURE(rv)) { 466 return rv; 467 } 468 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10q_4x10_hx5_user_acc[unit][instance_id]))); 469 pm4x10_info->access.user_acc = &pm4x10q_4x10_hx5_user_acc[unit][instance_id]; 470 pm4x10_info->access.addr = pAddr[instance_id]; 471 pm4x10_info->access.bus = NULL; 472 pm4x10_info->lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 473 pm4x10_info->core_num = pCoreNum[instance_id]; 474 pm4x10_info->core_num_int = 0; 475 pm4x10_info->rescal = -1; 476 477 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce16, 478 &(pm4x10_info->access), 479 2, &is_sim); 480 if (PORTMOD_FAILURE(rv)) { 481 return rv; 482 } 483 484 if (is_sim) { 485 pm4x10_info->access.bus->bus_capabilities |= 486 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 487 488 /* Firmward loader : Don't allow FW load on sim enviroment */ 489 pm4x10_info->fw_load_method = 490 phymodFirmwareLoadMethodNone; 491 } 492 return rv; 493 #else /* PORTMOD_PM4X10_QTC_SUPPORT */ 494 return SOC_E_UNAVAIL; 495 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 496 } 497 498 STATIC int 499 _soc_hx5_portctrl_pm4x10_qtc_portmod_init(int unit, int num_of_instances) 500 { 501 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 502 int rv = SOC_E_NONE; 503 portmod_pm_create_info_t pm4x10_qtc_info; 504 int instance_id = 0; 505 int first_port; 506 uint32 *pAddr, *pPort, *pCoreNum; 507 508 SOC_IF_ERROR_RETURN 509 (_soc_hx5_portctrl_device_addr_port_get(unit, 510 portmodDispatchTypePm4x10_qtc, 511 &pAddr, &pPort, &pCoreNum)); 512 if (!pAddr || !pPort) { 513 return SOC_E_INTERNAL; 514 } 515 516 /* Allocate PMs */ 517 SOC_IF_ERROR_RETURN 518 (soc_esw_portctrl_pm_user_access_alloc(unit, num_of_instances, 519 &pm4x10q_hx5_user_acc[unit])); 520 /* Allocate PMs */ 521 SOC_IF_ERROR_RETURN 522 (soc_esw_portctrl_pm_user_access_alloc(unit, num_of_instances, 523 &pm4x10q_4x10_hx5_user_acc[unit])); 524 525 for (instance_id = 0; PORTMOD_SUCCESS(rv) && (instance_id < num_of_instances); instance_id++) { 526 /* Pm4x10_qtc information*/ 527 rv = portmod_pm_create_info_t_init(unit, &pm4x10_qtc_info); 528 if (PORTMOD_FAILURE(rv)) { 529 break; 530 } 531 /* PM info */ 532 first_port = pPort[instance_id]; 533 534 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port); 535 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+1); 536 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+2); 537 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+3); 538 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+4); 539 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+5); 540 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+6); 541 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+7); 542 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+8); 543 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+9); 544 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+10); 545 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+11); 546 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+12); 547 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+13); 548 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+14); 549 PORTMOD_PBMP_PORT_ADD(pm4x10_qtc_info.phys, first_port+15); 550 551 pm4x10_qtc_info.type = portmodDispatchTypePm4x10_qtc; 552 553 /*pm_qtc infomration*/ 554 rv = _soc_hx5_portctrl_pm4x10_qtc_pm_qtc_init(unit, instance_id, 555 &pm4x10_qtc_info.pm_specific_info.pm4x10_qtc.pm_qtc_info); 556 if (PORTMOD_FAILURE(rv)) { 557 break; 558 } 559 560 /*pm4x10 infomration*/ 561 rv = _soc_hx5_portctrl_pm4x10_qtc_pm4x10_init(unit, instance_id, 562 &pm4x10_qtc_info.pm_specific_info.pm4x10_qtc.pm4x10_info); 563 if (PORTMOD_FAILURE(rv)) { 564 break; 565 } 566 567 /* Add PM_QTC to PortMod */ 568 rv = portmod_port_macro_add(unit, &pm4x10_qtc_info); 569 } 570 571 if (PORTMOD_FAILURE(rv)) { 572 for (instance_id=0; instance_id < num_of_instances; instance_id++) { 573 if (pm4x10q_hx5_user_acc[unit][instance_id].mutex) { 574 sal_mutex_destroy(pm4x10q_hx5_user_acc[unit][instance_id].mutex); 575 pm4x10q_hx5_user_acc[unit][instance_id].mutex = NULL; 576 } 577 578 if (pm4x10q_4x10_hx5_user_acc[unit][instance_id].mutex) { 579 sal_mutex_destroy(pm4x10q_4x10_hx5_user_acc[unit][instance_id].mutex); 580 pm4x10q_4x10_hx5_user_acc[unit][instance_id].mutex = NULL; 581 } 582 } 583 } 584 585 return rv; 586 #else /* PORTMOD_PM4X10_QTC_SUPPORT */ 587 return SOC_E_UNAVAIL; 588 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 589 } 590 591 STATIC int 592 _soc_hx5_portctrl_pm4x25_portmod_init(int unit, int num_of_instances) 593 { 594 #ifdef PORTMOD_PM4X25_SUPPORT 595 int rv = SOC_E_NONE; 596 portmod_pm_create_info_t pm_info; 597 int pmid = 0, blk, is_sim, found; 598 int first_port, idx, core_num, core_cnt; 599 uint32 *pAddr, *pPort,*pCoreNum; 600 601 SOC_IF_ERROR_RETURN 602 (_soc_hx5_portctrl_device_addr_port_get(unit, 603 portmodDispatchTypePm4x25, 604 &pAddr, &pPort,&pCoreNum)); 605 if (!pAddr || !pPort) { 606 return SOC_E_INTERNAL; 607 } 608 609 /* Allocate PMs */ 610 SOC_IF_ERROR_RETURN 611 (soc_esw_portctrl_pm_user_access_alloc(unit, 612 num_of_instances, 613 &pm4x25_hx5_user_acc[unit])); 614 615 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 616 617 rv = portmod_pm_create_info_t_init(unit, &pm_info); 618 if (PORTMOD_FAILURE(rv)) { 619 break; 620 } 621 /* PM info */ 622 first_port = pPort[pmid]; 623 624 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 625 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 626 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 627 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 628 629 found = 0; 630 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 631 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 632 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CLPORT) { 633 found = 1; 634 break; 635 } 636 } 637 if (!found) { 638 rv = SOC_E_INTERNAL; 639 break; 640 } 641 642 pm_info.type = portmodDispatchTypePm4x25; 643 644 /* Init user_acc for phymod access struct */ 645 rv = portmod_default_user_access_t_init(unit, 646 &(pm4x25_hx5_user_acc[unit][pmid])); 647 if (PORTMOD_FAILURE(rv)) { 648 break; 649 } 650 651 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_hx5_user_acc[unit][pmid]))); 652 pm4x25_hx5_user_acc[unit][pmid].unit = unit; 653 pm4x25_hx5_user_acc[unit][pmid].blk_id = blk; 654 pm4x25_hx5_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 655 if (pm4x25_hx5_user_acc[unit][pmid].mutex == NULL) { 656 rv = SOC_E_MEMORY; 657 break; 658 } 659 660 /* Specific info for PM4x25 */ 661 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x25.access); 662 if (PORTMOD_FAILURE(rv)) { 663 break; 664 } 665 666 pm_info.pm_specific_info.pm4x25.access.user_acc = 667 &(pm4x25_hx5_user_acc[unit][pmid]); 668 pm_info.pm_specific_info.pm4x25.access.addr = pAddr[pmid]; 669 pm_info.pm_specific_info.pm4x25.access.bus = NULL; /* Use default bus */ 670 pm_info.pm_specific_info.pm4x25.lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 671 pm_info.pm_specific_info.pm4x25.rescal = -1; 672 673 674 rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf16, 675 &(pm_info.pm_specific_info.pm4x25.access), 676 0, &is_sim); 677 678 if (PORTMOD_FAILURE(rv)) { 679 break; 680 } 681 682 if (is_sim) { 683 pm_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 684 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 685 686 /* Firmward loader : Don't allow FW load on sim enviroment */ 687 pm_info.pm_specific_info.pm4x25.fw_load_method = 688 phymodFirmwareLoadMethodNone; 689 } 690 691 /* Use default external loader if NULL */ 692 pm_info.pm_specific_info.pm4x25.external_fw_loader = NULL; 693 694 core_cnt = 1; 695 696 for (core_num = 0; core_num < core_cnt; core_num++) { 697 pm_info.pm_specific_info.pm4x25.core_num = pCoreNum? pCoreNum[pmid] : pmid; 698 pm_info.pm_specific_info.pm4x25.core_num_int = 0; 699 } 700 701 /* Add PM to PortMod */ 702 rv = portmod_port_macro_add(unit, &pm_info); 703 } 704 705 if (PORTMOD_FAILURE(rv)) { 706 for (pmid=0; pmid < num_of_instances; pmid++) { 707 if (pm4x25_hx5_user_acc[unit][pmid].mutex) { 708 sal_mutex_destroy(pm4x25_hx5_user_acc[unit][pmid].mutex); 709 pm4x25_hx5_user_acc[unit][pmid].mutex = NULL; 710 } 711 } 712 } 713 714 return rv; 715 #else /* PORTMOD_PM4X25_SUPPORT */ 716 return SOC_E_UNAVAIL; 717 #endif /* PORTMOD_PM4X25_SUPPORT */ 718 } 719 720 721 /* 722 * Function: 723 * soc_hx5_portctrl_pm_portmod_init 724 * Purpose: 725 * Initialize PortMod and PortMacro for Trident2Plus 726 * Add port macros (PM) to the unit's PortMod Manager (PMM). 727 * Parameters: 728 * unit - (IN) Unit number. 729 * Returns: 730 * SOC_E_XXX 731 */ 732 int 733 soc_hx5_portctrl_pm_portmod_init(int unit) 734 { 735 uint32 flags = 0; 736 int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0; 737 portmod_pm_instances_t *pm_types = NULL; 738 739 /* Call PortMod library initialization */ 740 SOC_IF_ERROR_RETURN( 741 _soc_hx5_portctrl_pm_init(unit, &max_phys, 742 &pm_types, &pms_arr_len)); 743 if (pms_arr_len == 0) { 744 return SOC_E_UNAVAIL; 745 } 746 747 /* 748 * If portmod was create - destroy and create again 749 * Better way would be to create once and leave it. 750 */ 751 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 752 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 753 } 754 755 PORTMOD_CREATE_F_PM_NULL_SET(flags); 756 757 SOC_IF_ERROR_RETURN 758 (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, max_phys, 759 pms_arr_len, pm_types)); 760 761 for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) { 762 #ifdef PORTMOD_PM4X10_SUPPORT 763 if (pm_types[count].type == portmodDispatchTypePm4x10) { 764 rv = _soc_hx5_portctrl_pm4x10_portmod_init 765 (unit, pm_types[count].instances); 766 } else 767 #endif /* PORTMOD_PM4X10_SUPPORT */ 768 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 769 if (pm_types[count].type == portmodDispatchTypePm4x10_qtc) { 770 rv = _soc_hx5_portctrl_pm4x10_qtc_portmod_init 771 (unit, pm_types[count].instances); 772 } else 773 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 774 #ifdef PORTMOD_PM4X25_SUPPORT 775 if (pm_types[count].type == portmodDispatchTypePm4x25) { 776 rv = _soc_hx5_portctrl_pm4x25_portmod_init 777 (unit, pm_types[count].instances); 778 } else 779 #endif /* PORTMOD_PM4X25_SUPPORT */ 780 { 781 rv = SOC_E_INTERNAL; 782 } 783 } 784 785 return rv; 786 } 787 788 /* 789 * Function: 790 * soc_hx5_portctrl_pm_portmod_deinit 791 * Purpose: 792 * Deinitialize PortMod and PortMacro for Trident2Plus. 793 * Free pm user access data. 794 * Parameters: 795 * unit - (IN) Unit number. 796 * Returns: 797 * SOC_E_NONE 798 */ 799 int 800 soc_hx5_portctrl_pm_portmod_deinit(int unit) 801 { 802 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 803 return SOC_E_NONE; 804 } 805 806 /* Free PMs structures */ 807 #ifdef PORTMOD_PM4X10_SUPPORT 808 if (pm4x10_hx5_user_acc[unit] != NULL) { 809 sal_free(pm4x10_hx5_user_acc[unit]); 810 pm4x10_hx5_user_acc[unit] = NULL; 811 } 812 #endif /* PORTMOD_PM4X10_SUPPORT */ 813 814 /* Free PMs structures */ 815 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 816 if (pm4x10q_hx5_user_acc[unit] != NULL) { 817 sal_free(pm4x10q_hx5_user_acc[unit]); 818 pm4x10q_hx5_user_acc[unit] = NULL; 819 } 820 #endif /* PORTMOD_PM4X10_SUPPORT */ 821 822 #ifdef PORTMOD_PM4X25_SUPPORT 823 if (pm4x25_hx5_user_acc[unit] != NULL) { 824 sal_free(pm4x25_hx5_user_acc[unit]); 825 pm4x25_hx5_user_acc[unit] = NULL; 826 } 827 #endif /* PORTMOD_PM4X25_SUPPORT */ 828 829 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 830 831 return SOC_E_NONE; 832 } 833 834 int 835 soc_hx5_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config) 836 { 837 #ifdef PORTMOD_PM4X10_SUPPORT 838 int pmid = 0, lane, phy_port; 839 int first_port, core_index, is_sim, type; 840 uint32 txlane_map, rxlane_map, i; 841 uint32 *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL; 842 uint32 tx_polarity, rx_polarity; 843 portmod_port_init_config_t *port_config_info; 844 phymod_firmware_load_method_t fw_load_method; 845 phymod_polarity_t polarity; /**< Lanes Polarity */ 846 phymod_lane_map_t lane_map; 847 uint8_t pm_found=0; 848 int max_index; 849 850 port_config_info = (portmod_port_init_config_t *)port_config; 851 852 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 853 pm_found = 0; 854 core_index = SOC_INFO(unit).port_serdes[port]; 855 856 for (i=0; i<SOC_HX5_PM4X10_QTC_COUNT; i++) { 857 if (core_index == _hx5_pm4x10q_core_num[i]) { 858 type = portmodDispatchTypePm4x10_qtc; 859 SOC_IF_ERROR_RETURN 860 (_soc_hx5_portctrl_device_addr_port_get(unit, type, 861 &pAddr, &pPort, &pCoreNum)); 862 pmid = i; 863 pm_found = 1; 864 break; 865 } 866 } 867 868 if (!pm_found) { 869 /* When port dones't find PM4x10Q, find PM4x10 again. */ 870 for (i=0; i<SOC_HX5_PM4X10_COUNT; i++) { 871 if (core_index == _hx5_pm4x10_core_num[i]) { 872 type = portmodDispatchTypePm4x10; 873 SOC_IF_ERROR_RETURN 874 (_soc_hx5_portctrl_device_addr_port_get(unit, type, 875 &pAddr, &pPort, &pCoreNum)); 876 pmid = i; 877 pm_found = 1; 878 break; 879 } 880 } 881 } 882 883 /* When port dones't find PM4x10, find PM4x25 again. */ 884 if (!pm_found) { 885 for (i=0; i<SOC_HX5_PM4X25_COUNT; i++) { 886 if (core_index == _hx5_pm4x25_core_num[i]) { 887 type = portmodDispatchTypePm4x25; 888 SOC_IF_ERROR_RETURN 889 (_soc_hx5_portctrl_device_addr_port_get(unit, type, 890 &pAddr, &pPort, &pCoreNum)); 891 pmid = i; 892 pm_found = 1; 893 break; 894 } 895 } 896 } 897 898 if (!pAddr || !pPort) { 899 return SOC_E_INTERNAL; 900 } 901 902 /* PM info */ 903 first_port = pPort[pmid]; 904 905 fw_load_method = phymodFirmwareLoadMethodExternal; 906 907 soc_physim_enable_get(unit, &is_sim); 908 909 if (is_sim) { 910 /* Firmward loader : Don't allow FW load on sim enviroment */ 911 fw_load_method = phymodFirmwareLoadMethodNone; 912 } else { 913 fw_load_method = soc_property_suffix_num_get(unit, pmid, 914 spn_LOAD_FIRMWARE, "quad", 915 phymodFirmwareLoadMethodInternal); 916 fw_load_method &= 0xff; 917 } 918 919 PORTMOD_IF_ERROR_RETURN(phymod_polarity_t_init(&polarity)); 920 921 max_index = IS_QSGMII_PORT(unit, port) ? SOC_PM_QTC_NUM_LANES : SOC_PM4X10_NUM_LANES; 922 923 /* Polarity */ 924 for (lane = 0; lane < max_index; lane++) { 925 phy_port = first_port + lane; 926 927 helix5_pm_port_polarity_get(unit, phy_port, lane, &tx_polarity, &rx_polarity); 928 929 polarity.rx_polarity |= rx_polarity; 930 polarity.tx_polarity |= tx_polarity; 931 } 932 933 /* Lane map */ 934 PORTMOD_IF_ERROR_RETURN(phymod_lane_map_t_init(&lane_map)); 935 936 phy_port = first_port; 937 938 helix5_pm_port_lanemap_get(unit, phy_port, &txlane_map, &rxlane_map); 939 940 polarity.rx_polarity |= rx_polarity; 941 polarity.tx_polarity |= tx_polarity; 942 943 lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES; 944 945 for(lane = 0 ; lane < SOC_PM4X10_NUM_LANES; lane++) { 946 lane_map.lane_map_tx[lane] = (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 947 SOC_PM4X10_LANE_MASK; 948 lane_map.lane_map_rx[lane] = (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 949 SOC_PM4X10_LANE_MASK; 950 } 951 sal_memcpy(&port_config_info->fw_load_method[0], &fw_load_method, 952 sizeof(phymod_firmware_load_method_t)); 953 port_config_info->fw_load_method_overwrite = 1; 954 sal_memcpy(&port_config_info->polarity[0], &polarity, 955 sizeof(phymod_polarity_t)); 956 port_config_info->polarity_overwrite = 1; 957 sal_memcpy(&port_config_info->lane_map[0], &lane_map, 958 sizeof(phymod_lane_map_t)); 959 port_config_info->lane_map_overwrite = 1; 960 961 return SOC_E_NONE; 962 #else /* PORTMOD_PM4X10_SUPPORT */ 963 return SOC_E_UNAVAIL; 964 #endif /* PORTMOD_PM4X10_SUPPORT */ 965 } 966 967 int 968 soc_hx5_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port) 969 { 970 int core_index; 971 uint32 i, *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL; 972 973 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 974 core_index = SOC_INFO(unit).port_serdes[port]; 975 976 #ifdef PORTMOD_PM4X10_SUPPORT 977 for (i=0; i<SOC_HX5_PM4X10_COUNT; i++) { 978 if (core_index == _hx5_pm4x10_core_num[i]) { 979 SOC_IF_ERROR_RETURN 980 (_soc_hx5_portctrl_device_addr_port_get(unit, 981 portmodDispatchTypePm4x10, 982 &pAddr, &pPort, &pCoreNum)); 983 return pAddr[i]; 984 } 985 } 986 #endif /* PORTMOD_PM4X10_SUPPORT */ 987 988 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 989 for (i=0; i<SOC_HX5_PM4X10_QTC_COUNT; i++) { 990 if (core_index == _hx5_pm4x10q_core_num[i]) { 991 SOC_IF_ERROR_RETURN 992 (_soc_hx5_portctrl_device_addr_port_get(unit, 993 portmodDispatchTypePm4x10_qtc, 994 &pAddr, &pPort, &pCoreNum)); 995 return pAddr[i]; 996 } 997 } 998 #endif /* PORTMOD_PM4X10_SUPPORT */ 999 1000 #ifdef PORTMOD_PM4X25_SUPPORT 1001 /* When port dones't find PM4x10, find PM4x25 again. */ 1002 for (i=0; i<SOC_HX5_PM4X25_COUNT; i++) { 1003 if (core_index == _hx5_pm4x25_core_num[i]) { 1004 SOC_IF_ERROR_RETURN 1005 (_soc_hx5_portctrl_device_addr_port_get(unit, 1006 portmodDispatchTypePm4x25, 1007 &pAddr, &pPort, &pCoreNum)); 1008 return pAddr[i]; 1009 } 1010 } 1011 #endif /* PORTMOD_PM4X25_SUPPORT */ 1012 1013 return -1; 1014 } 1015 1016 #define PORT_IS_FALCON(unit, phy_port) \ 1017 ((phy_port >= 65) && (phy_port <= 76)) ? 1 : 0 1018 1019 #define PORT_IS_PM4X10(unit, phy_port) \ 1020 ((phy_port >= 49) && (phy_port <= 64)) ? 1 : 0 1021 1022 #define PORT_IS_PM4X10_QTC(unit, phy_port) \ 1023 ((phy_port >= 1) && (phy_port <= 48)) ? 1 : 0 1024 1025 int 1026 soc_hx5_portctrl_pm_type_get(int unit, soc_port_t phy_port, 1027 int* pm_type) 1028 { 1029 if ((phy_port < 0) || (phy_port > 76)) { 1030 return SOC_E_PARAM; 1031 } 1032 1033 if (PORT_IS_FALCON(unit, phy_port)) { 1034 *pm_type = portmodDispatchTypePm4x25; 1035 } else if (PORT_IS_PM4X10(unit, phy_port)) { 1036 *pm_type = portmodDispatchTypePm4x10; 1037 } else if (PORT_IS_PM4X10_QTC(unit, phy_port)) { 1038 *pm_type = portmodDispatchTypePm4x10_qtc; 1039 } else { 1040 *pm_type = -1; 1041 } 1042 1043 return ((*pm_type == -1) ? SOC_E_UNAVAIL : SOC_E_NONE); 1044 } 1045 1046 #endif /* BCM_HELIX5_SUPPORT */