drv.c (168910B)
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 * StrataSwitch driver 8 */ 9 10 #include <soc/drv.h> 11 #ifdef _SHR_BSL_H_ 12 #error Header file soc/drv.h must not include bsl.h directly or indirectly 13 #endif 14 15 #include <shared/bsl.h> 16 17 #include <sal/appl/sal.h> 18 #include <sal/core/libc.h> 19 #include <shared/alloc.h> 20 #include <shared/switch.h> 21 #include <shared/bitop.h> 22 #include <sal/core/spl.h> 23 #include <sal/core/sync.h> 24 #include <sal/core/boot.h> 25 #include <sal/core/dpc.h> 26 27 #include <soc/cm.h> 28 #include <soc/drv.h> 29 #include <soc/dma.h> 30 #include <soc/register.h> 31 #include <soc/debug.h> 32 #if defined(BCM_PETRA_SUPPORT) 33 #include <soc/dpp/drv.h> 34 #endif 35 #ifdef BCM_DNX_SUPPORT 36 #include <soc/dnx/drv.h> 37 #include <soc/dnxc/drv.h> 38 #endif 39 #ifdef BCM_DFE_SUPPORT 40 #include <soc/dfe/cmn/dfe_drv.h> 41 #endif 42 #ifdef BCM_DNXF_SUPPORT 43 #include <soc/dnxf/cmn/dnxf_drv.h> 44 #endif 45 #ifdef BCM_WARM_BOOT_SUPPORT 46 #include <soc/mem.h> 47 #endif 48 #ifdef BCM_CMICM_SUPPORT 49 #include <soc/cmicm.h> 50 #endif 51 #ifdef BCM_IPROC_SUPPORT 52 #include <soc/iproc.h> 53 #endif 54 #ifdef INCLUDE_AVS 55 #include <soc/avs.h> 56 #endif /* INCLUDE_AVS */ 57 #if defined(PORTMOD_SUPPORT) && defined(BCM_ESW_SUPPORT) 58 #include <soc/esw/portctrl.h> 59 #include <soc/phy/phymod_sim.h> 60 #endif 61 62 #ifdef ADAPTER_SERVER_MODE 63 #define DRV_ADAPTER_SERVER_SUFFIX "_ADAPTER" 64 #endif /*ADAPTER_SERVER_MODE*/ 65 66 /* 67 * Driver global variables 68 * 69 * soc_control: per-unit driver control structure 70 * soc_persist: persistent per-unit driver control structure 71 * soc_ndev: the number of units created 72 * soc_ndev_attached: the number of units attached 73 * soc_family_suffix: a family suffix, configured by soc property soc_family. 74 * Used what parsing soc properties. 75 * If configured, and property.unit, property.chip and property.group was not 76 * found, property.family is searched for. 77 */ 78 soc_control_t *soc_control[SOC_MAX_NUM_DEVICES]; 79 soc_persist_t *soc_persist[SOC_MAX_NUM_DEVICES]; 80 int soc_ndev = 0; 81 /* soc_ndev_idx2dev_map maps the devices logical id to the physical device id 82 * e.g. if we have two devides with ids 0 and 2 and hence soc_ndev is 2, 83 * we will have this status: 84 * soc_ndev_idx2dev_map[0] will be 0, and 85 * soc_ndev_idx2dev_map[1] will be 2. 86 */ 87 int soc_ndev_idx2dev_map[SOC_MAX_NUM_DEVICES]; 88 int soc_eth_ndev = 0; 89 int soc_ndev_attached = 0; 90 int soc_all_ndev; 91 uint32 soc_state[SOC_MAX_NUM_DEVICES]; 92 char *soc_family_suffix[SOC_MAX_NUM_DEVICES] = {0}; 93 94 /* soc_wb_mim_state: indicate that all virtual ports / VPNs are MiM */ 95 /* Level 1 warm boot only */ 96 #ifdef BCM_WARM_BOOT_SUPPORT 97 int soc_wb_mim_state[SOC_MAX_NUM_DEVICES]; 98 #endif 99 100 #if defined(BCM_SAND_SUPPORT) 101 102 int soc_get_reg_first_block_id(int unit,soc_reg_t reg,uint32 *block) 103 { 104 soc_reg_info_t reg_info = SOC_REG_INFO(unit, reg); 105 int block_type = SOC_REG_FIRST_BLK_TYPE(reg_info.block); 106 int blk=-1; 107 int schan; 108 109 SOC_BLOCK_ITER(unit, blk, block_type) { 110 schan = SOC_BLOCK_INFO(unit,blk).schan; 111 *block = schan; 112 return SOC_E_NONE; 113 } 114 115 LOG_ERROR(BSL_LS_SOC_COMMON, 116 (BSL_META_U(unit, 117 "Cant Find block-id for reg %d\n"), 118 reg)); 119 120 return SOC_E_UNAVAIL; 121 122 } 123 #endif /* defined(BCM_SAND_SUPPORT) */ 124 125 /* 126 * Function: 127 * soc_misc_init 128 * Purpose: 129 * Initialize miscellaneous chip registers 130 * Parameters: 131 * unit - unit number 132 * Returns: 133 * SOC_E_XXX 134 */ 135 int 136 soc_misc_init(int unit) 137 { 138 LOG_VERBOSE(BSL_LS_SOC_COMMON, 139 (BSL_META_U(unit, 140 "soc_misc_init\n"))); 141 142 if (!soc_attached(unit)) { 143 return SOC_E_INIT; 144 } 145 146 if (SOC_IS_RCPU_ONLY(unit)) { 147 return SOC_E_NONE; 148 } 149 150 /* Perform Chip-Dependent Initializations */ 151 152 if (SOC_FUNCTIONS(unit)) { 153 if (SOC_FUNCTIONS(unit)->soc_misc_init) { 154 #ifdef BCM_XGS_SUPPORT 155 if (SOC_IS_XGS(unit)) { 156 /* Enable accelerated mem clear in case misc init is called 157 again */ 158 SOC_MEM_CLEAR_HW_ACC_SET(unit, 1); 159 } 160 #endif /* BCM_XGS_SUPPORT */ 161 SOC_IF_ERROR_RETURN(SOC_FUNCTIONS(unit)->soc_misc_init(unit)); 162 #ifdef BCM_XGS_SUPPORT 163 if (SOC_IS_XGS(unit)) { 164 /* Disable accelerated mem clear after misc init */ 165 SOC_MEM_CLEAR_HW_ACC_SET(unit, 0); 166 } 167 #endif /* BCM_XGS_SUPPORT */ 168 } 169 170 #ifdef INCLUDE_AVS 171 if (soc_feature(unit, soc_feature_avs_openloop)) { 172 soc_avs_openloop_main(unit); 173 } 174 #endif /* INCLUDE_AVS */ 175 176 } 177 178 #if defined(PORTMOD_SUPPORT) && defined(BCM_ESW_SUPPORT) 179 if (SOC_USE_PORTCTRL(unit)) { 180 SOC_IF_ERROR_RETURN(soc_esw_portctrl_init(unit)); 181 if (soc_property_get(unit, spn_PHY_SIMUL, 0) || SAL_BOOT_PLISIM) { 182 #if defined (BCM_WARM_BOOT_SUPPORT) 183 if (SOC_WARM_BOOT(unit)) { 184 SOC_IF_ERROR_RETURN(soc_physim_scache_recovery(unit)); 185 } else { 186 SOC_IF_ERROR_RETURN(soc_physim_scache_allocate(unit)); 187 } 188 #endif /* BCM_WARM_BOOT_SUPPORT */ 189 } 190 } 191 #endif 192 193 return SOC_E_NONE; 194 } 195 196 void 197 soc_family_suffix_update(int unit) 198 { 199 soc_family_suffix[unit] = soc_property_get_str(unit, spn_SOC_FAMILY); 200 } 201 202 /* 203 * Function: 204 * soc_init 205 * Purpose: 206 * Initialize a StrataSwitch without resetting it. 207 * Parameters: 208 * unit - StrataSwitch unit # 209 * Returns: 210 * SOC_E_XXX 211 */ 212 int 213 soc_init(int unit) 214 { 215 soc_family_suffix_update(unit); 216 217 #if defined(BCM_PETRA_SUPPORT) 218 if (SOC_IS_DPP(unit)) { 219 return (soc_dpp_init(unit, SOC_DPP_RESET_ACTION_OUT_RESET)); 220 } 221 #endif /* defined(BCM_PETRA_SUPPORT) */ 222 #if defined(BCM_DFE_SUPPORT) 223 if(SOC_IS_DFE(unit)) { 224 return (soc_dfe_init(unit,FALSE)); 225 } 226 #endif /* defined(BCM_DFE_SUPPORT) */ 227 #if defined(BCM_DNXF_SUPPORT) 228 if(SOC_IS_DNXF(unit)) { 229 return (soc_dnxf_init(unit,FALSE)); 230 } 231 #endif /* defined(BCM_DNXF_SUPPORT) */ 232 { 233 #ifdef BCM_ESW_SUPPORT 234 return(soc_do_init(unit, FALSE)); 235 #endif 236 } 237 238 return SOC_E_UNAVAIL; 239 } 240 241 /* 242 * Function: 243 * soc_deinit 244 * Purpose: 245 * DeInitialize a Device. 246 * Parameters: 247 * unit - Device unit # 248 * Returns: 249 * SOC_E_XXX 250 */ 251 int 252 soc_deinit(int unit) 253 { 254 #if defined(BCM_PETRA_SUPPORT) 255 if (SOC_IS_DPP(unit)) { 256 return (soc_dpp_deinit(unit)); 257 } 258 #endif /* defined(BCM_PETRA_SUPPORT) */ 259 260 #if defined(BCM_DFE_SUPPORT) 261 if (SOC_IS_DFE(unit)) { 262 return (soc_dfe_deinit(unit)); 263 } 264 #endif /* defined(BCM_DFE_SUPPORT) */ 265 #if defined(BCM_DNXF_SUPPORT) 266 if (SOC_IS_DNXF(unit)) { 267 return (soc_dnxf_deinit(unit)); 268 } 269 #endif /* defined(BCM_DNXF_SUPPORT) */ 270 /*inform that detaching device is done*/ 271 SOC_DETACH(unit,0); 272 273 return SOC_E_UNAVAIL; 274 } 275 276 /* 277 * Function: 278 * soc_device_reset 279 * Purpose: 280 * Perform different device reset modes/actions. 281 * Parameters: 282 * unit - Device unit # 283 * mode - reset mode: hard reset, soft reset, init .... 284 * action - im/out/inout. 285 * Returns: 286 * SOC_E_XXX 287 */ 288 int 289 soc_device_reset(int unit, int mode, int action) 290 { 291 292 #if defined(BCM_PETRA_SUPPORT) 293 if (SOC_IS_DPP(unit)) { 294 return (soc_dpp_device_reset(unit, mode, action)); 295 } 296 #endif /* defined(BCM_PETRA_SUPPORT) */ 297 298 #if defined(BCM_DNX_SUPPORT) 299 if (SOC_IS_DNX(unit)) { 300 return (soc_dnx_device_reset(unit, mode, action)); 301 } 302 #endif 303 304 #ifdef BCM_DFE_SUPPORT 305 if (SOC_IS_DFE(unit)) 306 { 307 return (soc_dfe_device_reset(unit, mode, action)); 308 } 309 #endif 310 311 #ifdef BCM_DNXF_SUPPORT 312 if (SOC_IS_DNXF(unit)) 313 { 314 return (soc_dnxf_device_reset(unit, mode, action)); 315 } 316 #endif 317 318 return SOC_E_UNAVAIL; 319 } 320 321 /* 322 * Function: 323 * soc_reset_init 324 * Purpose: 325 * Reset and initialize a StrataSwitch. 326 * Parameters: 327 * unit - StrataSwitch unit # 328 * Returns: 329 * SOC_E_XXX 330 */ 331 int 332 soc_reset_init(int unit) 333 { 334 soc_family_suffix[unit] = soc_property_get_str(unit, spn_SOC_FAMILY); 335 #if defined(BCM_PETRA_SUPPORT) 336 if (SOC_IS_DPP(unit)) { 337 return (soc_dpp_init(unit, SOC_DPP_RESET_ACTION_INOUT_RESET)); 338 } else 339 #endif /* defined(BCM_PETRA_SUPPORT) */ 340 #if defined(BCM_DFE_SUPPORT) 341 if (SOC_IS_DFE(unit)) { 342 return (soc_dfe_init(unit, TRUE)); 343 } else 344 #endif /* BCM_DFE_SUPPORT */ 345 #if defined(BCM_DNXF_SUPPORT) 346 if (SOC_IS_DNXF(unit)) { 347 return (soc_dnxf_init(unit, TRUE)); 348 } else 349 #endif /* BCM_DNXF_SUPPORT */ 350 { 351 #ifdef BCM_ESW_SUPPORT 352 return(soc_do_init(unit, TRUE)); 353 #endif 354 } 355 356 return SOC_E_UNAVAIL; 357 } 358 359 /* 360 * Function: 361 * soc_dev_name 362 * Purpose: 363 * Return official name (or optionally nickname) of attached chip. 364 * Parameters: 365 * unit - unit number 366 * Returns: 367 * Pointer to static string 368 */ 369 370 const char * 371 soc_dev_name(int unit) 372 { 373 const char *name = soc_cm_get_name(unit); 374 return (name == NULL ? "<UNKNOWN>" : name); 375 } 376 377 /* 378 * Function: 379 * soc_attached 380 * Purpose: 381 * Check if a specified SOC device is probed and attached. 382 * Returns: 383 * TRUE if attached, FALSE otherwise. 384 */ 385 int 386 soc_attached(int unit) 387 { 388 if (!SOC_UNIT_VALID(unit)) { 389 return(0); 390 } 391 392 return ((SOC_CONTROL(unit)->soc_flags & SOC_F_ATTACHED) != 0); 393 } 394 395 /* 396 * Function: 397 * _str_to_val 398 * Purpose: 399 * Convert string to value 400 * Parameters: 401 * str - (IN) value string 402 * val - (OUT) converted value 403 * scale - (IN) scale up factor (for decimal only) 404 * 1 means to multiply by 10 before return 405 * 2 means to multiply by 100 before return 406 * ... 407 * suffix - (OUT) the unit specified in the property (for decimal only) 408 * 'b' for 100b, or 'c' for 500c, ... 409 * Notes: 410 * The string is parsed as a C-style numeric constant. 411 */ 412 STATIC char * 413 _str_to_val(const char *str, int *val, int scale, char *suffix) 414 { 415 uint32 abs_val; 416 int neg, base, shift; 417 unsigned char symbol; 418 419 if (*str == '0' && str[1] != '.' && str[1] != ',') { 420 str++; 421 422 symbol = *str | 0x20; 423 if (symbol == 'x') { /* hexadecimal */ 424 str++; 425 for (abs_val = 0; *str != '\0'; str++) { 426 symbol = *str - '0'; 427 if (symbol < 10) { 428 abs_val = (abs_val << 4) | symbol; 429 continue; 430 } 431 symbol = (*str | 0x20) - 'a'; 432 if (symbol < 6) { 433 abs_val = (abs_val << 4) | (symbol + 10); 434 continue; 435 } 436 break; 437 } 438 } else { 439 if (symbol == 'b') { /* binary */ 440 base = 2; 441 shift = 1; 442 str++; 443 } else { /* octal */ 444 base = 8; 445 shift = 3; 446 } 447 for (abs_val = 0; *str != '\0'; str++) { 448 symbol = *str - '0'; 449 if (symbol < base) { 450 abs_val = (abs_val << shift) | symbol; 451 continue; 452 } 453 break; 454 } 455 } 456 *val = abs_val; 457 *suffix = (*str == ',') ? ',' : '\0'; 458 } else { 459 if (*str == '-') { 460 str++; 461 neg = TRUE; 462 } else { 463 neg = FALSE; 464 } 465 for (abs_val = 0; *str != '\0'; str++) { 466 symbol = *str - '0'; 467 if (symbol < 10) { 468 abs_val = abs_val * 10 + symbol; 469 continue; 470 } 471 break; 472 } 473 if (*str == '.') { 474 str++; 475 for (; scale > 0 && *str != '\0'; scale--, str++) { 476 symbol = *str - '0'; 477 if (symbol < 10) { 478 abs_val = abs_val * 10 + symbol; 479 continue; 480 } 481 break; 482 } 483 } 484 for (; scale > 0; scale--) { 485 abs_val *= 10; 486 } 487 488 *val = neg ? -(int)abs_val : (int)abs_val; 489 *suffix = *str; 490 } 491 492 return (char *)str; 493 } 494 495 /* 496 * Function: 497 * soc_property_get_str 498 * Purpose: 499 * Retrieve a global configuration property string. 500 * Parameters: 501 * unit - unit number 502 * name - base name of property to look up 503 * Notes: 504 * Each property requested is looked up with one suffix after 505 * another until it is found. Suffixes are tried in the following 506 * order: 507 * .<unit-num> (e.g. ".0") 508 * .<CHIP_TYPE> (e.g. BCM5680_B0) 509 * .<CHIP_GROUP> (e.g. BCM5680) 510 * <nothing> 511 */ 512 char * 513 soc_property_get_str(int unit, const char *name) 514 { 515 if (unit >= 0) { 516 /* length of name + \0 */ 517 int l = sal_strlen(name) + 1; 518 int ltemp; 519 char name_exp[SOC_PROPERTY_NAME_MAX], *s; 520 521 if (sal_snprintf(name_exp, SOC_PROPERTY_NAME_MAX, 522 "%s.%d", name, unit) >= SOC_PROPERTY_NAME_MAX) { 523 LOG_ERROR(BSL_LS_SOC_COMMON, 524 (BSL_META_U(unit, 525 "Unsupported soc_property length for %s.%d. " 526 "Max soc property length:%d\n"), 527 name, unit, SOC_PROPERTY_NAME_MAX)); 528 return NULL; 529 } 530 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 531 return s; 532 } 533 534 /* Remaining operations require that the unit is attached */ 535 if (soc_attached(unit)) { 536 537 ltemp = sal_strlen(SOC_UNIT_NAME(unit)); 538 539 /* check the length of <name>.<unit_name>\0 */ 540 if ((l + 1 + ltemp) > SOC_PROPERTY_NAME_MAX) { 541 return NULL; 542 } 543 sal_strncpy(name_exp + l, SOC_UNIT_NAME(unit), ltemp); 544 if (ltemp) 545 *(name_exp + l + ltemp) = '\0'; 546 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 547 return s; 548 } 549 550 ltemp = sal_strlen(SOC_UNIT_GROUP(unit)); 551 552 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPORT) 553 /* 554 * Reading <name>.<group name>_<revision name> 555 * For example: BCM8869X_B0 556 * Assuming: <group name> and <chip name without revision> are different but has the same length 557 */ 558 if (soc_feature(unit, soc_feature_prop_suffix_group_with_revision)) 559 { 560 int ltemp_unit_name; 561 ltemp_unit_name = sal_strlen(SOC_UNIT_NAME(unit)); 562 sal_strncpy(name_exp + l, SOC_UNIT_NAME(unit), ltemp_unit_name); 563 sal_strncpy(name_exp + l, SOC_UNIT_GROUP(unit), ltemp); 564 if (ltemp) 565 *(name_exp + l + ltemp_unit_name) = '\0'; 566 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 567 return s; 568 } 569 } 570 #endif /*BCM_DNX_SUPPORT || BCM_DNXF_SUPPORT */ 571 572 #if defined(BCM_DNX_SUPPORT) && defined(ADAPTER_SERVER_MODE) 573 if (SOC_IS_DNX(unit)){ 574 int len_adapter; 575 len_adapter = sal_strlen(DRV_ADAPTER_SERVER_SUFFIX); 576 577 /* check the length of <name>.<unit_group>_ADAPTER */ 578 if ((l + 1 + ltemp + len_adapter) > SOC_PROPERTY_NAME_MAX) { 579 return NULL; 580 } 581 sal_strncpy(name_exp + l, SOC_UNIT_GROUP(unit), ltemp); 582 sal_strncpy(name_exp + l + ltemp, DRV_ADAPTER_SERVER_SUFFIX, len_adapter); 583 if (ltemp) 584 *(name_exp + l + ltemp + len_adapter) = '\0'; 585 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 586 return s; 587 } 588 } 589 #endif /*BCM_DNX_SUPPORT && ADAPTER_SERVER_MODE*/ 590 591 /* check the length of <name>.<unit_group> */ 592 if ((l + 1 + ltemp) > SOC_PROPERTY_NAME_MAX) { 593 return NULL; 594 } 595 sal_strncpy(name_exp + l, SOC_UNIT_GROUP(unit), ltemp); 596 if (ltemp) 597 *(name_exp + l + ltemp) = '\0'; 598 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 599 return s; 600 } 601 602 #if defined(BCM_PETRA_SUPPORT) 603 /* workaround to include 88375,88680 in 88675 */ 604 if ( (sal_strstr(SOC_UNIT_GROUP(unit),"BCM88375")) || (sal_strstr(SOC_UNIT_GROUP(unit),"BCM88680")) ) { 605 sal_strncpy(name_exp + l, "BCM88675", ltemp); 606 } else if ( sal_strstr(SOC_UNIT_GROUP(unit),"BCM88270") ) { 607 /* workaround to include 88270 in 88470 */ 608 sal_strncpy(name_exp + l, "BCM88470", ltemp); 609 } 610 if (ltemp) 611 *(name_exp + l + ltemp) = '\0'; 612 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 613 return s; 614 } 615 #endif 616 617 if (soc_family_suffix[unit]) { 618 ltemp = sal_strlen(soc_family_suffix[unit]); 619 620 /* check the length of <name>.<soc_family_suffix> */ 621 if ((l + 1 + ltemp) > SOC_PROPERTY_NAME_MAX) { 622 return NULL; 623 } 624 sal_strncpy(name_exp + l, soc_family_suffix[unit], ltemp); 625 if (ltemp) 626 *(name_exp + l + ltemp) = '\0'; 627 if ((s = soc_cm_config_var_get(unit, name_exp)) != NULL) { 628 return s; 629 } 630 } 631 } 632 } 633 634 return soc_cm_config_var_get(unit, name); 635 } 636 637 /* 638 * Function: 639 * soc_property_get 640 * Purpose: 641 * Retrieve a global configuration numeric value. 642 * Parameters: 643 * unit - unit number 644 * name - base name of numeric property to look up 645 * defl - default value of numeric property 646 * Notes: 647 * See soc_property_get_str for suffix handling. 648 * The string is parsed as a C-style numeric constant. 649 */ 650 651 uint32 652 soc_property_get(int unit, const char *name, uint32 defl) 653 { 654 char *s; 655 656 if ((s = soc_property_get_str(unit, name)) == NULL) { 657 return defl; 658 } 659 660 return _shr_ctoi(s); 661 } 662 663 /* 664 * Function: 665 * soc_property_obj_attr_get 666 * Purpose: 667 * Retrieve a global configuration numeric value and its unit for the 668 * specified prefix, object and attribute. 669 * Parameters: 670 * unit - unit number 671 * prefix - prefix name of the numeric property to look up 672 * obj - object name of the numeric property to look up 673 * index - object index of the numeric property to look up 674 * attr - attribute name of the numeric property to look up 675 * scale - scale up factor (see _str_to_val) 676 * suffix - the unit specified in the property (see _str_to_val) 677 * defl - default value of numeric property 678 * Notes: 679 * The variable name is lookup up with a number of object suffixes 680 * until it is found. 681 * prefix.obj1.attr attribute of a particular object instance 682 * prefix.obj.attr attribute of the object type 683 * If none are found then the default value in defl is returned. 684 * See soc_property_get_str for other suffix handling in property name. 685 * See _str_to_val for value string handling. 686 * The string is parsed as a C-style numeric constant. 687 */ 688 689 uint32 690 soc_property_obj_attr_get(int unit, const char *prefix, const char *obj, 691 int index, const char *attr, int scale, 692 char *suffix, uint32 defl) 693 { 694 char *str; 695 int val; 696 char prop[SOC_PROPERTY_NAME_MAX]; 697 698 str = NULL; 699 700 701 if (index != -1) { 702 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 703 "%s.%s%d.%s", prefix, obj, index, attr) >= SOC_PROPERTY_NAME_MAX) { 704 LOG_ERROR(BSL_LS_SOC_COMMON, 705 (BSL_META_U(unit, 706 "Unsupported soc_property length for %s.%s%d.%s. " 707 "Max soc property length:%d\n"), 708 prefix, obj, index, attr, SOC_PROPERTY_NAME_MAX)); 709 return defl; 710 } 711 str = soc_property_get_str(unit, prop); 712 } 713 714 if (str == NULL) { 715 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 716 "%s.%s.%s", prefix, obj, attr) >= SOC_PROPERTY_NAME_MAX) { 717 LOG_ERROR(BSL_LS_SOC_COMMON, 718 (BSL_META_U(unit, 719 "Unsupported soc_property length for %s.%s.%s. " 720 "Max soc property length:%d\n"), 721 prefix, obj, attr, SOC_PROPERTY_NAME_MAX)); 722 return defl; 723 } 724 str = soc_property_get_str(unit, prop); 725 } 726 727 if (str == NULL) { 728 return defl; 729 } 730 731 (void)_str_to_val(str, &val, scale, suffix); 732 return (uint32)val; 733 } 734 735 /* 736 * Function: 737 * soc_property_get_pbmp 738 * Purpose: 739 * Retrieve a global configuration bitmap value. 740 * Parameters: 741 * unit - unit number 742 * name - base name of numeric property to look up 743 * defneg - should default bitmap be all 1's? 744 * Notes: 745 * See soc_property_get_str for suffix handling. 746 * The string can be more than 32 bits worth of 747 * data if it is in hex format (0x...). If not 748 * hex, it is treated as a 32 bit value. 749 */ 750 751 pbmp_t 752 soc_property_get_pbmp(int unit, const char *name, int defneg) 753 { 754 pbmp_t bm; 755 char *s; 756 757 if ((s = soc_property_get_str(unit, name)) == NULL) { 758 SOC_PBMP_CLEAR(bm); 759 if (defneg) { 760 SOC_PBMP_NEGATE(bm, bm); 761 } 762 return bm; 763 } 764 if (_shr_pbmp_decode(s, &bm) < 0) { 765 SOC_PBMP_CLEAR(bm); 766 } 767 return bm; 768 } 769 770 /* 771 * Function: 772 * soc_property_get_pbmp_default 773 * Purpose: 774 * Retrieve a global configuration bitmap value with specific default. 775 * Parameters: 776 * unit - unit number 777 * name - base name of numeric property to look up 778 * def_pbmp - default bitmap 779 * Notes: 780 * See soc_property_get_str for suffix handling. 781 * The string can be more than 32 bits worth of 782 * data if it is in hex format (0x...). If not 783 * hex, it is treated as a 32 bit value. 784 */ 785 786 pbmp_t 787 soc_property_get_pbmp_default(int unit, const char *name, 788 pbmp_t def_pbmp) 789 { 790 pbmp_t bm; 791 char *s; 792 793 if ((s = soc_property_get_str(unit, name)) == NULL) { 794 SOC_PBMP_ASSIGN(bm, def_pbmp); 795 return bm; 796 } 797 if (_shr_pbmp_decode(s, &bm) < 0) { 798 SOC_PBMP_CLEAR(bm); 799 } 800 return bm; 801 } 802 803 /* 804 * Function: 805 * soc_property_suffix_num_str_get 806 * Purpose: 807 * Retrieve a per-enumerated suffix global configuration bitmap value. 808 * Parameters: 809 * unit - unit number 810 * num - enumerated suffix for which property is applicable 811 * name - base name of numeric property to look up 812 * suffix - suffix of numeric property to look up 813 * pbmp_def - default value of bitmap property 814 * Notes: 815 * The variable name is lookup up with a number of suffixes 816 * until it is found. 817 * name_"suffix"0 enumerated suffix name 818 * name plain name 819 * If none are found then the default value in pbmp_def is returned. 820 * See soc_property_get_str for additional suffix handling. 821 * The string is parsed as an hexadecimal value 822 */ 823 824 pbmp_t 825 soc_property_suffix_num_pbmp_get(int unit, int num, const char *name, 826 const char *suffix, soc_pbmp_t pbmp_def) 827 { 828 pbmp_t bm; 829 char *s; 830 831 if ((s = soc_property_suffix_num_str_get(unit, num, name, suffix)) == NULL) { 832 SOC_PBMP_ASSIGN(bm, pbmp_def); 833 return bm; 834 } 835 if (_shr_pbmp_decode(s, &bm) < 0) { 836 SOC_PBMP_ASSIGN(bm, pbmp_def); 837 } 838 return bm; 839 } 840 841 842 /* 843 * Function: 844 * soc_property_get_bitmap_default 845 * Purpose: 846 * Retrieve a global configuration bitmap value with specific default. 847 * Parameters: 848 * unit - unit number 849 * name - base name of numeric property to look up 850 * def_bitmap - default bitmap 851 * bitmap - reterived bitmap 852 * Notes: 853 * See soc_property_get_str for suffix handling. 854 * The string can be more than 32 bits worth of 855 * data if it is in hex format (0x...). If not 856 * hex, it is treated as a 32 bit value. 857 */ 858 859 void 860 soc_property_get_bitmap_default(int unit, const char *name, 861 uint32 *bitmap, int max_words, uint32 *def_bitmap) 862 { 863 char *s; 864 865 if ((s = soc_property_get_str(unit, name)) == NULL) { 866 sal_memcpy(bitmap, def_bitmap, sizeof(uint32) * max_words); 867 return; 868 } 869 if (shr_bitop_str_decode(s, bitmap, max_words) < 0) { 870 sal_memset(bitmap, 0, sizeof(uint32) * max_words); 871 return; 872 } 873 } 874 875 /* 876 * Function: 877 * soc_property_get_csv 878 * Purpose: 879 * Retrieve a global configuration comma-separated value in an array. 880 * Parameters: 881 * unit - unit number 882 * name - base name of numeric property to look up 883 * val_array - Integer array to put the values 884 * val_max - Maximum number of elements to put into the array 885 * Notes: 886 * Returns the count of values read. 887 */ 888 889 int 890 soc_property_get_csv(int unit, const char *name, 891 int val_max, int *val_array) 892 { 893 char *str, suffix; 894 int count; 895 896 str = soc_property_get_str(unit, name); 897 if (str == NULL) { 898 return 0; 899 } 900 901 count = 0; 902 for (count = 0; count < val_max; count++) { 903 str = _str_to_val(str, &val_array[count], 0, &suffix); 904 if (suffix == ',') { 905 str++; 906 } else { 907 count++; 908 break; 909 } 910 } 911 912 return count; 913 } 914 915 /* 916 * Function: 917 * soc_property_port_get 918 * Purpose: 919 * Retrieve a per-port global configuration value 920 * Parameters: 921 * unit - unit number 922 * port - Zero-based port number. 923 * name - base name of numeric property to look up 924 * defl - default value of numeric property 925 * Notes: 926 * The variable name is lookup up with a number of suffixes 927 * until it is found. 928 * name_fe0 port name 929 * name_fe port type 930 * name_port1 logical port number (one based) 931 * name.port1 physical port number (one based) 932 * name_1 BCM API port number (untranslated) 933 * name plain name 934 * If none are found then NULL is returned 935 * See soc_property_get_str for additional suffix handling. 936 * The string is parsed as a C-style numeric constant. 937 */ 938 939 char * 940 soc_property_port_get_str(int unit, soc_port_t port, 941 const char *name) 942 { 943 char *s, *p; 944 char prop[SOC_PROPERTY_NAME_MAX], prop_alter[SOC_PROPERTY_NAME_MAX]; 945 int pno; 946 947 /* 948 * Try "name_fe0" if in valid range (can be out of range for 949 * subport / internal) 950 */ 951 if (port < SOC_MAX_NUM_PORTS) { 952 953 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 954 "%s_%s", name, SOC_PORT_NAME(unit, port)) >= SOC_PROPERTY_NAME_MAX) { 955 LOG_ERROR(BSL_LS_SOC_COMMON, 956 (BSL_META_U(unit, 957 "Unsupported soc_property length for %s_%s. " 958 "Max soc property length:%d\n"), 959 name, SOC_PORT_NAME(unit, port), SOC_PROPERTY_NAME_MAX)); 960 return NULL; 961 } 962 963 if ((s = soc_property_get_str(unit, prop)) != NULL) { 964 return s; 965 } 966 967 /* Try alternative name if available */ 968 if (SOC_PORT_NAME_ALTER_VALID(unit, port)) 969 { 970 if (sal_snprintf(prop_alter, SOC_PROPERTY_NAME_MAX, 971 "%s_%s", name, SOC_PORT_NAME_ALTER(unit, port)) >= SOC_PROPERTY_NAME_MAX) { 972 LOG_ERROR(BSL_LS_SOC_COMMON, 973 (BSL_META_U(unit, 974 "Unsupported soc_property length for %s_%s. " 975 "Max soc property length:%d\n"), 976 name, SOC_PORT_NAME_ALTER(unit, port), SOC_PROPERTY_NAME_MAX)); 977 return NULL; 978 } 979 980 if ((s = soc_property_get_str(unit, prop_alter)) != NULL) { 981 return s; 982 } 983 } 984 985 /* Try "name_fe" (strip off trailing digits) */ 986 p = &prop[sal_strlen(prop)-1]; 987 while (*p >= '0' && *p <= '9') { 988 --p; 989 } 990 *++p = '\0'; 991 if ((s = soc_property_get_str(unit, prop)) != NULL) { 992 return s; 993 } 994 995 /* Try alternative name if available */ 996 if (SOC_PORT_NAME_ALTER_VALID(unit, port)) 997 { 998 p = &prop_alter[sal_strlen(prop_alter)-1]; 999 while (*p >= '0' && *p <= '9') { 1000 --p; 1001 } 1002 *++p = '\0'; 1003 if ((s = soc_property_get_str(unit, prop_alter)) != NULL) { 1004 return s; 1005 } 1006 } 1007 } 1008 1009 /* Try "name.port%d" for explicit match first */ 1010 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1011 "%s.port%d", name, port+1) >= SOC_PROPERTY_NAME_MAX) { 1012 LOG_ERROR(BSL_LS_SOC_COMMON, 1013 (BSL_META_U(unit, 1014 "Unsupported soc_property length for %s.port%d. " 1015 "Max soc property length:%d\n"), 1016 name, port+1, SOC_PROPERTY_NAME_MAX)); 1017 return NULL; 1018 } 1019 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1020 return s; 1021 } 1022 1023 /* 1024 * Try "name_port1": search for matching port number. 1025 * In the case of the SOC_PORT macros, "port" is being 1026 * passed in as a ptype, not a variable. 1027 */ 1028 for (pno = 0; pno < SOC_PORT_NUM(unit, port); pno++) { 1029 if (SOC_PORT(unit, port, pno) == port) { 1030 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1031 "%s_port%d", name, pno+1) >= SOC_PROPERTY_NAME_MAX) { 1032 LOG_ERROR(BSL_LS_SOC_COMMON, 1033 (BSL_META_U(unit, 1034 "Unsupported soc_property length for %s.port%d. " 1035 "Max soc property length:%d\n"), 1036 name, pno+1, SOC_PROPERTY_NAME_MAX)); 1037 return NULL; 1038 } 1039 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1040 return s; 1041 } 1042 break; 1043 } 1044 } 1045 1046 1047 /* Try "name_%d" for raw logical port match */ 1048 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1049 "%s_%d", name, port) >= SOC_PROPERTY_NAME_MAX) { 1050 LOG_ERROR(BSL_LS_SOC_COMMON, 1051 (BSL_META_U(unit, 1052 "Unsupported soc_property length for %s_%d. " 1053 "Max soc property length:%d\n"), 1054 name, port, SOC_PROPERTY_NAME_MAX)); 1055 return NULL; 1056 } 1057 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1058 return s; 1059 } 1060 1061 /* try plain "name" */ 1062 1063 if ((s = soc_property_get_str(unit, name)) != NULL) { 1064 return s; 1065 } 1066 1067 return NULL; 1068 } 1069 1070 /* 1071 * Function: 1072 * soc_property_port_get 1073 * Purpose: 1074 * Retrieve a per-port global configuration numeric value. 1075 * Parameters: 1076 * unit - unit number 1077 * port - Zero-based port number. 1078 * name - base name of numeric property to look up 1079 * defl - default value of numeric property 1080 * Notes: 1081 * See soc_property_port_get_str for parsing details. 1082 */ 1083 1084 uint32 1085 soc_property_port_get(int unit, soc_port_t port, 1086 const char *name, uint32 defl) 1087 { 1088 char *s; 1089 1090 s = soc_property_port_get_str(unit, port, name); 1091 if (s) { 1092 return _shr_ctoi(s); 1093 } 1094 1095 return defl; 1096 } 1097 1098 /* 1099 * Function: 1100 * soc_property_port_num_get 1101 * Purpose: 1102 * Retrieve a per-port global configuration value 1103 * Parameters: 1104 * unit - unit number 1105 * port - Zero-based port number. 1106 * name - base name of numeric property to look up 1107 * defl - default value of numeric property 1108 * Notes: 1109 * The variable name is lookup up with a number of suffixes 1110 * until it is found. 1111 * name_1 BCM API port number (untranslated) 1112 * If none are found then NULL is returned 1113 * See soc_property_get_str for additional suffix handling. 1114 * The string is parsed as a C-style numeric constant. 1115 */ 1116 1117 char * 1118 soc_property_port_num_get_str(int unit, soc_port_t port, 1119 const char *name) 1120 { 1121 char *s; 1122 char prop[SOC_PROPERTY_NAME_MAX]; 1123 1124 /* Try "name_%d" for raw logical port match */ 1125 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1126 "%s_%d", name, port) >= SOC_PROPERTY_NAME_MAX) { 1127 LOG_ERROR(BSL_LS_SOC_COMMON, 1128 (BSL_META_U(unit, 1129 "Unsupported soc_property length for %s_%d. " 1130 "Max soc property length:%d\n"), 1131 name, port, SOC_PROPERTY_NAME_MAX)); 1132 return NULL; 1133 } 1134 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1135 return s; 1136 } 1137 1138 return NULL; 1139 } 1140 1141 /* 1142 * Function: 1143 * soc_property_port_num_get 1144 * Purpose: 1145 * Retrieve a per-port global configuration numeric value. 1146 * Parameters: 1147 * unit - unit number 1148 * port - Zero-based port number. 1149 * name - base name of numeric property to look up 1150 * defl - default value of numeric property 1151 * Notes: 1152 * See soc_property_port_get_str for parsing details. 1153 */ 1154 1155 uint32 1156 soc_property_port_num_get(int unit, soc_port_t port, 1157 const char *name, uint32 defl) 1158 { 1159 char *s; 1160 1161 s = soc_property_port_num_get_str(unit, port, name); 1162 if (s) { 1163 return _shr_ctoi(s); 1164 } 1165 1166 return defl; 1167 } 1168 1169 /* 1170 * Function: 1171 * soc_property_phy_get_str 1172 * Purpose: 1173 * Retrieve a per-phy global configuration value 1174 * Parameters: 1175 * unit - unit number 1176 * pport - physical port number 1177 * phy_num - PHY number in chain (1: innermost external PHY) 1178 * phy_port - PHY port (0:line, 1:system) 1179 * lane - PHY lane number on selected PHY port 1180 * name - base name of numeric property to look up 1181 * Notes: 1182 * The variable name is looked up up with a number of suffixes 1183 * until a match is found: 1184 * name{1.2} physical port number + PHY number 1185 * name{1} physical port number (match any PHY number) 1186 * name{1.2.0.1} physical port number + PHY number/port/lane 1187 * If no match is found, then the physical port number is 1188 * converted to a logical port number and sent through 1189 * soc_property_port_get_str for additional matching. 1190 */ 1191 1192 char * 1193 soc_property_phy_get_str(int unit, int pport, 1194 int phy_num, int phy_port, int lane, 1195 const char *name) 1196 { 1197 char *s; 1198 char prop[SOC_PROPERTY_NAME_MAX]; 1199 soc_port_t port; 1200 int len; 1201 1202 if (phy_num >= 0) { 1203 /* Try "name{%d.%d.%d.%d}" for exact PHY lane match */ 1204 len = sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, "%s{%d.%d.%d.%d}", 1205 name, pport, phy_num, phy_port, lane); 1206 if (len >= SOC_PROPERTY_NAME_MAX) { 1207 LOG_ERROR(BSL_LS_SOC_COMMON, 1208 (BSL_META_U(unit, 1209 "SOC property %s{%d.%d.%d.%d} too long. " 1210 "Max soc property length: %d\n"), 1211 name, pport, phy_num, phy_port, lane, 1212 SOC_PROPERTY_NAME_MAX)); 1213 return NULL; 1214 } 1215 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1216 return s; 1217 } 1218 /* Try "name{%d.%d.%d}" for exact PHY port match */ 1219 len = sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, "%s{%d.%d.%d}", 1220 name, pport, phy_num, phy_port); 1221 if (len >= SOC_PROPERTY_NAME_MAX) { 1222 LOG_ERROR(BSL_LS_SOC_COMMON, 1223 (BSL_META_U(unit, 1224 "SOC property %s{%d.%d.%d} too long. " 1225 "Max soc property length: %d\n"), 1226 name, pport, phy_num, phy_port, 1227 SOC_PROPERTY_NAME_MAX)); 1228 return NULL; 1229 } 1230 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1231 return s; 1232 } 1233 /* Try "name{%d.%d}" for exact PHY match */ 1234 len = sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, "%s{%d.%d}", 1235 name, pport, phy_num); 1236 if (len >= SOC_PROPERTY_NAME_MAX) { 1237 LOG_ERROR(BSL_LS_SOC_COMMON, 1238 (BSL_META_U(unit, 1239 "SOC property %s{%d.%d} too long. " 1240 "Max soc property length: %d\n"), 1241 name, pport, phy_num, 1242 SOC_PROPERTY_NAME_MAX)); 1243 return NULL; 1244 } 1245 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1246 return s; 1247 } 1248 } 1249 1250 /* Try "name{%d}" for specific physical port match */ 1251 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1252 "%s{%d}", name, pport) >= SOC_PROPERTY_NAME_MAX) { 1253 LOG_ERROR(BSL_LS_SOC_COMMON, 1254 (BSL_META_U(unit, 1255 "SOC property %s{%d} too long. " 1256 "Max soc property length: %d\n"), 1257 name, pport, SOC_PROPERTY_NAME_MAX)); 1258 return NULL; 1259 } 1260 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1261 return s; 1262 } 1263 1264 if (SOC_PORT_VALID_RANGE(unit, pport)) { 1265 port = pport; 1266 if (soc_feature(unit, soc_feature_logical_port_num)) { 1267 port = SOC_INFO(unit).port_p2l_mapping[pport]; 1268 } 1269 return soc_property_port_get_str(unit, port, name); 1270 } 1271 1272 return NULL; 1273 } 1274 1275 /* 1276 * Function: 1277 * soc_property_phy_get 1278 * Purpose: 1279 * Retrieve a per-PHY global configuration numeric value. 1280 * Parameters: 1281 * unit - unit number 1282 * port - physical port number 1283 * phy_num - PHY number in chain 1284 * phy_port - PHY port 1285 * lane - PHY lane number on selected PHY port 1286 * name - base name of numeric property to look up 1287 * defl - default value of numeric property 1288 * Notes: 1289 * See soc_property_phy_get_str for parsing details. 1290 */ 1291 1292 uint32 1293 soc_property_phy_get(int unit, int port, 1294 int phy_num, int phy_port, int lane, 1295 const char *name, uint32 defl) 1296 { 1297 char *s; 1298 1299 s = soc_property_phy_get_str(unit, port, phy_num, phy_port, lane, name); 1300 if (s) { 1301 return _shr_ctoi(s); 1302 } 1303 1304 return defl; 1305 } 1306 1307 /* 1308 * Function: 1309 * soc_property_phys_port_get 1310 * Purpose: 1311 * Retrieve a per-physical port global configuration numeric value. 1312 * Parameters: 1313 * unit - unit number 1314 * pport - physical port number 1315 * name - base name of numeric property to look up 1316 * defl - default value of numeric property 1317 * Notes: 1318 * See soc_property_phy_get_str for parsing details. 1319 */ 1320 1321 uint32 1322 soc_property_phys_port_get(int unit, int pport, 1323 const char *name, uint32 defl) 1324 { 1325 char *s; 1326 1327 s = soc_property_phy_get_str(unit, pport, -1, -1, -1, name); 1328 if (s) { 1329 return _shr_ctoi(s); 1330 } 1331 1332 return defl; 1333 } 1334 1335 /* 1336 * Function: 1337 * soc_property_port_obj_attr_get 1338 * Purpose: 1339 * Retrieve a global configuration numeric value and its unit for the 1340 * specified prefix, object and attribute. 1341 * Parameters: 1342 * unit - unit number 1343 * port - Zero-based port number. 1344 * prefix - prefix name of the numeric property to look up 1345 * obj - object name of the numeric property to look up 1346 * index - object index of the numeric property to look up 1347 * attr - attribute name of the numeric property to look up 1348 * scale - scale up factor (see _str_to_val) 1349 * suffix - the unit specified in the property (see _str_to_val) 1350 * defl - default value of numeric property 1351 * Notes: 1352 * The variable name is lookup up with a number of object suffixes 1353 * until it is found. 1354 * prefix.obj1.attr attribute of a particular object instance 1355 * prefix.obj.attr attribute of the object type 1356 * If none are found then the default value in defl is returned. 1357 * See soc_property_port_get_str for other suffix handling in property 1358 * name. 1359 * See _str_to_val for value string handling. 1360 * The string is parsed as a C-style numeric constant. 1361 */ 1362 1363 uint32 1364 soc_property_port_obj_attr_get(int unit, soc_port_t port, const char *prefix, 1365 const char *obj, int index, const char *attr, 1366 int scale, char *suffix, uint32 defl) 1367 { 1368 char *str; 1369 int val; 1370 char prop[SOC_PROPERTY_NAME_MAX]; 1371 1372 str = NULL; 1373 1374 if (index != -1) { 1375 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1376 "%s.%s%d.%s", prefix, obj, index, attr) >= SOC_PROPERTY_NAME_MAX) { 1377 LOG_ERROR(BSL_LS_SOC_COMMON, 1378 (BSL_META_U(unit, 1379 "Unsupported soc_property length for %s.%s%d.%s. " 1380 "Max soc property length:%d\n"), 1381 prefix, obj, index, attr, SOC_PROPERTY_NAME_MAX)); 1382 return defl; 1383 1384 } 1385 str = soc_property_port_get_str(unit, port, prop); 1386 } 1387 1388 if (str == NULL) { 1389 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1390 "%s.%s.%s", prefix, obj, attr) >= SOC_PROPERTY_NAME_MAX) { 1391 LOG_ERROR(BSL_LS_SOC_COMMON, 1392 (BSL_META_U(unit, 1393 "Unsupported soc_property length for %s.%s.%s. " 1394 "Max soc property length:%d\n"), 1395 prefix, obj, attr, SOC_PROPERTY_NAME_MAX)); 1396 return defl; 1397 1398 } 1399 str = soc_property_port_get_str(unit, port, prop); 1400 } 1401 1402 if (str == NULL) { 1403 return defl; 1404 } 1405 1406 (void)_str_to_val(str, &val, scale, suffix); 1407 return (uint32)val; 1408 } 1409 1410 int 1411 soc_property_port_get_csv(int unit, soc_port_t port, const char *name, 1412 int val_max, int *val_array) 1413 { 1414 char *str, suffix; 1415 int count; 1416 1417 str = soc_property_port_get_str(unit, port, name); 1418 if (str == NULL) { 1419 return 0; 1420 } 1421 1422 count = 0; 1423 for (count = 0; count < val_max; count++) { 1424 str = _str_to_val(str, &val_array[count], 0, &suffix); 1425 if (suffix == ',') { 1426 str++; 1427 } else { 1428 count++; 1429 break; 1430 } 1431 } 1432 1433 return count; 1434 } 1435 1436 /* 1437 * Function: 1438 * soc_property_cos_get 1439 * Purpose: 1440 * Retrieve a per-port global configuration value 1441 * Parameters: 1442 * unit - unit number 1443 * cos - Zero-based cos number. 1444 * name - base name of numeric property to look up 1445 * defl - default value of numeric property 1446 * Notes: 1447 * The variable name is lookup up with a number of suffixes 1448 * until it is found. 1449 * name.cos1 cos number (one based) 1450 * name plain name 1451 * If none are found then NULL is returned 1452 * See soc_property_get_str for additional suffix handling. 1453 * The string is parsed as a C-style numeric constant. 1454 */ 1455 1456 char * 1457 soc_property_cos_get_str(int unit, soc_cos_t cos, 1458 const char *name) 1459 { 1460 char *s; 1461 char prop[SOC_PROPERTY_NAME_MAX]; 1462 1463 /* try "name.cos%d" for explicit match first */ 1464 /* check length of <name>.cos<cos>\0 */ 1465 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1466 "%s.cos%d", name, (cos + 1)) >= SOC_PROPERTY_NAME_MAX) { 1467 LOG_ERROR(BSL_LS_SOC_COMMON, 1468 (BSL_META_U(unit, 1469 "Unsupported soc_property length for %s.cos%d. " 1470 "Max soc property length:%d\n"), 1471 name, (cos + 1), SOC_PROPERTY_NAME_MAX)); 1472 return NULL; 1473 } 1474 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1475 return(s); 1476 } 1477 /* try plain "name" */ 1478 if ((s = soc_property_get_str(unit, name)) != NULL) { 1479 return(s); 1480 } 1481 1482 return(NULL); 1483 } 1484 1485 1486 /* 1487 * Function: 1488 * soc_property_cos_get 1489 * Purpose: 1490 * Retrieve a per-cos global configuration numeric value. 1491 * Parameters: 1492 * unit - unit number 1493 * cos - Zero-based cos number. 1494 * name - base name of numeric property to look up 1495 * defl - default value of numeric property 1496 * Notes: 1497 * The variable name is lookup up with a number of suffixes 1498 * until it is found. 1499 * name_cos1 cos number (one based) 1500 * name plain name 1501 * If none are found then the default value in defl is returned. 1502 * See soc_property_get_str for additional suffix handling. 1503 * The string is parsed as a C-style numeric constant. 1504 */ 1505 uint32 1506 soc_property_cos_get(int unit, soc_cos_t cos, 1507 const char *name, uint32 defl) 1508 { 1509 char *s; 1510 1511 s = soc_property_cos_get_str(unit, cos, name); 1512 if (s) { 1513 return _shr_ctoi(s); 1514 } 1515 1516 return defl; 1517 } 1518 1519 1520 /* 1521 * Function: 1522 * soc_property_suffix_num_get 1523 * Purpose: 1524 * Retrieve a per-enumerated suffix global configuration numeric value. 1525 * Parameters: 1526 * unit - unit number 1527 * num - enumerated suffix for which property is applicable 1528 * name - base name of numeric property to look up 1529 * suffix - suffix of numeric property to look up 1530 * defl - default value of numeric property 1531 * Notes: 1532 * The variable name is lookup up with a number of suffixes 1533 * until it is found. 1534 * name_"suffix"0 enumerated suffix name 1535 * name plain name 1536 * If none are found then the default value in defl is returned. 1537 * See soc_property_get_str for additional suffix handling. 1538 * The string is parsed as a C-style numeric constant. 1539 */ 1540 1541 uint32 1542 soc_property_suffix_num_get(int unit, int num, const char *name, 1543 const char *suffix, uint32 defl) 1544 { 1545 char *s; 1546 char prop[SOC_PROPERTY_NAME_MAX]; 1547 1548 /* try "name_'suffix'0" */ 1549 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1550 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1551 LOG_ERROR(BSL_LS_SOC_COMMON, 1552 (BSL_META_U(unit, 1553 "Unsupported soc_property length for %s_%s%1d. " 1554 "Max soc property length:%d\n"), 1555 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1556 return defl; 1557 } 1558 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1559 return _shr_ctoi(s); 1560 } 1561 1562 /* try "name.port%d.suffix" for explicit match first */ 1563 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1564 "%s.port%d.%s", name, num+1, suffix) >= SOC_PROPERTY_NAME_MAX) { 1565 LOG_ERROR(BSL_LS_SOC_COMMON, 1566 (BSL_META_U(unit, 1567 "Unsupported soc_property length for %s.port%d.%s. " 1568 "Max soc property length:%d\n"), 1569 name, num+1, suffix, SOC_PROPERTY_NAME_MAX)); 1570 return defl; 1571 } 1572 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1573 return _shr_ctoi(s); 1574 } 1575 1576 /* try "name_'suffix'" */ 1577 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1578 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 1579 LOG_ERROR(BSL_LS_SOC_COMMON, 1580 (BSL_META_U(unit, 1581 "Unsupported soc_property length for %s_%s. " 1582 "Max soc property length:%d\n"), 1583 name, suffix, SOC_PROPERTY_NAME_MAX)); 1584 return defl; 1585 } 1586 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1587 return _shr_ctoi(s); 1588 } 1589 1590 /* try plain "name" */ 1591 if ((s = soc_property_get_str(unit, name)) != NULL) { 1592 return _shr_ctoi(s); 1593 } 1594 1595 return defl; 1596 } 1597 1598 /* 1599 * Function: 1600 * soc_property_suffix_num_get_only_suffix 1601 * Purpose: 1602 * Retrieve a per-enumerated suffix global configuration numeric value. 1603 * Parameters: 1604 * unit - unit number 1605 * num - enumerated suffix for which property is applicable 1606 * name - base name of numeric property to look up 1607 * suffix - suffix of numeric property to look up 1608 * defl - default value of numeric property 1609 * Notes: 1610 * The variable name is lookup up with a number of suffixes 1611 * until it is found. 1612 * name_"suffix"0 enumerated suffix name 1613 * If none are found then the default value in defl is returned. 1614 * See soc_property_get_str for additional suffix handling. 1615 * The string is parsed as a C-style numeric constant. 1616 */ 1617 1618 uint32 1619 soc_property_suffix_num_get_only_suffix(int unit, int num, const char *name, 1620 const char *suffix, uint32 defl) 1621 { 1622 char *s; 1623 char prop[SOC_PROPERTY_NAME_MAX]; 1624 1625 /* try "name_'suffix'0" */ 1626 /* check length of <name>_<suffix><num>\0 */ 1627 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1628 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1629 LOG_ERROR(BSL_LS_SOC_COMMON, 1630 (BSL_META_U(unit, 1631 "Unsupported soc_property length for %s_%s%1d. " 1632 "Max soc property length:%d\n"), 1633 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1634 return defl; 1635 } 1636 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1637 return _shr_ctoi(s); 1638 } 1639 1640 /* try "name.port%d.suffix" for explicit match first */ 1641 /* check length of <name>.port<num>.<suffix>\0 */ 1642 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1643 "%s.port%d.%s", name, num+1, suffix) >= SOC_PROPERTY_NAME_MAX) { 1644 LOG_ERROR(BSL_LS_SOC_COMMON, 1645 (BSL_META_U(unit, 1646 "Unsupported soc_property length for %s.port%d.%s. " 1647 "Max soc property length:%d\n"), 1648 name, num+1, suffix, SOC_PROPERTY_NAME_MAX)); 1649 return defl; 1650 } 1651 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1652 return _shr_ctoi(s); 1653 } 1654 1655 /* try "name_'suffix'" */ 1656 /* check length of <name>_<suffix>\0 */ 1657 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1658 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 1659 LOG_ERROR(BSL_LS_SOC_COMMON, 1660 (BSL_META_U(unit, 1661 "Unsupported soc_property length for %s_%s. " 1662 "Max soc property length:%d\n"), 1663 name, suffix, SOC_PROPERTY_NAME_MAX)); 1664 return defl; 1665 } 1666 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1667 return _shr_ctoi(s); 1668 } 1669 1670 return defl; 1671 } 1672 1673 /* 1674 * Function: 1675 * soc_property_suffix_num_str_get 1676 * Purpose: 1677 * Retrieve a per-enumerated suffix global configuration numeric value. 1678 * Parameters: 1679 * unit - unit number 1680 * num - enumerated suffix for which property is applicable 1681 * name - base name of numeric property to look up 1682 * suffix - suffix of numeric property to look up 1683 * defl - default value of numeric property 1684 * Notes: 1685 * The variable name is lookup up with a number of suffixes 1686 * until it is found. 1687 * name_"suffix"0 enumerated suffix name 1688 * name plain name 1689 * If none are found then the default value in defl is returned. 1690 * See soc_property_get_str for additional suffix handling. 1691 * The string is parsed as a C-style numeric constant. 1692 */ 1693 1694 1695 char* 1696 soc_property_suffix_num_str_get(int unit, int num, const char *name, 1697 const char *suffix) 1698 { 1699 char *s; 1700 char prop[SOC_PROPERTY_NAME_MAX]; 1701 1702 /* try "name_'suffix'0" */ 1703 /* check length of <name>_<suffix>\0 */ 1704 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1705 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1706 LOG_ERROR(BSL_LS_SOC_COMMON, 1707 (BSL_META_U(unit, 1708 "Unsupported soc_property length for %s_%s%1d. " 1709 "Max soc property length:%d\n"), 1710 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1711 return NULL; 1712 } 1713 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1714 return s; 1715 } 1716 1717 1718 /* try "name.port%d.suffix" for explicit match first */ 1719 /* check length of <name>.port<num>.<suffix>\0 */ 1720 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1721 "%s.port%d.%s", name, num+1, suffix) >= SOC_PROPERTY_NAME_MAX) { 1722 LOG_ERROR(BSL_LS_SOC_COMMON, 1723 (BSL_META_U(unit, 1724 "Unsupported soc_property length for %s.port%d.%s. " 1725 "Max soc property length:%d\n"), 1726 name, num+1, suffix, SOC_PROPERTY_NAME_MAX)); 1727 return NULL; 1728 } 1729 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1730 return s; 1731 } 1732 1733 /* try "name_'suffix'" */ 1734 /* check length of <name>_<suffix>\0 */ 1735 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1736 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 1737 LOG_ERROR(BSL_LS_SOC_COMMON, 1738 (BSL_META_U(unit, 1739 "Unsupported soc_property length for %s_%s. " 1740 "Max soc property length:%d\n"), 1741 name, suffix, SOC_PROPERTY_NAME_MAX)); 1742 return NULL; 1743 } 1744 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1745 return s; 1746 } 1747 1748 /* try plain "name" */ 1749 if ((s = soc_property_get_str(unit, name)) != NULL) { 1750 return s; 1751 } 1752 1753 return NULL; 1754 } 1755 1756 1757 /* 1758 * Function: 1759 * soc_property_suffix_num_only_suffix_str_get 1760 * Purpose: 1761 * Retrieve a per-enumerated suffix global configuration numeric value. 1762 * Parameters: 1763 * unit - unit number 1764 * num - enumerated suffix for which property is applicable 1765 * name - base name of numeric property to look up 1766 * suffix - suffix of numeric property to look up 1767 * defl - default value of numeric property 1768 * Notes: 1769 * The variable name is lookup up with a number of suffixes 1770 * until it is found. 1771 * name_"suffix"0 enumerated suffix name 1772 * name plain name 1773 * If none are found then the default value in defl is returned. 1774 * See soc_property_get_str for additional suffix handling. 1775 * The string is parsed as a C-style numeric constant. 1776 */ 1777 1778 1779 char* 1780 soc_property_suffix_num_only_suffix_str_get(int unit, int num, const char *name, 1781 const char *suffix) 1782 { 1783 char *s; 1784 char prop[SOC_PROPERTY_NAME_MAX]; 1785 1786 /* try "name_'suffix'0" */ 1787 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1788 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1789 LOG_ERROR(BSL_LS_SOC_COMMON, 1790 (BSL_META_U(unit, 1791 "Unsupported soc_property length for %s_%s%1d. " 1792 "Max soc property length:%d\n"), 1793 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1794 return NULL; 1795 } 1796 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1797 return s; 1798 } 1799 1800 /* try "name.port%d.suffix" for explicit match first */ 1801 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1802 "%s.port%d.%s", name, num+1, suffix) >= SOC_PROPERTY_NAME_MAX) { 1803 LOG_ERROR(BSL_LS_SOC_COMMON, 1804 (BSL_META_U(unit, 1805 "Unsupported soc_property length for %s.port%d.%s. " 1806 "Max soc property length:%d\n"), 1807 name, num+1, suffix, SOC_PROPERTY_NAME_MAX)); 1808 return NULL; 1809 } 1810 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1811 return s; 1812 } 1813 1814 /* try "name_'suffix'" */ 1815 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1816 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 1817 LOG_ERROR(BSL_LS_SOC_COMMON, 1818 (BSL_META_U(unit, 1819 "Unsupported soc_property length for %s_%s. " 1820 "Max soc property length:%d\n"), 1821 name, suffix, SOC_PROPERTY_NAME_MAX)); 1822 return NULL; 1823 1824 } 1825 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1826 return s; 1827 } 1828 1829 return NULL; 1830 } 1831 /* 1832 * Function: 1833 * soc_property_port_suffix_num_get 1834 * Purpose: 1835 * Retrieve a per-port, per-enumerated suffix global 1836 * configuration numeric value. 1837 * Parameters: 1838 * unit - unit number 1839 * port - Zero-based port number. 1840 * num - enumerated suffix for which property is applicable 1841 * name - base name of numeric property to look up 1842 * suffix - suffix of numeric property to look up 1843 * defl - default value of numeric property 1844 * Notes: 1845 * The variable name is lookup up with a number of suffixes 1846 * until it is found. 1847 * name_"suffix"0_port enumerated suffix name per port 1848 * name_"suffix"0 enumerated suffix name 1849 * name_port plain name per port 1850 * name plain name 1851 * If none are found then the default value in defl is returned. 1852 * See soc_property_get_str for additional suffix handling. 1853 * The string is parsed as a C-style numeric constant. 1854 */ 1855 1856 uint32 1857 soc_property_port_suffix_num_get(int unit, soc_port_t port, 1858 int num, const char *name, 1859 const char *suffix, uint32 defl) 1860 { 1861 char *s; 1862 char prop[SOC_PROPERTY_NAME_MAX]; 1863 1864 /* "name_'suffix'#" */ 1865 /* check length of <name>_<suffix><num>\0 */ 1866 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1867 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1868 LOG_ERROR(BSL_LS_SOC_COMMON, 1869 (BSL_META_U(unit, 1870 "Unsupported soc_property length for %s_%s%1d. " 1871 "Max soc property length:%d\n"), 1872 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1873 return defl; 1874 } 1875 1876 /* try "name_'suffix'#" per port*/ 1877 if ((s = soc_property_port_get_str(unit, port, prop)) != NULL) { 1878 return _shr_ctoi(s); 1879 } 1880 1881 /* try "name_'suffix'#" */ 1882 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1883 return _shr_ctoi(s); 1884 } 1885 1886 /* "name_'suffix'" */ 1887 /* check length of <name>_<suffix>\0 */ 1888 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1889 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 1890 LOG_ERROR(BSL_LS_SOC_COMMON, 1891 (BSL_META_U(unit, 1892 "Unsupported soc_property length for %s_%s. " 1893 "Max soc property length:%d\n"), 1894 name, suffix, SOC_PROPERTY_NAME_MAX)); 1895 return defl; 1896 } 1897 /* try "name_'suffix'" per port */ 1898 if ((s = soc_property_port_get_str(unit, port, prop)) != NULL) { 1899 return _shr_ctoi(s); 1900 } 1901 1902 /* try "name_'suffix'"*/ 1903 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1904 return _shr_ctoi(s); 1905 } 1906 1907 1908 /* try plain "name" per port*/ 1909 if ((s = soc_property_port_get_str(unit, port, name)) != NULL) { 1910 return _shr_ctoi(s); 1911 } 1912 1913 /* try plain "name" */ 1914 if ((s = soc_property_get_str(unit, name)) != NULL) { 1915 return _shr_ctoi(s); 1916 } 1917 1918 return defl; 1919 } 1920 1921 1922 uint32 1923 soc_property_port_suffix_num_match_port_get(int unit, soc_port_t port, 1924 int num, const char *name, 1925 const char *suffix, uint32 defl) 1926 { 1927 char *s; 1928 char prop[SOC_PROPERTY_NAME_MAX]; 1929 1930 /* "name_'suffix'" */ 1931 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1932 "%s_%s_%d", name, suffix, port) >= SOC_PROPERTY_NAME_MAX) { 1933 LOG_ERROR(BSL_LS_SOC_COMMON, 1934 (BSL_META_U(unit, 1935 "Unsupported soc_property length for %s_%s. " 1936 "Max soc property length:%d\n"), 1937 name, suffix, SOC_PROPERTY_NAME_MAX)); 1938 return defl; 1939 } 1940 /* only check "name_'suffix'" per port */ 1941 if ((s = soc_property_get_str(unit, prop)) != NULL) { 1942 return _shr_ctoi(s); 1943 } 1944 1945 return defl; 1946 1947 } 1948 1949 1950 /* 1951 * Function: 1952 * soc_property_port_suffix_num_get_str 1953 * Purpose: 1954 * Retrieve a per-port, per-enumerated suffix global 1955 * configuration string value. 1956 * Parameters: 1957 * unit - unit number 1958 * port - Zero-based port number. 1959 * num - enumerated suffix for which property is applicable 1960 * name - base name of numeric property to look up 1961 * suffix - suffix of numeric property to look up 1962 * Notes: 1963 * The variable name is lookup up with a number of suffixes 1964 * until it is found. 1965 * name_"suffix"0_port enumerated suffix name per port 1966 * name_"suffix"0 enumerated suffix name 1967 * name_port plain name per port 1968 * name plain name 1969 * If none are found then the NULL is returned. 1970 * See soc_property_get_str for additional suffix handling. 1971 * The string is parsed as a C-style numeric constant. 1972 */ 1973 1974 char* 1975 soc_property_port_suffix_num_get_str(int unit, soc_port_t port, 1976 int num, const char *name, 1977 const char *suffix) 1978 { 1979 char *s; 1980 char prop[SOC_PROPERTY_NAME_MAX]; 1981 1982 /* "name_'suffix'#" */ 1983 /* check length of <name>_<suffix><num>\0 */ 1984 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 1985 "%s_%s%1d", name, suffix, num) >= SOC_PROPERTY_NAME_MAX) { 1986 LOG_ERROR(BSL_LS_SOC_COMMON, 1987 (BSL_META_U(unit, 1988 "Unsupported soc_property length for %s_%s%1d. " 1989 "Max soc property length:%d\n"), 1990 name, suffix, num, SOC_PROPERTY_NAME_MAX)); 1991 return NULL; 1992 } 1993 /* try "name_'suffix'#" per port*/ 1994 if ((s = soc_property_port_get_str(unit, port, prop)) != NULL) { 1995 return s; 1996 } 1997 1998 /* try "name_'suffix'#" */ 1999 if ((s = soc_property_get_str(unit, prop)) != NULL) { 2000 return s; 2001 } 2002 2003 2004 /* "name_'suffix'" */ 2005 /* check length of <name>_<suffix>\0 */ 2006 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 2007 "%s_%s", name, suffix) >= SOC_PROPERTY_NAME_MAX) { 2008 LOG_ERROR(BSL_LS_SOC_COMMON, 2009 (BSL_META_U(unit, 2010 "Unsupported soc_property length for %s_%s. " 2011 "Max soc property length:%d\n"), 2012 name, suffix, SOC_PROPERTY_NAME_MAX)); 2013 return NULL; 2014 } 2015 /* try "name_'suffix'" per port */ 2016 if ((s = soc_property_port_get_str(unit, port, prop)) != NULL) { 2017 return s; 2018 } 2019 /* try "name_'suffix'"*/ 2020 if ((s = soc_property_get_str(unit, prop)) != NULL) { 2021 return s; 2022 } 2023 2024 /* try plain "name" per port*/ 2025 if ((s = soc_property_port_get_str(unit, port, name)) != NULL) { 2026 return s; 2027 } 2028 2029 /* try plain "name" */ 2030 if ((s = soc_property_get_str(unit, name)) != NULL) { 2031 return s; 2032 } 2033 2034 return NULL; 2035 } 2036 2037 2038 /* 2039 * Function: 2040 * soc_property_uc_get_str 2041 * Purpose: 2042 * Retrieve a per-uc global configuration value 2043 * Parameters: 2044 * unit - unit number 2045 * uc - Microcontroller number. 0 is PCI Host. 2046 * name - base name of numeric property to look up 2047 * Notes: 2048 * The variable name is lookup up with a number of suffixes 2049 * until it is found. 2050 * name_"suffix" suffix is pci | uc0 | uc1 ... 2051 * name plain name 2052 * If none are found then NULL is returned. 2053 * See soc_property_get_str for additional suffix handling. 2054 * The string is parsed as a C-style numeric constant. 2055 */ 2056 char * 2057 soc_property_uc_get_str(int unit, int uc, 2058 const char *name) 2059 { 2060 char *s; 2061 char prop[SOC_PROPERTY_NAME_MAX]; 2062 2063 /* try "name_uc%d" for explicit match first */ 2064 if (0 == uc) { 2065 /* check length of <name>_pci\0 */ 2066 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 2067 "%s_pci", name) >= SOC_PROPERTY_NAME_MAX) { 2068 LOG_ERROR(BSL_LS_SOC_COMMON, 2069 (BSL_META_U(unit, 2070 "Unsupported soc_property length for %s_pci. " 2071 "Max soc property length:%d\n"), 2072 name, SOC_PROPERTY_NAME_MAX)); 2073 return NULL; 2074 2075 } 2076 if ((s = soc_property_get_str(unit, prop)) != NULL) { 2077 return(s); 2078 } 2079 } else { 2080 2081 /* check length of <name>_uc<uc>\0 */ 2082 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 2083 "%s_uc%d", name, (uc - 1)) >= SOC_PROPERTY_NAME_MAX) { 2084 LOG_ERROR(BSL_LS_SOC_COMMON, 2085 (BSL_META_U(unit, 2086 "Unsupported soc_property length for %s_uc%d. " 2087 "Max soc property length:%d\n"), 2088 name, (uc - 1), SOC_PROPERTY_NAME_MAX)); 2089 return NULL; 2090 } 2091 if ((s = soc_property_get_str(unit, prop)) != NULL) { 2092 return(s); 2093 } 2094 } 2095 2096 /* try plain "name" */ 2097 if ((s = soc_property_get_str(unit, name)) != NULL) { 2098 return(s); 2099 } 2100 2101 return(NULL); 2102 } 2103 2104 /* 2105 * Function: 2106 * soc_property_uc_get 2107 * Purpose: 2108 * Retrieve a per-uc global configuration value 2109 * Parameters: 2110 * unit - unit number 2111 * uc - Microcontroller number. 0 is PCI Host. 2112 * name - base name of numeric property to look up 2113 * defl - default value of numeric property 2114 * Notes: 2115 * The variable name is lookup up with a number of suffixes 2116 * until it is found. 2117 * name_"suffix" suffix is pci | uc0 | uc1 ... 2118 * name plain name 2119 * If none are found then the default value in defl is returned. 2120 * See soc_property_get_str for additional suffix handling. 2121 * The string is parsed as a C-style numeric constant. 2122 */ 2123 uint32 2124 soc_property_uc_get(int unit, int uc, 2125 const char *name, uint32 defl) 2126 { 2127 char *s; 2128 2129 s = soc_property_uc_get_str(unit, uc, name); 2130 if (s) { 2131 return _shr_ctoi(s); 2132 } 2133 2134 return defl; 2135 } 2136 2137 /* 2138 * Function: 2139 * soc_property_ci_get_str 2140 * Purpose: 2141 * Retrieve a per-ci global configuration value 2142 * Parameters: 2143 * unit - unit number 2144 * ci - Chip Intergface Number. 2145 * name - base name of numeric property to look up 2146 * Notes: 2147 * The variable name is lookup up with a number of suffixes 2148 * until it is found. 2149 * name_"suffix" suffix is ci0 | ci1 ... 2150 * name plain name 2151 * If none are found then NULL is returned. 2152 * See soc_property_get_str for additional suffix handling. 2153 * The string is parsed as a C-style numeric constant. 2154 */ 2155 char * 2156 soc_property_ci_get_str(int unit, int ci, 2157 const char *name) 2158 { 2159 char *s; 2160 char prop[SOC_PROPERTY_NAME_MAX]; 2161 2162 /* try "name_ci%d" for explicit match first */ 2163 /* check length of <name>_ci<ci>\0 */ 2164 if (sal_snprintf(prop, SOC_PROPERTY_NAME_MAX, 2165 "%s_ci%d", name, ci) >= SOC_PROPERTY_NAME_MAX) { 2166 LOG_ERROR(BSL_LS_SOC_COMMON, 2167 (BSL_META_U(unit, 2168 "Unsupported soc_property length for %s_ci%d. " 2169 "Max soc property length:%d\n"), 2170 name, ci, SOC_PROPERTY_NAME_MAX)); 2171 return NULL; 2172 } 2173 if ((s = soc_property_get_str(unit, prop)) != NULL) { 2174 return(s); 2175 } 2176 /* try plain "name" */ 2177 if ((s = soc_property_get_str(unit, name)) != NULL) { 2178 return(s); 2179 } 2180 2181 return(NULL); 2182 } 2183 2184 /* 2185 * Function: 2186 * soc_property_ci_get 2187 * Purpose: 2188 * Retrieve a per-ci global configuration value 2189 * Parameters: 2190 * unit - unit number 2191 * ci - Chip Intergface Number. 2192 * name - base name of numeric property to look up 2193 * defl - default value of numeric property 2194 * Notes: 2195 * The variable name is lookup up with a number of suffixes 2196 * until it is found. 2197 * name_"suffix" suffix is ci0 | ci1 ... 2198 * name plain name 2199 * If none are found then the default value in defl is returned. 2200 * See soc_property_get_str for additional suffix handling. 2201 * The string is parsed as a C-style numeric constant. 2202 */ 2203 uint32 2204 soc_property_ci_get(int unit, int ci, 2205 const char *name, uint32 defl) 2206 { 2207 char *s; 2208 2209 s = soc_property_ci_get_str(unit, ci, name); 2210 if (s) { 2211 return _shr_ctoi(s); 2212 } 2213 2214 return defl; 2215 } 2216 2217 /* 2218 * Function: 2219 * soc_property_ci_get_csv 2220 * Purpose: 2221 * Retrieve a per-ci global configuration comma-separated value in an array. 2222 * Parameters: 2223 * unit - unit number 2224 * ci - Chip Intergface Number. 2225 * name - base name of numeric property to look up 2226 * val_array - Integer array to put the values 2227 * val_max - Maximum number of elements to put into the array 2228 * Notes: 2229 * Returns the count of values read. 2230 * The variable name is lookup up with a number of suffixes 2231 * until it is found. 2232 * name_"suffix" suffix is ci0 | ci1 ... 2233 * name plain name 2234 * If none are found then the default value in defl is returned. 2235 * See soc_property_ci_get_str for additional suffix handling. 2236 * The string is parsed as a C-style numeric constant. 2237 */ 2238 int 2239 soc_property_ci_get_csv(int unit, int ci, const char *name, 2240 int val_max, int *val_array) 2241 { 2242 char *str, suffix; 2243 int count; 2244 2245 str = soc_property_ci_get_str(unit, ci, name); 2246 if (str == NULL) { 2247 return 0; 2248 } 2249 2250 count = 0; 2251 for (count = 0; count < val_max; count++) { 2252 str = _str_to_val(str, &val_array[count], 0, &suffix); 2253 if (suffix == ',') { 2254 str++; 2255 } else { 2256 count++; 2257 break; 2258 } 2259 } 2260 2261 return count; 2262 } 2263 2264 soc_block_name_t soc_block_port_names[] = 2265 SOC_BLOCK_PORT_NAMES_INITIALIZER; 2266 soc_block_name_t soc_block_names[] = 2267 SOC_BLOCK_NAMES_INITIALIZER; 2268 2269 2270 soc_block_name_t soc_dpp_block_port_names[] = 2271 SOC_BLOCK_DPP_PORT_NAMES_INITIALIZER; 2272 soc_block_name_t soc_dpp_block_names[] = 2273 SOC_BLOCK_DPP_NAMES_INITIALIZER; 2274 2275 char * 2276 soc_block_port_name_lookup_ext(soc_block_t blk, int unit) 2277 { 2278 int i; 2279 2280 { 2281 for (i = 0; soc_block_port_names[i].blk != SOC_BLK_NONE; i++) { 2282 if (soc_block_port_names[i].blk == blk) { 2283 if (blk == SOC_BLK_GXPORT) { 2284 if (SOC_IS_TD_TT(unit) && !SOC_IS_HELIX5(unit)) { 2285 return "xlport"; 2286 } 2287 } else if (blk == SOC_BLK_BSAFE) { 2288 if (SOC_IS_TD_TT(unit)) { 2289 return "otpc"; 2290 } 2291 } 2292 return soc_block_port_names[i].name; 2293 } 2294 } 2295 } 2296 return "?"; 2297 } 2298 2299 char * 2300 soc_block_name_lookup_ext(soc_block_t blk, int unit) 2301 { 2302 int i; 2303 2304 #if defined(BCM_SAND_SUPPORT) 2305 if (SOC_IS_SAND(unit)) { 2306 for (i = 0; soc_dpp_block_names[i].blk != SOC_BLK_NONE; i++) { 2307 if (soc_dpp_block_names[i].blk == blk) { 2308 return soc_dpp_block_names[i].name; 2309 } 2310 } 2311 } 2312 else 2313 #endif 2314 2315 { 2316 for (i = 0; soc_block_names[i].blk != SOC_BLK_NONE; i++) { 2317 if (soc_block_names[i].blk == blk) { 2318 if (blk == SOC_BLK_GXPORT) { 2319 if (SOC_IS_TD_TT(unit) && !SOC_IS_HELIX5(unit)) { 2320 return "xlport"; 2321 } 2322 } else if (blk == SOC_BLK_BSAFE) { 2323 if (SOC_IS_TD_TT(unit)) { 2324 return "otpc"; 2325 } 2326 } 2327 return soc_block_names[i].name; 2328 } 2329 } 2330 } 2331 return "?"; 2332 } 2333 2334 soc_block_t 2335 soc_block_port_name_match(char *name) 2336 { 2337 int i; 2338 2339 2340 for (i = 0; soc_block_port_names[i].blk != SOC_BLK_NONE; i++) { 2341 if (sal_strcmp(soc_block_port_names[i].name, name) == 0) { 2342 return soc_block_port_names[i].blk; 2343 } 2344 } 2345 return SOC_BLK_NONE; 2346 } 2347 2348 soc_block_t 2349 soc_block_name_match(int unit, char *name) 2350 { 2351 int i; 2352 2353 #if defined(BCM_SAND_SUPPORT) 2354 if (SOC_IS_SAND(unit)) 2355 { 2356 for (i = 0; soc_dpp_block_names[i].blk != SOC_BLK_NONE; i++) 2357 { 2358 if (sal_strncasecmp(soc_dpp_block_names[i].name, name, strlen(soc_dpp_block_names[i].name)) == 0) 2359 { 2360 return soc_dpp_block_names[i].blk; 2361 } 2362 } 2363 } 2364 else 2365 #endif 2366 { 2367 2368 for (i = 0; soc_block_names[i].blk != SOC_BLK_NONE; i++) { 2369 if (sal_strcmp(soc_block_names[i].name, name) == 0) { 2370 return soc_block_names[i].blk; 2371 } 2372 } 2373 } 2374 return SOC_BLK_NONE; 2375 } 2376 2377 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 2378 /* 2379 * Function: 2380 * soc_xport_type_update 2381 * Purpose: 2382 * Rewrite the SOC control port structures to reflect the 10G port mode, 2383 * and reinitialize the port 2384 * Parameters: 2385 * unit - XGS unit #. 2386 * port - XGS port # on unit. 2387 * mode - (0 fo iee,1 for higig variants,encap value for other modes ) 2388 * Returns: 2389 * None. 2390 * Notes: 2391 * Must pause linkscan and take COUNTER_LOCK before calling this. 2392 */ 2393 void 2394 soc_xport_type_update(int unit, soc_port_t port, int mode) 2395 { 2396 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 2397 soc_info_t *si; 2398 soc_port_t it_port; 2399 int blk, blktype; 2400 int port_speed; 2401 2402 si = &SOC_INFO(unit); 2403 2404 /* We need to lock the SOC structures until we finish the update */ 2405 SOC_CONTROL_LOCK(unit); 2406 2407 port_speed = (0 != si->port_init_speed[port]) ? 2408 si->port_init_speed[port] : si->port_speed_max[port]; 2409 if (mode == 1) { 2410 SOC_PBMP_PORT_ADD(si->st.bitmap, port); 2411 SOC_PBMP_PORT_ADD(si->hg.bitmap, port); 2412 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port); 2413 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port); 2414 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2415 SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, port); 2416 SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, port); 2417 } else if( mode == SOC_ENCAP_CPRI) { 2418 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port); 2419 SOC_PBMP_PORT_ADD(si->cpri.bitmap, port); 2420 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port); 2421 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port); 2422 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2423 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 2424 SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, port); 2425 } else if( mode == SOC_ENCAP_RSVD4) { 2426 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port); 2427 SOC_PBMP_PORT_ADD(si->rsvd4.bitmap, port); 2428 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port); 2429 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port); 2430 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2431 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 2432 SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, port); 2433 } else { 2434 SOC_PBMP_PORT_ADD(si->ether.bitmap, port); 2435 if ((port_speed >= 100000) && (si->port_speed_max[port] >= 100000)){ 2436 SOC_PBMP_PORT_ADD(si->ce.bitmap, port); 2437 } else if ((port_speed < 10000) && (si->port_speed_max[port] < 10000)) { 2438 SOC_PBMP_PORT_ADD(si->ge.bitmap, port); 2439 } else { 2440 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 2441 } 2442 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port); 2443 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 2444 SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, port); 2445 SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, port); 2446 } 2447 2448 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \ 2449 si->ptype.num = 0; \ 2450 si->ptype.min = si->ptype.max = -1; \ 2451 PBMP_ITER(si->ptype.bitmap, it_port) { \ 2452 si->ptype.port[si->ptype.num++] = it_port; \ 2453 if (si->ptype.min < 0) { \ 2454 si->ptype.min = it_port; \ 2455 } \ 2456 if (it_port > si->ptype.max) { \ 2457 si->ptype.max = it_port; \ 2458 } \ 2459 } 2460 2461 /* Recalculate port type data */ 2462 RECONFIGURE_PORT_TYPE_INFO(ether); 2463 RECONFIGURE_PORT_TYPE_INFO(st); 2464 RECONFIGURE_PORT_TYPE_INFO(hg); 2465 RECONFIGURE_PORT_TYPE_INFO(xe); 2466 RECONFIGURE_PORT_TYPE_INFO(ge); 2467 RECONFIGURE_PORT_TYPE_INFO(ce); 2468 RECONFIGURE_PORT_TYPE_INFO(cpri); 2469 RECONFIGURE_PORT_TYPE_INFO(rsvd4); 2470 #undef RECONFIGURE_PORT_TYPE_INFO 2471 2472 soc_dport_map_update(unit); 2473 2474 /* Resolve block membership for registers */ 2475 if (SOC_IS_FB_FX_HX(unit)) { /* Not HBS */ 2476 for (blk = 0; SOC_BLOCK_INFO(unit, blk).type >= 0; blk++) { 2477 blktype = SOC_BLOCK_INFO(unit, blk).type; 2478 switch (blktype) { 2479 case SOC_BLK_IPIPE: 2480 if (!mode) { 2481 SOC_PBMP_PORT_ADD(si->block_bitmap[blk], port); 2482 } else { 2483 SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], port); 2484 } 2485 break; 2486 case SOC_BLK_IPIPE_HI: 2487 if (mode) { 2488 SOC_PBMP_PORT_ADD(si->block_bitmap[blk], port); 2489 } else { 2490 SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], port); 2491 } 2492 break; 2493 case SOC_BLK_EPIPE: 2494 if (!mode) { 2495 SOC_PBMP_PORT_ADD(si->block_bitmap[blk], port); 2496 } else { 2497 SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], port); 2498 } 2499 break; 2500 case SOC_BLK_EPIPE_HI: 2501 if (mode) { 2502 SOC_PBMP_PORT_ADD(si->block_bitmap[blk], port); 2503 } else { 2504 SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], port); 2505 } 2506 break; 2507 } 2508 } 2509 } 2510 2511 /* Release SOC structures lock */ 2512 SOC_CONTROL_UNLOCK(unit); 2513 2514 #else /* BCM_FIREBOLT_SUPPORT || BCM_BRADLEY_SUPPORT */ 2515 COMPILER_REFERENCE(unit); 2516 COMPILER_REFERENCE(port); 2517 COMPILER_REFERENCE(mode); 2518 #endif 2519 } 2520 2521 /* 2522 * Function: 2523 * soc_xport_type_mode_update 2524 * Purpose: 2525 * Rewrite the SOC control port structures to reflect the current port 2526 * mode, and reinitialize the port. 2527 * 2528 * This function is simular to soc_xport_type_update() but the differnce 2529 * here is the encap type updated will check higig encap modes of 2530 * {HG/HG2/HG2-LITE/IEEE} for different encap bitmap assignment. 2531 * Parameters: 2532 * unit - XGS unit #. 2533 * port - XGS port # on unit. 2534 * hg_mode - (IEEE/HG/HG2/HG2-LITE) 2535 * Returns: 2536 * None. 2537 * Notes: 2538 * Must pause linkscan and take COUNTER_LOCK before calling this. 2539 */ 2540 void 2541 soc_xport_type_mode_update(int unit, soc_port_t port, int hg_mode) 2542 { 2543 soc_info_t *si; 2544 soc_port_t it_port; 2545 2546 si = &SOC_INFO(unit); 2547 2548 /* We need to lock the SOC structures until we finish the update */ 2549 SOC_CONTROL_LOCK(unit); 2550 2551 if (hg_mode != SOC_ENCAP_IEEE) { 2552 SOC_PBMP_PORT_ADD(si->st.bitmap, port); 2553 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port); 2554 /* special process for HG-Lite support to avoid wrong PBMP assignment. 2555 * 2556 * Note : 2557 * the 'to_hg_port' for this special design must carry proper encap mode 2558 * instead of TRUE/FALSE only. 2559 */ 2560 if (hg_mode == SOC_ENCAP_HIGIG2_LITE) { 2561 SOC_PBMP_PORT_ADD(si->hl.bitmap, port); 2562 /* for XE or GE no more pbmp update, 2563 * for HG remove HG and add XE 2564 */ 2565 if (IS_HG_PORT(unit, port)) { 2566 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 2567 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 2568 } 2569 } else { 2570 /* for HG/HG2 case (GE port expected not allowed here) */ 2571 SOC_PBMP_PORT_ADD(si->hg.bitmap, port); 2572 SOC_PBMP_PORT_REMOVE(si->hl.bitmap, port); 2573 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2574 } 2575 } else { 2576 /* To IEEE mode */ 2577 if (IS_HG_PORT(unit, port)) { 2578 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 2579 } 2580 SOC_PBMP_PORT_ADD(si->ether.bitmap, port); 2581 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port); 2582 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 2583 SOC_PBMP_PORT_REMOVE(si->hl.bitmap, port); 2584 } 2585 2586 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \ 2587 si->ptype.num = 0; \ 2588 si->ptype.min = si->ptype.max = -1; \ 2589 PBMP_ITER(si->ptype.bitmap, it_port) { \ 2590 si->ptype.port[si->ptype.num++] = it_port; \ 2591 if (si->ptype.min < 0) { \ 2592 si->ptype.min = it_port; \ 2593 } \ 2594 if (it_port > si->ptype.max) { \ 2595 si->ptype.max = it_port; \ 2596 } \ 2597 } 2598 2599 /* Recalculate port type data */ 2600 RECONFIGURE_PORT_TYPE_INFO(ether); 2601 RECONFIGURE_PORT_TYPE_INFO(st); 2602 RECONFIGURE_PORT_TYPE_INFO(hg); 2603 RECONFIGURE_PORT_TYPE_INFO(xe); 2604 #undef RECONFIGURE_PORT_TYPE_INFO 2605 2606 soc_dport_map_update(unit); 2607 2608 /* Release SOC structures lock */ 2609 SOC_CONTROL_UNLOCK(unit); 2610 } 2611 2612 /* 2613 * Function: 2614 * soc_pci_burst_enable 2615 * Purpose: 2616 * Turn on read/write bursting in the cmic 2617 * Parameters: 2618 * unit - unit number 2619 * 2620 * Our hardware by default does not accept burst transactions. 2621 * These transactions need to be enabled in the CMIC_CONFIG register 2622 * before a burst is performed or the cmic will hang. 2623 * 2624 * This code should be called directly after endian configuration to 2625 * enable bursting as soon as possible. 2626 */ 2627 2628 void 2629 soc_pci_burst_enable(int unit) 2630 { 2631 uint32 reg; 2632 2633 /* Make sure these reads/writes are not combined */ 2634 sal_usleep(1000); 2635 2636 /* Enable Read/Write bursting in the CMIC */ 2637 #ifdef BCM_CMICM_SUPPORT 2638 if(soc_feature(unit, soc_feature_cmicm)) { 2639 return; 2640 } 2641 #endif /* CMICM Support */ 2642 #ifdef BCM_CMICX_SUPPORT 2643 if(soc_feature(unit, soc_feature_cmicx)) { 2644 return; 2645 } 2646 #endif /* CMICX Support */ 2647 2648 reg = soc_pci_read(unit, CMIC_CONFIG); 2649 reg |= (CC_RD_BRST_EN | CC_WR_BRST_EN); 2650 soc_pci_write(unit, CMIC_CONFIG, reg); 2651 2652 /* Make sure our previous write is not combined */ 2653 sal_usleep(1000); 2654 } 2655 /* 2656 * Function: soc_endian_get 2657 * Purpose: Returns the required endian configuration for this device. 2658 * For iProc-based switch designs the CMIC PIO endianness 2659 * configuration is shared for the internal and external 2660 * CPU hosts, and in this case we force the internal PIO 2661 * interface to little endian and perform any required PCI 2662 * endianness conversion in the iProc PCI interfce. 2663 * 2664 * Parameters: dev - device handle 2665 * pio - (OUTPUT) receives the PIO endian configuration. 2666 * packet - (OUTPUT) receives the PACKET endian configuration. 2667 * other - (OUTPUT) receives the OTHER endian configuration. 2668 * 2669 * Returns: SOC_E_XXX 2670 */ 2671 2672 void 2673 soc_endian_get(int unit, int *pio, int *packet, int *other) 2674 { 2675 soc_cm_get_endian(unit, pio, packet, other); 2676 2677 #ifdef BCM_IPROC_SUPPORT 2678 if (soc_feature(unit, soc_feature_iproc)) { 2679 if ((soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) && *pio) { 2680 /* 2681 * If big_pio is set, then we assume that the iProc 2682 * PCI bridge will byte-swap all access types, 2683 * i.e. both PIO and DMA access. 2684 * 2685 * In order to avoid double-swapping, we then need to 2686 * invert the DMA endianness setting in the CMIC. 2687 */ 2688 *other ^= 1; 2689 *packet ^= 1; 2690 *pio ^= 1; 2691 } 2692 } 2693 #endif 2694 #if defined(CMIC_SOFT_BYTE_SWAP) 2695 *pio ^= 1; 2696 #endif /* CMIC_SOFT_BYTE_SWAP */ 2697 } 2698 2699 /* 2700 * Function: 2701 * soc_endian_config (private) 2702 * Purpose: 2703 * Utility routine for configuring CMIC endian select register. 2704 * Parameters: 2705 * unit - unit number 2706 */ 2707 2708 void 2709 soc_endian_config(int unit) 2710 { 2711 uint32 val = 0; 2712 int big_pio, big_packet, big_other; 2713 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 2714 int cmc, cmc_start, cmc_end; 2715 #endif 2716 2717 soc_endian_get(unit, &big_pio, &big_packet, &big_other); 2718 2719 #ifdef BCM_CMICX_SUPPORT 2720 if (soc_feature(unit, soc_feature_cmicx)) { 2721 int y; 2722 cmc_start = 0; 2723 cmc_end = SOC_CMCS_NUM(unit) - 1; 2724 2725 2726 for (cmc = cmc_start; cmc <= cmc_end; cmc++) { 2727 if (big_packet) { 2728 for(y = 0; y < CMICX_N_DMA_CHAN; y++) { 2729 soc_cmicx_pktdma_data_endian_set(unit, cmc, y, big_packet); 2730 } 2731 /* Set Tx header endian same as packet DMA endian */ 2732 soc_cmicx_pktdma_hdr_endian_set(unit, 0, 0, big_packet); 2733 } 2734 if (big_other) { 2735 /* Set Packet DMA Descriptor and EP_TO_CPU_HDR Endianness */ 2736 for(y = 0; y < CMICX_N_DMA_CHAN; y++) { 2737 soc_cmicx_pktdma_desc_endian_set(unit, cmc, y, big_other); 2738 /* 2739 * For DMA channel0 in CMC0 which is used for transmission, 2740 * header endian setting should be same as packet DMA endian. 2741 * For other CMCs' channels which are used for receive, 2742 * EP_TO_CPU_HDR endian setting should be same as DCB endian. 2743 */ 2744 if (cmc != 0 || y != 0) { 2745 /* Set Rx EP_TO_CPU_HDR endian same as DCB endian */ 2746 soc_cmicx_pktdma_hdr_endian_set(unit, cmc, y, big_other); 2747 } 2748 } 2749 #ifdef BCM_SBUSDMA_SUPPORT 2750 if (soc_feature(unit, soc_feature_sbusdma)) { 2751 uint32 num_sbusdma; 2752 num_sbusdma = soc_sbusdma_cmc_max_num_ch_get(unit); 2753 for(y = 0; y < num_sbusdma; y++) { 2754 soc_sbusdma_ch_endian_set(unit, cmc, y, 1); 2755 } 2756 } 2757 #endif 2758 #ifdef BCM_FIFODMA_SUPPORT 2759 for(y = 0; y < CMICX_N_FIFODMA_CHAN; y++) { 2760 soc_fifodma_ch_endian_set(unit, y, 1); 2761 } 2762 #endif 2763 } 2764 } 2765 } 2766 #endif 2767 2768 #ifdef BCM_CMICM_SUPPORT 2769 if (soc_feature(unit, soc_feature_cmicm)) { 2770 int y; 2771 uint32 pio_endian = (big_pio) ? 0x01010101 : 0; 2772 2773 /* 2774 * Configure endianness for PCI PIO accesss. 2775 * 2776 * Note that this register has no effect for iProc-based 2777 * switch designs. 2778 */ 2779 soc_pci_write(unit, CMIC_COMMON_PCIE_PIO_ENDIANESS_OFFSET, pio_endian); 2780 2781 #ifdef BCM_IPROC_SUPPORT 2782 if (soc_feature(unit, soc_feature_iproc)) { 2783 WRITE_CMIC_COMMON_UC0_PIO_ENDIANESSr(unit, pio_endian); 2784 } 2785 #endif 2786 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc)) { 2787 cmc_start = 0; 2788 cmc_end = SOC_CMCS_NUM(unit) - 1; 2789 } else { 2790 cmc_start = SOC_PCI_CMC(unit); 2791 cmc_end = cmc_start; 2792 } 2793 2794 for (cmc = cmc_start; cmc <= cmc_end; cmc++) { 2795 if (big_packet) { 2796 for(y = 0; y < N_DMA_CHAN; y++) { 2797 val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,y)); 2798 val |= PKTDMA_BIG_ENDIAN; 2799 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,y), val); 2800 } 2801 } 2802 if (big_other) { 2803 /* Set Packet DMA Descriptor Endianness */ 2804 for(y = 0; y < N_DMA_CHAN; y++) { 2805 val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,y)); 2806 val |= PKTDMA_DESC_BIG_ENDIAN; 2807 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,y), val); 2808 } 2809 #ifdef BCM_SBUSDMA_SUPPORT 2810 if (soc_feature(unit, soc_feature_sbusdma)) { 2811 for(y=0; y < CMIC_CMCx_SBUSDMA_CHAN_MAX ; y++) { 2812 /* dma/slam */ 2813 val = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, y)); 2814 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &val, 2815 HOSTMEMWR_ENDIANESSf, 1); 2816 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &val, 2817 HOSTMEMRD_ENDIANESSf, 1); 2818 soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc,y), val); 2819 2820 val = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, y)); 2821 2822 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, 2823 &val, DESCRIPTOR_ENDIANESSf, 1); 2824 soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, y), val); 2825 } 2826 } else 2827 #endif 2828 { 2829 /* Set SLAM DMA Endianness */ 2830 val = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc)); 2831 val |= SLDMA_BIG_ENDIAN; 2832 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), val); 2833 2834 /* Set STATS DMA Endianness */ 2835 val = soc_pci_read(unit, CMIC_CMCx_STAT_DMA_CFG_OFFSET(cmc)); 2836 val |= STDMA_BIG_ENDIAN; 2837 soc_pci_write(unit, CMIC_CMCx_STAT_DMA_CFG_OFFSET(cmc), val); 2838 2839 /* Set TABLE DMA Endianness */ 2840 val = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc)); 2841 val |= TDMA_BIG_ENDIAN; 2842 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), val); 2843 } 2844 2845 /* Set FIFO DMA Endianness */ 2846 for(y = 0; y < N_DMA_CHAN; y++) { 2847 val = soc_pci_read(unit, CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(cmc,y)); 2848 val |= FIFODMA_BIG_ENDIAN; 2849 soc_pci_write(unit, CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(cmc,y), val); 2850 } 2851 2852 /* Set Cross Coupled Memory Endianness */ 2853 /* NA for PCI */ 2854 } 2855 } 2856 } else 2857 #endif 2858 { 2859 if (big_pio) { 2860 val |= ES_BIG_ENDIAN_PIO; 2861 } 2862 2863 if (big_packet) { 2864 val |= ES_BIG_ENDIAN_DMA_PACKET; 2865 } 2866 2867 if (big_other) { 2868 val |= ES_BIG_ENDIAN_DMA_OTHER; 2869 } 2870 2871 if ((SOC_IS_HAWKEYE(unit) || SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) && 2872 soc_property_get(unit, spn_EB2_2BYTES_BIG_ENDIAN, 0)) { 2873 val |= EN_BIG_ENDIAN_EB2_2B_SEL; 2874 } 2875 #ifdef BCM_SHADOW_SUPPORT 2876 if (SOC_IS_SHADOW(unit) && soc_property_get(unit, spn_DEVICE_EB_VLI, 0)) { 2877 val = 0x30000030; 2878 } 2879 #endif 2880 soc_pci_write(unit, CMIC_ENDIAN_SELECT, val); 2881 } 2882 } 2883 2884 void 2885 soc_pci_ep_config(int unit, int pcie) 2886 { 2887 #if defined(BCM_IPROC_SUPPORT) && defined(BCM_CMICM_SUPPORT) 2888 uint32 rval; 2889 int pci_num = pcie; 2890 int base_cmc = SOC_PCI_CMC(unit); 2891 int num_of_cmc = 1; 2892 int cmc; 2893 char *propkey; 2894 int configure_one_to_one_remap[CMIC_CMC_NUM_MAX] = {TRUE, TRUE, TRUE}; 2895 uint32 remap_entries_reserved; 2896 2897 if(SOC_IS_DPP(unit)){ 2898 num_of_cmc = SOC_PCI_CMCS_NUM(unit); 2899 } 2900 2901 if (soc_feature(unit, soc_feature_iproc) && 2902 soc_feature(unit, soc_feature_cmicm) && 2903 (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE)) { 2904 2905 if (pcie == -1) { /* Auto-Detect PCI # */ 2906 if ((soc_cm_get_bus_type(unit) & SOC_DEV_BUS_ALT)) { 2907 pci_num = 1; 2908 } else { 2909 pci_num = 0; 2910 } 2911 } 2912 /* consider remap_entries_reserved!=0 only for cmc=1 and pci_cmc=0 */ 2913 /* this is the only constelation that the remap management is allowed */ 2914 propkey = spn_HOST_MEMORY_ADDRESS_REMAP_ENTRIES_RESERVED_CMC; 2915 for(cmc=base_cmc;cmc<num_of_cmc+base_cmc;cmc++) 2916 { 2917 remap_entries_reserved = soc_property_port_get(unit, cmc, propkey, 0); 2918 if(remap_entries_reserved != 0) 2919 { 2920 if ((cmc == 1) && (base_cmc == 0)) 2921 { 2922 configure_one_to_one_remap[cmc] = FALSE; 2923 } 2924 } 2925 } 2926 2927 if (pci_num == 0) { 2928 for(cmc=base_cmc;cmc<num_of_cmc+base_cmc;cmc++){ 2929 if ((SOC_IS_JERICHO(unit)) && (configure_one_to_one_remap[cmc] == FALSE)) 2930 { 2931 /** don't remap at all here. it will be made once allocating new host_buff and setting HOSTMEM_START_ADDRESS */ 2932 /** see function _soc_mem_sbus_fifo_dma_start_memreg and _soc_mem_address_remap_allocation_init */ 2933 } 2934 else 2935 { 2936 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_0_OFFSET(cmc), 0x144D2450); 2937 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_1_OFFSET(cmc), 0x19617595); 2938 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_2_OFFSET(cmc), 0x1E75C6DA); 2939 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_3_OFFSET(cmc), 0x1f); 2940 } 2941 2942 } 2943 } else { 2944 for(cmc=base_cmc;cmc<num_of_cmc+base_cmc;cmc++){ 2945 if ((SOC_IS_JERICHO(unit)) && (configure_one_to_one_remap[cmc] == FALSE)) 2946 { 2947 /** don't remap at all here. it will be made once allocating new host_buff and setting HOSTMEM_START_ADDRESS */ 2948 /** see function _soc_mem_sbus_fifo_dma_start_memreg and _soc_mem_address_remap_allocation_init */ 2949 } 2950 else 2951 { 2952 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_0_OFFSET(cmc), 0x248e2860); 2953 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_1_OFFSET(cmc), 0x29a279a5); 2954 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_2_OFFSET(cmc), 0x2eb6caea); 2955 soc_pci_write(unit, CMIC_CMCx_HOSTMEM_ADDR_REMAP_3_OFFSET(cmc), 0x2f); 2956 } 2957 2958 rval = soc_pci_read(unit, CMIC_CMCx_PCIE_MISCEL_OFFSET(cmc)); 2959 soc_reg_field_set(unit, CMIC_CMC0_PCIE_MISCELr, 2960 &rval, MSI_ADDR_SELf, 1); 2961 soc_pci_write(unit, CMIC_CMCx_PCIE_MISCEL_OFFSET(cmc), rval); 2962 } 2963 } 2964 } 2965 #endif 2966 } 2967 2968 /* 2969 * Function: 2970 * soc_autoz_set 2971 * Purpose: 2972 * Set the autoz bit in the active mac 2973 * Parameters: 2974 * unit - SOC unit # 2975 * port - port number on device. 2976 * enable - Boolean value to set state 2977 * Returns: 2978 * SOC_E_XXX 2979 */ 2980 int 2981 soc_autoz_set(int unit, soc_port_t port, int enable) 2982 { 2983 /* XGS (Hercules): AutoZ not supported */ 2984 return SOC_E_NONE; 2985 } 2986 2987 /* 2988 * Function: 2989 * soc_autoz_get 2990 * Purpose: 2991 * Get the state of the autoz bit in the active MAC 2992 * Parameters: 2993 * unit - SOC unit # 2994 * port - port number on device. 2995 * enable - (OUT) Boolean pointer to return state 2996 * Returns: 2997 * SOC_E_XXX 2998 */ 2999 int 3000 soc_autoz_get(int unit, soc_port_t port, int *enable) 3001 { 3002 /* XGS (Hercules): AutoZ not supported */ 3003 *enable = 0; 3004 return SOC_E_NONE; 3005 } 3006 3007 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) */ 3008 3009 3010 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 3011 3012 int 3013 soc_event_register(int unit, soc_event_cb_t cb, void *userdata) 3014 { 3015 soc_control_t *soc; 3016 soc_event_cb_list_t *curr, *prev; 3017 3018 3019 /* Input validation */ 3020 if (!SOC_UNIT_VALID(unit)) { 3021 return SOC_E_UNIT; 3022 } 3023 3024 if (NULL == cb) { 3025 return SOC_E_PARAM; 3026 } 3027 3028 soc = SOC_CONTROL(unit); 3029 curr = prev = soc->ev_cb_head; 3030 3031 if (NULL == curr) { /* Fist time a call back registered */ 3032 curr = (soc_event_cb_list_t *)sal_alloc(sizeof(soc_event_cb_list_t), 3033 "event call back linked list"); 3034 if (NULL == curr) { 3035 return SOC_E_MEMORY; 3036 } 3037 curr->cb = cb; 3038 curr->userdata = userdata; 3039 curr->next = NULL; 3040 soc->ev_cb_head = curr; 3041 } else { /* Not a first registered callback */ 3042 while (NULL != curr) { 3043 if ((curr->cb == cb) && (curr->userdata == userdata)) { 3044 /* call back with exact same userdata exists - nothing to be done */ 3045 return SOC_E_NONE; 3046 } 3047 prev = curr; 3048 curr = prev->next; 3049 } 3050 curr = (soc_event_cb_list_t *)sal_alloc(sizeof(soc_event_cb_list_t), 3051 "event call back linked list"); 3052 if (NULL == curr) { 3053 return SOC_E_MEMORY; 3054 } 3055 curr->cb = cb; 3056 curr->userdata = userdata; 3057 curr->next = NULL; 3058 prev->next = curr; 3059 } 3060 3061 return SOC_E_NONE; 3062 } 3063 3064 int 3065 soc_event_unregister(int unit, soc_event_cb_t cb, void *userdata) 3066 { 3067 soc_control_t *soc; 3068 soc_event_cb_list_t *curr, *prev; 3069 3070 /* Input validation */ 3071 if (!SOC_UNIT_VALID(unit)) { 3072 return SOC_E_UNIT; 3073 } 3074 3075 if (NULL == cb) { 3076 return SOC_E_PARAM; 3077 } 3078 3079 soc = SOC_CONTROL(unit); 3080 curr = prev = soc->ev_cb_head; 3081 3082 while (NULL != curr) { 3083 if (curr->cb == cb) { 3084 if ((NULL != userdata) && (curr->userdata != userdata)) { 3085 /* No match keep searching */ 3086 prev = curr; 3087 curr = curr->next; 3088 continue; 3089 } 3090 /* if cb & userdata matches or userdata is NULL -> delete */ 3091 if (curr == soc->ev_cb_head) { 3092 soc->ev_cb_head = curr->next; 3093 sal_free((void *)curr); 3094 break; 3095 } 3096 prev->next = curr->next; 3097 sal_free((void *)curr); 3098 break; 3099 } 3100 prev = curr; 3101 curr = curr->next; 3102 } 3103 3104 return (SOC_E_NONE); 3105 } 3106 3107 int 3108 soc_event_generate(int unit, soc_switch_event_t event, uint32 arg1, 3109 uint32 arg2, uint32 arg3) 3110 { 3111 soc_control_t *soc; 3112 soc_event_cb_list_t *curr, *curr_next; 3113 soc_event_cb_t curr_cb; 3114 3115 /* Input validation */ 3116 if (!SOC_UNIT_VALID(unit)) { 3117 return SOC_E_UNIT; 3118 } 3119 3120 #ifdef _SOC_SER_ENABLE_CLI_DBG 3121 if ((event == SOC_SWITCH_EVENT_PARITY_ERROR) && 3122 SOC_MEM_IS_VALID(unit, arg2)) { 3123 LOG_ERROR(BSL_LS_SOC_COMMON, 3124 (BSL_META_U(unit, 3125 "unit %d SOC_SWITCH_EVENT_PARITY_ERROR, " 3126 "correction_type = %d mem %s, index %d\n"), 3127 unit, arg1, SOC_MEM_NAME(unit, arg2), arg3)); 3128 } 3129 if ((event == SOC_SWITCH_EVENT_PARITY_ERROR) && 3130 (arg1 == SOC_SWITCH_EVENT_DATA_ERROR_LOG)) { 3131 LOG_ERROR(BSL_LS_SOC_COMMON, 3132 (BSL_META_U(unit, 3133 "unit %d SOC_SWITCH_EVENT_DATA_ERROR_LOG, " 3134 "log_id = %0d, arg3 = %0d \n"), 3135 unit, arg2, arg3)); 3136 } 3137 #endif /* _SOC_SER_ENABLE_CLI_DBG */ 3138 3139 soc = SOC_CONTROL(unit); 3140 curr = soc->ev_cb_head; 3141 if (NULL != curr) { 3142 curr_cb = curr->cb; 3143 /* coverity[copy_paste_error] */ 3144 curr_next = curr->next; 3145 3146 while ((NULL != curr) && (curr->next == curr_next)) { 3147 curr_cb(unit, event, arg1, arg2, arg3, curr->userdata); 3148 3149 if (curr_next != NULL) { 3150 curr_cb = curr_next->cb; 3151 curr_next = curr_next->next; 3152 } 3153 curr = curr->next; 3154 } 3155 } 3156 3157 return (SOC_E_NONE); 3158 } 3159 3160 void 3161 soc_event_assert(const char *expr, const char *file, int line) 3162 { 3163 uint32 arg1, arg3; 3164 3165 arg1 = PTR_TO_INT(file); 3166 arg3 = PTR_HI_TO_INT(file); 3167 3168 soc_event_generate(0, SOC_SWITCH_EVENT_ASSERT_ERROR, arg1, line, arg3); 3169 _default_assert(expr, file, line); 3170 } 3171 3172 #endif /*defined(BCM_ESW_SUPPORT) || defined(PORTMOD_SUPPORT) */ 3173 3174 3175 #if defined(BCM_XGS3_SWITCH_SUPPORT) || defined(BCM_PETRA_SUPPORT) 3176 /* 3177 * LCPLL lock check for FBX devices 3178 */ 3179 void 3180 soc_xgxs_lcpll_lock_check(int unit) 3181 { 3182 if ((!SAL_BOOT_PLISIM) && (!SAL_BOOT_QUICKTURN) && 3183 soc_feature(unit, soc_feature_xgxs_lcpll)) { 3184 uint32 val; 3185 int pll_lock_usec = 500000; 3186 int locked = 0; 3187 int retry = 3; 3188 soc_timeout_t to; 3189 3190 /* Check if LCPLL locked */ 3191 while (!locked && retry--) { 3192 soc_timeout_init(&to, pll_lock_usec, 0); 3193 while (!soc_timeout_check(&to)) { 3194 #if defined(BCM_RAVEN_SUPPORT) 3195 if (SOC_REG_IS_VALID(unit, CMIC_XGXS_PLL_STATUSr)) { 3196 READ_CMIC_XGXS_PLL_STATUSr(unit, &val); 3197 locked = soc_reg_field_get(unit, CMIC_XGXS_PLL_STATUSr, 3198 val, CMIC_XG_PLL_LOCKf); 3199 } else 3200 #endif 3201 { 3202 READ_CMIC_XGXS_PLL_CONTROL_2r(unit, &val); 3203 locked = soc_reg_field_get(unit, CMIC_XGXS_PLL_CONTROL_2r, 3204 val, PLL_SM_FREQ_PASSf); 3205 } 3206 if (locked) { 3207 break; 3208 } 3209 } 3210 if (!locked) { 3211 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &val); 3212 soc_reg_field_set(unit, CMIC_XGXS_PLL_CONTROL_1r, &val, 3213 RESETf, 1); 3214 WRITE_CMIC_XGXS_PLL_CONTROL_1r(unit, val); 3215 sal_usleep(100); 3216 3217 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &val); 3218 val |= 0xf0000000; 3219 WRITE_CMIC_XGXS_PLL_CONTROL_1r(unit, val); 3220 sal_usleep(100); 3221 3222 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &val); 3223 soc_reg_field_set(unit, CMIC_XGXS_PLL_CONTROL_1r, &val, 3224 RESETf, 0); 3225 WRITE_CMIC_XGXS_PLL_CONTROL_1r(unit, val); 3226 sal_usleep(50); 3227 } 3228 } 3229 3230 if (!locked) { 3231 LOG_ERROR(BSL_LS_SOC_COMMON, 3232 (BSL_META_U(unit, 3233 "fbx_lcpll_lock_check: LCPLL not locked on unit %d " 3234 "status = 0x%08x\n"), 3235 unit, val)); 3236 } 3237 } 3238 } 3239 #endif /* BCM_XGS3_SWITCH_SUPPORT || BCM_PETRA_SUPPORT*/ 3240 3241 3242 #if defined(BCM_BIGMAC_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_XMAC_SUPPORT) 3243 /* Reset XGXS (unicore, hyperlite, ...) via BigMAC fusion interface or port 3244 * registers */ 3245 int 3246 soc_xgxs_reset(int unit, soc_port_t port) 3247 { 3248 soc_reg_t reg; 3249 uint64 rval64; 3250 #ifdef BCM_IPROC_SUPPORT 3251 uint32 rval; 3252 #endif 3253 int reset_sleep_usec; 3254 soc_field_t rstb_hw, rstb_mdioregs, rstb_pll, 3255 txd1_g_fifo_restb, txd10_g_fifo_restb, 3256 pwrdwn, pwrdwn_pll; 3257 3258 reset_sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 3259 3260 reg = MAC_XGXS_CTRLr; 3261 #if defined(BCM_TRIUMPH_SUPPORT) 3262 if (SOC_IS_TR_VL(unit) && !SOC_IS_TRIUMPH2(unit) && !SOC_IS_APOLLO(unit) && 3263 !SOC_IS_ENDURO(unit) && !SOC_IS_HURRICANE(unit) && !SOC_IS_VALKYRIE2(unit) && 3264 (port == 6 || port == 7 || port == 18 || port == 19 || 3265 port == 35 || port == 36 || port == 46 || port == 47)) { 3266 reg = XGPORT_XGXS_CTRLr; 3267 } 3268 #endif /* BCM_TRIUMPH_SUPPORT */ 3269 #if defined(BCM_SCORPION_SUPPORT) 3270 if (SOC_IS_SC_CQ(unit) && (port >= 25 && port <= 28)) { 3271 reg = QGPORT_MAC_XGXS_CTRLr; 3272 } 3273 #endif /* BCM_SCORPION_SUPPORT */ 3274 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 3275 if (SOC_IS_TD_TT(unit) || SOC_IS_SHADOW(unit)) { 3276 reg = XLPORT_XGXS_CTRL_REGr; 3277 } 3278 #endif /* BCM_TRIDENT_SUPPORT */ 3279 #if defined(BCM_KATANA_SUPPORT) 3280 if (SOC_IS_KATANAX(unit) && !SOC_IS_SABER2(unit)) { 3281 reg = XPORT_XGXS_CTRLr; 3282 } 3283 #endif /* BCM_KATANA_SUPPORT */ 3284 #if defined(BCM_SABER2_SUPPORT) 3285 if(SOC_IS_SABER2(unit)) { 3286 if(IS_MXQ_PORT(unit, port)) { 3287 reg = XPORT_XGXS_CTRLr; 3288 } else { 3289 reg = XLPORT_XGXS0_CTRL_REGr; 3290 } 3291 } 3292 #endif 3293 #if defined(BCM_TRIUMPH3_SUPPORT) 3294 if (SOC_IS_TRIUMPH3(unit)) { 3295 reg = PORT_XGXS0_CTRL_REGr; 3296 } 3297 #endif /* BCM_TRIUMPH3_SUPPORT */ 3298 #if defined(BCM_PETRA_SUPPORT) 3299 if (SOC_IS_ARAD(unit)) { 3300 reg = PORT_XGXS_0_CTRL_REGr; 3301 } 3302 #endif /* BCM_PETRA_SUPPORT */ 3303 3304 if (((SOC_IS_HELIX4(unit) && SOC_INFO(unit).port_l2p_mapping[port] == 49) || 3305 (SOC_IS_KATANA2(unit) && port == 40)) && 3306 (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE)) { 3307 /* REFSEL=2'b01, REFDIV=2'b00, REF_TERM_SEL=1'b1. */ 3308 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3309 if (SOC_IS_HELIX4(unit)) { 3310 soc_reg64_field32_set(unit, reg, &rval64, REFSELf, 1); 3311 } 3312 if (SOC_IS_KATANA2(unit)) { 3313 soc_reg64_field32_set(unit, reg, &rval64, REFSELf, 0); 3314 } 3315 soc_reg64_field32_set(unit, reg, &rval64, REF_TERM_SELf, 1); 3316 soc_reg64_field32_set(unit, reg, &rval64, REFDIVf, 0); 3317 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3318 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3319 #ifdef BCM_IPROC_SUPPORT 3320 SOC_IF_ERROR_RETURN(READ_IPROC_WRAP_MISC_CONTROLr(unit, &rval)); 3321 if (SOC_IS_HELIX4(unit)) { 3322 soc_reg_field_set(unit, IPROC_WRAP_MISC_CONTROLr, &rval, 3323 QUAD_SERDES_CTRL_SELf, 0); 3324 } else if (SOC_IS_KATANA2(unit)) { 3325 soc_reg_field_set(unit, IPROC_WRAP_MISC_CONTROLr, &rval, 3326 UNICORE_SERDES_CTRL_SELf, 0); 3327 } 3328 SOC_IF_ERROR_RETURN(WRITE_IPROC_WRAP_MISC_CONTROLr(unit, rval)); 3329 #endif 3330 } 3331 3332 #if defined(BCM_XGS3_SWITCH_SUPPORT) || defined(BCM_PETRA_SUPPORT) 3333 if (SOC_REG_FIELD_VALID(unit, reg, LCREFENf) || 3334 SOC_REG_FIELD_VALID(unit, reg, LCREF_ENf)) { 3335 int lcpll; 3336 soc_field_t lcpll_f; 3337 3338 lcpll_f = SOC_REG_FIELD_VALID(unit, reg, LCREFENf) ? LCREFENf : LCREF_ENf; 3339 /* 3340 * Reference clock selection 3341 */ 3342 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 3343 SAL_BOOT_QUICKTURN ? 0 : 1); 3344 if (lcpll && !SOC_IS_ARAD(unit)) { /* Internal LCPLL reference clock */ 3345 /* Double-check LCPLL lock */ 3346 soc_xgxs_lcpll_lock_check(unit); 3347 } 3348 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3349 soc_reg64_field32_set(unit, reg, &rval64, lcpll_f, lcpll ? 1 : 0); 3350 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3351 } 3352 #endif /* BCM_XGS3_SWITCH_SUPPORT || BCM_PETRA_SUPPORT*/ 3353 3354 #ifdef BCM_PETRA_SUPPORT 3355 if (SOC_IS_ARAD(unit)) { 3356 pwrdwn = PWR_DWNf; 3357 pwrdwn_pll = PWR_DWN_PLLf; 3358 rstb_hw = RST_B_HWf; 3359 rstb_mdioregs = RST_B_MDIOREGSf; 3360 rstb_pll = RST_B_PLLf; 3361 txd1_g_fifo_restb = TXD_1_G_FIFO_RST_Bf; 3362 txd10_g_fifo_restb = TXD_10_G_FIFO_RST_Bf; 3363 } else 3364 #endif /* BCM_PETRA_SUPPORT */ 3365 { 3366 pwrdwn = PWRDWNf; 3367 pwrdwn_pll = PWRDWN_PLLf; 3368 rstb_hw = RSTB_HWf; 3369 rstb_mdioregs = RSTB_MDIOREGSf; 3370 rstb_pll = RSTB_PLLf; 3371 txd1_g_fifo_restb = TXD1G_FIFO_RSTBf; 3372 txd10_g_fifo_restb = TXD10G_FIFO_RSTBf; 3373 } 3374 3375 /* 3376 * XGXS MAC initialization steps. 3377 * 3378 * A minimum delay is required between various initialization steps. 3379 * There is no maximum delay. The values given are very conservative 3380 * including the timeout for PLL lock. 3381 */ 3382 /* Release reset (if asserted) to allow bigmac to initialize */ 3383 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3384 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3385 if (soc_reg_field_valid(unit, reg, pwrdwn)) { 3386 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3387 } 3388 if (soc_reg_field_valid(unit, reg, pwrdwn_pll)) { 3389 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3390 } 3391 if (soc_reg_field_valid(unit,reg, HW_RSTLf)) { 3392 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 1); 3393 } else if (soc_reg_field_valid(unit,reg, rstb_hw)) { 3394 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3395 } 3396 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3397 sal_usleep(reset_sleep_usec); 3398 3399 /* Power down and reset */ 3400 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3401 if (soc_reg_field_valid(unit, reg, pwrdwn)) { 3402 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 1); 3403 } 3404 if (soc_reg_field_valid(unit, reg, pwrdwn_pll)) { 3405 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 1); 3406 } 3407 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 1); 3408 if (soc_reg_field_valid(unit, reg, HW_RSTLf)) { 3409 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 0); 3410 } else if (soc_reg_field_valid(unit, reg, rstb_hw)) { 3411 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 0); 3412 } 3413 if (soc_reg_field_valid(unit, reg, TXFIFO_RSTLf)) { 3414 soc_reg64_field32_set(unit, reg, &rval64, TXFIFO_RSTLf, 0); 3415 } else if (soc_reg_field_valid(unit, reg, txd1_g_fifo_restb)) { 3416 soc_reg64_field32_set(unit, reg, &rval64, 3417 txd1_g_fifo_restb, 0); 3418 soc_reg64_field32_set(unit, reg, &rval64, 3419 txd10_g_fifo_restb, 0); 3420 } 3421 if (soc_reg_field_valid(unit, reg, AFIFO_RSTf)) { 3422 soc_reg64_field32_set(unit, reg, &rval64, AFIFO_RSTf, 1); 3423 } 3424 3425 if (SOC_IS_TRX(unit) || SOC_IS_ARAD(unit)) { /* How about Bradley */ 3426 if (soc_reg_field_valid(unit,reg, rstb_mdioregs)) { 3427 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 0); 3428 } 3429 if (soc_reg_field_valid(unit,reg, rstb_pll)) { 3430 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 0); 3431 } 3432 if (soc_reg_field_valid(unit,reg, BIGMACRSTLf)) { 3433 soc_reg64_field32_set(unit, reg, &rval64, BIGMACRSTLf, 0); 3434 } 3435 } 3436 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3437 sal_usleep(reset_sleep_usec); 3438 3439 /* 3440 * Bring up both digital and analog clocks 3441 * 3442 * NOTE: Many MAC registers are not accessible until the PLL is locked. 3443 * An S-Channel timeout will occur before that. 3444 */ 3445 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3446 if (soc_reg_field_valid(unit, reg, pwrdwn)) { 3447 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3448 } 3449 if (soc_reg_field_valid(unit, reg, pwrdwn_pll)) { 3450 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3451 } 3452 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3453 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3454 sal_usleep(reset_sleep_usec); 3455 3456 /* Bring XGXS out of reset, AFIFO_RST stays 1. */ 3457 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3458 if (soc_reg_field_valid(unit, reg, HW_RSTLf)) { 3459 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 1); 3460 } else if (soc_reg_field_valid(unit, reg, rstb_hw)) { 3461 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3462 } 3463 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3464 sal_usleep(reset_sleep_usec); 3465 3466 if (SOC_IS_TRX(unit) || SOC_IS_ARAD(unit)) { /* How about Bradley */ 3467 /* Bring MDIO registers out of reset */ 3468 if (soc_reg_field_valid(unit,reg, rstb_mdioregs)) { 3469 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3470 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 1); 3471 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3472 } 3473 3474 /* Activate all clocks */ 3475 if (soc_reg_field_valid(unit,reg, rstb_pll)) { 3476 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3477 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 1); 3478 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3479 } 3480 3481 /* Bring BigMac out of reset*/ 3482 if (soc_reg_field_valid(unit,reg, BIGMACRSTLf)) { 3483 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3484 soc_reg64_field32_set(unit, reg, &rval64, BIGMACRSTLf, 1); 3485 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3486 } 3487 } 3488 3489 /* Bring Tx FIFO out of reset */ 3490 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3491 if (soc_reg_field_valid(unit, reg, TXFIFO_RSTLf)) { 3492 soc_reg64_field32_set(unit, reg, &rval64, TXFIFO_RSTLf, 1); 3493 } else if (soc_reg_field_valid(unit, reg, txd1_g_fifo_restb)) { 3494 soc_reg64_field32_set(unit, reg, &rval64, 3495 txd1_g_fifo_restb, 0xf); 3496 soc_reg64_field32_set(unit, reg, &rval64, 3497 txd10_g_fifo_restb, 1); 3498 } 3499 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3500 3501 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 3502 defined(BCM_FIREBOLT2_SUPPORT) 3503 /* Release LMD reset */ 3504 if (soc_feature(unit, soc_feature_lmd)) { 3505 #if defined(BCM_FIREBOLT2_SUPPORT) 3506 if (SOC_REG_IS_VALID(unit, CMIC_1000_BASE_X_MODEr)) { 3507 uint32 lmd_cmic, lmd_bmp, lmd_ether_bmp; 3508 int hg_offset; 3509 3510 hg_offset = port - SOC_HG_OFFSET(unit); 3511 3512 /* 3513 * COVERITY 3514 * It is kept intentional, API may be modified to return error 3515 */ 3516 /* coverity[result_independent_of_operands] */ 3517 SOC_IF_ERROR_RETURN 3518 (READ_CMIC_1000_BASE_X_MODEr(unit, &lmd_cmic)); 3519 lmd_bmp = 3520 soc_reg_field_get(unit, CMIC_1000_BASE_X_MODEr, 3521 lmd_cmic, LMD_ENABLEf); 3522 lmd_ether_bmp = 3523 soc_reg_field_get(unit, CMIC_1000_BASE_X_MODEr, 3524 lmd_cmic, LMD_1000BASEX_ENABLEf); 3525 if (IS_LMD_ENABLED_PORT(unit, port)) { 3526 lmd_bmp |= (1 << hg_offset); 3527 if (IS_XE_PORT(unit,port)) { 3528 lmd_ether_bmp |= (1 << hg_offset); 3529 } else { 3530 lmd_ether_bmp &= ~(1 << hg_offset); 3531 } 3532 } else { 3533 lmd_bmp &= ~(1 << hg_offset); 3534 lmd_ether_bmp &= ~(1 << hg_offset); 3535 } 3536 soc_reg_field_set(unit, CMIC_1000_BASE_X_MODEr, 3537 &lmd_cmic, LMD_ENABLEf, lmd_bmp); 3538 soc_reg_field_set(unit, CMIC_1000_BASE_X_MODEr, &lmd_cmic, 3539 LMD_1000BASEX_ENABLEf, lmd_ether_bmp); 3540 3541 /* 3542 * COVERITY 3543 * It is kept intentional, API may be modified to return error 3544 */ 3545 /* coverity[result_independent_of_operands] */ 3546 SOC_IF_ERROR_RETURN 3547 (WRITE_CMIC_1000_BASE_X_MODEr(unit, lmd_cmic)); 3548 } 3549 #endif /* BCM_FIREBOLT2_SUPPORT */ 3550 3551 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64)); 3552 soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, LMD_RSTBf, 1); 3553 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64)); 3554 } 3555 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || 3556 * BCM_FIREBOLT2_SUPPORT */ 3557 return SOC_E_NONE; 3558 } 3559 3560 int 3561 soc_xgxs_in_reset(int unit, soc_port_t port) 3562 { 3563 soc_reg_t reg; 3564 uint64 rval64; 3565 int reset_sleep_usec; 3566 soc_field_t rstb_hw, rstb_mdioregs, rstb_pll, 3567 txd1_g_fifo_restb, txd10_g_fifo_restb, 3568 pwrdwn, pwrdwn_pll; 3569 3570 reset_sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 3571 3572 reg = MAC_XGXS_CTRLr; 3573 #if defined(BCM_TRIUMPH_SUPPORT) 3574 if (SOC_IS_TR_VL(unit) && !SOC_IS_TRIUMPH2(unit) && !SOC_IS_APOLLO(unit) && 3575 !SOC_IS_ENDURO(unit) && !SOC_IS_HURRICANE(unit) && !SOC_IS_VALKYRIE2(unit) && 3576 (port == 6 || port == 7 || port == 18 || port == 19 || 3577 port == 35 || port == 36 || port == 46 || port == 47)) { 3578 reg = XGPORT_XGXS_CTRLr; 3579 } 3580 #endif /* BCM_TRIUMPH_SUPPORT */ 3581 #if defined(BCM_SCORPION_SUPPORT) 3582 if (SOC_IS_SC_CQ(unit) && (port >= 25 && port <= 28)) { 3583 reg = QGPORT_MAC_XGXS_CTRLr; 3584 } 3585 #endif /* BCM_SCORPION_SUPPORT */ 3586 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 3587 if (SOC_IS_TD_TT(unit) || SOC_IS_SHADOW(unit)) { 3588 reg = XLPORT_XGXS_CTRL_REGr; 3589 } 3590 #endif /* BCM_TRIDENT_SUPPORT */ 3591 #if defined(BCM_KATANA_SUPPORT) 3592 if (SOC_IS_KATANAX(unit)) { 3593 reg = XPORT_XGXS_CTRLr; 3594 } 3595 #endif /* BCM_KATANA_SUPPORT */ 3596 #if defined(BCM_SABER2_SUPPORT) 3597 if(SOC_IS_SABER2(unit)) { 3598 if(IS_MXQ_PORT(unit, port)) { 3599 reg = XPORT_XGXS_CTRLr; 3600 } else { 3601 reg = XLPORT_XGXS0_CTRL_REGr; 3602 } 3603 } 3604 #endif 3605 #if defined(BCM_TRIUMPH3_SUPPORT) 3606 if (SOC_IS_TRIUMPH3(unit)) { 3607 reg = PORT_XGXS0_CTRL_REGr; 3608 } 3609 #endif /* BCM_TRIUMPH3_SUPPORT */ 3610 #if defined(BCM_PETRA_SUPPORT) 3611 if (SOC_IS_ARAD(unit)) { 3612 reg = PORT_XGXS_0_CTRL_REGr; 3613 } 3614 #endif /* BCM_PETRA_SUPPORT */ 3615 3616 #if defined(BCM_XGS3_SWITCH_SUPPORT) || defined(BCM_PETRA_SUPPORT) 3617 if (SOC_REG_FIELD_VALID(unit, reg, LCREFENf) || 3618 SOC_REG_FIELD_VALID(unit, reg, LCREF_ENf)) { 3619 int lcpll; 3620 soc_field_t lcpll_f; 3621 3622 lcpll_f = SOC_REG_FIELD_VALID(unit, reg, LCREFENf) ? LCREFENf : LCREF_ENf; 3623 /* 3624 * Reference clock selection 3625 */ 3626 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 3627 SAL_BOOT_QUICKTURN ? 0 : 1); 3628 if (lcpll && !SOC_IS_ARAD(unit)) { /* Internal LCPLL reference clock */ 3629 /* Double-check LCPLL lock */ 3630 soc_xgxs_lcpll_lock_check(unit); 3631 } 3632 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3633 soc_reg64_field32_set(unit, reg, &rval64, lcpll_f, lcpll ? 1 : 0); 3634 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3635 } 3636 #endif /* BCM_XGS3_SWITCH_SUPPORT || BCM_PETRA_SUPPORT*/ 3637 3638 #ifdef BCM_PETRA_SUPPORT 3639 if (SOC_IS_ARAD(unit)) { 3640 pwrdwn = PWR_DWNf; 3641 pwrdwn_pll = PWR_DWN_PLLf; 3642 rstb_hw = RST_B_HWf; 3643 rstb_mdioregs = RST_B_MDIOREGSf; 3644 rstb_pll = RST_B_PLLf; 3645 txd1_g_fifo_restb = TXD_1_G_FIFO_RST_Bf; 3646 txd10_g_fifo_restb = TXD_10_G_FIFO_RST_Bf; 3647 } else 3648 #endif /* BCM_PETRA_SUPPORT */ 3649 { 3650 pwrdwn = PWRDWNf; 3651 pwrdwn_pll = PWRDWN_PLLf; 3652 rstb_hw = RSTB_HWf; 3653 rstb_mdioregs = RSTB_MDIOREGSf; 3654 rstb_pll = RSTB_PLLf; 3655 txd1_g_fifo_restb = TXD1G_FIFO_RSTBf; 3656 txd10_g_fifo_restb = TXD10G_FIFO_RSTBf; 3657 } 3658 3659 /* 3660 * XGXS MAC initialization steps. 3661 * 3662 * A minimum delay is required between various initialization steps. 3663 * There is no maximum delay. The values given are very conservative 3664 * including the timeout for PLL lock. 3665 */ 3666 /* Release reset (if asserted) to allow bigmac to initialize */ 3667 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3668 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3669 if (soc_reg_field_valid(unit, reg, pwrdwn)) { 3670 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3671 } 3672 if (soc_reg_field_valid(unit, reg, pwrdwn_pll)) { 3673 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3674 } 3675 if (soc_reg_field_valid(unit,reg, HW_RSTLf)) { 3676 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 1); 3677 } else if (soc_reg_field_valid(unit,reg, rstb_hw)) { 3678 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3679 } 3680 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3681 sal_usleep(reset_sleep_usec); 3682 3683 /* Power down and reset */ 3684 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3685 if (soc_reg_field_valid(unit, reg, pwrdwn)) { 3686 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 1); 3687 } 3688 if (soc_reg_field_valid(unit, reg, pwrdwn_pll)) { 3689 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 1); 3690 } 3691 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 1); 3692 if (soc_reg_field_valid(unit, reg, HW_RSTLf)) { 3693 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 0); 3694 } else if (soc_reg_field_valid(unit, reg, rstb_hw)) { 3695 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 0); 3696 } 3697 if (soc_reg_field_valid(unit, reg, TXFIFO_RSTLf)) { 3698 soc_reg64_field32_set(unit, reg, &rval64, TXFIFO_RSTLf, 0); 3699 } else if (soc_reg_field_valid(unit, reg, txd1_g_fifo_restb)) { 3700 soc_reg64_field32_set(unit, reg, &rval64, 3701 txd1_g_fifo_restb, 0); 3702 soc_reg64_field32_set(unit, reg, &rval64, 3703 txd10_g_fifo_restb, 0); 3704 } 3705 if (soc_reg_field_valid(unit, reg, AFIFO_RSTf)) { 3706 soc_reg64_field32_set(unit, reg, &rval64, AFIFO_RSTf, 1); 3707 } 3708 3709 if (SOC_IS_TRX(unit) || SOC_IS_ARAD(unit)) { /* How about Bradley */ 3710 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 0); 3711 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 0); 3712 if (soc_reg_field_valid(unit,reg, BIGMACRSTLf)) { 3713 soc_reg64_field32_set(unit, reg, &rval64, BIGMACRSTLf, 0); 3714 } 3715 } 3716 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3717 sal_usleep(reset_sleep_usec); 3718 3719 return SOC_E_NONE; 3720 } 3721 3722 #endif /* BCM_BIGMAC_SUPPORT || BCM_PETRA_SUPPORT*/ 3723 3724 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_PETRA_SUPPORT) 3725 int 3726 soc_wc_xgxs_reset(int unit, soc_port_t port, int reg_idx) 3727 { 3728 #if defined(BCM_TRIUMPH3_SUPPORT) 3729 const static soc_reg_t tr3_regs[] = { 3730 PORT_XGXS0_CTRL_REGr, 3731 PORT_XGXS1_CTRL_REGr, 3732 PORT_XGXS2_CTRL_REGr 3733 }; 3734 #endif /* BCM_TRIUMPH3_SUPPORT */ 3735 #ifdef BCM_PETRA_SUPPORT 3736 const static soc_reg_t arad_regs[] = { 3737 PORT_XGXS_0_CTRL_REGr, 3738 PORT_XGXS_1_CTRL_REGr, 3739 PORT_XGXS_2_CTRL_REGr 3740 }; 3741 #endif /* BCM_TRIUMPH3_SUPPORT */ 3742 soc_reg_t reg; 3743 uint64 rval64; 3744 int reset_sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 3745 int lcpll; 3746 soc_field_t rstb_hw, rstb_mdioregs, rstb_pll, 3747 txd1_g_fifo_restb, txd10_g_fifo_restb, 3748 pwrdwn, pwrdwn_pll; 3749 3750 #if defined(BCM_TRIUMPH3_SUPPORT) 3751 if (SOC_IS_TRIUMPH3(unit)) { 3752 reg = tr3_regs[reg_idx]; 3753 } else 3754 #endif /* BCM_TRIUMPH3_SUPPORT */ 3755 #ifdef BCM_PETRA_SUPPORT 3756 if (SOC_IS_ARAD(unit)) { 3757 reg = arad_regs[reg_idx]; 3758 } else 3759 #endif /* BCM_PETRA_SUPPORT */ 3760 { 3761 reg = XLPORT_XGXS_CTRL_REGr; 3762 } 3763 3764 #ifdef BCM_PETRA_SUPPORT 3765 if (SOC_IS_ARAD(unit)) { 3766 pwrdwn = PWR_DWNf; 3767 pwrdwn_pll = PWR_DWN_PLLf; 3768 rstb_hw = RST_B_HWf; 3769 rstb_mdioregs = RST_B_MDIOREGSf; 3770 rstb_pll = RST_B_PLLf; 3771 txd1_g_fifo_restb = TXD_1_G_FIFO_RST_Bf; 3772 txd10_g_fifo_restb = TXD_10_G_FIFO_RST_Bf; 3773 } else 3774 #endif /* BCM_PETRA_SUPPORT */ 3775 { 3776 pwrdwn = PWRDWNf; 3777 pwrdwn_pll = PWRDWN_PLLf; 3778 rstb_hw = RSTB_HWf; 3779 rstb_mdioregs = RSTB_MDIOREGSf; 3780 rstb_pll = RSTB_PLLf; 3781 txd1_g_fifo_restb = TXD1G_FIFO_RSTBf; 3782 txd10_g_fifo_restb = TXD10G_FIFO_RSTBf; 3783 } 3784 3785 /* 3786 * Reference clock selection 3787 */ 3788 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 3789 SAL_BOOT_QUICKTURN ? 0 : 1); 3790 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3791 soc_reg64_field32_set(unit, reg, &rval64, LCREF_ENf, lcpll ? 1 : 0); 3792 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3793 3794 /* 3795 * XGXS MAC initialization steps. 3796 * 3797 * A minimum delay is required between various initialization steps. 3798 * There is no maximum delay. The values given are very conservative 3799 * including the timeout for PLL lock. 3800 */ 3801 /* Release reset (if asserted) to allow xmac/cmac to initialize */ 3802 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3803 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3804 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3805 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3806 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3807 sal_usleep(reset_sleep_usec); 3808 3809 /* Power down and reset */ 3810 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 1); 3811 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 1); 3812 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 1); 3813 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 0); 3814 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 0); 3815 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 0); 3816 soc_reg64_field32_set(unit, reg, &rval64, txd1_g_fifo_restb, 0); 3817 soc_reg64_field32_set(unit, reg, &rval64, txd10_g_fifo_restb, 0); 3818 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3819 sal_usleep(reset_sleep_usec); 3820 3821 /* 3822 * Bring up both digital and analog clocks 3823 * 3824 * NOTE: Many MAC registers are not accessible until the PLL is locked. 3825 * An S-Channel timeout will occur before that. 3826 */ 3827 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3828 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3829 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3830 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3831 sal_usleep(reset_sleep_usec); 3832 3833 /* Bring XGXS out of reset */ 3834 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3835 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3836 sal_usleep(reset_sleep_usec); 3837 3838 /* Bring MDIO registers out of reset */ 3839 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 1); 3840 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3841 3842 /* Activate all clocks */ 3843 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 1); 3844 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3845 3846 /* Bring Tx FIFO out of reset */ 3847 soc_reg64_field32_set(unit, reg, &rval64, txd1_g_fifo_restb, 0xf); 3848 soc_reg64_field32_set(unit, reg, &rval64, txd10_g_fifo_restb, 1); 3849 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3850 3851 return SOC_E_NONE; 3852 } 3853 3854 int 3855 soc_wc_xgxs_in_reset(int unit, soc_port_t port, int reg_idx) 3856 { 3857 #ifdef BCM_TRIUMPH3_SUPPORT 3858 const static soc_reg_t tr3_regs[] = { 3859 PORT_XGXS0_CTRL_REGr, 3860 PORT_XGXS1_CTRL_REGr, 3861 PORT_XGXS2_CTRL_REGr 3862 }; 3863 #endif /* BCM_TRIUMPH3_SUPPORT */ 3864 #ifdef BCM_PETRA_SUPPORT 3865 const static soc_reg_t arad_regs[] = { 3866 PORT_XGXS_0_CTRL_REGr, 3867 PORT_XGXS_1_CTRL_REGr, 3868 PORT_XGXS_2_CTRL_REGr 3869 }; 3870 #endif /* BCM_TRIUMPH3_SUPPORT */ 3871 soc_reg_t reg; 3872 uint64 rval64; 3873 int reset_sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 3874 int lcpll; 3875 soc_field_t rstb_hw, rstb_mdioregs, rstb_pll, 3876 txd1_g_fifo_restb, txd10_g_fifo_restb, 3877 pwrdwn, pwrdwn_pll; 3878 3879 #ifdef BCM_TRIUMPH3_SUPPORT 3880 if (SOC_IS_TRIUMPH3(unit)) { 3881 reg = tr3_regs[reg_idx]; 3882 } else 3883 #endif /* BCM_TRIUMPH3_SUPPORT */ 3884 #ifdef BCM_PETRA_SUPPORT 3885 if (SOC_IS_ARAD(unit)) { 3886 reg = arad_regs[reg_idx]; 3887 } else 3888 #endif /* BCM_PETRA_SUPPORT */ 3889 { 3890 reg = XLPORT_XGXS_CTRL_REGr; 3891 } 3892 3893 #ifdef BCM_PETRA_SUPPORT 3894 if (SOC_IS_ARAD(unit)) { 3895 pwrdwn = PWR_DWNf; 3896 pwrdwn_pll = PWR_DWN_PLLf; 3897 rstb_hw = RST_B_HWf; 3898 rstb_mdioregs = RST_B_MDIOREGSf; 3899 rstb_pll = RST_B_PLLf; 3900 txd1_g_fifo_restb = TXD_1_G_FIFO_RST_Bf; 3901 txd10_g_fifo_restb = TXD_10_G_FIFO_RST_Bf; 3902 } else 3903 #endif /* BCM_PETRA_SUPPORT */ 3904 { 3905 pwrdwn = PWRDWNf; 3906 pwrdwn_pll = PWRDWN_PLLf; 3907 rstb_hw = RSTB_HWf; 3908 rstb_mdioregs = RSTB_MDIOREGSf; 3909 rstb_pll = RSTB_PLLf; 3910 txd1_g_fifo_restb = TXD1G_FIFO_RSTBf; 3911 txd10_g_fifo_restb = TXD10G_FIFO_RSTBf; 3912 } 3913 3914 /* 3915 * Reference clock selection 3916 */ 3917 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 3918 SAL_BOOT_QUICKTURN ? 0 : 1); 3919 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 3920 soc_reg64_field32_set(unit, reg, &rval64, LCREF_ENf, lcpll ? 1 : 0); 3921 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3922 3923 /* 3924 * XGXS MAC initialization steps. 3925 * 3926 * A minimum delay is required between various initialization steps. 3927 * There is no maximum delay. The values given are very conservative 3928 * including the timeout for PLL lock. 3929 */ 3930 /* Release reset (if asserted) to allow xmac/cmac to initialize */ 3931 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 3932 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 0); 3933 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 0); 3934 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 1); 3935 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3936 sal_usleep(reset_sleep_usec); 3937 3938 /* Power down and reset */ 3939 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn, 1); 3940 soc_reg64_field32_set(unit, reg, &rval64, pwrdwn_pll, 1); 3941 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 1); 3942 soc_reg64_field32_set(unit, reg, &rval64, rstb_hw, 0); 3943 soc_reg64_field32_set(unit, reg, &rval64, rstb_mdioregs, 0); 3944 soc_reg64_field32_set(unit, reg, &rval64, rstb_pll, 0); 3945 soc_reg64_field32_set(unit, reg, &rval64, txd1_g_fifo_restb, 0); 3946 soc_reg64_field32_set(unit, reg, &rval64, txd10_g_fifo_restb, 0); 3947 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 3948 sal_usleep(reset_sleep_usec); 3949 3950 return SOC_E_NONE; 3951 } 3952 3953 int 3954 soc_wc_xgxs_pll_check(int unit, soc_port_t port, int reg_idx) 3955 { 3956 #ifdef BCM_TRIUMPH3_SUPPORT 3957 const static soc_reg_t tr3_regs[] = { 3958 PORT_XGXS0_STATUS_GEN_REGr, 3959 PORT_XGXS1_STATUS_GEN_REGr, 3960 PORT_XGXS2_STATUS_GEN_REGr 3961 }; 3962 #endif /* BCM_TRIUMPH3_SUPPORT */ 3963 soc_reg_t reg; 3964 uint32 rval; 3965 int phy_port, block, retry; 3966 int lock_sleep_usec = 5000; 3967 3968 #ifdef BCM_TRIUMPH3_SUPPORT 3969 if (SOC_IS_TRIUMPH3(unit)) { 3970 reg = tr3_regs[reg_idx]; 3971 } else 3972 #endif /* BCM_TRIUMPH3_SUPPORT */ 3973 { 3974 reg = XLPORT_XGXS_STATUS_GEN_REGr; 3975 } 3976 3977 retry = 10; 3978 3979 /* Check TxPLL lock status */ 3980 while (retry > 0) { 3981 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 3982 if (soc_reg_field_get(unit, reg, rval, TXPLL_LOCKf)) { 3983 return SOC_E_NONE; 3984 } 3985 sal_usleep(lock_sleep_usec); 3986 retry--; 3987 } 3988 3989 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3990 block = SOC_PORT_BLOCK(unit, phy_port); 3991 LOG_ERROR(BSL_LS_SOC_COMMON, 3992 (BSL_META_U(unit, 3993 "unit %d %s TXPLL not locked\n"), 3994 unit, SOC_BLOCK_NAME(unit, block))); 3995 return SOC_E_NONE; 3996 } 3997 3998 int 3999 soc_wc_xgxs_power_down(int unit, soc_port_t port, int reg_idx) 4000 { 4001 #if defined(BCM_TRIUMPH3_SUPPORT) 4002 const static soc_reg_t tr3_regs[] = { 4003 PORT_XGXS0_CTRL_REGr, 4004 PORT_XGXS1_CTRL_REGr, 4005 PORT_XGXS2_CTRL_REGr 4006 }; 4007 #endif /* BCM_TRIUMPH3_SUPPORT */ 4008 soc_reg_t reg; 4009 uint64 rval64; 4010 4011 #if defined(BCM_TRIUMPH3_SUPPORT) 4012 if (SOC_IS_TRIUMPH3(unit)) { 4013 reg = tr3_regs[reg_idx]; 4014 } else 4015 #endif /* BCM_TRIUMPH3_SUPPORT */ 4016 { 4017 reg = XLPORT_XGXS_CTRL_REGr; 4018 } 4019 4020 /* Power down and reset */ 4021 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 4022 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 1); 4023 soc_reg64_field32_set(unit, reg, &rval64, PWRDWN_PLLf, 1); 4024 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 1); 4025 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 0); 4026 soc_reg64_field32_set(unit, reg, &rval64, RSTB_MDIOREGSf, 0); 4027 soc_reg64_field32_set(unit, reg, &rval64, RSTB_PLLf, 0); 4028 soc_reg64_field32_set(unit, reg, &rval64, TXD1G_FIFO_RSTBf, 0); 4029 soc_reg64_field32_set(unit, reg, &rval64, TXD10G_FIFO_RSTBf, 0); 4030 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4031 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4032 (BSL_META_U(unit, 4033 "Power down wc for port: %d\n"), port)); 4034 return SOC_E_NONE; 4035 } 4036 #endif /* BCM_TRIDENT_SUPPORT */ 4037 4038 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_SABER2_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 4039 /* 4040 * function: _soc_xgxs_reset_single_tsc 4041 * purpose: reset a single TSC associate with a TD2/TD2+ port 4042 */ 4043 STATIC soc_error_t 4044 _soc_xgxs_reset_single_tsc(int unit, soc_port_t port, soc_reg_t reg) { 4045 4046 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4047 int lcpll; 4048 uint64 rval64; 4049 /* 4050 * Reference clock selection 4051 */ 4052 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 4053 SAL_BOOT_QUICKTURN ? 0 : 1); 4054 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 4055 if (SOC_IS_TOMAHAWK3(unit) && reg == CDPORT_XGXS0_CTRL_REGr) { 4056 #if 0 4057 4058 soc_reg64_field32_set(unit, reg, &rval64, PLL0_REFIN_ENf, lcpll ? 1 : 0); 4059 soc_reg64_field32_set(unit, reg, &rval64, PLL1_REFIN_ENf, lcpll ? 1 : 0); 4060 #endif 4061 } else { 4062 soc_reg64_field32_set(unit, reg, &rval64, REFIN_ENf, lcpll ? 1 : 0); 4063 } 4064 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4065 #if 0 4066 4067 /* For TH3 field is named differently */ 4068 if (SOC_IS_TOMAHAWK3(unit)) { 4069 if (soc_reg_field_valid(unit, reg, TSC_IDDQf)) { 4070 soc_reg64_field32_set(unit, reg, &rval64, TSC_IDDQf, 0); 4071 } 4072 } 4073 #endif 4074 /* 4075 * For TH+/TH2/Apache B0 default behaviour of CLPORT port IDDQ is changed, 4076 * TH2 default behaviour of XLPORT IDDQ is changed, 4077 * port init sequence must be adjusted to bring tsc out of reset properly 4078 */ 4079 if (soc_feature(unit, soc_feature_iddq_new_default) && 4080 ((reg == CLPORT_XGXS0_CTRL_REGr) || 4081 (SOC_IS_TOMAHAWK2(unit) && reg == XLPORT_XGXS0_CTRL_REGr) || 4082 (SOC_IS_MONTEREY(unit) && reg == XLPORT_XGXS0_CTRL_REGr) || 4083 (SOC_IS_TOMAHAWK3(unit) && reg == XLPORT_XGXS0_CTRL_REGr))) { 4084 if (soc_reg_field_valid(unit, reg, IDDQf)) { 4085 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 4086 } 4087 } 4088 4089 if (SOC_IS_GREYHOUND2(unit)) { 4090 if ((reg == XLPORT_XGXS0_CTRL_REGr) || 4091 (reg == CLPORT_XGXS0_CTRL_REGr)) { 4092 if (soc_reg_field_valid(unit, reg, IDDQf)) { 4093 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 4094 } 4095 } 4096 } 4097 4098 /* Deassert power down */ 4099 /* For TH3 field is named differently */ 4100 if (SOC_IS_TOMAHAWK3(unit) && reg == CDPORT_XGXS0_CTRL_REGr) { 4101 soc_reg64_field32_set(unit, reg, &rval64, TSC_PWRDWNf, 0); 4102 } else { 4103 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 0); 4104 } 4105 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4106 sal_usleep(sleep_usec); 4107 4108 /*for TH3 PM8x50, we need to choose TVCO clk source, chip default is PLL0 4109 however for TH3 need to use PLL1*/ 4110 if (SOC_IS_TOMAHAWK3(unit) && reg == CDPORT_XGXS0_CTRL_REGr) { 4111 soc_reg64_field32_set(unit, reg, &rval64, TSC_CLK_SELf, 1); 4112 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4113 sal_usleep(sleep_usec); 4114 } 4115 4116 /* Reset XGXS */ 4117 /* For TH3 field is named differently */ 4118 if (SOC_IS_TOMAHAWK3(unit) && reg == CDPORT_XGXS0_CTRL_REGr) { 4119 soc_reg64_field32_set(unit, reg, &rval64, TSC_RSTBf, 0); 4120 } else { 4121 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 0); 4122 } 4123 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4124 sal_usleep(sleep_usec+10000); 4125 4126 /* Bring XGXS out of reset */ 4127 /* For TH3 field is named differently */ 4128 if (SOC_IS_TOMAHAWK3(unit) && reg == CDPORT_XGXS0_CTRL_REGr) { 4129 soc_reg64_field32_set(unit, reg, &rval64, TSC_RSTBf, 1); 4130 } else { 4131 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 1); 4132 } 4133 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4134 sal_usleep(sleep_usec); 4135 4136 /* Bring reference clock out of reset */ 4137 if (soc_reg_field_valid(unit, reg, RSTB_REFCLKf)) { 4138 soc_reg64_field32_set(unit, reg, &rval64, RSTB_REFCLKf, 1); 4139 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4140 } 4141 /* Activate clocks */ 4142 if (soc_reg_field_valid(unit, reg, RSTB_PLLf)) { 4143 soc_reg64_field32_set(unit, reg, &rval64, RSTB_PLLf, 1); 4144 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4145 } 4146 return SOC_E_NONE; 4147 } 4148 4149 /* 4150 * function: _soc_xgxs_powerdown_single_tsc 4151 * purpose: Powerdown a single TSC associate with a TD2/TH/TD2+/TH2 port 4152 */ 4153 STATIC soc_error_t 4154 _soc_xgxs_powerdown_single_tsc(int unit, soc_port_t port, soc_reg_t reg) { 4155 4156 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4157 int lcpll; 4158 uint64 rval64; 4159 /* 4160 * Reference clock selection 4161 */ 4162 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 4163 SAL_BOOT_QUICKTURN ? 0 : 1); 4164 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 4165 soc_reg64_field32_set(unit, reg, &rval64, REFIN_ENf, lcpll ? 1 : 0); 4166 4167 /* 4168 * For TH+/TH2/Apache B0 default behaviour of CLPORT port IDDQ is changed, 4169 * TH2 default befhavior of XLPORT IDDQ is changed, 4170 * port init sequence must be adjusted to bring tsc out of reset properly 4171 */ 4172 if (soc_feature(unit, soc_feature_iddq_new_default) && 4173 ((reg == CLPORT_XGXS0_CTRL_REGr) || (reg == PMQ_XGXS0_CTRL_REGr) || 4174 ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TRIDENT3X(unit)) && 4175 (reg == XLPORT_XGXS0_CTRL_REGr)))) { 4176 if (soc_reg_field_valid(unit, reg, IDDQf)) { 4177 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 4178 } 4179 } 4180 4181 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4182 4183 if (soc_feature(unit, soc_feature_iddq_new_default) && 4184 ((reg == CLPORT_XGXS0_CTRL_REGr) || 4185 ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TRIDENT3X(unit)) && 4186 (reg == XLPORT_XGXS0_CTRL_REGr)))) { 4187 sal_usleep(sleep_usec); 4188 } 4189 4190 /* Deassert power down */ 4191 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 0); 4192 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4193 sal_usleep(sleep_usec); 4194 4195 /* Reset XGXS */ 4196 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 0); 4197 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4198 4199 return SOC_E_NONE; 4200 } 4201 4202 /* 4203 * function: _soc_xgxs_powerup_single_tsc 4204 * purpose: Powerup a single TSC associate with a TD2/TH/TD2+/TH2 port 4205 */ 4206 STATIC soc_error_t 4207 _soc_xgxs_powerup_single_tsc(int unit, soc_port_t port, soc_reg_t reg) { 4208 4209 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4210 uint64 rval64; 4211 4212 /* Bring XGXS out of reset */ 4213 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 4214 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 1); 4215 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4216 sal_usleep(sleep_usec); 4217 4218 /* Bring reference clock out of reset */ 4219 if (soc_reg_field_valid(unit, reg, RSTB_REFCLKf)) { 4220 soc_reg64_field32_set(unit, reg, &rval64, RSTB_REFCLKf, 1); 4221 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4222 } 4223 /* Activate clocks */ 4224 if (soc_reg_field_valid(unit, reg, RSTB_PLLf)) { 4225 soc_reg64_field32_set(unit, reg, &rval64, RSTB_PLLf, 1); 4226 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 4227 } 4228 return SOC_E_NONE; 4229 } 4230 4231 /* 4232 * function: _soc_xgxs_reset_tsc_triplet 4233 * purpose: reset a TSC-12 associate with a TD2+ 100G port 4234 */ 4235 STATIC soc_error_t 4236 _soc_xgxs_reset_tsc_triplet(int unit, soc_port_t port) { 4237 /* 4238 * TD2+ 100G case, PGWs have TSCs mapped as follows. 4239 * (This mapping is common for all PGWs regardless of Odd/Even) 4240 * PGW_TSC0_CTRL_REGr,->| | 4241 * PGW_TSC1_CTRL_REGr,->|TSC-12 | 4242 * PGW_TSC2_CTRL_REGr,->| | 4243 * PGW_TSC3_CTRL_REGr -> TSC-4 4244 * All 3 Control registers associated with a TSC-12 must be reset for 4245 * a 100G port to be reset. 4246 */ 4247 const static soc_reg_t ctrl_regs_td2plus[] = { 4248 PGW_TSC0_CTRL_REGr, 4249 PGW_TSC1_CTRL_REGr, 4250 PGW_TSC2_CTRL_REGr, 4251 PGW_TSC3_CTRL_REGr, 4252 }; 4253 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4254 int lcpll; 4255 int i; 4256 uint64 rval64; 4257 4258 /*This sequence is the same as in _soc_xgxs_reset_single_tsc, but across 4259 *all 3 TSC-4s within a TSC-12 4260 */ 4261 /* Reference clock selection */ 4262 for (i = 0; i < 3; i++) { 4263 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 4264 SAL_BOOT_QUICKTURN ? 0 : 1); 4265 SOC_IF_ERROR_RETURN(soc_reg_get(unit, ctrl_regs_td2plus[i], port, 0, 4266 &rval64)); 4267 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, REFIN_ENf, 4268 lcpll ? 1 : 0); 4269 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4270 rval64)); 4271 } 4272 4273 /* Deassert power down */ 4274 for (i = 0; i < 3; i++) { 4275 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, PWRDWNf, 0); 4276 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4277 rval64)); 4278 sal_usleep(sleep_usec); 4279 } 4280 4281 /* Reset XGXS */ 4282 for (i = 0; i < 3; i++) { 4283 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, RSTB_HWf, 0); 4284 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4285 rval64)); 4286 sal_usleep(sleep_usec+10000); 4287 } 4288 4289 /* Bring XGXS out of reset */ 4290 for (i = 0; i < 3; i++) { 4291 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, RSTB_HWf, 1); 4292 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4293 rval64)); 4294 sal_usleep(sleep_usec); 4295 } 4296 4297 /* Bring reference clock out of reset */ 4298 for (i = 0; i < 3; i++) { 4299 if (soc_reg_field_valid(unit, ctrl_regs_td2plus[i], RSTB_REFCLKf)) { 4300 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, 4301 RSTB_REFCLKf, 1); 4302 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4303 rval64)); 4304 } 4305 } 4306 4307 /* Activate clocks */ 4308 for (i = 0; i < 3; i++) { 4309 if (soc_reg_field_valid(unit, ctrl_regs_td2plus[i], RSTB_PLLf)) { 4310 soc_reg64_field32_set(unit, ctrl_regs_td2plus[i], &rval64, 4311 RSTB_PLLf, 1); 4312 SOC_IF_ERROR_RETURN(soc_reg_set(unit, ctrl_regs_td2plus[i], port, 0, 4313 rval64)); 4314 } 4315 } 4316 return SOC_E_NONE; 4317 } 4318 4319 /* Check the port argument is indicating a block id */ 4320 #define SOC_IS_BLKID_PORT(_blkid_port) \ 4321 (_blkid_port & SOC_REG_ADDR_BLOCK_ID_MASK) 4322 /* Get the block type from the port argument which is a block id */ 4323 #define SOC_BLOCK_TYPE_BLKID_PORT(_u, _blkid_port) \ 4324 (SOC_BLOCK_TYPE(_u, (_blkid_port & ~SOC_REG_ADDR_BLOCK_ID_MASK))) 4325 4326 /* 4327 * function: soc_tsc_xgxs_reset 4328 * purpose: Reset all TSCs associated with the passed port. 4329 */ 4330 soc_error_t 4331 soc_tsc_xgxs_reset(int unit, soc_port_t port, int reg_idx) 4332 { 4333 soc_error_t rv = SOC_E_NONE; 4334 const static soc_reg_t ctrl_regs[] = { 4335 XLPORT_XGXS0_CTRL_REGr, 4336 XLPORT_XGXS0_CTRL_REGr, 4337 XLPORT_XGXS0_CTRL_REGr, 4338 XLPORT_XGXS0_CTRL_REGr, 4339 }; 4340 const static soc_reg_t cxxport_ctrl_regs[] = { 4341 CXXPORT_XGXS0_CTRL0_REGr, 4342 CXXPORT_XGXS0_CTRL1_REGr, 4343 CXXPORT_XGXS0_CTRL2_REGr, 4344 }; 4345 4346 soc_reg_t reg = ctrl_regs[reg_idx]; 4347 4348 if ((port > 0) && SOC_IS_BLKID_PORT(port)) { 4349 if (SOC_BLOCK_TYPE_BLKID_PORT(unit, port) == SOC_BLK_PMQ) { 4350 reg = GPORT_XGXS0_CTRL_REGr; 4351 } 4352 } else if (IS_CXX_PORT(unit, port)) { 4353 reg = cxxport_ctrl_regs[reg_idx]; 4354 } else if (IS_CL_PORT(unit, port) || IS_CLG2_PORT(unit, port)) { 4355 reg = CLPORT_XGXS0_CTRL_REGr; 4356 } else if (IS_CD_PORT(unit, port)) { 4357 reg = CDPORT_XGXS0_CTRL_REGr; 4358 } 4359 4360 if ((!SOC_IS_TRIDENT2X(unit) 4361 && !SOC_IS_TITAN2PLUS(unit)) 4362 || SOC_IS_APACHE(unit)) { 4363 rv = _soc_xgxs_reset_single_tsc(unit, port, reg); 4364 } else { 4365 int block_num; 4366 int pgw_block; 4367 const static soc_reg_t ctrl_regs_td2plus[] = { 4368 PGW_TSC0_CTRL_REGr, 4369 PGW_TSC1_CTRL_REGr, 4370 PGW_TSC2_CTRL_REGr, 4371 PGW_TSC3_CTRL_REGr, 4372 }; 4373 4374 /* For blocks which are not valid resetting the TSC can crash the SDK */ 4375 block_num = (SOC_INFO(unit).port_l2p_mapping[port]-1)/16; 4376 pgw_block =PGW_CL_BLOCK(unit, block_num); 4377 if ( pgw_block < 0 || !SOC_INFO(unit).block_valid[pgw_block]) { 4378 return rv; 4379 } 4380 if (!SOC_IS_TD2P_TT2P(unit)) { 4381 reg = ctrl_regs[reg_idx]; 4382 } else { 4383 reg = ctrl_regs_td2plus[reg_idx]; 4384 } 4385 /* for TD2 and TD2+ non-100G ports, reset only one TSC*/ 4386 if (!SOC_IS_TD2P_TT2P(unit) || 4387 SOC_INFO(unit).port_speed_max[port] < 100000) { 4388 rv = _soc_xgxs_reset_single_tsc(unit, port, reg); 4389 } else { 4390 rv = _soc_xgxs_reset_tsc_triplet(unit, port); 4391 } 4392 } 4393 return rv; 4394 } 4395 4396 /* 4397 * function: soc_tsc_xgxs_power_mode 4398 * purpose: Reset all TSCs associated with the passed port. 4399 */ 4400 soc_error_t 4401 soc_tsc_xgxs_power_mode(int unit, soc_port_t port, int reg_idx, int power_down) 4402 { 4403 soc_error_t rv = SOC_E_NONE; 4404 soc_reg_t reg = XLPORT_XGXS0_CTRL_REGr; 4405 4406 /* must check if "port" is a block before IS_CL_PORT */ 4407 if (SOC_IS_BLKID_PORT(port)) { 4408 if (SOC_BLOCK_TYPE_BLKID_PORT(unit, port) == SOC_BLK_PMQPORT) { 4409 reg = PMQ_XGXS0_CTRL_REGr; 4410 } 4411 } else if (IS_CL_PORT(unit, port)) { 4412 reg = CLPORT_XGXS0_CTRL_REGr; 4413 4414 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 4415 /* CLPORT act as refclk master should always be active */ 4416 if (soc_feature(unit, soc_feature_pm_refclk_master)) { 4417 int clport_blk, phy_port; 4418 soc_info_t *si = &SOC_INFO(unit); 4419 4420 phy_port = si->port_l2p_mapping[port]; 4421 clport_blk = SOC_PORT_BLOCK(unit, phy_port); 4422 if (SHR_BITGET(si->pm_ref_master_bitmap, clport_blk)) { 4423 return SOC_E_NONE; 4424 } 4425 } 4426 #endif 4427 } 4428 4429 if (power_down) { 4430 rv = _soc_xgxs_powerdown_single_tsc(unit, port, reg); 4431 } else { 4432 rv = _soc_xgxs_powerup_single_tsc(unit, port, reg); 4433 } 4434 return rv; 4435 } 4436 4437 int 4438 soc_tsc_xgxs_pll_check(int unit, soc_port_t port, int reg_idx) 4439 { 4440 const static soc_field_t status_fields[] = { 4441 TSC_0_AFE_PLL_LOCKf, TSC_1_AFE_PLL_LOCKf, 4442 TSC_2_AFE_PLL_LOCKf, TSC_3_AFE_PLL_LOCKf, 4443 TSC_4_AFE_PLL_LOCKf, TSC_5_AFE_PLL_LOCKf, 4444 TSC_6_AFE_PLL_LOCKf, TSC_7_AFE_PLL_LOCKf, 4445 TSC_8_AFE_PLL_LOCKf, TSC_9_AFE_PLL_LOCKf, 4446 TSC_10_AFE_PLL_LOCKf, TSC_11_AFE_PLL_LOCKf, 4447 TSC_12_AFE_PLL_LOCKf, TSC_13_AFE_PLL_LOCKf, 4448 TSC_14_AFE_PLL_LOCKf, TSC_15_AFE_PLL_LOCKf, 4449 TSC_16_AFE_PLL_LOCKf, TSC_17_AFE_PLL_LOCKf, 4450 TSC_18_AFE_PLL_LOCKf, TSC_19_AFE_PLL_LOCKf, 4451 TSC_20_AFE_PLL_LOCKf, TSC_21_AFE_PLL_LOCKf, 4452 TSC_22_AFE_PLL_LOCKf, TSC_23_AFE_PLL_LOCKf, 4453 TSC_24_AFE_PLL_LOCKf, TSC_25_AFE_PLL_LOCKf, 4454 TSC_26_AFE_PLL_LOCKf, TSC_27_AFE_PLL_LOCKf, 4455 TSC_28_AFE_PLL_LOCKf, TSC_29_AFE_PLL_LOCKf, 4456 TSC_30_AFE_PLL_LOCKf, TSC_31_AFE_PLL_LOCKf, 4457 }; 4458 soc_reg_t reg; 4459 soc_field_t field; 4460 uint32 rval; 4461 int retry; 4462 int lock_sleep_usec = 5000; 4463 4464 reg = TOP_TSC_AFE_PLL_STATUSr; 4465 field = status_fields[SOC_INFO(unit).port_serdes[port]]; 4466 4467 retry = 10; 4468 4469 /* Check TxPLL lock status */ 4470 while (retry > 0) { 4471 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4472 if (soc_reg_field_get(unit, reg, rval, field)) { 4473 return SOC_E_NONE; 4474 } 4475 sal_usleep(lock_sleep_usec); 4476 retry--; 4477 } 4478 4479 LOG_ERROR(BSL_LS_SOC_COMMON, 4480 (BSL_META_U(unit, 4481 "unit %d TSC %d TXPLL not locked\n"), 4482 unit, SOC_INFO(unit).port_serdes[port])); 4483 return SOC_E_NONE; 4484 } 4485 #endif /* BCM_TRIDENT2_SUPPORT || BCM_HURRICANE2_SUPPORT */ 4486 4487 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 4488 /* 4489 * Function: 4490 * soc_xgxs_reset_master_tsc 4491 * Purpose: 4492 * Reset TSCs that need to be initialized to master mode. 4493 * In Tomahawk2, there are 8 port macros that will driven directly from 4494 * the system board and they will act as the refclk master to drive the 4495 * other instances. These port macros should always be initialized to 4496 * master mode and should always be active. 4497 * Parameters: 4498 * unit - SOC unit # 4499 * Returns: 4500 * SOC_E_XXX 4501 */ 4502 4503 int 4504 soc_xgxs_reset_master_tsc(int unit) 4505 { 4506 soc_info_t *si = &SOC_INFO(unit); 4507 int clport_blk, block; 4508 uint64 rval64; 4509 uint32 addr; 4510 uint8 at; 4511 soc_reg_t reg = CLPORT_XGXS0_CTRL_REGr; 4512 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4513 4514 if (soc_feature(unit, soc_feature_pm_refclk_master)) { 4515 4516 addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0, TRUE, &block, &at); 4517 4518 SHR_BIT_ITER(si->pm_ref_master_bitmap, SOC_MAX_NUM_BLKS, clport_blk) { 4519 block = SOC_BLOCK_INFO(unit, clport_blk).cmic; 4520 4521 /* Set TSC in master mode */ 4522 SOC_REG_RST_VAL_GET(unit, CLPORT_XGXS0_CTRL_REGr, rval64); 4523 soc_reg64_field32_set(unit, reg, &rval64, REFIN_ENf, 0); 4524 soc_reg64_field32_set(unit, reg, &rval64, REFOUT_ENf, 1); 4525 SOC_IF_ERROR_RETURN(_soc_reg64_set(unit, block, at, addr, rval64)); 4526 4527 /* 4528 * For TH2 default behaviour of CLPORT port IDDQ is changed, port 4529 * init sequence must be adjusted to bring tsc out of reset properly 4530 */ 4531 if (soc_feature(unit, soc_feature_iddq_new_default)) { 4532 if (soc_reg_field_valid(unit, reg, IDDQf)) { 4533 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 4534 } 4535 } 4536 4537 /* Deassert power down */ 4538 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 0); 4539 SOC_IF_ERROR_RETURN(_soc_reg64_set(unit, block, at, addr, rval64)); 4540 sal_usleep(sleep_usec); 4541 4542 /* Reset XGXS */ 4543 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 0); 4544 SOC_IF_ERROR_RETURN(_soc_reg64_set(unit, block, at, addr, rval64)); 4545 4546 sal_usleep(sleep_usec + 10000); 4547 4548 /* Bring XGXS out of reset */ 4549 soc_reg64_field32_set(unit, reg, &rval64, RSTB_HWf, 1); 4550 SOC_IF_ERROR_RETURN(_soc_reg64_set(unit, block, at, addr, rval64)); 4551 sal_usleep(sleep_usec); 4552 } 4553 } 4554 4555 return SOC_E_NONE; 4556 } 4557 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 4558 4559 #ifdef BCM_XGS5_SWITCH_PORT_SUPPORT 4560 int 4561 soc_pm_power_mode_set(int unit, soc_port_t port, int reg_idx, int power_down) 4562 { 4563 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 4564 defined(BCM_SABER2_SUPPORT) 4565 SOC_IF_ERROR_RETURN 4566 (soc_tsc_xgxs_power_mode(unit, port, reg_idx, power_down)); 4567 #endif 4568 return SOC_E_NONE; 4569 } 4570 #endif /* BCM_XGS5_SWITCH_PORT_SUPPORT */ 4571 4572 #if defined(BCM_GREYHOUND2_SUPPORT) 4573 /* 4574 * function: soc_sgmii4px2_reset 4575 * purpose: Reset all SGMII4PX2. 4576 */ 4577 soc_error_t 4578 soc_sgmii4px2_reset(int unit, soc_port_t port, int reg_idx) 4579 { 4580 const static soc_reg_t ctrl_regs[] = { 4581 GPORT_SGMII0_CTRL_REGr, 4582 GPORT_SGMII1_CTRL_REGr 4583 }; 4584 uint32 rval; 4585 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 4586 4587 soc_reg_t reg = ctrl_regs[reg_idx]; 4588 4589 /* 4590 * Reference clock selection 4591 */ 4592 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 4593 soc_reg_field_set(unit, reg, &rval, IDDQf, 1); 4594 soc_reg_field_set(unit, reg, &rval, PWRDWNf, 1); 4595 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4596 sal_usleep(sleep_usec); 4597 4598 /* Analog section powered */ 4599 soc_reg_field_set(unit, reg, &rval, IDDQf, 0); 4600 /* Deassert power down */ 4601 soc_reg_field_set(unit, reg, &rval, PWRDWNf, 0); 4602 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4603 sal_usleep(sleep_usec); 4604 4605 /* Bring SGMII out of reset */ 4606 soc_reg_field_set(unit, reg, &rval, RSTB_HWf, 1); 4607 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4608 sal_usleep(sleep_usec); 4609 4610 /* Activate MDIO on SGMII */ 4611 soc_reg_field_set(unit, reg, &rval, RSTB_MDIOREGSf, 1); 4612 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4613 sal_usleep(sleep_usec); 4614 4615 /* Activate clocks */ 4616 soc_reg_field_set(unit, reg, &rval, RSTB_PLLf, 1); 4617 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4618 4619 return SOC_E_NONE; 4620 } 4621 #endif /* BCM_GREYHOUND2_SUPPORT */ 4622 4623 int soc_is_valid_block_instance(int unit, soc_block_types_t block_types, 4624 int block_instance, int *is_valid) 4625 { 4626 4627 int nof_block_instances; 4628 4629 if (is_valid == NULL) { 4630 return SOC_E_PARAM; 4631 } 4632 4633 if (block_instance < 0) { 4634 return SOC_E_PARAM; 4635 } 4636 4637 /*default*/ 4638 nof_block_instances = 0; 4639 4640 #ifdef BCM_DFE_SUPPORT 4641 if(SOC_IS_DFE(unit)) { 4642 int rv = soc_dfe_nof_block_instances(unit, block_types, &nof_block_instances); 4643 SOC_IF_ERROR_RETURN(rv); 4644 } 4645 #endif 4646 #ifdef BCM_DNXF_SUPPORT 4647 if(SOC_IS_DNXF(unit)) { 4648 int rv = soc_dnxf_nof_block_instances(unit, block_types, &nof_block_instances); 4649 SOC_IF_ERROR_RETURN(rv); 4650 } 4651 #endif 4652 #ifdef BCM_PETRA_SUPPORT 4653 if(SOC_IS_ARAD(unit)) { 4654 int rv = soc_dpp_nof_block_instances(unit, block_types, &nof_block_instances); 4655 SOC_IF_ERROR_RETURN(rv); 4656 } 4657 #endif 4658 4659 #ifdef BCM_DNX_SUPPORT 4660 if(SOC_IS_DNX(unit)) { 4661 int rv = soc_dnxc_nof_block_instances(unit, block_types, &nof_block_instances); 4662 SOC_IF_ERROR_RETURN(rv); 4663 } 4664 #endif 4665 *is_valid = (block_instance < nof_block_instances ); 4666 4667 return SOC_E_NONE; 4668 } 4669 4670 /* 4671 * Function: 4672 * soc_phy_firmware_load 4673 * Purpose: 4674 * Load firmware into internal SerDes core. 4675 * Parameters: 4676 * unit - unit number 4677 * port - port number on device. 4678 * fw_data - firmware (binary byte array) 4679 * fw_size - size of firmware (in bytes) 4680 * Returns: 4681 * SOC_E_XXX 4682 * Notes: 4683 * This function is simply a wrapper for a device-specific implementation. 4684 */ 4685 4686 int 4687 soc_phy_firmware_load(int unit, int port, uint8 *fw_data, int fw_size) 4688 { 4689 soc_phy_firmware_load_f firmware_load; 4690 4691 firmware_load = SOC_FUNCTIONS(unit)->soc_phy_firmware_load; 4692 if (firmware_load != NULL) { 4693 return firmware_load(unit, port, fw_data, fw_size); 4694 } 4695 return SOC_E_UNAVAIL; 4696 } 4697 4698 4699 #ifdef BCM_LEDPROC_SUPPORT 4700 4701 /* 4702 * Function: 4703 * soc_ledproc_config 4704 * Purpose: 4705 * Load a program into the LED microprocessor from a buffer 4706 * and start it running. 4707 * Parameters: 4708 * unit - StrataSwitch unit # 4709 * program - Array of up to 256 program bytes 4710 * bytes - Number of bytes in array, 0 to disable ledproc, upper 16bit 4711 * specifies which LED processor(0,1,2, ...). 4712 * Notes: 4713 * Also clears the LED processor data RAM from 0x80-0xff 4714 * so the LED program has a known state at startup. 4715 */ 4716 4717 int 4718 soc_ledproc_config(int unit, const uint8 *program, int bytes) 4719 { 4720 int offset; 4721 uint32 val; 4722 uint32 led_ctrl; 4723 uint32 led_prog_base; 4724 uint32 led_data_base; 4725 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 4726 int led_num; 4727 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 4728 4729 if (!soc_feature(unit, soc_feature_led_proc)) { 4730 return SOC_E_UNAVAIL; 4731 } 4732 4733 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 4734 led_num = (bytes >> 16) & 0xff; /* led processor instance */ 4735 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 4736 bytes &= 0xffff; 4737 4738 #ifdef BCM_TOMAHAWK_SUPPORT 4739 if (SOC_IS_TOMAHAWK(unit) && soc_feature(unit, soc_feature_led_cmicd_v2)) { 4740 /* CMICd v2 supports 3 LED processors */ 4741 if (led_num == 0) { 4742 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4743 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4744 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4745 } else if (led_num == 1) { 4746 led_ctrl = CMIC_LEDUP1_CTRL_OFFSET; 4747 led_prog_base = CMIC_LEDUP1_PROGRAM_RAM_OFFSET; 4748 led_data_base = CMIC_LEDUP1_DATA_RAM_OFFSET; 4749 } else if (led_num == 2) { 4750 led_ctrl = CMIC_LEDUP2_CTRL_OFFSET; 4751 led_prog_base = CMIC_LEDUP2_PROGRAM_RAM_OFFSET; 4752 led_data_base = CMIC_LEDUP2_DATA_RAM_OFFSET; 4753 } else { 4754 return SOC_E_PARAM; 4755 } 4756 } else 4757 #endif /* BCM_TOMAHAWK_SUPPORT */ 4758 #ifdef BCM_TOMAHAWK2_SUPPORT 4759 if (SOC_IS_TOMAHAWK2(unit) && soc_feature(unit, soc_feature_led_cmicd_v4)) { 4760 /* CMICd v4 supports 5 LED processors */ 4761 if (led_num == 0) { 4762 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4763 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4764 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4765 } else if (led_num == 1) { 4766 led_ctrl = CMIC_LEDUP1_CTRL_OFFSET; 4767 led_prog_base = CMIC_LEDUP1_PROGRAM_RAM_OFFSET; 4768 led_data_base = CMIC_LEDUP1_DATA_RAM_OFFSET; 4769 } else if (led_num == 2) { 4770 led_ctrl = CMIC_LEDUP2_CTRL_OFFSET; 4771 led_prog_base = CMIC_LEDUP2_PROGRAM_RAM_OFFSET; 4772 led_data_base = CMIC_LEDUP2_DATA_RAM_OFFSET; 4773 } else if (led_num == 3) { 4774 led_ctrl = CMIC_LEDUP3_CTRL_OFFSET; 4775 led_prog_base = CMIC_LEDUP3_PROGRAM_RAM_OFFSET; 4776 led_data_base = CMIC_LEDUP3_DATA_RAM_OFFSET; 4777 } else if (led_num == 4) { 4778 led_ctrl = CMIC_LEDUP4_CTRL_OFFSET; 4779 led_prog_base = CMIC_LEDUP4_PROGRAM_RAM_OFFSET; 4780 led_data_base = CMIC_LEDUP4_DATA_RAM_OFFSET; 4781 } else { 4782 return SOC_E_PARAM; 4783 } 4784 } else 4785 #endif /* BCM_TOMAHAWK2_SUPPORT */ 4786 #ifdef BCM_CMICM_SUPPORT 4787 if (soc_feature(unit, soc_feature_cmicm)) { 4788 #if defined(BCM_TRIDENT2_SUPPORT) 4789 /* CMICm supports 2 LED processors */ 4790 if (SOC_IS_TD2_TT2(unit)) { 4791 if (led_num == 0) { 4792 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4793 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4794 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4795 } else if (led_num == 1) { 4796 led_ctrl = CMIC_LEDUP1_CTRL_OFFSET; 4797 led_prog_base = CMIC_LEDUP1_PROGRAM_RAM_OFFSET; 4798 led_data_base = CMIC_LEDUP1_DATA_RAM_OFFSET; 4799 } else { 4800 return SOC_E_PARAM; 4801 } 4802 } else 4803 #endif 4804 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 4805 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) { 4806 if (led_num == 0) { 4807 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4808 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4809 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4810 } else if (led_num == 1) { 4811 led_ctrl = CMIC_LEDUP1_CTRL_OFFSET; 4812 led_prog_base = CMIC_LEDUP1_PROGRAM_RAM_OFFSET; 4813 led_data_base = CMIC_LEDUP1_DATA_RAM_OFFSET; 4814 } else { 4815 return SOC_E_PARAM; 4816 } 4817 } else 4818 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 4819 { 4820 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4821 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4822 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4823 } 4824 } else 4825 #endif 4826 4827 /* use soc_feature if more switches use two ledprocs */ 4828 #ifdef BCM_TRIDENT_SUPPORT 4829 if (SOC_IS_TD_TT(unit)) { 4830 if (led_num == 0) { 4831 led_ctrl = CMICE_LEDUP0_CTRL; 4832 led_prog_base = CMICE_LEDUP0_PROGRAM_RAM_BASE; 4833 led_data_base = CMICE_LEDUP0_DATA_RAM_BASE; 4834 } else if (led_num == 1) { /* Trident only has two */ 4835 led_ctrl = CMICE_LEDUP1_CTRL; 4836 led_prog_base = CMICE_LEDUP1_PROGRAM_RAM_BASE; 4837 led_data_base = CMICE_LEDUP1_DATA_RAM_BASE; 4838 } else { 4839 return SOC_E_PARAM; 4840 } 4841 } else 4842 #endif /* BCM_TRIDENT_SUPPORT */ 4843 4844 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 4845 #ifdef BCM_CMICM_SUPPORT 4846 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) { 4847 if (led_num == 0) { 4848 led_ctrl = CMIC_LEDUP0_CTRL_OFFSET; 4849 led_prog_base = CMIC_LEDUP0_PROGRAM_RAM_OFFSET; 4850 led_data_base = CMIC_LEDUP0_DATA_RAM_OFFSET; 4851 } else if (led_num == 1) { 4852 led_ctrl = CMIC_LEDUP1_CTRL_OFFSET; 4853 led_prog_base = CMIC_LEDUP1_PROGRAM_RAM_OFFSET; 4854 led_data_base = CMIC_LEDUP1_DATA_RAM_OFFSET; 4855 } else { 4856 return SOC_E_PARAM; 4857 } 4858 } else 4859 #endif 4860 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 4861 { 4862 /* Only Single LED Processor used.. */ 4863 led_ctrl = CMIC_LED_CTRL; 4864 led_prog_base = CMIC_LED_PROGRAM_RAM_BASE; 4865 led_data_base = CMIC_LED_DATA_RAM_BASE; 4866 } 4867 4868 val = soc_pci_read(unit, led_ctrl); 4869 val &= ~LC_LED_ENABLE; 4870 soc_pci_write(unit, led_ctrl, val); 4871 4872 if (bytes == 0) { 4873 return SOC_E_NONE; 4874 } 4875 4876 for (offset = 0; offset < CMIC_LED_PROGRAM_RAM_SIZE; offset++) { 4877 soc_pci_write(unit, 4878 led_prog_base + CMIC_LED_REG_SIZE * offset, 4879 (offset < bytes) ? (uint32) program[offset] : 0); 4880 } 4881 4882 for (offset = 0x80; offset < CMIC_LED_DATA_RAM_SIZE; offset++) { 4883 soc_pci_write(unit, 4884 led_data_base + CMIC_LED_REG_SIZE * offset, 4885 0); 4886 } 4887 4888 val = soc_pci_read(unit, led_ctrl); 4889 val |= LC_LED_ENABLE; 4890 soc_pci_write(unit, led_ctrl, val); 4891 4892 return SOC_E_NONE; 4893 } 4894 4895 #endif /* BCM_LEDPROC_SUPPORT */ 4896 4897 /******************************************* 4898 * @function soc_sbusdma_lock_init 4899 * purpose API to Initialize SBUSDMA 4900 * locks and Semaphores. This will also be used 4901 * for TSLAMDMA and TABLEDMA 4902 * 4903 * @param unit [in] unit 4904 * 4905 * @returns SOC_E_NONE 4906 * @returns SOC_E_XXX 4907 * 4908 * @end 4909 */ 4910 int soc_sbusdma_lock_init(int unit) 4911 { 4912 soc_control_t *soc = SOC_CONTROL(unit); 4913 int cmc, ch; 4914 4915 /* init locks */ 4916 soc->tdma_enb = 0; 4917 soc->tslam_enb = 0; 4918 for (cmc = 0; cmc < SOC_CMCS_NUM_MAX; cmc++) { 4919 for (ch = 0; ch < SOC_SBUSDMA_CH_PER_CMC; ch++) { 4920 soc->sbusDmaMutexs[cmc][ch] = NULL; 4921 soc->sbusDmaIntrs[cmc][ch] = NULL; 4922 } 4923 } 4924 if (SAL_BOOT_QUICKTURN) { 4925 soc->sbusDmaTimeout = SBUS_TIMEOUT_QT; 4926 } else { 4927 soc->sbusDmaTimeout = SBUS_TIMEOUT; 4928 } 4929 soc->sbusDmaTimeout = soc_property_get(unit, spn_DMA_DESC_TIMEOUT_USEC, 4930 soc->sbusDmaTimeout); 4931 SOC_STAT(unit)->err_sbusdma_intr_res = 0; 4932 /* by default it will be cmc0 when there is no multi pci cmc property */ 4933 if (soc->sbusDmaTimeout) { 4934 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 4935 for (ch = 0; ch < SOC_SBUSDMA_CH_PER_CMC; ch++) { 4936 soc->sbusDmaMutexs[cmc][ch] = sal_mutex_create("SbusDMA"); 4937 if (soc->sbusDmaMutexs[cmc][ch] == NULL) { 4938 LOG_ERROR(BSL_LS_SOC_COMMON, 4939 (BSL_META_U(unit, 4940 "failed to allocate sbusDmaMutexs"))); 4941 (void)soc_sbusdma_lock_deinit(unit); 4942 return SOC_E_MEMORY; 4943 } 4944 soc->sbusDmaIntrs[cmc][ch] = sal_sem_create("SBUSDMA interrupt", 4945 sal_sem_BINARY, 0); 4946 if (soc->sbusDmaIntrs[cmc][ch] == NULL) { 4947 LOG_ERROR(BSL_LS_SOC_COMMON, 4948 (BSL_META_U(unit, 4949 "failed to allocate sbusDmaIntrs"))); 4950 (void)soc_sbusdma_lock_deinit(unit); 4951 return SOC_E_MEMORY; 4952 } 4953 } 4954 } 4955 4956 soc->sbusDmaIntrEnb = soc_property_get(unit, 4957 spn_DMA_DESC_INTR_ENABLE, 0); 4958 } 4959 4960 /* Init TDMA/ TSLAM */ 4961 4962 if (soc_feature(unit, soc_feature_table_dma) && 4963 soc_property_get(unit, spn_TABLE_DMA_ENABLE, 1)) { 4964 if (SAL_BOOT_QUICKTURN) { 4965 soc->tableDmaTimeout = TDMA_TIMEOUT_QT; 4966 } else { 4967 soc->tableDmaTimeout = TDMA_TIMEOUT; 4968 #ifdef BCM_CMICX_SUPPORT 4969 if(soc_feature(unit, soc_feature_cmicx)) { 4970 soc->tableDmaTimeout = 3 * TDMA_TIMEOUT; 4971 } 4972 #endif /* CMICX Support */ 4973 } 4974 soc->tableDmaTimeout = soc_property_get(unit, spn_TDMA_TIMEOUT_USEC, 4975 soc->tableDmaTimeout); 4976 soc->tableDmaIntrEnb = soc_property_get(unit, 4977 spn_TDMA_INTR_ENABLE, 1); 4978 soc->tdma_enb = 1; 4979 } 4980 4981 if (soc_feature(unit, soc_feature_tslam_dma) && 4982 soc_property_get(unit, spn_TSLAM_DMA_ENABLE, 1)) { 4983 if (SAL_BOOT_QUICKTURN) { 4984 soc->tslamDmaTimeout = TSLAM_TIMEOUT_QT; 4985 } else { 4986 soc->tslamDmaTimeout = TSLAM_TIMEOUT; 4987 #ifdef BCM_CMICX_SUPPORT 4988 if(soc_feature(unit, soc_feature_cmicx)) { 4989 soc->tslamDmaTimeout = 3 * TSLAM_TIMEOUT; 4990 } 4991 #endif /* CMICX Support */ 4992 } 4993 soc->tslamDmaTimeout = soc_property_get(unit, spn_TSLAM_TIMEOUT_USEC, 4994 soc->tslamDmaTimeout); 4995 soc->tslamDmaIntrEnb = soc_property_get(unit, 4996 spn_TSLAM_INTR_ENABLE, 1); 4997 soc->tslam_enb = 1; 4998 } 4999 5000 /* Init default channels */ 5001 soc->tdma_ch = 0; 5002 soc->tslam_ch = 1; 5003 #ifdef BCM_SBUSDMA_SUPPORT 5004 soc->desc_ch = 2; 5005 #endif 5006 5007 #if defined(BCM_SAND_SUPPORT) 5008 /* In the current DMA implementation, SLAM and table DMA need to both be enabled or disabled */ 5009 if (soc->tslam_enb != soc->tdma_enb && SOC_IS_SAND(unit)) { 5010 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "SLAM DMA and table DMA need to both be either enabled or disabled\n"))); 5011 return SOC_E_PARAM; 5012 } 5013 #endif /* defined(BCM_SAND_SUPPORT) */ 5014 return SOC_E_NONE; 5015 } 5016 5017 /******************************************* 5018 * @function soc_sbusdma_lock_deinit 5019 * purpose API to deinit SBUSDMA 5020 * locks and Semaphores 5021 * 5022 * @param unit [in] unit 5023 * 5024 * @returns SOC_E_NONE 5025 * 5026 * @end 5027 */ 5028 int soc_sbusdma_lock_deinit(int unit) 5029 { 5030 soc_control_t *soc = SOC_CONTROL(unit); 5031 int cmc, ch; 5032 5033 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 5034 for (ch = 0; ch < SOC_SBUSDMA_CH_PER_CMC; ch++) { 5035 if (soc->sbusDmaMutexs[cmc][ch]) { 5036 sal_mutex_destroy(soc->sbusDmaMutexs[cmc][ch]); 5037 soc->sbusDmaMutexs[cmc][ch] = NULL; 5038 } 5039 if (soc->sbusDmaIntrs[cmc][ch]) { 5040 sal_sem_destroy(soc->sbusDmaIntrs[cmc][ch]); 5041 soc->sbusDmaIntrs[cmc][ch] = NULL; 5042 } 5043 } 5044 } 5045 soc->tdma_enb = 0; 5046 soc->tslam_enb = 0; 5047 return SOC_E_NONE; 5048 } 5049 static soc_chip_info_vectors_t chip_info_vect; 5050 5051 int 5052 soc_chip_info_vect_config(soc_chip_info_vectors_t *vect) 5053 { 5054 if (vect == NULL) { 5055 return SOC_E_PARAM; 5056 } 5057 5058 chip_info_vect = *vect; 5059 5060 return SOC_E_NONE; 5061 } 5062 5063 int 5064 soc_icid_default_get(int unit, uint8 *data, int size) 5065 { 5066 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5067 (BSL_META("Get default ICID data length " 5068 "%d bytes.\n"), size)); 5069 5070 if (!data) { 5071 return SOC_E_PARAM; 5072 } 5073 5074 if (chip_info_vect.icid_get) { 5075 if (chip_info_vect.icid_get(unit, data, size) < 0) { 5076 return SOC_E_UNAVAIL; 5077 } 5078 } else { 5079 return SOC_E_UNAVAIL; 5080 } 5081 5082 return SOC_E_NONE; 5083 } 5084 5085 /* 5086 * Function: 5087 * soc_cpu_flow_ctrl 5088 * Purpose: 5089 * Enable/Disable flow control assertion from CMIC to MMU. 5090 * Parameters: 5091 * unit - Unit to init 5092 * enable - Enable/Disable flow control assertion. 5093 * Returns: 5094 * SOC_E_XXX 5095 */ 5096 int 5097 soc_cpu_flow_ctrl(int unit, int enable) { 5098 5099 /* Input validation */ 5100 if (!SOC_UNIT_VALID(unit)) { 5101 return SOC_E_UNIT; 5102 } 5103 5104 #if defined(BCM_HURRICANE2_SUPPORT) 5105 if (SOC_IS_HURRICANE2(unit) || SOC_IS_HURRICANE3(unit) || 5106 SOC_IS_GREYHOUND(unit)) { 5107 uint32 addr, fval, rval = 0; 5108 5109 if (enable) { 5110 fval = 0x00000000; 5111 } else { 5112 fval = 0xffffffff; 5113 } 5114 soc_reg_field_set(unit, CMIC_PKT_COS_0r, &rval, COSf, fval); 5115 addr = soc_reg_addr(unit, CMIC_PKT_COS_0r, REG_PORT_ANY, 0); 5116 soc_pci_write(unit, addr, rval); 5117 soc_reg_field_set(unit, CMIC_PKT_COS_1r, &rval, COSf, fval); 5118 addr = soc_reg_addr(unit, CMIC_PKT_COS_1r, REG_PORT_ANY, 0); 5119 soc_pci_write(unit, addr, rval); 5120 } 5121 #endif /* BCM_HURRICANE2_SUPPORT */ 5122 return SOC_E_NONE; 5123 } 5124