switch.c (14396B)
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 * SOC switch Utilities 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <soc/drv.h> 13 #include <soc/error.h> 14 #include <soc/scache.h> 15 #include <shared/alloc.h> 16 #include <soc/phy/phyctrl.h> 17 18 #ifdef BCM_WARM_BOOT_SUPPORT 19 20 #define SOC_CONTROL_WB_PART_0_VER_1_0 SOC_SCACHE_VERSION(1,0) 21 #define SOC_CONTROL_WB_PART_0_DEFAULT_VER SOC_CONTROL_WB_PART_0_VER_1_0 22 23 /* 24 * List of software-only switch controls that need to be recovered in Level 2. 25 * There is no way to recover these controls in level 1 warmboot. 26 * 27 * The following enum is used to identify the boolean controls. 28 */ 29 enum soc_wb_boolean_controls_0_e { 30 socControlUseGport = 0, 31 socControlL2PortBlocking = 1, 32 socControlAbortOnError = 2, 33 socControlCount = 3 34 }; 35 36 #define SOC_CONTROL_WB_NUM_ELE_0 8 37 static int soc_wb_boolean_controls_0[SOC_CONTROL_WB_NUM_ELE_0] = 38 { 39 socControlUseGport, 40 socControlL2PortBlocking, 41 socControlAbortOnError, 42 -1, 43 -1, 44 -1, 45 -1, 46 -1 47 }; 48 49 /* 50 * Function: 51 * soc_switch_control_scache_size_get 52 * Description: 53 * Get the size of scache size required for level 2 WarmBoot. 54 * Parameters: 55 * unit - (IN) SOC device number. 56 * part - (IN) Warmboot partition number. 57 * version - (IN) WarmBoot Level 2 scache version for switch module. 58 * Returns: 59 * Size of scache space required in bytes. 60 */ 61 STATIC int 62 soc_switch_control_scache_size_get(int unit, int part, int version) 63 { 64 int alloc_size = 0; 65 66 if (part == SOC_SCACHE_SWITCH_CONTROL_PART0) { 67 if (version >= SOC_CONTROL_WB_PART_0_VER_1_0) { 68 alloc_size += 1; 69 } 70 71 /* 72 * if (version >= SOC_CONTROL_WB_PART_0_VER_1_1) { 73 * // alloc_size += n; 74 * } 75 */ 76 77 } 78 79 return alloc_size; 80 } 81 82 /* 83 * Function: 84 * soc_switch_control_scache_init 85 * Description: 86 * WarmBoot recovery procedure for recovering global switch controls. 87 * Parameters: 88 * unit - (IN) BCM device number. 89 * Returns: 90 * BCM_E_XXX 91 */ 92 int 93 soc_switch_control_scache_init(int unit) 94 { 95 int rv = SOC_E_NONE; 96 int i, arg, part; 97 int stable_size; 98 uint32 alloc_sz; 99 uint8 *switch_scache; 100 uint16 default_ver, recovered_ver; 101 soc_scache_handle_t scache_handle; 102 int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE; 103 104 /* Limited scache mode unsupported */ 105 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 106 return (SOC_E_NONE); 107 } 108 109 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 110 if (!stable_size) { 111 /* stable not allocated */ 112 return SOC_E_NONE; 113 } 114 115 part = SOC_SCACHE_SWITCH_CONTROL_PART0; 116 default_ver = SOC_CONTROL_WB_PART_0_DEFAULT_VER; 117 118 alloc_sz = soc_switch_control_scache_size_get(unit, part, default_ver); 119 120 SOC_SCACHE_ALIGN_SIZE(alloc_sz); 121 alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE; 122 123 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_SWITCH_CONTROL, part); 124 125 /* Get the pointer for the Level 2 cache */ 126 rv = soc_extended_scache_ptr_get(unit, scache_handle, create, 127 create ? alloc_sz : 0, 128 &switch_scache); 129 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 130 return rv; 131 } else if (SOC_E_NOT_FOUND == rv && !create) { 132 /* Not yet allocated in upgrade */ 133 rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE, 134 alloc_sz, 135 &switch_scache); 136 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 137 return rv; 138 } 139 } else if (SOC_FAILURE(rv)) { 140 return rv; 141 } 142 143 /* recover version info */ 144 sal_memcpy(&recovered_ver, switch_scache, sizeof(uint16)); 145 146 /* Advance over scache control info */ 147 switch_scache += SOC_WB_SCACHE_CONTROL_SIZE; 148 149 /* If cold-booting or re-init in cold, return from here */ 150 if (!SOC_WARM_BOOT(unit)) { 151 return SOC_E_NONE; 152 } 153 154 /* Scache Version 1.0 */ 155 if (recovered_ver >= SOC_CONTROL_WB_PART_0_VER_1_0) { 156 for (i = 0; (i < SOC_CONTROL_WB_NUM_ELE_0); i++) { 157 if (-1 != soc_wb_boolean_controls_0[i]) { 158 arg = !!(*switch_scache & (1 << i)); 159 switch (i) { 160 case socControlUseGport: 161 SOC_USE_GPORT_SET(unit, arg); 162 break; 163 case socControlL2PortBlocking: 164 SOC_L2X_GROUP_ENABLE_SET(unit, arg); 165 break; 166 case socControlAbortOnError: 167 #ifdef BCM_CB_ABORT_ON_ERR 168 SOC_CB_ABORT_ON_ERR(unit) = arg; 169 #endif /* BCM_CB_ABORT_ON_ERR */ 170 break; 171 default: 172 break; 173 } 174 } 175 } 176 switch_scache++; 177 } 178 179 /* 180 * if (recovered_ver >= SOC_CONTROL_WB_PART_0_VER_1_1) { 181 * // Recover state corresponding to WB version 1.1 182 * } 183 */ 184 185 return rv; 186 } 187 188 /* 189 * Function: 190 * soc_switch_control_scache_sync 191 * Description: 192 * Save golbal switch state to scache. 193 * Parameters: 194 * unit - (IN) BCM device number. 195 * Returns: 196 * SOC_E_XXX 197 */ 198 int 199 soc_switch_control_scache_sync(int unit) 200 { 201 int i, arg; 202 int rv = SOC_E_NONE; 203 uint8 sc_map = 0; 204 uint16 default_ver; 205 uint32 alloc_get; 206 uint8 *switch_scache; 207 soc_scache_handle_t scache_handle; 208 209 /* Limited scache mode unsupported */ 210 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 211 return SOC_E_NONE; 212 } 213 214 default_ver = SOC_CONTROL_WB_PART_0_DEFAULT_VER; 215 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 216 SOC_SCACHE_SWITCH_CONTROL, 217 SOC_SCACHE_SWITCH_CONTROL_PART0); 218 219 /* Get the pointer for the Level 2 cache */ 220 rv = soc_scache_ptr_get(unit, scache_handle, 221 &switch_scache, &alloc_get); 222 223 SOC_IF_ERROR_RETURN(rv); 224 225 /* save default version */ 226 sal_memcpy(switch_scache, &default_ver, sizeof(uint16)); 227 switch_scache += SOC_WB_SCACHE_CONTROL_SIZE; 228 229 /* Enable bits if the corresponding switch control is set */ 230 for (i = 0; (i < SOC_CONTROL_WB_NUM_ELE_0); i++) { 231 if (-1 != soc_wb_boolean_controls_0[i]) { 232 arg = 0; 233 switch (i) { 234 case socControlUseGport: 235 arg = SOC_USE_GPORT(unit); 236 break; 237 case socControlL2PortBlocking: 238 arg = SOC_L2X_GROUP_ENABLE_GET(unit); 239 break; 240 case socControlAbortOnError: 241 #ifdef BCM_CB_ABORT_ON_ERR 242 arg = SOC_CB_ABORT_ON_ERR(unit); 243 #endif /* BCM_CB_ABORT_ON_ERR */ 244 break; 245 default: 246 break; 247 } 248 if (arg) { 249 sc_map |= (1 << i); 250 } 251 } 252 } 253 *switch_scache = sc_map; 254 255 switch_scache++; 256 257 return rv; 258 } 259 260 #endif /* BCM_WARM_BOOT_SUPPORT */ 261 262 /* 263 * Function: 264 * soc_switch_sync_mux_from_pbm 265 * Description: 266 * Convert a port index to SyncE L1 recovered clock mux setting 267 * Parameters: 268 * unit - (IN) BCM device number. 269 * port - (IN) Port index 270 * mux - (OUT) Mux setting corresponding to port 271 * Returns: 272 * SOC_E_XXX 273 */ 274 int 275 soc_switch_sync_mux_from_port(int unit, 276 int port, 277 int *mux) 278 { 279 if (!SOC_PORT_VALID(unit, port) || 280 !SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) { 281 return SOC_E_PARAM; 282 } 283 284 #ifdef BCM_HURRICANE3_SUPPORT 285 if (SOC_IS_HURRICANE3(unit)) { 286 if (SOC_PORT_VALID(unit, port)) { 287 int addr = soc_phy_addr_of_port(unit, port); 288 /* See _hurricane3_phy_addr_default for values used below */ 289 if (addr >= 0x81 && addr <= 0x88) { 290 *mux = (16 + (addr - 0x81)); 291 return SOC_E_NONE; 292 } 293 if (addr >= 0x89 && addr <= 0x90) { 294 *mux = (32 + (addr - 0x89)); 295 return SOC_E_NONE; 296 } 297 if (addr == 0xa1) { 298 int lane = INT_PHY_SW_STATE(unit, port)->lane_num; 299 *mux = 4 + lane; 300 return SOC_E_NONE; 301 } 302 if (addr == 0xa5) { 303 int lane = INT_PHY_SW_STATE(unit, port)->lane_num; 304 *mux = 8 + lane; 305 return SOC_E_NONE; 306 } 307 if (addr == 0xa9) { 308 int lane = INT_PHY_SW_STATE(unit, port)->lane_num; 309 *mux = 24 + lane; 310 return SOC_E_NONE; 311 } 312 if (addr == 0xad) { 313 int lane = INT_PHY_SW_STATE(unit, port)->lane_num; 314 *mux = 40 + lane; 315 return SOC_E_NONE; 316 } 317 } 318 return SOC_E_PARAM; 319 } 320 #endif /* BCM_HURRICANE3_SUPPORT */ 321 322 /* Default behavior: */ 323 *mux = port - 1; 324 325 return SOC_E_NONE; 326 } 327 328 /* 329 * Function: 330 * soc_switch_sync_mux_from_pbm 331 * Description: 332 * Convert a PBM value to SyncE L1 recovered clock mux setting 333 * Parameters: 334 * unit - (IN) BCM device number. 335 * pbm - (IN) Port BitMap with desired port 336 * mux - (OUT) Mux setting corresponding to PBM 337 * Returns: 338 * SOC_E_XXX 339 */ 340 int 341 soc_switch_sync_mux_from_pbm(int unit, 342 pbmp_t pbm, 343 int *mux) 344 { 345 int count, port; 346 347 SOC_PBMP_COUNT(pbm, count); 348 349 if (count != 1) { 350 return SOC_E_PARAM; 351 } 352 353 SOC_PBMP_ITER(pbm, port) { 354 SOC_IF_ERROR_RETURN(soc_switch_sync_mux_from_port(unit, port, mux)); 355 } 356 357 return SOC_E_NONE; 358 } 359 360 /* 361 * Function: 362 * soc_switch_sync_mux_from_pll 363 * Description: 364 * Convert a port index to SyncE L1 recovered clock mux setting 365 * Parameters: 366 * unit - (IN) BCM device number. 367 * pll - (IN) PLL reference 368 * mux - (OUT) Mux setting corresponding to PLL 369 * Returns: 370 * SOC_E_XXX 371 */ 372 int 373 soc_switch_sync_mux_from_pll(int unit, 374 soc_recov_clk_src_t src, 375 int *mux) 376 { 377 #ifdef BCM_KATANA_SUPPORT 378 if (SOC_IS_KATANA(unit)) { 379 switch (src) { 380 case SOC_RCVR_CLK_SERDES_PLL: 381 *mux = 34; 382 return SOC_E_NONE; 383 case SOC_RCVR_CLK_MASTER_PLL: 384 *mux = 35; 385 return SOC_E_NONE; 386 default: 387 return SOC_E_PARAM; 388 } 389 } 390 #endif 391 392 #ifdef BCM_KATANA2_SUPPORT 393 if (SOC_IS_KATANA2(unit)) { 394 switch (src) { 395 case SOC_RCVR_CLK_SERDES_PLL: 396 *mux = 40; 397 return SOC_E_NONE; 398 case SOC_RCVR_CLK_MASTER_PLL: 399 *mux = 41; 400 return SOC_E_NONE; 401 case SOC_RCVR_CLK_EXT_PHY_0: 402 *mux = 41; 403 return SOC_E_NONE; 404 default: 405 return SOC_E_PARAM; 406 } 407 } 408 #endif 409 410 #ifdef BCM_SABER2_SUPPORT 411 if (SOC_IS_SABER2(unit)) { 412 switch (src) { 413 case SOC_RCVR_CLK_SERDES_PLL: 414 *mux = 28; 415 return SOC_E_NONE; 416 case SOC_RCVR_CLK_MASTER_PLL: 417 *mux = 29; 418 return SOC_E_NONE; 419 case SOC_RCVR_CLK_EXT_PHY_0: 420 *mux = 30; 421 return SOC_E_NONE; 422 default: 423 return SOC_E_PARAM; 424 } 425 } 426 #endif 427 428 #ifdef BCM_HELIX4_SUPPORT 429 if (SOC_IS_HELIX4(unit)) { 430 switch (src) { 431 case SOC_RCVR_CLK_XGPLL_0: 432 *mux = 64; 433 return SOC_E_NONE; 434 case SOC_RCVR_CLK_XGPLL_1: 435 *mux = 65; 436 return SOC_E_NONE; 437 default: 438 return SOC_E_PARAM; 439 } 440 } 441 #endif 442 443 #ifdef BCM_HURRICANE2_SUPPORT 444 if (SOC_IS_HURRICANE2(unit)) { 445 switch (src) { 446 case SOC_RCVR_CLK_XGPLL_0: 447 *mux = 28; 448 return SOC_E_NONE; 449 case SOC_RCVR_CLK_XGPLL_1: 450 *mux = 29; 451 return SOC_E_NONE; 452 case SOC_RCVR_CLK_EXT_PHY_0: 453 *mux = 26; 454 return SOC_E_NONE; 455 case SOC_RCVR_CLK_EXT_PHY_1: 456 *mux = 27; 457 return SOC_E_NONE; 458 default: 459 return SOC_E_PARAM; 460 } 461 } 462 #endif 463 464 #ifdef BCM_HURRICANE3_SUPPORT 465 if (SOC_IS_HURRICANE3(unit)) { 466 switch (src) { 467 case SOC_RCVR_CLK_XGPLL_0: 468 *mux = 0; 469 return SOC_E_NONE; 470 case SOC_RCVR_CLK_XGPLL_1: 471 *mux = 1; 472 return SOC_E_NONE; 473 case SOC_RCVR_CLK_EXT_PHY_0: 474 *mux = 2; 475 return SOC_E_NONE; 476 case SOC_RCVR_CLK_EXT_PHY_1: 477 *mux = 3; 478 return SOC_E_NONE; 479 default: 480 return SOC_E_PARAM; 481 } 482 } 483 #endif 484 485 #ifdef BCM_GREYHOUND_SUPPORT 486 if (SOC_IS_GREYHOUND(unit)) { 487 switch (src) { 488 case SOC_RCVR_CLK_XGPLL_0: 489 *mux = 28; 490 return SOC_E_NONE; 491 case SOC_RCVR_CLK_XGPLL_1: 492 *mux = 29; 493 return SOC_E_NONE; 494 case SOC_RCVR_CLK_EXT_PHY_0: 495 *mux = 26; 496 return SOC_E_NONE; 497 case SOC_RCVR_CLK_EXT_PHY_1: 498 *mux = 27; 499 return SOC_E_NONE; 500 default: 501 return SOC_E_PARAM; 502 } 503 } 504 #endif 505 506 #if (defined(BCM_TOMAHAWK_SUPPORT) || \ 507 defined(BCM_APACHE_SUPPORT) || \ 508 defined(BCM_TRIDENT2X_SUPPORT)) 509 510 /* Note: These chips have a separate mux to pick between port and 511 a specific LCPLL. We return the value for that mux here. */ 512 513 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT2X(unit)) { 514 switch (src) { 515 case SOC_RCVR_CLK_XGPLL_0: 516 *mux = 1; 517 return SOC_E_NONE; 518 case SOC_RCVR_CLK_XGPLL_1: 519 *mux = 2; 520 return SOC_E_NONE; 521 case SOC_RCVR_CLK_XGPLL_2: 522 *mux = 3; 523 return SOC_E_NONE; 524 case SOC_RCVR_CLK_XGPLL_3: 525 *mux = 4; 526 return SOC_E_NONE; 527 default: 528 return SOC_E_PARAM; 529 } 530 } 531 #endif /* TOMAHAWK / APACHE / TRIDENT2X */ 532 533 return SOC_E_UNAVAIL; 534 }