portctrl.c (13595B)
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/mem.h> 15 #include <soc/esw/portctrl.h> 16 #include <soc/esw/portctrl_internal.h> 17 #include <soc/greyhound.h> 18 #include <shared/bsl.h> 19 #include <soc/phy/phymod_sim.h> 20 #include <soc/portmod/portmod.h> 21 22 #ifdef BCM_GREYHOUND_SUPPORT 23 #define SOC_GH_PM4X10_COUNT 6 24 #define SOC_GH_PM4X10_PORT_0 02 25 #define SOC_GH_PM4X10_PORT_1 18 26 #define SOC_GH_PM4X10_PORT_2 22 27 #define SOC_GH_PM4X10_PORT_3 26 28 #define SOC_GH_PM4X10_PORT_4 30 29 #define SOC_GH_PM4X10_PORT_5 34 30 31 static uint32_t _gh_addr[SOC_GH_PM4X10_COUNT] = { 32 0x81, 0xA1, 0xA5, 0xA9, 0xAD, 0xB1}; 33 34 static uint32_t _gh_port[SOC_GH_PM4X10_COUNT] = { 35 SOC_GH_PM4X10_PORT_0, 36 SOC_GH_PM4X10_PORT_1, 37 SOC_GH_PM4X10_PORT_2, 38 SOC_GH_PM4X10_PORT_3, 39 SOC_GH_PM4X10_PORT_4, 40 SOC_GH_PM4X10_PORT_5, 41 }; 42 43 portmod_pm_instances_t gh_pm_types[] = { 44 #ifdef PORTMOD_PM4X10_SUPPORT 45 {portmodDispatchTypePm4x10, SOC_GH_PM4X10_COUNT}, 46 #endif 47 }; 48 49 #define SOC_GH_MAX_PHYS 160 /* 128 XLMACS, 32 CLMAC's */ 50 51 #ifdef PORTMOD_PM4X10_SUPPORT 52 static portmod_default_user_access_t *pm4x10_gh_user_acc[SOC_MAX_NUM_DEVICES]; 53 #endif /* PORTMOD_PM4X10_SUPPORT */ 54 55 soc_portctrl_functions_t soc_gh_portctrl_func = { 56 soc_gh_portctrl_pm_portmod_init, 57 soc_gh_portctrl_pm_portmod_deinit, 58 NULL, /*soc_portctrl_pm_port_config_get*/ 59 NULL, /*soc_portctrl_pm_port_phyaddr_get*/ 60 NULL, /*soc_portctrl_port_ability_update*/ 61 NULL, /*soc_portctrl_pm_type_get*/ 62 NULL, 63 NULL 64 }; 65 66 STATIC int 67 _soc_gh_portctrl_pm_init(int unit, int *max_phys, 68 portmod_pm_instances_t **pm_types, 69 int *pms_arr_len) 70 { 71 *max_phys = SOC_GH_MAX_PHYS; 72 *pm_types = gh_pm_types; 73 *pms_arr_len = sizeof(gh_pm_types)/sizeof(portmod_pm_instances_t); 74 return SOC_E_NONE; 75 } 76 77 STATIC int 78 _soc_gh_portctrl_device_addr_port_get(int unit, int pm_type, 79 uint32_t **addr, 80 uint32_t **port, 81 uint32_t **core_num) 82 { 83 *addr = _gh_addr; 84 *port = _gh_port; 85 *core_num = NULL; 86 return SOC_E_NONE; 87 } 88 89 STATIC int 90 _soc_gh_portctrl_pm_user_acc_flag_set(int unit, 91 portmod_default_user_access_t* pm_user_access) 92 { 93 PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_SET((pm_user_access)); 94 return SOC_E_NONE; 95 } 96 97 STATIC int 98 _soc_gh_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 99 { 100 #ifdef PORTMOD_PM4X10_SUPPORT 101 int rv = SOC_E_NONE; 102 portmod_pm_create_info_t pm_info; 103 int pmid = 0, blk, is_sim, lane, phy, found, logical_port; 104 int first_port, idx, ref_clk_prop = 0, core_num, core_cnt; 105 uint32 txlane_map, rxlane_map, *pAddr, *pPort, *pCoreNum; 106 uint32 tx_polarity, rx_polarity; 107 108 SOC_IF_ERROR_RETURN 109 (_soc_gh_portctrl_device_addr_port_get(unit, 110 portmodDispatchTypePm4x10, 111 &pAddr, &pPort, &pCoreNum)); 112 if (!pAddr || !pPort) { 113 return SOC_E_INTERNAL; 114 } 115 116 /* Allocate PMs */ 117 SOC_IF_ERROR_RETURN 118 (soc_esw_portctrl_pm_user_access_alloc(unit, 119 num_of_instances, 120 &pm4x10_gh_user_acc[unit])); 121 122 for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) { 123 124 rv = portmod_pm_create_info_t_init(unit, &pm_info); 125 if (PORTMOD_FAILURE(rv)) { 126 break; 127 } 128 /* PM info */ 129 first_port = pPort[pmid]; 130 131 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port); 132 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 133 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2); 134 PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3); 135 136 found = 0; 137 for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 138 blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 139 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){ 140 found = 1; 141 break; 142 } 143 } 144 145 if (!found) { 146 rv = SOC_E_INTERNAL; 147 break; 148 } 149 150 pm_info.type = portmodDispatchTypePm4x10; 151 152 /* Init user_acc for phymod access struct */ 153 rv = portmod_default_user_access_t_init(unit, 154 &(pm4x10_gh_user_acc[unit][pmid])); 155 if (PORTMOD_FAILURE(rv)) { 156 break; 157 } 158 159 SOC_IF_ERROR_RETURN( 160 _soc_gh_portctrl_pm_user_acc_flag_set(unit, 161 &(pm4x10_gh_user_acc[unit][pmid]))); 162 163 pm4x10_gh_user_acc[unit][pmid].unit = unit; 164 pm4x10_gh_user_acc[unit][pmid].blk_id = blk; 165 pm4x10_gh_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex"); 166 if (pm4x10_gh_user_acc[unit][pmid].mutex == NULL) { 167 rv = SOC_E_MEMORY; 168 break; 169 } 170 171 /* Specific info for PM4x10 */ 172 rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access); 173 if (PORTMOD_FAILURE(rv)) { 174 break; 175 } 176 177 pm_info.pm_specific_info.pm4x10.access.user_acc = 178 &(pm4x10_gh_user_acc[unit][pmid]); 179 pm_info.pm_specific_info.pm4x10.access.addr = pAddr[pmid]; 180 pm_info.pm_specific_info.pm4x10.access.bus = NULL; /* Use default bus */ 181 182 rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 183 &(pm_info.pm_specific_info.pm4x10.access), 184 0, &is_sim); 185 if (PORTMOD_FAILURE(rv)) { 186 break; 187 } 188 189 if (is_sim) { 190 pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |= 191 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL); 192 193 /* Firmward loader : Don't allow FW load on sim enviroment */ 194 pm_info.pm_specific_info.pm4x10.fw_load_method = 195 phymodFirmwareLoadMethodNone; 196 } else { 197 pm_info.pm_specific_info.pm4x10.fw_load_method = 198 soc_property_suffix_num_get(unit, pmid, 199 spn_LOAD_FIRMWARE, "quad", 200 phymodFirmwareLoadMethodExternal); 201 pm_info.pm_specific_info.pm4x10.fw_load_method &= 0xff; 202 } 203 204 /* Use default external loader if NULL */ 205 pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL; 206 207 rv = phymod_polarity_t_init 208 (&(pm_info.pm_specific_info.pm4x10.polarity)); 209 if (PORTMOD_FAILURE(rv)) { 210 break; 211 } 212 213 /* Polarity */ 214 for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) { 215 /* need to add more conditions */ 216 phy = first_port+lane; 217 rx_polarity = soc_property_suffix_num_get(unit, phy, 218 spn_PHY_RX_POLARITY_FLIP, "phy", 0xFFFFFFFF); 219 tx_polarity = soc_property_suffix_num_get(unit, phy, 220 spn_PHY_TX_POLARITY_FLIP, "phy", 0xFFFFFFFF); 221 222 logical_port = SOC_INFO(unit).port_p2l_mapping[phy]; 223 224 if (rx_polarity == 0xFFFFFFFF) { 225 rx_polarity = soc_property_port_get(unit, logical_port, 226 spn_PHY_RX_POLARITY_FLIP, 0); 227 pm_info.pm_specific_info.pm4x10.polarity.rx_polarity 228 |= rx_polarity; 229 } else { 230 pm_info.pm_specific_info.pm4x10.polarity.rx_polarity 231 |= ((rx_polarity & 0x1) << lane); 232 } 233 234 if (tx_polarity == 0xFFFFFFFF) { 235 tx_polarity = soc_property_port_get( 236 unit, logical_port, 237 spn_PHY_TX_POLARITY_FLIP, 0); 238 pm_info.pm_specific_info.pm4x10.polarity.tx_polarity 239 |= tx_polarity; 240 } else { 241 pm_info.pm_specific_info.pm4x10.polarity.tx_polarity 242 |= ((tx_polarity & 0x1) << lane); 243 } 244 } 245 246 /* Lane map */ 247 rv = phymod_lane_map_t_init 248 (&(pm_info.pm_specific_info.pm4x10.lane_map)); 249 if (PORTMOD_FAILURE(rv)) { 250 break; 251 } 252 253 logical_port = SOC_INFO(unit).port_p2l_mapping[first_port]; 254 core_cnt = 1; 255 256 for (core_num = 0; core_num < core_cnt; core_num++) { 257 txlane_map = soc_property_port_suffix_num_get(unit, logical_port, 258 core_num, 259 spn_XGXS_TX_LANE_MAP, 260 "core", 0x3210); 261 rxlane_map = soc_property_port_suffix_num_get(unit, logical_port, 262 core_num, 263 spn_XGXS_RX_LANE_MAP, 264 "core", 0x3210); 265 266 #ifdef _PORTMOD_VERBOSE_ 267 soc_esw_portctrl_dump_txrx_lane_map(unit, first_port, logical_port, 268 core_num, txlane_map, rxlane_map, 269 txlane_map, rxlane_map); 270 #endif /* _PORTMOD_VERBOSE_ */ 271 pm_info.pm_specific_info.pm4x10.lane_map.num_of_lanes = 272 SOC_PM4X10_NUM_LANES; 273 274 pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid; 275 pm_info.pm_specific_info.pm4x10.core_num_int = 0; 276 pm_info.pm_specific_info.pm4x10.rescal = -1; 277 278 for(lane=0 ; lane<SOC_PM4X10_NUM_LANES; lane++) { 279 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_tx[lane] = 280 (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 281 SOC_PM4X10_LANE_MASK; 282 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_rx[lane] = 283 (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) & 284 SOC_PM4X10_LANE_MASK; 285 } 286 } 287 288 ref_clk_prop = soc_property_port_get(unit, first_port, 289 spn_XGXS_LCPLL_XTAL_REFCLK, phymodRefClk156Mhz); 290 291 if ((ref_clk_prop == 125) ||( ref_clk_prop == 1)) 292 pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk125Mhz; 293 else /* ((ref_clk_prop == 156) ||( ref_clk_prop == 0)) */ 294 pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk156Mhz; 295 296 pm_info.pm_specific_info.pm4x10.portmod_phy_external_reset 297 = soc_esw_portctrl_reset_tsc3_cb; 298 299 /* Add PM to PortMod */ 300 rv = portmod_port_macro_add(unit, &pm_info); 301 } 302 303 if (PORTMOD_FAILURE(rv)) { 304 for (pmid=0; pmid < num_of_instances; pmid++) { 305 if (pm4x10_gh_user_acc[unit][pmid].mutex) { 306 sal_mutex_destroy(pm4x10_gh_user_acc[unit][pmid].mutex); 307 pm4x10_gh_user_acc[unit][pmid].mutex = NULL; 308 } 309 } 310 } 311 312 return rv; 313 #else /* PORTMOD_PM4X10_SUPPORT */ 314 return SOC_E_UNAVAIL; 315 #endif /* PORTMOD_PM4X10_SUPPORT */ 316 } 317 318 /* 319 * Function: 320 * soc_gh_portctrl_pm_portmod_init 321 * Purpose: 322 * Initialize PortMod and PortMacro for Greyhound. 323 * Add port macros (PM) to the unit's PortMod Manager (PMM). 324 * Parameters: 325 * unit - (IN) Unit number. 326 * Returns: 327 * SOC_E_XXX 328 */ 329 int 330 soc_gh_portctrl_pm_portmod_init(int unit) 331 { 332 int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0; 333 portmod_pm_instances_t *pm_types = NULL; 334 335 /* Call PortMod library initialization */ 336 SOC_IF_ERROR_RETURN( 337 _soc_gh_portctrl_pm_init(unit, &max_phys, 338 &pm_types, &pms_arr_len)); 339 if (pms_arr_len == 0) { 340 return SOC_E_UNAVAIL; 341 } 342 343 /* 344 * If portmod was create - destroy and create again 345 * Better way would be to create once and leave it. 346 */ 347 if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) { 348 SOC_IF_ERROR_RETURN(portmod_destroy(unit)); 349 } 350 351 SOC_IF_ERROR_RETURN 352 (portmod_create(unit, 0, SOC_MAX_NUM_PORTS, max_phys, 353 pms_arr_len, pm_types)); 354 355 for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) { 356 #ifdef PORTMOD_PM4X10_SUPPORT 357 if (pm_types[count].type == portmodDispatchTypePm4x10) { 358 rv = _soc_gh_portctrl_pm4x10_portmod_init 359 (unit, pm_types[count].instances); 360 } else 361 #endif 362 { 363 rv = SOC_E_INTERNAL; 364 } 365 } 366 367 return rv; 368 } 369 370 /* 371 * Function: 372 * soc_gh_portctrl_pm_portmod_deinit 373 * Purpose: 374 * Deinitialize PortMod and PortMacro for Greyhound. 375 * Free pm user access data. 376 * Parameters: 377 * unit - (IN) Unit number. 378 * Returns: 379 * SOC_E_NONE 380 */ 381 int 382 soc_gh_portctrl_pm_portmod_deinit(int unit) 383 { 384 if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) { 385 return SOC_E_NONE; 386 } 387 388 /* Free PMs structures */ 389 #ifdef PORTMOD_PM4X10_SUPPORT 390 if (pm4x10_gh_user_acc[unit] != NULL) { 391 sal_free(pm4x10_gh_user_acc[unit]); 392 } 393 #endif /* PORTMOD_PM4X10_SUPPORT */ 394 return SOC_E_NONE; 395 } 396 397 #endif /* BCM_GREYHOUND_SUPPORT */ 398