portctrl.c (27701B)
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 <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 14 #include <soc/debug.h> 15 #include <soc/util.h> 16 #include <soc/mem.h> 17 #include <soc/esw/portctrl.h> 18 #include <soc/esw/portctrl_internal.h> 19 #include <soc/tomahawk.h> 20 #include <soc/phy/phymod_sim.h> 21 #include <soc/portmod/portmod.h> 22 23 #ifdef BCM_TOMAHAWK_SUPPORT 24 #define SOC_TH_PM4X10_COUNT 1 25 #define SOC_TH_PM4X25_COUNT 32 26 27 #define SOC_TH_PM4X10_PORT_1 129 /* xe0 = 66, xe1 = 100 */ 28 29 static uint32_t _th_pm4x10_addr[SOC_TH_PM4X10_COUNT] = { 0x1C1 }; 30 static uint32_t _th_pm4x10_port[SOC_TH_PM4X10_COUNT] = { SOC_TH_PM4X10_PORT_1}; 31 32 #define SOC_TH_PM4X25_PORT_1 1 33 #define SOC_TH_PM4X25_PORT_2 5 34 #define SOC_TH_PM4X25_PORT_3 9 35 #define SOC_TH_PM4X25_PORT_4 13 36 #define SOC_TH_PM4X25_PORT_5 17 37 #define SOC_TH_PM4X25_PORT_6 21 38 #define SOC_TH_PM4X25_PORT_7 25 39 #define SOC_TH_PM4X25_PORT_8 29 40 #define SOC_TH_PM4X25_PORT_9 33 41 #define SOC_TH_PM4X25_PORT_10 37 42 #define SOC_TH_PM4X25_PORT_11 41 43 #define SOC_TH_PM4X25_PORT_12 45 44 #define SOC_TH_PM4X25_PORT_13 49 45 #define SOC_TH_PM4X25_PORT_14 53 46 #define SOC_TH_PM4X25_PORT_15 57 47 #define SOC_TH_PM4X25_PORT_16 61 48 #define SOC_TH_PM4X25_PORT_17 65 49 #define SOC_TH_PM4X25_PORT_18 69 50 #define SOC_TH_PM4X25_PORT_19 73 51 #define SOC_TH_PM4X25_PORT_20 77 52 #define SOC_TH_PM4X25_PORT_21 81 53 #define SOC_TH_PM4X25_PORT_22 85 54 #define SOC_TH_PM4X25_PORT_23 89 55 #define SOC_TH_PM4X25_PORT_24 93 56 #define SOC_TH_PM4X25_PORT_25 97 57 #define SOC_TH_PM4X25_PORT_26 101 58 #define SOC_TH_PM4X25_PORT_27 105 59 #define SOC_TH_PM4X25_PORT_28 109 60 #define SOC_TH_PM4X25_PORT_29 113 61 #define SOC_TH_PM4X25_PORT_30 117 62 #define SOC_TH_PM4X25_PORT_31 121 63 #define SOC_TH_PM4X25_PORT_32 125 64 65 static uint32_t _th_pm4x25_addr[SOC_TH_PM4X25_COUNT] = { 66 0x81, 0x85, 0x89, 0x8D, 67 0x91, 0x95, 0xA1, 0xA5, 68 0xA9, 0xAD, 0xc1, 0xC5, 69 0xC9, 0xCD, 0xD1, 0xD5, 70 0xE1, 0xE5, 0xE9, 0xED, 71 0xF1, 0xF5, 0x181, 0x185, 72 0x189, 0x18D, 0x1A1, 0x1A5, 73 0x1A9, 0x1AD, 0x1B1, 0x1B5 74 }; 75 76 static uint32_t _th_pm4x25_core_num[SOC_TH_PM4X25_COUNT] = { 77 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; 78 79 static uint32_t _th_pm4x10_core_num[SOC_TH_PM4X10_COUNT] = {32}; 80 81 static uint32_t _th_pm4x25_port[SOC_TH_PM4X25_COUNT] = { 82 SOC_TH_PM4X25_PORT_1, SOC_TH_PM4X25_PORT_2, 83 SOC_TH_PM4X25_PORT_3, SOC_TH_PM4X25_PORT_4, 84 SOC_TH_PM4X25_PORT_5, SOC_TH_PM4X25_PORT_6, 85 SOC_TH_PM4X25_PORT_7, SOC_TH_PM4X25_PORT_8, 86 SOC_TH_PM4X25_PORT_9, SOC_TH_PM4X25_PORT_10, 87 SOC_TH_PM4X25_PORT_11, SOC_TH_PM4X25_PORT_12, 88 SOC_TH_PM4X25_PORT_13, SOC_TH_PM4X25_PORT_14, 89 SOC_TH_PM4X25_PORT_15, SOC_TH_PM4X25_PORT_16, 90 SOC_TH_PM4X25_PORT_17, SOC_TH_PM4X25_PORT_18, 91 SOC_TH_PM4X25_PORT_19, SOC_TH_PM4X25_PORT_20, 92 SOC_TH_PM4X25_PORT_21, SOC_TH_PM4X25_PORT_22, 93 SOC_TH_PM4X25_PORT_23, SOC_TH_PM4X25_PORT_24, 94 SOC_TH_PM4X25_PORT_25, SOC_TH_PM4X25_PORT_26, 95 SOC_TH_PM4X25_PORT_27, SOC_TH_PM4X25_PORT_28, 96 SOC_TH_PM4X25_PORT_29, SOC_TH_PM4X25_PORT_30, 97 SOC_TH_PM4X25_PORT_31, SOC_TH_PM4X25_PORT_32 98 }; 99 100 portmod_pm_instances_t th_pm_types[] = { 101 #ifdef PORTMOD_PM4X10_SUPPORT 102 {portmodDispatchTypePm4x10, SOC_TH_PM4X10_COUNT}, 103 #endif 104 #ifdef PORTMOD_PM4X25_SUPPORT 105 {portmodDispatchTypePm4x25, SOC_TH_PM4X25_COUNT}, 106 #endif 107 }; 108 109 #define SOC_TH_MAX_PHYS 164 /* ((32+1)x4) 132 XLMACS, 32 CLMAC's */ 110 111 #ifdef PORTMOD_PM4X10_SUPPORT 112 static portmod_default_user_access_t *pm4x10_th_user_acc[SOC_MAX_NUM_DEVICES]; 113 #endif /* PORTMOD_PM4X10_SUPPORT */ 114 115 #ifdef PORTMOD_PM4X25_SUPPORT 116 static portmod_default_user_access_t *pm4x25_th_user_acc[SOC_MAX_NUM_DEVICES]; 117 #endif /* PORTMOD_PM4X25_SUPPORT */ 118 119 soc_portctrl_functions_t soc_th_portctrl_func = { 120 soc_th_portctrl_pm_portmod_init, 121 soc_th_portctrl_pm_portmod_deinit, 122 NULL, /*soc_portctrl_pm_port_config_get*/ 123 soc_th_portctrl_pm_port_phyaddr_get, 124 NULL, /* soc_portctrl_port_ability_update*/ 125 NULL, /* soc_portctrl_pm_type_get*/ 126 NULL, 127 NULL 128 }; 129 130 STATIC int 131 _soc_th_portctrl_pm_init(int unit, int *max_phys, 132 portmod_pm_instances_t **pm_types, 133 int *pms_arr_len) 134 { 135 *max_phys = SOC_TH_MAX_PHYS; 136 *pm_types = th_pm_types; 137 *pms_arr_len = sizeof(th_pm_types)/sizeof(portmod_pm_instances_t); 138 return SOC_E_NONE; 139 } 140 141 STATIC int 142 _soc_th_portctrl_device_addr_port_get(int unit, int pm_type, 143 uint32_t **addr, 144 uint32_t **port, 145 uint32_t **core_num) 146 { 147 *addr = NULL; 148 *port = NULL; 149 *core_num = NULL; 150 151 #ifdef PORTMOD_PM4X10_SUPPORT 152 if (pm_type == portmodDispatchTypePm4x10) { 153 *addr = _th_pm4x10_addr; 154 *port = _th_pm4x10_port; 155 *core_num = _th_pm4x10_core_num; 156 } 157 #endif 158 #ifdef PORTMOD_PM4X25_SUPPORT 159 if (pm_type == portmodDispatchTypePm4x25){ 160 *addr = _th_pm4x25_addr; 161 *port = _th_pm4x25_port; 162 *core_num = _th_pm4x25_core_num; 163 } 164 #endif 165 166 return SOC_E_NONE; 167 } 168 169 STATIC int 170 _soc_th_portctrl_pm_user_acc_flag_set(int unit, 171 portmod_default_user_access_t* pm_user_access) 172 { 173 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((pm_user_access)); 174 PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((pm_user_access)); 175 return SOC_E_NONE; 176 } 177 178 /* 179 * Polarity get looks for physical port based config first. This will enable 180 * the user to define the polarity for all ports weather mapped to logical 181 * port or not. 182 * 183 * For legacy compatibility - we still look for the logical port 184 * config setup. 185 */ 186 STATIC void 187 _soc_th_portctrl_pm_port_polarity_get 188 (int unit, int logical_port, int physical_port, int lane, 189 uint32 *tx_pol, uint32* rx_pol) 190 { 191 uint32 rx_polarity, tx_polarity, num_lanes = 1; 192 193 if (logical_port != -1) { 194 num_lanes = SOC_INFO(unit).port_num_lanes[logical_port]; 195 } 196 197 rx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 198 spn_PHY_RX_POLARITY_FLIP, 0xFFFFFFFF); 199 200 if (rx_polarity == 0xFFFFFFFF) { 201 rx_polarity = soc_property_port_get(unit, logical_port, 202 spn_PHY_XAUI_RX_POLARITY_FLIP, 0x0); 203 *rx_pol = (num_lanes == 1) ? ((rx_polarity & 0x1) << lane): rx_polarity; 204 } else { 205 *rx_pol = (rx_polarity & 0x1) << lane; 206 } 207 208 tx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 209 spn_PHY_TX_POLARITY_FLIP, 0xFFFFFFFF); 210 if (tx_polarity == 0xFFFFFFFF) { 211 tx_polarity = soc_property_port_get(unit, logical_port, 212 spn_PHY_XAUI_TX_POLARITY_FLIP, 0x0); 213 *tx_pol = (num_lanes == 1) ? ((tx_polarity & 0x1) << lane) : tx_polarity; 214 } else { 215 *tx_pol = (tx_polarity & 0x1) << lane; 216 } 217 218 } 219 220 /* 221 * lanemap get looks for physical port based config first. This will enable 222 * the user to define the lanemap for all ports weather mapped to logical 223 * port or not. 224 * 225 * For legacy compatibility - we still look for the logical port 226 * config setup. 227 */ 228 STATIC 229 void _soc_th_portctrl_pm_port_lanemap_get 230 (int unit, int logical_port, int physical_port, int core_num, 231 uint32 *txlane_map, uint32* rxlane_map) 232 { 233 234 *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 235 spn_PHY_RX_LANE_MAP, 0xFFFFFFFF); 236 237 if (*rxlane_map == 0xFFFFFFFF) { 238 *rxlane_map = soc_property_port_suffix_num_get(unit, logical_port, 239 core_num, spn_XGXS_RX_LANE_MAP, 240 "core", 0x3210); 241 } 242 243 *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 244 spn_PHY_TX_LANE_MAP, 0xFFFFFFFF); 245 246 if (*txlane_map == 0xFFFFFFFF) { 247 *txlane_map = soc_property_port_suffix_num_get(unit, logical_port, 248 core_num, spn_XGXS_TX_LANE_MAP, 249 "core", 0x3210); 250 } 251 } 252 253 STATIC int 254 _soc_th_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 255 { 256 #ifdef PORTMOD_PM4X10_SUPPORT 257 int rv = SOC_E_NONE; 258 portmod_pm_create_info_t pm_info; 259 int pmid = 0, blk, is_sim, lane, phy, found, logical_port; 260 int first_port, idx, ref_clk_prop = 0, core_num, core_cnt; 261 uint32 txlane_map, rxlane_map, *pAddr, *pPort, *pCoreNum; 262 uint32 tx_polarity, rx_polarity; 263 264 SOC_IF_ERROR_RETURN 265 (_soc_th_portctrl_device_addr_port_get(unit, 266 portmodDispatchTypePm4x10, 267 &pAddr, &pPort, &pCoreNum)); 268 if (!pAddr || !pPort) { 269 return SOC_E_INTERNAL; 270 } 271 272 /* Allocate PMs */ 273 SOC_IF_ERROR_RETURN 274 (soc_esw_portctrl_pm_user_access_alloc(unit, 275 num_of_instances, 276 &pm4x10_th_user_acc[unit])); 277 278 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 279 280 rv = portmod_pm_create_info_t_init(unit, &pm_info); 281 if (PORTMOD_FAILURE(rv)) { 282 break; 283 } 284 /* PM info */ 285 first_port = pPort[pmid]; 286 287 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 288 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 289 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 290 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 291 292 found = 0; 293 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 294 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 295 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){ 296 found = 1; 297 break; 298 } 299 } 300 301 if (!found) { 302 rv = SOC_E_INTERNAL; 303 break; 304 } 305 306 pm_info.type = portmodDispatchTypePm4x10; 307 308 /* Init user_acc for phymod access struct */ 309 rv = portmod_default_user_access_t_init(unit, 310 &(pm4x10_th_user_acc[unit][pmid])); 311 if (PORTMOD_FAILURE(rv)) { 312 break; 313 } 314 315 SOC_IF_ERROR_RETURN( 316 _soc_th_portctrl_pm_user_acc_flag_set(unit, 317 &(pm4x10_th_user_acc[unit][pmid]))); 318 319 pm4x10_th_user_acc[unit][pmid].unit = unit; 320 pm4x10_th_user_acc[unit][pmid].blk_id = blk; 321 pm4x10_th_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 322 if (pm4x10_th_user_acc[unit][pmid].mutex == NULL) { 323 rv = SOC_E_MEMORY; 324 break; 325 } 326 327 /* Specific info for PM4x10 */ 328 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access); 329 if (PORTMOD_FAILURE(rv)) { 330 break; 331 } 332 333 pm_info.pm_specific_info.pm4x10.access.user_acc = 334 &(pm4x10_th_user_acc[unit][pmid]); 335 pm_info.pm_specific_info.pm4x10.access.addr = pAddr[pmid]; 336 pm_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 337 338 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 339 &(pm_info.pm_specific_info.pm4x10.access), 340 0, &is_sim); 341 if (PORTMOD_FAILURE(rv)) { 342 break; 343 } 344 345 if (is_sim) { 346 pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |= 347 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 348 349 /* Firmward loader : Don't allow FW load on sim enviroment */ 350 pm_info.pm_specific_info.pm4x10.fw_load_method = 351 phymodFirmwareLoadMethodNone; 352 } else { 353 pm_info.pm_specific_info.pm4x10.fw_load_method = 354 soc_property_suffix_num_get(unit, pmid, 355 spn_LOAD_FIRMWARE, "quad", 356 phymodFirmwareLoadMethodExternal); 357 pm_info.pm_specific_info.pm4x10.fw_load_method &= 0xff; 358 } 359 360 /* Use default external loader if NULL */ 361 pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 362 363 /* Polarity */ 364 rv = phymod_polarity_t_init 365 (&(pm_info.pm_specific_info.pm4x10.polarity)); 366 if (PORTMOD_FAILURE(rv)) { 367 break; 368 } 369 370 for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) { 371 phy = first_port+lane; 372 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 373 374 _soc_th_portctrl_pm_port_polarity_get 375 (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity); 376 377 pm_info.pm_specific_info.pm4x10.polarity.rx_polarity |= rx_polarity; 378 pm_info.pm_specific_info.pm4x10.polarity.tx_polarity |= tx_polarity; 379 380 if (SOC_INFO(unit).port_num_lanes[logical_port] >= SOC_PM4X10_NUM_LANES) break; 381 } 382 383 /* Lane map */ 384 rv = phymod_lane_map_t_init 385 (&(pm_info.pm_specific_info.pm4x10.lane_map)); 386 if (PORTMOD_FAILURE(rv)) { 387 break; 388 } 389 390 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 391 core_cnt = 1; 392 393 for (core_num = 0; core_num < core_cnt; core_num++) { 394 _soc_th_portctrl_pm_port_lanemap_get 395 (unit, logical_port, first_port, core_num, &txlane_map, &rxlane_map); 396 397 /* possible internal swap to be added */ 398 399 #ifdef _PORTMOD_VERBOSE_ 400 soc_esw_portctrl_dump_txrx_lane_map(unit, first_port, logical_port, 401 core_num, txlane_map, rxlane_map, 402 txlane_map, rxlane_map); 403 #endif /* _PORTMOD_VERBOSE_ */ 404 pm_info.pm_specific_info.pm4x10.lane_map.num_of_lanes = 405 SOC_PM4X10_NUM_LANES; 406 407 pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid; 408 pm_info.pm_specific_info.pm4x10.core_num_int = 0; 409 pm_info.pm_specific_info.pm4x10.rescal = -1; 410 411 for(lane=0 ; lane<SOC_PM4X10_NUM_LANES; lane++) { 412 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_tx[lane] = 413 (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 414 SOC_PM4X10_LANE_MASK; 415 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_rx[lane] = 416 (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 417 SOC_PM4X10_LANE_MASK; 418 } 419 } 420 421 ref_clk_prop = soc_property_port_get(unit, first_port, 422 spn_XGXS_LCPLL_XTAL_REFCLK, 156); 423 424 if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)){ 425 pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk156Mhz; 426 } 427 else if (ref_clk_prop == 125){ 428 pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk125Mhz; 429 } 430 else { 431 LOG_ERROR(BSL_LS_SOC_PORT, 432 (BSL_META_UP(unit, first_port, 433 "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop)); 434 return SOC_E_PARAM ; 435 } 436 437 pm_info.pm_specific_info.pm4x10.portmod_phy_external_reset 438 = soc_esw_portctrl_reset_tsc3_cb; 439 440 /* 4x10 is only used in mgmt ports */ 441 pm_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoNone; 442 443 /* Add PM to PortMod */ 444 rv = portmod_port_macro_add(unit, &pm_info); 445 } 446 447 if (PORTMOD_FAILURE(rv)) { 448 for (pmid=0; pmid < num_of_instances; pmid++) { 449 if (pm4x10_th_user_acc[unit][pmid].mutex) { 450 sal_mutex_destroy(pm4x10_th_user_acc[unit][pmid].mutex); 451 pm4x10_th_user_acc[unit][pmid].mutex = NULL; 452 } 453 } 454 } 455 456 return rv; 457 #else /* PORTMOD_PM4X10_SUPPORT */ 458 return SOC_E_UNAVAIL; 459 #endif /* PORTMOD_PM4X10_SUPPORT */ 460 } 461 462 STATIC int 463 _soc_th_portctrl_pm4x25_portmod_init(int unit, int num_of_instances) 464 { 465 #ifdef PORTMOD_PM4X25_SUPPORT 466 int rv = SOC_E_NONE; 467 portmod_pm_create_info_t pm_info; 468 int pmid = 0, blk, is_sim, lane, phy, found, logical_port; 469 int first_port, idx, ref_clk_prop, core_num, core_cnt; 470 uint32 txlane_map, rxlane_map, *pAddr, *pPort,*pCoreNum; 471 uint32 tx_polarity, rx_polarity; 472 473 SOC_IF_ERROR_RETURN 474 (_soc_th_portctrl_device_addr_port_get(unit, 475 portmodDispatchTypePm4x25, 476 &pAddr, &pPort,&pCoreNum)); 477 if (!pAddr || !pPort) { 478 return SOC_E_INTERNAL; 479 } 480 481 /* Allocate PMs */ 482 SOC_IF_ERROR_RETURN 483 (soc_esw_portctrl_pm_user_access_alloc(unit, 484 num_of_instances, 485 &pm4x25_th_user_acc[unit])); 486 487 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 488 489 rv = portmod_pm_create_info_t_init(unit, &pm_info); 490 if (PORTMOD_FAILURE(rv)) { 491 break; 492 } 493 /* PM info */ 494 first_port = pPort[pmid]; 495 496 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 497 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 498 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 499 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 500 501 found = 0; 502 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 503 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 504 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CLPORT){ 505 found = 1; 506 break; 507 } 508 } 509 510 if (!found) { 511 rv = SOC_E_INTERNAL; 512 break; 513 } 514 515 pm_info.type = portmodDispatchTypePm4x25; 516 517 /* Init user_acc for phymod access struct */ 518 rv = portmod_default_user_access_t_init(unit, 519 &(pm4x25_th_user_acc[unit][pmid])); 520 if (PORTMOD_FAILURE(rv)) { 521 break; 522 } 523 524 PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_th_user_acc[unit][pmid]))); 525 PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x25_th_user_acc[unit][pmid]))); 526 pm4x25_th_user_acc[unit][pmid].unit = unit; 527 pm4x25_th_user_acc[unit][pmid].blk_id = blk; 528 pm4x25_th_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 529 if (pm4x25_th_user_acc[unit][pmid].mutex == NULL) { 530 rv = SOC_E_MEMORY; 531 break; 532 } 533 534 /* Specific info for PM4x25 */ 535 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x25.access); 536 if (PORTMOD_FAILURE(rv)) { 537 break; 538 } 539 540 pm_info.pm_specific_info.pm4x25.access.user_acc = 541 &(pm4x25_th_user_acc[unit][pmid]); 542 pm_info.pm_specific_info.pm4x25.access.addr = pAddr[pmid]; 543 pm_info.pm_specific_info.pm4x25.access.bus = NULL; /* Use default bus */ 544 545 rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 546 &(pm_info.pm_specific_info.pm4x25.access), 547 0, &is_sim); 548 549 if (PORTMOD_FAILURE(rv)) { 550 break; 551 } 552 553 if (is_sim) { 554 pm_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 555 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 556 557 /* Firmward loader : Don't allow FW load on sim enviroment */ 558 pm_info.pm_specific_info.pm4x25.fw_load_method = 559 phymodFirmwareLoadMethodNone; 560 } else { 561 pm_info.pm_specific_info.pm4x25.fw_load_method = 562 soc_property_suffix_num_get(unit, pmid, 563 spn_LOAD_FIRMWARE, "quad", 564 phymodFirmwareLoadMethodExternal); 565 pm_info.pm_specific_info.pm4x25.fw_load_method &= 0xff; 566 } 567 568 /* Use default external loader if NULL */ 569 pm_info.pm_specific_info.pm4x25.external_fw_loader = NULL; 570 571 /* Polarity */ 572 rv = phymod_polarity_t_init (&(pm_info.pm_specific_info.pm4x25.polarity)); 573 if (PORTMOD_FAILURE(rv)) { 574 break; 575 } 576 577 for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) { 578 phy = first_port+lane; 579 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 580 581 _soc_th_portctrl_pm_port_polarity_get 582 (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity); 583 584 pm_info.pm_specific_info.pm4x25.polarity.rx_polarity |= rx_polarity; 585 pm_info.pm_specific_info.pm4x25.polarity.tx_polarity |= tx_polarity; 586 587 if (SOC_INFO(unit).port_num_lanes[logical_port] >= SOC_PM4X25_NUM_LANES) break; 588 } 589 590 /* Lane map */ 591 rv = phymod_lane_map_t_init 592 (&(pm_info.pm_specific_info.pm4x25.lane_map)); 593 if (PORTMOD_FAILURE(rv)) { 594 break; 595 } 596 597 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 598 core_cnt = 1; 599 600 for (core_num = 0; core_num < core_cnt; core_num++) { 601 _soc_th_portctrl_pm_port_lanemap_get 602 (unit, logical_port, first_port, core_num, &txlane_map, &rxlane_map); 603 604 /* possible internal swap to be added */ 605 606 pm_info.pm_specific_info.pm4x25.lane_map.num_of_lanes = 607 SOC_PM4X25_NUM_LANES; 608 609 pm_info.pm_specific_info.pm4x25.core_num = pCoreNum? pCoreNum[pmid] : pmid; 610 pm_info.pm_specific_info.pm4x25.core_num_int = 0; 611 pm_info.pm_specific_info.pm4x25.rescal = -1; 612 613 for(lane=0 ; lane<SOC_PM4X25_NUM_LANES; lane++) { 614 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_tx[lane] = 615 (txlane_map >> (lane * SOC_PM4X25_NUM_LANES)) & 616 SOC_PM4X25_LANE_MASK; 617 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_rx[lane] = 618 (rxlane_map >> (lane * SOC_PM4X25_NUM_LANES)) & 619 SOC_PM4X25_LANE_MASK; 620 } 621 } 622 623 ref_clk_prop = soc_property_port_get(unit, first_port, 624 spn_XGXS_LCPLL_XTAL_REFCLK, 156); 625 626 if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)){ 627 pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk156Mhz; 628 } 629 else if (ref_clk_prop == 125){ 630 pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk125Mhz; 631 } 632 else { 633 LOG_ERROR(BSL_LS_SOC_PORT, 634 (BSL_META_UP(unit, first_port, 635 "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop)); 636 return SOC_E_PARAM ; 637 } 638 639 /* Add PM to PortMod */ 640 rv = portmod_port_macro_add(unit, &pm_info); 641 } 642 643 if (PORTMOD_FAILURE(rv)) { 644 for (pmid=0; pmid < num_of_instances; pmid++) { 645 if (pm4x25_th_user_acc[unit][pmid].mutex) { 646 sal_mutex_destroy(pm4x25_th_user_acc[unit][pmid].mutex); 647 pm4x25_th_user_acc[unit][pmid].mutex = NULL; 648 } 649 } 650 } 651 652 return rv; 653 #else /* PORTMOD_PM4X25_SUPPORT */ 654 return SOC_E_UNAVAIL; 655 #endif /* PORTMOD_PM4X25_SUPPORT */ 656 } 657 658 /* 659 * Function: 660 * soc_th_portctrl_pm_portmod_init 661 * Purpose: 662 * Initialize PortMod and PortMacro for Tomahawk 663 * Add port macros (PM) to the unit's PortMod Manager (PMM). 664 * Parameters: 665 * unit - (IN) Unit number. 666 * Returns: 667 * SOC_E_XXX 668 */ 669 int 670 soc_th_portctrl_pm_portmod_init(int unit) 671 { 672 int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0; 673 portmod_pm_instances_t *pm_types = NULL; 674 675 /* Call PortMod library initialization */ 676 SOC_IF_ERROR_RETURN( 677 _soc_th_portctrl_pm_init(unit, &max_phys, 678 &pm_types, &pms_arr_len)); 679 if (pms_arr_len == 0) { 680 return SOC_E_UNAVAIL; 681 } 682 683 /* 684 * If portmod was create - destroy and create again 685 * Better way would be to create once and leave it. 686 */ 687 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 688 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 689 } 690 691 SOC_IF_ERROR_RETURN 692 (portmod_create(unit, 0, SOC_MAX_NUM_PORTS, max_phys, 693 pms_arr_len, pm_types)); 694 695 for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) { 696 #ifdef PORTMOD_PM4X10_SUPPORT 697 if (pm_types[count].type == portmodDispatchTypePm4x10) { 698 rv = _soc_th_portctrl_pm4x10_portmod_init 699 (unit, pm_types[count].instances); 700 } else 701 #endif /* PORTMOD_PM4X10_SUPPORT */ 702 #ifdef PORTMOD_PM4X25_SUPPORT 703 if (pm_types[count].type == portmodDispatchTypePm4x25) { 704 rv = _soc_th_portctrl_pm4x25_portmod_init 705 (unit, pm_types[count].instances); 706 } else 707 #endif /* PORTMOD_PM4X25_SUPPORT */ 708 { 709 rv = SOC_E_INTERNAL; 710 } 711 } 712 713 return rv; 714 } 715 716 /* 717 * Function: 718 * soc_th_portctrl_pm_portmod_deinit 719 * Purpose: 720 * Deinitialize PortMod and PortMacro for Tomahawk. 721 * Free pm user access data. 722 * Parameters: 723 * unit - (IN) Unit number. 724 * Returns: 725 * SOC_E_NONE 726 */ 727 int 728 soc_th_portctrl_pm_portmod_deinit(int unit) 729 { 730 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 731 return SOC_E_NONE; 732 } 733 734 /* Free PMs structures */ 735 #ifdef PORTMOD_PM4X10_SUPPORT 736 if (pm4x10_th_user_acc[unit] != NULL) { 737 sal_free(pm4x10_th_user_acc[unit]); 738 pm4x10_th_user_acc[unit] = NULL; 739 } 740 #endif /* PORTMOD_PM4X10_SUPPORT */ 741 742 #ifdef PORTMOD_PM4X25_SUPPORT 743 if (pm4x25_th_user_acc[unit] != NULL) { 744 sal_free(pm4x25_th_user_acc[unit]); 745 pm4x25_th_user_acc[unit] = NULL; 746 } 747 #endif /* PORTMOD_PM4X25_SUPPORT */ 748 return SOC_E_NONE; 749 } 750 751 int 752 soc_th_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port) 753 { 754 int phy, core_index; 755 uint32 i, *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL; 756 757 phy = SOC_INFO(unit).port_l2p_mapping[port]; 758 759 /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */ 760 core_index = (phy - 1) / SOC_PM4X10_NUM_LANES; 761 #ifdef PORTMOD_PM4X10_SUPPORT 762 for (i=0; i<SOC_TH_PM4X10_COUNT; i++) { 763 if (core_index == _th_pm4x10_core_num[i]) { 764 SOC_IF_ERROR_RETURN 765 (_soc_th_portctrl_device_addr_port_get(unit, 766 portmodDispatchTypePm4x10, 767 &pAddr, &pPort, &pCoreNum)); 768 return pAddr[i]; 769 } 770 } 771 #endif /* PORTMOD_PM4X10_SUPPORT */ 772 773 #ifdef PORTMOD_PM4X25_SUPPORT 774 /* When port dones't find PM4x10, find PM4x25 again. */ 775 for (i=0; i<SOC_TH_PM4X25_COUNT; i++) { 776 if (core_index == _th_pm4x25_core_num[i]) { 777 SOC_IF_ERROR_RETURN 778 (_soc_th_portctrl_device_addr_port_get(unit, 779 portmodDispatchTypePm4x25, 780 &pAddr, &pPort, &pCoreNum)); 781 return pAddr[i]; 782 } 783 } 784 #endif /* PORTMOD_PM4X25_SUPPORT */ 785 786 return -1; 787 } 788 789 #endif /* BCM_TOMAHAWK_SUPPORT */