common.c (74765B)
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 * File: soc_common.c 8 * Purpose: Common functions for soc drivers 9 * Requires: 10 */ 11 12 #include <soc/defs.h> 13 #include <assert.h> 14 #include <sal/core/libc.h> 15 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/cm.h> 19 #include <soc/debug.h> 20 #include <soc/mem.h> 21 #include <soc/cmic.h> 22 #ifdef BCM_CMICM_SUPPORT 23 #include <soc/cmicm.h> 24 #endif 25 26 #ifdef BCM_IPROC_SUPPORT 27 #include <soc/iproc.h> 28 #endif 29 30 #if defined(BCM_DFE_SUPPORT) 31 #include <soc/dfe/cmn/dfe_drv.h> 32 #endif 33 #ifdef BCM_DNX_SUPPORT 34 #include <bcm/types.h> 35 #include <bcm_int/dnx/algo/port/algo_port_mgmt.h> 36 #include <bcm_int/dnx/algo/port/algo_port_utils.h> 37 #include <soc/dnx/drv.h> 38 #endif 39 #if defined(BCM_PETRA_SUPPORT) 40 #include <soc/dpp/drv.h> 41 #endif 42 43 #if defined(BCM_KATANA2_SUPPORT) 44 #include <soc/katana2.h> 45 #endif 46 47 #if defined(BCM_GREYHOUND_SUPPORT) 48 #include <soc/greyhound.h> 49 #endif 50 51 #if defined(BCM_SABER2_SUPPORT) 52 #include <soc/saber2.h> 53 #endif 54 55 #if defined(BCM_METROLITE_SUPPORT) 56 #include <soc/metrolite.h> 57 #endif 58 59 #ifdef BCM_TOMAHAWK3_SUPPORT 60 #define CDMAC_OFFSET_CNT 0x10000 61 #define CDMAC0_STAGE_ID 1 62 #define CDMAC1_STAGE_ID 2 63 #endif 64 65 /* Initialize composite block types */ 66 uint32 _soc_block_ports_t[] = { 67 SOC_BLK_PORT_INITIALIZER 68 }; 69 70 uint32 _soc_block_cpu_t[] = { 71 SOC_BLK_CPU_INITIALIZER 72 }; 73 74 uint32 _soc_block_ether_t[] = { 75 SOC_BLK_ETHER_INITIALIZER 76 }; 77 78 uint32 _soc_block_higig_t[] = { 79 SOC_BLK_HIGIG_INITIALIZER 80 }; 81 82 uint32 _soc_block_fabric_t[] = { 83 SOC_BLK_FABRIC_INITIALIZER 84 }; 85 86 uint32 _soc_block_net_t[] = { 87 SOC_BLK_NET_INITIALIZER 88 }; 89 90 uint32 _soc_block_hgport_t[] = { 91 SOC_BLK_HGPORT_INITIALIZER 92 }; 93 94 95 /* The granularity of register addresses, indexed by soc_regtype_t */ 96 int soc_regtype_gran[] = { 97 1, /* soc_schan_reg, */ 98 1, /* soc_genreg, */ 99 1, /* soc_portreg, */ 100 1, /* soc_ppportreg, */ 101 1, /* soc_cosreg, */ 102 1, /* soc_pipereg, */ 103 1, /* soc_xpereg, */ 104 1, /* soc_slicereg */ 105 1, /* soc_layerreg */ 106 1, /* soc_itmreg */ 107 1, /* soc_ebreg */ 108 4, /* soc_cpureg, */ 109 4, /* soc_pci_cfg_reg, */ 110 1, /* soc_phy_reg, */ 111 1, /* soc_spi_reg, */ 112 4, /* soc_mcsreg, */ 113 4, /* soc_iprocreg, */ 114 4, /* soc_hostmem_w, */ 115 2, /* soc_hostmem_h, */ 116 1, /* soc_hostmem_b, */ 117 1, /* soc_customreg, */ 118 0, /* soc_invalidreg */ 119 }; 120 121 /* Names of register types, indexed by soc_regtype_t */ 122 char *soc_regtypenames[] = { 123 "schan", /* soc_schan_reg, */ 124 "general", /* soc_genreg, */ 125 "port", /* soc_portreg, */ 126 "ppport", /* soc_ppportreg, */ 127 "cos", /* soc_cosreg, */ 128 "pipe", /* soc_pipereg, */ 129 "xpe", /* soc_xpereg, */ 130 "slice", /* soc_slicereg, */ 131 "layer", /* soc_layerreg, */ 132 "itm", /* soc_itmreg */ 133 "eb", /* soc_ebreg */ 134 "cpu", /* soc_cpureg, */ 135 "pci_cfg", /* soc_pci_cfg_reg, */ 136 "phy", /* soc_phy_reg, */ 137 "spi", /* soc_spi_reg, */ 138 "mcs", /* soc_mcsreg, */ 139 "iproc", /* soc_iprocreg, */ 140 "mem_word", /* soc_hostmem_w, */ 141 "mem_hword", /* soc_hostmem_h, */ 142 "mem_byte", /* soc_hostmem_b, */ 143 "custom", /* soc_customreg, */ 144 "invalid" /* soc_invalidreg */ 145 }; 146 147 /**************************************************************** 148 * 149 * This array maps from specific chip enum value to the group 150 * to which the chip belongs. 151 * 152 * NB: Order of this array must match soc_chip_types_e from soc/defs.h 153 */ 154 soc_chip_groups_t soc_chip_type_map[SOC_CHIP_TYPES_COUNT] = { 155 SOC_CHIP_TYPE_MAP_INIT 156 }; 157 158 159 /**************************************************************** 160 * 161 * This array maps type indices to names. 162 * 163 * Indexed by soc_chip_types 164 */ 165 char *soc_chip_type_names[SOC_CHIP_TYPES_COUNT] = { 166 SOC_CHIP_TYPE_NAMES_INIT 167 }; 168 169 /**************************************************************** 170 * 171 * This array maps group indices to names. 172 * 173 * Indexed by soc_chip_groups_t 174 */ 175 char* soc_chip_group_names[SOC_CHIP_GROUPS_COUNT] = { 176 SOC_CHIP_GROUP_NAMES_INIT 177 }; 178 179 /* 180 * The following routines can be called for CMIC (PCI memory space) 181 * registers or for SOC registers. The register type is indicated 182 * in rt. 183 */ 184 185 /* Match block against a list */ 186 /* Internally retreives block type from index */ 187 int 188 SOC_BLOCK_IS_TYPE(int unit, int blk_idx, int *list) 189 { 190 int _bidx = 0; 191 while(list[_bidx] != SOC_BLOCK_TYPE_INVALID) { 192 if (SOC_BLOCK_TYPE(unit, blk_idx) == list[_bidx]) { 193 return TRUE; 194 } 195 _bidx++; 196 } 197 return FALSE; 198 } 199 200 /* Checks if a blk type is part of a composite type */ 201 /* Internally retreives block type from index */ 202 int 203 SOC_BLOCK_IS_COMPOSITE(int unit, int blk_idx, int type) 204 { 205 uint32 *blks = NULL; 206 uint8 _tidx = 0; 207 208 switch(type) { 209 case SOC_BLK_PORT: 210 blks = _soc_block_ports_t; 211 break; 212 case SOC_BLK_CPU: 213 blks = _soc_block_cpu_t; 214 break; 215 case SOC_BLK_ETHER: 216 blks = _soc_block_ether_t; 217 break; 218 case SOC_BLK_HIGIG: 219 blks = _soc_block_higig_t; 220 break; 221 case SOC_BLK_FABRIC: 222 blks = _soc_block_fabric_t; 223 break; 224 case SOC_BLK_NET: 225 blks = _soc_block_net_t; 226 break; 227 case SOC_BLK_HGPORT: 228 blks = _soc_block_hgport_t; 229 break; 230 default: return FALSE; 231 } 232 while(blks[_tidx] != SOC_BLOCK_TYPE_INVALID) { 233 if (SOC_BLOCK_TYPE(unit, blk_idx) == blks[_tidx]) { 234 return TRUE; 235 } 236 _tidx++; 237 } 238 return FALSE; 239 } 240 241 /* Match a block type against a block list. 242 * Type could be specific or composite like PORT. 243 * As an optimization one could use SOC_BLOCK_IS if type is 244 * known to not be composite. 245 */ 246 int 247 SOC_BLOCK_IN_LIST(int *blk, int type) 248 { 249 int _bidx = 0; 250 uint32 *blks = NULL; 251 while(blk[_bidx] != SOC_BLOCK_TYPE_INVALID) { 252 int _tidx = 0; 253 uint8 composite = TRUE; 254 switch(type) { 255 case SOC_BLK_PORT: 256 blks = _soc_block_ports_t; 257 break; 258 case SOC_BLK_CPU: 259 blks = _soc_block_cpu_t; 260 break; 261 case SOC_BLK_ETHER: 262 blks = _soc_block_ether_t; 263 break; 264 case SOC_BLK_HIGIG: 265 blks = _soc_block_higig_t; 266 break; 267 case SOC_BLK_FABRIC: 268 blks = _soc_block_fabric_t; 269 break; 270 case SOC_BLK_NET: 271 blks = _soc_block_net_t; 272 break; 273 case SOC_BLK_HGPORT: 274 blks = _soc_block_hgport_t; 275 break; 276 default: composite = FALSE; 277 } 278 /* when composite is non-null, you are coming from non-default 279 case above and no need to check blks for NULL */ 280 if (composite) { 281 /* coverity[dead_error_condition] */ 282 if (blks == NULL) { 283 /* 284 * Coverity 285 * Defencive check. 286 * coverity[dead_error_line] 287 */ 288 return FALSE; 289 } 290 while(blks[_tidx] != SOC_BLOCK_TYPE_INVALID) { 291 if (blk[_bidx] == blks[_tidx]) { 292 return TRUE; 293 } 294 _tidx++; 295 } 296 return FALSE; 297 } else if (blk[_bidx] == type) { 298 return TRUE; 299 } 300 _bidx++; 301 } 302 return FALSE; 303 } 304 #ifdef BCM_CMICM_SUPPORT 305 /* 306 * There is some PCI addresses that are not mapped to any register. 307 * Accessing some of them lead to BUS error. So it is unreasonable to access 308 * the invalid addresses. 309 */ 310 static int 311 soc_cpureg_address_is_invalid(int unit, soc_regaddrinfo_t *ainfo) { 312 int off; 313 314 off = SOC_REG_BASE(unit, ainfo->reg); 315 if (soc_feature(unit, soc_feature_time_v3_no_bs)){ 316 if (off >= CMIC_BS0_CONFIG_OFFSET && 317 off <= CMIC_BS1_INITIAL_CRC_OFFSET){ 318 return TRUE; 319 } 320 } 321 if (off >= CMIC_MMU_COSLC_COUNT_ADDR_OFFSET && 322 off < CMIC_TIM0_TIMER1LOAD_OFFSET) { 323 return TRUE; 324 } 325 326 /* 327 * These registers do not ack the CPU until the FSCHAN read cycle is completed. 328 * Meaning you must activate a proper FSCHAN read command in order to read these registers. 329 */ 330 switch (ainfo->reg) { 331 case CMIC_CMC0_FSCHAN_DATA32r : 332 case CMIC_CMC0_FSCHAN_DATA64_LOr : 333 case CMIC_FSCHAN_DATA32r : 334 case CMIC_FSCHAN_DATA64_LOr : 335 case CMIC_CMC1_FSCHAN_DATA32r : 336 case CMIC_CMC1_FSCHAN_DATA64_LOr : 337 case CMIC_CMC2_FSCHAN_DATA32r : 338 case CMIC_CMC2_FSCHAN_DATA64_LOr : 339 return TRUE; 340 default: 341 /* Do Nothing */ 342 break; 343 } 344 return FALSE; 345 } 346 #endif 347 348 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 349 int 350 soc_anyreg_read(int unit, soc_regaddrinfo_t *ainfo, uint64 *data) 351 { 352 uint32 tmpdata; 353 int rv = SOC_E_NONE; 354 soc_regtype_t type; 355 int port = ainfo->port; 356 357 if (ainfo->reg < 0) { 358 type = soc_genreg; 359 } else { 360 type = SOC_REG_INFO(unit, ainfo->reg).regtype; 361 } 362 363 #if defined(BCM_SAND_SUPPORT) 364 if (SOC_IS_SAND(unit)) { 365 if ((ainfo->port >=0) || (ainfo->port & SOC_REG_ADDR_INSTANCE_MASK)) { 366 port = ainfo->port; 367 } else { 368 port = REG_PORT_ANY; 369 } 370 } 371 #endif 372 373 switch (type) { 374 case soc_cpureg: 375 #ifdef BCM_CMICM_SUPPORT 376 if (soc_feature(unit, soc_feature_cmicm)) { 377 if (soc_feature(unit, soc_feature_cpureg_dump)){ 378 if (soc_cpureg_address_is_invalid(unit, ainfo)) { 379 rv = SOC_E_INTERNAL; 380 break; 381 } 382 } 383 } 384 #endif 385 tmpdata = soc_pci_read(unit, ainfo->addr); 386 COMPILER_64_SET(*data, 0, tmpdata); 387 break; 388 #ifdef BCM_CMICM_SUPPORT 389 case soc_mcsreg: 390 tmpdata = soc_pci_mcs_read(unit, ainfo->addr); 391 COMPILER_64_SET(*data, 0, tmpdata); 392 break; 393 #endif 394 #ifdef BCM_IPROC_SUPPORT 395 case soc_iprocreg: 396 tmpdata = soc_cm_iproc_read(unit, ainfo->addr); 397 COMPILER_64_SET(*data, 0, tmpdata); 398 break; 399 #endif 400 case soc_customreg: 401 case soc_genreg: 402 case soc_portreg: 403 case soc_ppportreg: 404 #if defined(BCM_TRIDENT2_SUPPORT) 405 if (soc_feature(unit, soc_feature_pgw_mac_rsv_mask_remap) && 406 ainfo->reg == PGW_MAC_RSV_MASKr) { 407 int block; 408 uint8 acc_type; 409 410 ainfo->addr = soc_reg_addr_get(unit, PGW_MAC_RSV_MASKr, 411 ainfo->port, 0, 412 SOC_REG_ADDR_OPTION_NONE, 413 &block, &acc_type); 414 ainfo->addr &= 0xffffff00; 415 ainfo->addr |= 416 (SOC_INFO(unit).port_l2p_mapping[ainfo->port] - 1) & 0xf; 417 rv = _soc_reg32_get(unit, block, acc_type, ainfo->addr, &tmpdata); 418 if (SOC_SUCCESS(rv)) { 419 COMPILER_64_SET(*data, 0, tmpdata); 420 } 421 break; 422 } else 423 #endif /* BCM_TRIDENT2_SUPPORT */ 424 if (ainfo->valid && (int)ainfo->reg >= 0 && 425 SOC_REG_IS_VALID(unit, ainfo->reg) && 426 SOC_REG_IS_64(unit, ainfo->reg)) { 427 if (soc_feature(unit, soc_feature_new_sbus_format)) { 428 rv = soc_reg_get(unit, ainfo->reg, port, ainfo->idx, data); 429 } else { 430 rv = soc_reg_read(unit, ainfo->reg, ainfo->addr, data); 431 } 432 } else { 433 if (soc_feature(unit, soc_feature_new_sbus_format)) { 434 rv = soc_reg32_get(unit, ainfo->reg, port, ainfo->idx, 435 &tmpdata); 436 } else { 437 rv = soc_reg32_read(unit, ainfo->addr, &tmpdata); 438 } 439 COMPILER_64_SET(*data, 0, tmpdata); 440 } 441 break; 442 443 case soc_pipereg: 444 case soc_xpereg: 445 case soc_itmreg: 446 case soc_ebreg: 447 case soc_slicereg: 448 case soc_layerreg: 449 if (soc_feature(unit, soc_feature_new_sbus_format)) { 450 if (ainfo->valid && (int)ainfo->reg >= 0 && 451 SOC_REG_IS_VALID(unit, ainfo->reg) && 452 SOC_REG_IS_64(unit, ainfo->reg)) { 453 rv = soc_reg_get(unit, ainfo->reg, ainfo->port, ainfo->idx, data); 454 } else { 455 rv = soc_reg32_get(unit, ainfo->reg, ainfo->port, ainfo->idx, &tmpdata); 456 COMPILER_64_SET(*data, 0, tmpdata); 457 } 458 break; 459 } 460 case soc_cosreg: 461 if (ainfo->valid && (int)ainfo->reg >= 0 && 462 SOC_REG_IS_VALID(unit, ainfo->reg) && 463 SOC_REG_IS_64(unit, ainfo->reg)) { 464 if (soc_feature(unit, soc_feature_new_sbus_format)) { 465 rv = soc_reg_get(unit, ainfo->reg, ainfo->cos, ainfo->idx, data); 466 } else { 467 rv = soc_reg_read(unit, ainfo->reg, ainfo->addr, data); 468 } 469 } else { 470 if (soc_feature(unit, soc_feature_new_sbus_format)) { 471 rv = soc_reg32_get(unit, ainfo->reg, ainfo->cos, ainfo->idx, &tmpdata); 472 } else { 473 rv = soc_reg32_read(unit, ainfo->addr, &tmpdata); 474 } 475 COMPILER_64_SET(*data, 0, tmpdata); 476 } 477 break; 478 default: 479 assert(0); 480 rv = SOC_E_INTERNAL; 481 break; 482 } 483 484 return rv; 485 } 486 487 488 /* 489 * Function: 490 * soc_anyreg_write 491 * Purpose: 492 * Write a soc register according to type 493 * Parameters: 494 * unit - soc unit number 495 * ainfo - address information structure 496 * data - 64 bit data. Will type correctly for register. 497 * Returns: 498 * BCM_E_XXX 499 * Notes: 500 * This routine requires ainfo->addr to be 501 * properly set. 502 * If it is a 64-bit register, then additionally, ainfo->valid 503 * must be set and ainfo->reg must be set properly. 504 */ 505 506 int 507 soc_anyreg_write(int unit, soc_regaddrinfo_t *ainfo, uint64 data) 508 { 509 uint32 tmpdata = 0; 510 int rv = SOC_E_NONE; 511 soc_regtype_t type; 512 int port = ainfo->port; 513 514 if (ainfo->reg < 0) { 515 type = soc_genreg; 516 } else { 517 if (!SOC_REG_IS_VALID(unit, ainfo->reg)) { 518 return SOC_E_PARAM; 519 } 520 type = SOC_REG_INFO(unit, ainfo->reg).regtype; 521 } 522 523 #if defined(BCM_SAND_SUPPORT) 524 if (SOC_IS_SAND(unit)) { 525 if ((ainfo->port >=0) || (ainfo->port & SOC_REG_ADDR_INSTANCE_MASK)) { 526 port = ainfo->port; 527 } else { 528 port = REG_PORT_ANY; 529 } 530 } 531 #endif 532 533 switch (type) { 534 case soc_cpureg: 535 #ifdef BCM_CMICM_SUPPORT 536 if (soc_feature(unit, soc_feature_cmicm)) { 537 if (soc_feature(unit, soc_feature_cpureg_dump)){ 538 if (soc_cpureg_address_is_invalid(unit, ainfo)) { 539 rv = SOC_E_INTERNAL; 540 break; 541 } 542 } 543 } 544 #endif 545 COMPILER_64_TO_32_LO(tmpdata, data); 546 soc_pci_write(unit, ainfo->addr, tmpdata); 547 break; 548 #ifdef BCM_CMICM_SUPPORT 549 case soc_mcsreg: 550 COMPILER_64_TO_32_LO(tmpdata, data); 551 soc_pci_mcs_write(unit, ainfo->addr, tmpdata); 552 break; 553 #endif 554 #ifdef BCM_IPROC_SUPPORT 555 case soc_iprocreg: 556 COMPILER_64_TO_32_LO(tmpdata, data); 557 soc_cm_iproc_write(unit, ainfo->addr, tmpdata); 558 break; 559 #endif 560 case soc_customreg: 561 case soc_genreg: 562 case soc_portreg: 563 case soc_ppportreg: 564 case soc_pipereg: 565 case soc_xpereg: 566 case soc_itmreg: 567 case soc_ebreg: 568 case soc_slicereg: 569 case soc_layerreg: 570 case soc_cosreg: 571 if (type == soc_cosreg) { 572 port = ainfo->cos; 573 } 574 #if defined(BCM_TRIDENT2_SUPPORT) 575 if (soc_feature(unit, soc_feature_pgw_mac_rsv_mask_remap) && 576 ainfo->reg == PGW_MAC_RSV_MASKr) { 577 int block; 578 uint8 acc_type; 579 580 ainfo->addr = soc_reg_addr_get(unit, PGW_MAC_RSV_MASKr, 581 ainfo->port, 0, 582 SOC_REG_ADDR_OPTION_WRITE, 583 &block, &acc_type); 584 ainfo->addr &= 0xffffff00; 585 ainfo->addr |= 586 (SOC_INFO(unit).port_l2p_mapping[ainfo->port] - 1) & 0xf; 587 tmpdata = COMPILER_64_LO(data); 588 rv = _soc_reg32_set(unit, block, acc_type, ainfo->addr, tmpdata); 589 } else 590 #endif /* BCM_TRIDENT2_SUPPORT */ 591 if (ainfo->valid && (int)ainfo->reg >= 0) { 592 if (SOC_REG_IS_64(unit, ainfo->reg)) { 593 if (soc_feature(unit, soc_feature_new_sbus_format)) { 594 rv = soc_reg64_set(unit, ainfo->reg, port, ainfo->idx, data); 595 } else { 596 rv = soc_reg64_write(unit, ainfo->addr, data); 597 } 598 } else { 599 COMPILER_64_TO_32_LO(tmpdata, data); 600 if (soc_feature(unit, soc_feature_new_sbus_format)) { 601 rv = soc_reg32_set(unit, ainfo->reg, port, ainfo->idx, tmpdata); 602 } else { 603 rv = soc_reg32_write(unit, ainfo->addr, tmpdata); 604 } 605 } 606 #if defined(BCM_XGS_SUPPORT) 607 if (soc_feature(unit, soc_feature_regs_as_mem)) { 608 if (SOC_REG_IS_64(unit, ainfo->reg)) { 609 (void)soc_ser_reg_cache_set(unit, ainfo->reg, port < 0 ? 0 : port, 610 ainfo->idx, data); 611 } else { 612 (void)soc_ser_reg32_cache_set(unit, ainfo->reg, port < 0 ? 0 : port, 613 ainfo->idx < 0 ? 0 : ainfo->idx, tmpdata); 614 } 615 } 616 #endif /* BCM_XGS_SUPPORT */ 617 } else { /* Left around for some legacy support */ 618 rv = soc_reg32_write(unit, ainfo->addr, tmpdata); 619 } 620 break; 621 default: 622 assert(0); 623 rv = SOC_E_INTERNAL; 624 break; 625 } 626 return rv; 627 } 628 629 #define UPDATE_BP(bp) while (*(bp)) (bp)++; 630 631 /* This is inefficient, because it does a lookup for each field. */ 632 void 633 soc_reg_sprint_data(int unit, char *bp, char *infix, soc_reg_t reg, 634 uint32 value) 635 { 636 int i, n; 637 soc_field_t field; 638 int len; 639 char buf[24]; 640 641 if (!SOC_REG_IS_VALID(unit, reg)) { 642 return; 643 } 644 n = SOC_REG_INFO(unit, reg).nFields; 645 for (i = 0; i < n; i++) { 646 field = SOC_REG_INFO(unit, reg).fields[i].field; 647 len = SOC_REG_INFO(unit, reg).fields[i].len; 648 if (i == n - 1) { 649 infix = ""; 650 } 651 #if defined(SOC_NO_NAMES) 652 sal_sprintf(buf, "#%%d = 0x%%0%dx%%s", (len + 3) >> 2); 653 sal_sprintf(bp, buf, field, 654 soc_reg_field_get(unit, reg, value, field), infix); 655 #else 656 sal_sprintf(buf, "%%s = 0x%%0%dx%%s", (len + 3) >> 2); 657 sal_sprintf(bp, buf, soc_fieldnames[field], 658 soc_reg_field_get(unit, reg, value, field), infix); 659 #endif 660 UPDATE_BP(bp); 661 } 662 } 663 664 void 665 soc_reg_sprint_addr(int unit, char *bp, soc_regaddrinfo_t *ainfo) 666 { 667 soc_field_info_t *finfop = 0; 668 int msb, lsb; 669 soc_reg_info_t *reginfo; 670 int len = 0; 671 672 if (!ainfo->valid) { 673 len = sal_strlen("Invalid Address"); 674 sal_strncpy(bp, "Invalid Address", len); 675 bp[len] = '\0'; 676 return; 677 } 678 if (ainfo->reg != INVALIDr && SOC_REG_IS_VALID(unit, ainfo->reg)) { 679 reginfo = &SOC_REG_INFO(unit, ainfo->reg); 680 if (ainfo->field != INVALIDf) { 681 SOC_FIND_FIELD(ainfo->field, 682 reginfo->fields, 683 reginfo->nFields, 684 finfop); 685 assert(finfop); 686 if (finfop->flags & SOCF_LE) { 687 msb = finfop->bp + finfop->len - 1; 688 lsb = finfop->bp; 689 } else { 690 msb = finfop->bp; 691 lsb = finfop->bp + finfop->len - 1; 692 } 693 sal_sprintf(bp, "[%d:%d] ", msb, lsb); 694 UPDATE_BP(bp); 695 } 696 } else { 697 len = sal_strlen("Reserved"); 698 sal_strncpy(bp, "Reserved", len); 699 bp[len] = '\0'; 700 return; 701 } 702 703 #ifdef SOC_NO_NAMES 704 sal_sprintf(bp, "#%d", ainfo->reg); 705 #else 706 sal_sprintf(bp, "%s", SOC_REG_NAME(unit, ainfo->reg)); 707 #endif /* SOC_NO_NAMES */ 708 UPDATE_BP(bp); 709 710 if (SOC_REG_ARRAY(unit, ainfo->reg)) { 711 sal_sprintf(bp, "(%d)", ainfo->idx); 712 UPDATE_BP(bp); 713 } 714 if (ainfo->cos != -1) { 715 sal_sprintf(bp, ".%d", ainfo->cos); 716 UPDATE_BP(bp); 717 } 718 if ((reginfo->regtype != soc_portreg) && 719 (reginfo->regtype != soc_ppportreg) && 720 (reginfo->regtype != soc_customreg)) { 721 *bp++ = '.'; 722 len = sal_strlen(SOC_BLOCK_NAME(unit, ainfo->block)); 723 sal_strncpy(bp, SOC_BLOCK_NAME(unit, ainfo->block), len); 724 if (len) 725 bp[len] = '\0'; 726 UPDATE_BP(bp); 727 } 728 if (reginfo->regtype == soc_ppportreg) { 729 *bp++ = '.'; 730 sal_sprintf(bp, "pp%d", ainfo->port); 731 UPDATE_BP(bp); 732 } 733 if (reginfo->regtype == soc_portreg || reginfo->regtype == soc_customreg) { 734 *bp++ = '.'; 735 len = sal_strlen(SOC_PORT_NAME(unit, ainfo->port)); 736 sal_strncpy(bp, SOC_PORT_NAME(unit, ainfo->port), len); 737 bp[len] = '\0'; 738 UPDATE_BP(bp); 739 } 740 if (finfop) { 741 #ifdef SOC_NO_NAMES 742 sal_sprintf(bp, ".#%d", ainfo->field); 743 #else 744 sal_sprintf(bp, ".%s", soc_fieldnames[ainfo->field]); 745 #endif /* SOC_NO_NAMES */ 746 UPDATE_BP(bp); 747 } 748 } 749 #undef UPDATE_BP 750 751 #define SOC_E_IGNORE -6000 752 753 /* 754 * This handles the iteration for a particular register addr info 755 * It does it across all array entries if the register is an array reg. 756 */ 757 static int 758 _do_reg_iter(int unit, soc_reg_iter_f do_it, 759 soc_regaddrinfo_t *ainfo, void *data, int *done) 760 { 761 int first_array_idx, idx; 762 int num_els, gran; 763 int rv = SOC_E_NONE; 764 uint32 base_addr; 765 soc_reg_t reg; 766 767 /* The granularity of register addresses, indexed by soc_regtype_t */ 768 /* new bus format */ 769 int soc_regtype_gran_new_bus[] = { 770 1, /* soc_schan_reg, */ 771 1 << 8, /* soc_genreg, */ 772 1, /* soc_portreg, */ 773 1, /* soc_ppportreg, */ 774 1, /* soc_cosreg, */ 775 1 << 8, /* soc_pipereg, */ 776 1 << 8, /* soc_xpereg, */ 777 1 << 8, /* soc_slicereg */ 778 1 << 8, /* soc_layerreg */ 779 4, /* soc_cpureg, */ 780 4, /* soc_pci_cfg_reg, */ 781 1, /* soc_phy_reg, */ 782 1, /* soc_spi_reg, */ 783 4, /* soc_mcsreg, */ 784 4, /* soc_iprocreg, */ 785 4, /* soc_hostmem_w, */ 786 2, /* soc_hostmem_h, */ 787 1, /* soc_hostmem_b, */ 788 1 << 8, /* soc_customreg, */ 789 0, /* soc_invalidreg */ 790 }; 791 int reg_type_no = 0; 792 793 reg = ainfo->reg; 794 reg_type_no = SOC_REG_INFO(unit, reg).regtype; 795 if (ainfo->reg == INVALIDr || !SOC_REG_IS_VALID(unit, ainfo->reg) || 796 reg_type_no >= COUNTOF(soc_regtype_gran_new_bus)) { 797 return SOC_E_PARAM; 798 } 799 800 base_addr = ainfo->addr; 801 gran = (soc_feature(unit, soc_feature_new_sbus_format))? 802 soc_regtype_gran_new_bus[reg_type_no]: 803 SOC_REG_GRAN(unit, reg); 804 805 if (SOC_IS_GREYHOUND2(unit) && 806 (SOC_REG_INFO(unit, reg).regtype == soc_genreg) && 807 (SOC_REG_FIRST_BLK_TYPE(SOC_REG_INFO(unit, reg).block) == SOC_BLK_TAF)) { 808 gran = 1; 809 } 810 811 if (SOC_REG_ARRAY(unit, reg) || SOC_REG_IS_ARRAY(unit, reg)) { 812 num_els = SOC_REG_NUMELS(unit, reg); 813 first_array_idx = SOC_REG_INFO(unit, reg).first_array_index; 814 } else { 815 num_els = 1; 816 first_array_idx = 0; 817 } 818 819 for (idx = first_array_idx; (idx < first_array_idx + num_els) && !*done; idx++) { 820 if (SOC_REG_IS_ARRAY(unit, reg)) { 821 ainfo->addr = base_addr + (idx - first_array_idx) * SOC_REG_ELEM_SKIP(unit, reg); 822 } else if (SOC_REG_ARRAY(unit, reg)) { 823 ainfo->addr = base_addr + (idx * gran); 824 if (SOC_REG_ARRAY2(unit, reg)) { 825 ainfo->addr = base_addr + (idx * gran * 2); 826 } else if (SOC_REG_ARRAY4(unit, reg)) { 827 ainfo->addr = base_addr + (idx * gran * 4); 828 } 829 } else { 830 ainfo->addr = base_addr + (idx * gran); /* idx == 0 */ 831 } 832 ainfo->idx = idx; 833 if ((SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_NO_DGNL) && 834 (idx == ainfo->port)) { 835 continue; 836 } 837 rv = (*do_it)(unit, ainfo, data); 838 switch (rv) { 839 case SOC_E_NONE: 840 break; 841 case SOC_E_IGNORE: 842 rv = SOC_E_NONE; 843 *done = 1; 844 break; 845 default: 846 *done = 1; 847 break; 848 } 849 } 850 851 ainfo->addr = base_addr; 852 return rv; 853 } 854 855 #ifdef BCM_KATANA2_SUPPORT 856 /* EMC registers common to KT2 and SB2*/ 857 static soc_reg_t emc_regs[] = 858 { 859 CI0_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 860 CI0_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 861 CI1_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 862 CI1_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 863 EMC_BUFFER_EMPTY_FULL_STATUS_DEBUGr, 864 EMC_CFGr, 865 EMC_CI_FULL_STATUS_DEBUGr, 866 EMC_CSDB_0_BUFFER_PAR_STATUS_DEBUGr, 867 EMC_CSDB_1_BUFFER_PAR_STATUS_DEBUGr, 868 EMC_CSDB_MEM_DEBUGr, 869 EMC_ECC_DEBUG_0r, 870 EMC_ECC_DEBUG_1r, 871 EMC_ERRORr, 872 EMC_ERROR_0r, 873 EMC_ERROR_1r, 874 EMC_ERROR_2r, 875 EMC_ERROR_3r, 876 EMC_ERROR_MASK_0r, 877 EMC_ERROR_MASK_1r, 878 EMC_ERROR_MASK_2r, 879 EMC_ERROR_MASK_3r, 880 EMC_FREE_POOL_SIZESr, 881 EMC_GLOBAL_1B_ECC_ERROR_COUNT_DEBUGr, 882 EMC_GLOBAL_2B_ECC_ERROR_COUNT_DEBUGr, 883 EMC_IRRB_BUFFER_ECC_STATUS_DEBUGr, 884 EMC_IRRB_BUFFER_FILL_LEVEL_DEBUGr, 885 EMC_IRRB_BUFFER_WATERMARK_DEBUGr, 886 EMC_IRRB_THRESHOLDSr, 887 EMC_RFCQ_BUFFER_ECC_STATUS_DEBUGr, 888 EMC_RFCQ_BUFFER_FILL_LEVEL_DEBUGr, 889 EMC_RFCQ_BUFFER_WATERMARK_DEBUGr, 890 EMC_RFCQ_MEM_DEBUGr, 891 EMC_RSFP_BUFFER_ECC_STATUS_DEBUGr, 892 EMC_RSFP_BUFFER_FILL_LEVEL_DEBUGr, 893 EMC_RSFP_MEM_DEBUGr, 894 EMC_SWAT_BUFFER_ECC_STATUS_DEBUGr, 895 EMC_SWAT_MEM_DEBUGr, 896 EMC_TO_CI0_RD_REQ_COUNT_DEBUGr, 897 EMC_TO_CI0_WR_REQ_COUNT_DEBUGr, 898 EMC_TO_CI1_RD_REQ_COUNT_DEBUGr, 899 EMC_TO_CI1_WR_REQ_COUNT_DEBUGr, 900 EMC_WLCT_MEM_DEBUGr, 901 EMC_WLCT_MERGED_RETURN_WTAG_FIFO_MEM_DEBUGr, 902 EMC_WLCT_MERGED_RETURN_WTAG_FIFO_NFULL_THRESHOLDr, 903 EMC_WTFP_BUFFER_ECC_STATUS_DEBUGr, 904 EMC_WTFP_BUFFER_FILL_LEVEL_DEBUGr, 905 EMC_WTFP_MEM_DEBUGr, 906 EMC_WTOQ_BUFFER_ECC_STATUS_DEBUGr, 907 EMC_WTOQ_BUFFER_FILL_LEVEL_DEBUGr, 908 EMC_WTOQ_MEM_DEBUGr, 909 ITE_TO_EMC_WR_REQ_SOP_COUNT_DEBUGr, 910 MMU_ITE_EMC_BACKPRESSURE_DEBUG_CONFIGr, 911 MMU_ITE_EMC_BACKPRESSURE_DEBUG_STATUSr 912 }; 913 914 /* EMC registers of KT2 */ 915 static soc_reg_t kt2_emc_regs[] = 916 { 917 CI2_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 918 CI2_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 919 CI3_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 920 CI3_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 921 CI4_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 922 CI4_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 923 CI5_TO_EMC_CELL_DATA_RETURN_COUNT_DEBUGr, 924 CI5_TO_EMC_WTAG_RETURN_COUNT_DEBUGr, 925 EMC_CSDB_2_BUFFER_PAR_STATUS_DEBUGr, 926 EMC_CSDB_3_BUFFER_PAR_STATUS_DEBUGr, 927 EMC_CSDB_4_BUFFER_PAR_STATUS_DEBUGr, 928 EMC_CSDB_5_BUFFER_PAR_STATUS_DEBUGr, 929 EMC_ERRB_0_BUFFER_ECC_STATUS_DEBUGr, 930 EMC_ERRB_0_BUFFER_FILL_LEVEL_DEBUGr, 931 EMC_ERRB_0_BUFFER_WATERMARK_DEBUGr, 932 EMC_ERRB_0_MEM_DEBUGr, 933 EMC_ERRB_1_BUFFER_ECC_STATUS_DEBUGr, 934 EMC_ERRB_1_BUFFER_FILL_LEVEL_DEBUGr, 935 EMC_ERRB_1_BUFFER_WATERMARK_DEBUGr, 936 EMC_ERRB_1_MEM_DEBUGr, 937 EMC_ERRB_FIFO_NFULL_THRESHOLDr, 938 EMC_EWRB_0_BUFFER_0_ECC_STATUS_DEBUGr, 939 EMC_EWRB_0_BUFFER_1_ECC_STATUS_DEBUGr, 940 EMC_EWRB_0_BUFFER_FILL_LEVEL_DEBUGr, 941 EMC_EWRB_0_BUFFER_WATERMARK_DEBUGr, 942 EMC_EWRB_0_MEM_DEBUGr, 943 EMC_EWRB_1_BUFFER_0_ECC_STATUS_DEBUGr, 944 EMC_EWRB_1_BUFFER_1_ECC_STATUS_DEBUGr, 945 EMC_EWRB_1_BUFFER_FILL_LEVEL_DEBUGr, 946 EMC_EWRB_1_BUFFER_WATERMARK_DEBUGr, 947 EMC_EWRB_1_MEM_DEBUGr, 948 EMC_EWRB_FIFO_NFULL_THRESHOLDr, 949 EMC_IWRB_BUFFER_ECC_STATUS_DEBUGr, 950 EMC_IWRB_BUFFER_FILL_LEVEL_DEBUGr, 951 EMC_IWRB_BUFFER_WATERMARK_DEBUGr, 952 EMC_IWRB_MEM_DEBUGr, 953 EMC_IWRB_SIZEr, 954 EMC_TO_CI2_RD_REQ_COUNT_DEBUGr, 955 EMC_TO_CI2_WR_REQ_COUNT_DEBUGr, 956 EMC_TO_CI3_RD_REQ_COUNT_DEBUGr, 957 EMC_TO_CI3_WR_REQ_COUNT_DEBUGr, 958 EMC_TO_CI4_RD_REQ_COUNT_DEBUGr, 959 EMC_TO_CI4_WR_REQ_COUNT_DEBUGr, 960 EMC_TO_CI5_RD_REQ_COUNT_DEBUGr, 961 EMC_TO_CI5_WR_REQ_COUNT_DEBUGr, 962 EMC_WCMT_BUFFER_ECC_STATUS_DEBUGr, 963 EMC_WCMT_MEM_DEBUGr, 964 EMC_WLCT0_LOWER_A_BUFFER_ECC_STATUS_DEBUGr, 965 EMC_WLCT1_MERGED_RETURN_WTAG_FIFO_ECC_STATUS_DEBUGr, 966 EMC_WLCT0_LOWER_B_BUFFER_ECC_STATUS_DEBUGr, 967 EMC_WLCT0_MERGED_RETURN_WTAG_FIFO_ECC_STATUS_DEBUGr, 968 EMC_WLCT0_UPPER_A_BUFFER_ECC_STATUS_DEBUGr, 969 EMC_WLCT0_UPPER_B_BUFFER_ECC_STATUS_DEBUGr, 970 EMC_WLCT1_LOWER_A_BUFFER_ECC_STATUS_DEBUGr, 971 EMC_WLCT1_LOWER_B_BUFFER_ECC_STATUS_DEBUGr, 972 EMC_WLCT1_UPPER_A_BUFFER_ECC_STATUS_DEBUGr, 973 EMC_WLCT1_UPPER_B_BUFFER_ECC_STATUS_DEBUGr, 974 EXT_BUFFER_POOL_CONG_STATEr, 975 EMC_WLCT2_LOWER_A_BUFFER_ECC_STATUS_DEBUGr, 976 EMC_WLCT2_LOWER_B_BUFFER_ECC_STATUS_DEBUGr, 977 EMC_WLCT2_MERGED_RETURN_WTAG_FIFO_ECC_STATUS_DEBUGr, 978 EMC_WLCT2_UPPER_A_BUFFER_ECC_STATUS_DEBUGr, 979 EMC_WLCT2_UPPER_B_BUFFER_ECC_STATUS_DEBUGr 980 }; 981 982 static soc_reg_t sb2_emc_regs[] = 983 { 984 EMC_FIXED_PATTERN_DEBUGr, 985 EMC_IRRB_MEM_DEBUGr, 986 EMC_TO_ITE_WR_REQ_PKT_COMPLETE_COUNT_DEBUGr, 987 EMC_WLCT_BUFFER_ECC_STATUS_DEBUGr, 988 EMC_WLCT_MERGED_RETURN_WTAG_FIFO_ECC_STATUS_DEBUGr, 989 EMC_WLCT_MERGED_RETURN_WTAG_FIFO_FILL_LEVEL_DEBUGr, 990 EMC_WLCT_MERGED_RETURN_WTAG_FIFO_WATERMARK_DEBUGr, 991 ITE_TO_EMC_WR_REQ_EOP_COUNT_DEBUGr 992 }; 993 994 static int 995 _is_emc_reg(int unit, soc_reg_t reg) 996 { 997 int i; 998 999 /* EMC registers common to KT2 and SB2*/ 1000 for (i = 0; i < (sizeof(emc_regs)/sizeof(soc_reg_t)); i++) { 1001 if (emc_regs[i] == reg) { 1002 return 1; 1003 } 1004 } 1005 1006 /* EMC registers of KT2 */ 1007 if (SOC_IS_KATANA2(unit) && !(SOC_IS_SABER2(unit))){ 1008 for (i = 0; i < (sizeof(kt2_emc_regs)/sizeof(soc_reg_t)); i++) { 1009 if (kt2_emc_regs[i] == reg) { 1010 return 1; 1011 } 1012 } 1013 } 1014 1015 /* EMC registers of SB2 */ 1016 if (SOC_IS_SABER2(unit)) { 1017 for (i = 0; i < (sizeof(sb2_emc_regs)/sizeof(soc_reg_t)); i++) { 1018 if (sb2_emc_regs[i] == reg) { 1019 return 1; 1020 } 1021 } 1022 } 1023 1024 return 0; 1025 } 1026 #endif 1027 1028 int 1029 soc_reg_iterate(int unit, soc_reg_iter_f do_it, void *data) 1030 { 1031 soc_reg_t reg; 1032 soc_port_t port; 1033 soc_cos_t cos; 1034 int blk; 1035 soc_block_types_t regblktype; 1036 soc_regaddrinfo_t ainfo; 1037 int done; 1038 #ifdef BCM_TRIUMPH2_SUPPORT 1039 int skip_cpu; 1040 #endif 1041 int phy_port; 1042 int port_num_blktype; 1043 int i; 1044 int idx_min, idx_max, idx; 1045 1046 ainfo.valid = 1; 1047 ainfo.field = INVALIDf; 1048 1049 #ifdef BCM_TRIUMPH2_SUPPORT 1050 skip_cpu = soc_property_get(unit, "cmic_regtest_skip", 1); 1051 #endif 1052 1053 for (reg = 0; reg < NUM_SOC_REG; reg++) { 1054 if (!SOC_REG_IS_VALID(unit, reg)) { 1055 continue; 1056 } 1057 if (!SOC_REG_IS_ENABLED(unit, reg)) { 1058 continue; 1059 } 1060 done = 0; 1061 ainfo.reg = reg; 1062 regblktype = SOC_REG_INFO(unit, reg).block; 1063 if (SAL_BOOT_QUICKTURN && (SOC_BLOCK_IS(regblktype, SOC_BLK_BSAFE))) { 1064 continue; 1065 } 1066 switch (SOC_REG_INFO(unit, reg).regtype) { 1067 case soc_ppportreg: 1068 PBMP_PP_ALL_ITER(unit, port) { 1069 ainfo.port = port; 1070 ainfo.addr = soc_reg_addr_get(unit, reg, ainfo.port, 0, 1071 SOC_REG_ADDR_OPTION_NONE, 1072 &ainfo.block, &ainfo.acc_type); 1073 ainfo.cos = -1; 1074 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1075 if (done) { 1076 break; 1077 } 1078 } 1079 break; 1080 case soc_customreg: 1081 case soc_portreg: 1082 PBMP_ALL_ITER(unit, port) { 1083 if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT)) { 1084 if (SOC_BLOCK_IS(regblktype, SOC_BLK_PGW_CL)) { 1085 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype; 1086 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1087 blk = -1; 1088 for (i = 0; i < port_num_blktype; i++) { 1089 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 1090 if (blk < 0) { 1091 break; 1092 } 1093 if (SOC_REG_BLOCK_IN_LIST(unit, reg, 1094 SOC_BLOCK_TYPE(unit, blk))) { 1095 break; 1096 } 1097 } 1098 if (blk < 0) { 1099 continue; 1100 } 1101 } else if (!SOC_REG_BLOCK_IN_LIST(unit, reg, 1102 SOC_PORT_TYPE(unit, port))) { 1103 continue; 1104 } 1105 } 1106 #ifdef BCM_FIREBOLT_SUPPORT 1107 if (SOC_IS_FBX(unit)) { 1108 if (SOC_BLOCK_IS(regblktype, SOC_BLK_IPIPE_HI) && 1109 ((!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, 1110 IPIPE_HI_BLOCK(unit)), port)))) { 1111 continue; 1112 } 1113 if (SOC_BLOCK_IS(regblktype, SOC_BLK_EPIPE_HI) && 1114 ((!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, 1115 EPIPE_HI_BLOCK(unit)), port)))) { 1116 continue; 1117 } 1118 } 1119 #endif 1120 #ifdef BCM_GREYHOUND_SUPPORT 1121 if(SOC_IS_GREYHOUND(unit) && (SOC_BLOCK_IS(regblktype, SOC_BLK_XLPORT)|| 1122 SOC_BLOCK_IS(regblktype, SOC_BLK_GXPORT))){ 1123 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype; 1124 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1125 blk = -1; 1126 for (i = 0; i < port_num_blktype; i++) { 1127 if (regblktype[0] == SOC_BLK_XLPORT){ 1128 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 1129 NULL, &blk, NULL, 0) > 0){ 1130 /* get the correct blk */ 1131 break; 1132 } 1133 } 1134 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 1135 if (blk < 0) { 1136 break; 1137 } 1138 if (SOC_BLOCK_IS(regblktype, 1139 SOC_BLOCK_TYPE(unit, blk))) { 1140 break; 1141 } 1142 } 1143 if (blk <= 0) { 1144 continue; 1145 } 1146 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 1147 NULL, NULL, NULL, 0) == SOC_E_NOT_FOUND){ 1148 /* port register not belong to pgw_gx and pgw_xl */ 1149 if (!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, blk), port)){ 1150 /* check the valid blk bitmap*/ 1151 continue; 1152 } 1153 } else if (regblktype[0] == SOC_BLK_XLPORT){ 1154 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 1155 NULL, &blk, NULL, 1) > 0){ 1156 /* check the valid blk */ 1157 continue; 1158 } 1159 } 1160 } 1161 #endif 1162 1163 #ifdef BCM_TOMAHAWK3_SUPPORT 1164 if (SOC_IS_TOMAHAWK3(unit)) { 1165 if ((regblktype[0] == SOC_BLK_CDMAC) && 1166 IS_CPU_PORT(unit,port)) { 1167 continue; 1168 } 1169 } 1170 #endif 1171 ainfo.port = port; 1172 ainfo.addr = soc_reg_addr_get(unit, reg, ainfo.port, 0, 1173 SOC_REG_ADDR_OPTION_NONE, 1174 &ainfo.block, &ainfo.acc_type); 1175 ainfo.block = -1; 1176 ainfo.cos = -1; 1177 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1178 if (done) { 1179 break; 1180 } 1181 } 1182 break; 1183 case soc_cosreg: 1184 for (cos = 0; cos < NUM_COS(unit) && !done; cos++) { 1185 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1186 ainfo.port = SOC_BLOCK_PORT(unit, blk); 1187 ainfo.addr = soc_reg_addr_get(unit, reg, ainfo.port, cos, 1188 SOC_REG_ADDR_OPTION_NONE, 1189 &ainfo.block, &ainfo.acc_type); 1190 ainfo.block = blk; 1191 ainfo.cos = cos; 1192 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1193 if (done) { 1194 break; 1195 } 1196 } 1197 } 1198 break; 1199 case soc_genreg: 1200 if (SOC_BLOCK_IS(regblktype, SOC_BLK_ESM) && 1201 (!soc_feature(unit, soc_feature_esm_support) || (SOC_CONTROL(unit)->tcam_info == NULL))) { 1202 break; 1203 } 1204 #ifdef BCM_KATANA2_SUPPORT 1205 if (SOC_IS_KATANA2(unit)) { 1206 if (_is_emc_reg(unit, reg) || SOC_BLOCK_IS(regblktype, SOC_BLK_CI)) { 1207 if (soc_feature(unit, soc_feature_ddr3)) { 1208 /* Don't read external RAM related registers if same 1209 * is not present or not configured */ 1210 if (!(soc_property_get(unit, spn_EXT_RAM_PRESENT, 0) && 1211 soc_property_get(unit, spn_PBMP_EXT_MEM, 0))) { 1212 break; 1213 } 1214 } else { 1215 /* Don't read external RAM related regs if 1216 * feature not supported */ 1217 break; 1218 } 1219 } 1220 } 1221 #endif 1222 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1223 switch (regblktype[0]) { 1224 case SOC_BLK_PMQPORT: 1225 case SOC_BLK_PMQ: 1226 case SOC_BLK_PGW_CL: 1227 ainfo.port = SOC_REG_ADDR_INSTANCE_MASK | 1228 SOC_BLOCK_NUMBER(unit, blk); 1229 break; 1230 1231 #ifdef BCM_MONTEREY_SUPPORT 1232 case SOC_BLK_CPRI: 1233 ainfo.port = SOC_BLOCK_PORT(unit, blk); 1234 break; 1235 #endif 1236 default: 1237 ainfo.port = SOC_BLOCK_PORT(unit, blk); 1238 break; 1239 } 1240 #ifdef BCM_DNX_SUPPORT 1241 if (SOC_IS_DNX(unit) && ((regblktype[0] == SOC_BLK_CDPORT) || 1242 (regblktype[0] == SOC_BLK_CDMAC))) { 1243 dnx_startup_test_function_f test_function = dnx_startup_test_functions[unit]; 1244 if(test_function == NULL) { 1245 bcm_pbmp_t valid_ports; 1246 bcm_port_t valid_port; 1247 int phy_port = 0; 1248 int cd_block = 0; 1249 if (dnx_algo_port_logicals_get(unit, BCM_CORE_ALL, DNX_ALGO_PORT_LOGICALS_TYPE_NIF, 0, &valid_ports) < 0) /* Get NIF logical port bitmap */ 1250 { 1251 break; 1252 } 1253 BCM_PBMP_ITER(valid_ports, valid_port) 1254 { 1255 phy_port = SOC_INFO(unit).port_l2p_mapping[valid_port]; /* Get NIF port first phy */ 1256 cd_block = SOC_PORT_BLOCK(unit, phy_port); 1257 if (blk == cd_block) 1258 { 1259 break; 1260 } 1261 } 1262 if (blk != cd_block) 1263 { 1264 continue; 1265 } 1266 } 1267 } 1268 #endif 1269 #ifdef BCM_GREYHOUND_SUPPORT 1270 if (SOC_IS_GREYHOUND(unit) && ((regblktype[0] == SOC_BLK_XLPORT) || 1271 (regblktype[0] == SOC_BLK_GXPORT))) { 1272 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, ainfo.port, 1273 NULL, NULL, NULL, 0) == SOC_E_NOT_FOUND){ 1274 /* port register not belong to pgw_gx and pgw_xl */ 1275 if (!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, blk), ainfo.port)){ 1276 /* check the valid blk bitmap*/ 1277 continue; 1278 } 1279 } else if (regblktype[0] == SOC_BLK_XLPORT){ 1280 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, ainfo.port, 1281 NULL, &blk, NULL, 1) > 0){ 1282 /* check the valid blk */ 1283 continue; 1284 } 1285 } 1286 } 1287 #endif 1288 1289 #ifdef BCM_PETRA_SUPPORT 1290 if ((SOC_IS_ARAD(unit)) && (regblktype[0] == SOC_BLK_GPORT)) { 1291 break; 1292 } 1293 #endif /*BCM_PETRA_SUPPORT*/ 1294 1295 #ifdef BCM_HURRICANE3_SUPPORT 1296 if ((SOC_IS_HURRICANE3(unit)) && 1297 (regblktype[0] == SOC_BLK_PGW_GE)) { 1298 1299 ainfo.port = SOC_REG_ADDR_INSTANCE_MASK | 1300 SOC_BLOCK_NUMBER(unit, blk); 1301 } 1302 #endif 1303 1304 #ifdef BCM_MONTEREY_SUPPORT 1305 if (regblktype[0] == SOC_BLK_CPRI && !IS_CPRI_PORT(unit, ainfo.port )) { 1306 continue; 1307 } 1308 #endif 1309 ainfo.addr = soc_reg_addr_get(unit, reg, ainfo.port, 1310 (SOC_REG_ARRAY(unit, reg) || SOC_REG_IS_ARRAY(unit, reg)) ? SOC_REG_INFO(unit, reg).first_array_index : 0, 1311 SOC_REG_ADDR_OPTION_NONE, 1312 &ainfo.block, &ainfo.acc_type); 1313 1314 ainfo.block = blk; 1315 ainfo.cos = -1; 1316 if (!soc_feature(unit, soc_feature_esm_support) && 1317 soc_feature(unit, soc_feature_new_sbus_format) && 1318 SOC_BLOCK_IS(regblktype, SOC_BLK_IPIPE)) { /* Needs update per chip */ 1319 if (SOC_IS_TRIUMPH3(unit) && 1320 SOC_REG_ADDR_STAGE(ainfo.addr) == 0x9) { /* IESMIF */ 1321 continue; 1322 } 1323 } 1324 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1325 if (done) { 1326 break; 1327 } 1328 } 1329 break; 1330 case soc_cpureg: 1331 /* Skip CPU registers in soc iteration. */ 1332 #ifdef BCM_TRIUMPH2_SUPPORT 1333 if (SOC_IS_TRIUMPH2(unit) && !skip_cpu) { 1334 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1335 ainfo.port = SOC_BLOCK_PORT(unit, blk); 1336 ainfo.addr = soc_reg_addr(unit, reg, ainfo.port, 0); 1337 ainfo.block = blk; 1338 ainfo.cos = -1; 1339 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1340 if (done) { 1341 break; 1342 } 1343 } 1344 } 1345 #endif 1346 break; 1347 case soc_mcsreg: 1348 case soc_iprocreg: 1349 /* Skip MCS registers in soc iteration. */ 1350 break; 1351 case soc_pipereg: 1352 case soc_xpereg: 1353 case soc_itmreg: 1354 case soc_ebreg: 1355 case soc_slicereg: 1356 case soc_layerreg: 1357 idx_min = 0; 1358 switch (SOC_REG_INFO(unit, reg).regtype) { 1359 case soc_pipereg: 1360 idx_max = NUM_PIPE(unit) - 1; 1361 break; 1362 case soc_xpereg: 1363 idx_max = NUM_XPE(unit) - 1; 1364 break; 1365 case soc_itmreg: 1366 idx_max = NUM_ITM(unit) - 1; 1367 break; 1368 case soc_ebreg: 1369 idx_max = NUM_EB(unit) - 1; 1370 break; 1371 case soc_slicereg: 1372 idx_max = NUM_SLICE(unit) - 1; 1373 break; 1374 case soc_layerreg: 1375 idx_max = NUM_LAYER(unit) - 1; 1376 break; 1377 default: 1378 assert(0); 1379 return 0; 1380 } 1381 1382 for (idx = idx_min; idx <= idx_max && !done; idx++) { 1383 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1384 ainfo.port = SOC_REG_ADDR_INSTANCE_MASK | idx; 1385 ainfo.addr = soc_reg_addr_get(unit, reg, ainfo.port, 0, 1386 SOC_REG_ADDR_OPTION_NONE, 1387 &ainfo.block, 1388 &ainfo.acc_type); 1389 ainfo.block = blk; 1390 ainfo.cos = -1; 1391 _do_reg_iter(unit, do_it, &ainfo, data, &done); 1392 if (done) { 1393 break; 1394 } 1395 } 1396 } 1397 break; 1398 default: 1399 assert(0); 1400 break; 1401 } 1402 } 1403 1404 return 0; 1405 } 1406 1407 /* 1408 * Given an address, fill in an regaddrinfo structure 1409 * This can only be called for SOC registers, not for CPU registers 1410 */ 1411 void 1412 soc_regaddrinfo_get(int unit, soc_regaddrinfo_t *ainfo, uint32 addr) 1413 { 1414 int i, idx; 1415 int blk = 0, bindex, port, phy_port; 1416 uint32 minadr, maxadr; 1417 soc_regtype_t regtype; 1418 int reg; 1419 uint32 offset; /* base address */ 1420 int block = -1; /* block number */ 1421 int pindex; /* port/cos index field */ 1422 int aindex = 0; /* array index field */ 1423 soc_block_t portblktype; 1424 #ifdef BCM_TOMAHAWK3_SUPPORT 1425 soc_reg_t reg_excep_list[]={MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr, 1426 MMU_RQE_REPL_PORT_AGG_MAPr}; 1427 int reg_index, num_regs, add_exception = 0; 1428 #endif 1429 1430 1431 ainfo->addr = addr; 1432 ainfo->valid = 1; 1433 ainfo->reg = INVALIDr; 1434 1435 { 1436 portblktype = SOC_BLK_PORT; 1437 } 1438 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1439 block = ((addr >> SOC_BLOCK_BP) & 0xf) | 1440 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 1441 /* extract fields from addr */ 1442 if (SOC_IS_HERCULES(unit)) { 1443 offset = addr & 0xfffff; 1444 pindex = 0; 1445 aindex = 0; 1446 #if defined(BCM_TRIDENT_SUPPORT) 1447 } else if (SOC_IS_TD_TT(unit)) { 1448 offset = addr & 0x3f080fff; 1449 pindex = (addr >> SOC_REGIDX_BP) & 0x7f; 1450 aindex = addr & 0xfff; 1451 #endif /* BCM_TRIDENT_SUPPORT */ 1452 #if defined(BCM_FIREBOLT_SUPPORT) 1453 } else if (SOC_IS_FBX(unit)) { 1454 offset = addr & 0x3f0c0fff; 1455 pindex = (addr >> SOC_REGIDX_BP) & 0x3f; 1456 if (addr & 0x80000000) { 1457 pindex += 64; 1458 } 1459 aindex = addr & 0xfff; 1460 #endif 1461 } else { 1462 offset = addr & 0xc0fff; 1463 pindex = (addr >> SOC_REGIDX_BP) & 0x3f; 1464 aindex = addr & 0xfff; 1465 } 1466 } else { 1467 pindex = addr & 0xff; 1468 if (addr & 0x02000000) { 1469 offset = addr; 1470 } else { 1471 offset = addr & 0xffffff00; 1472 } 1473 } 1474 1475 /* find the matching block */ 1476 /* we find the last matching block to make things work with cmic/cpic */ 1477 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1478 blk = -1; 1479 for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) { 1480 if (SOC_BLOCK_INFO(unit, i).cmic == block) { 1481 blk = i; 1482 /* break; */ 1483 } 1484 } 1485 } 1486 assert(blk >= 0); 1487 for (reg = 0; reg < NUM_SOC_REG; reg++) { 1488 if (!SOC_REG_IS_VALID(unit, reg)) { 1489 continue; 1490 } 1491 minadr = SOC_REG_INFO(unit, reg).offset; 1492 if (offset < minadr) { 1493 continue; 1494 } 1495 if (SOC_REG_IS_ARRAY(unit, reg)) { 1496 maxadr = minadr + (SOC_REG_NUMELS(unit, reg) - 1)*SOC_REG_ELEM_SKIP(unit, reg); 1497 } else if (SOC_REG_ARRAY(unit, reg)) { 1498 if (SOC_REG_ARRAY2(unit, reg)) { 1499 maxadr = minadr + 1500 2 * (SOC_REG_GRAN(unit, reg) * (SOC_REG_NUMELS(unit, reg) - 1)); 1501 } else if (SOC_REG_ARRAY4(unit, reg)) { 1502 maxadr = minadr + 1503 4 * (SOC_REG_GRAN(unit, reg) * (SOC_REG_NUMELS(unit, reg) - 1)); 1504 } else { 1505 maxadr = minadr + 1506 (SOC_REG_GRAN(unit, reg) * (SOC_REG_NUMELS(unit, reg) - 1)); 1507 } 1508 } else { 1509 maxadr = minadr; 1510 } 1511 if (offset > maxadr) { 1512 continue; 1513 } 1514 1515 if (SOC_REG_ARRAY2(unit, reg)) { 1516 if ( (offset & 0x1) != (minadr & 0x1) ) { 1517 /* make sure last bit are same as the base addr when array stride is 2 */ 1518 continue; 1519 } 1520 } 1521 if (SOC_REG_ARRAY4(unit, reg)) { 1522 if ( (offset & 0x11) != (minadr & 0x11) ) { 1523 /* make sure last two bit are same as the base addr when array stride is 4 */ 1524 continue; 1525 } 1526 } 1527 regtype = SOC_REG_INFO(unit, reg).regtype; 1528 if ((regtype == soc_cpureg) || (regtype == soc_mcsreg) || (regtype == soc_iprocreg)) { 1529 continue; 1530 } 1531 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1532 if (!SOC_BLOCK_IS_TYPE(unit, blk, SOC_REG_INFO(unit, reg).block)) { 1533 continue; 1534 } 1535 } 1536 1537 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1538 ainfo->block = blk; 1539 } 1540 1541 if (SOC_REG_IS_ARRAY(unit, reg)) { 1542 for(idx=0 ; idx<SOC_REG_NUMELS(unit, reg) ; idx++) { 1543 if(minadr+idx*SOC_REG_ELEM_SKIP(unit, reg) == offset) { 1544 ainfo->reg = reg; 1545 ainfo->field = INVALIDf; 1546 ainfo->cos = -1; 1547 ainfo->port = -1; 1548 ainfo->idx = idx; 1549 return; 1550 } 1551 } 1552 continue; 1553 } 1554 1555 if (SOC_REG_ARRAY(unit, reg)) { 1556 if (soc_feature(unit, soc_feature_new_sbus_format)) { 1557 aindex = (offset - SOC_REG_BASE(unit, reg)) >> 8; 1558 } else { 1559 aindex = (offset - SOC_REG_BASE(unit, reg)); 1560 } 1561 if (SOC_REG_ARRAY2(unit, reg)) { 1562 ainfo->idx = aindex / (2 * SOC_REG_GRAN(unit, reg)); 1563 } else if (SOC_REG_ARRAY4(unit, reg)) { 1564 ainfo->idx = aindex / (4 * SOC_REG_GRAN(unit, reg)); 1565 } else { 1566 ainfo->idx = aindex / SOC_REG_GRAN(unit, reg); 1567 } 1568 } else { 1569 ainfo->idx = -1; 1570 } 1571 1572 ainfo->reg = reg; 1573 ainfo->field = INVALIDf; 1574 ainfo->cos = -1; 1575 ainfo->port = -1; 1576 switch (regtype) { 1577 case soc_customreg: 1578 case soc_ppportreg: 1579 case soc_portreg: 1580 if (SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, portblktype)) { 1581 for (phy_port = 0; ; phy_port++) { 1582 if (soc_feature(unit, soc_feature_logical_port_num)) { 1583 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1584 if (port < 0) { 1585 continue; 1586 } 1587 } else { 1588 port = phy_port; 1589 } 1590 blk = SOC_PORT_BLOCK(unit, phy_port); 1591 bindex = SOC_PORT_BINDEX(unit, phy_port); 1592 if (blk < 0 && bindex < 0) { /* end of list */ 1593 break; 1594 } 1595 if (blk < 0) { /* empty slot */ 1596 continue; 1597 } 1598 1599 if ((uint32)blk == ainfo->block && bindex == pindex) { 1600 ainfo->port = port; 1601 break; 1602 } 1603 } 1604 if (ainfo->port == -1) { 1605 ainfo->reg = INVALIDr; 1606 } 1607 } else { 1608 if (soc_feature(unit, soc_feature_logical_port_num) && 1609 SOC_REG_INFO(unit, reg).block[0] == SOC_BLK_MMU) { 1610 #ifdef BCM_TOMAHAWK3_SUPPORT 1611 /*MMU register with device port indexing*/ 1612 num_regs = sizeof(reg_excep_list) / sizeof(soc_reg_t); 1613 for (reg_index = 0;reg_index < num_regs; reg_index++) { 1614 if (reg_excep_list[reg_index] == reg) { 1615 add_exception = 1; 1616 break; 1617 } 1618 } 1619 if (add_exception) { 1620 ainfo->port = pindex; 1621 } else 1622 1623 #endif 1624 { 1625 phy_port = SOC_INFO(unit).port_m2p_mapping[pindex]; 1626 ainfo->port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1627 } 1628 } else { 1629 ainfo->port = pindex; 1630 } 1631 } 1632 break; 1633 case soc_cosreg: 1634 if (pindex >= 0 && pindex <= NUM_COS(unit)) { 1635 ainfo->cos = pindex; 1636 } else { 1637 ainfo->reg = INVALIDr; 1638 } 1639 break; 1640 case soc_genreg: 1641 if (pindex != 0) { 1642 ainfo->reg = INVALIDr; 1643 } 1644 break; 1645 default: 1646 assert(0); 1647 } 1648 break; 1649 } 1650 } 1651 1652 /* 1653 * Given an address, fill in an regaddrinfo structure 1654 * This can only be called for SOC registers, not for CPU registers 1655 */ 1656 void 1657 soc_regaddrinfo_extended_get(int unit, soc_regaddrinfo_t *ainfo, 1658 soc_block_t block, int acc_type, uint32 addr) 1659 { 1660 int i; 1661 int blk, bindex, port, phy_port = 0, cmic; 1662 int actual_blk; /* For broadcast blocks this will be a broadcast member block, otherwise it will be the block itself */ 1663 uint32 minadr, maxadr; 1664 soc_regtype_t regtype; 1665 int reg; 1666 uint32 offset; /* base address */ 1667 int pindex; /* port/cos index field */ 1668 int aindex; /* array index field */ 1669 soc_block_t portblktype; 1670 soc_block_types_t regblktype; 1671 int port_num_blktype; 1672 #ifdef BCM_SAND_SUPPORT 1673 int use_orig_address = 0; 1674 #endif 1675 #ifdef BCM_TOMAHAWK3_SUPPORT 1676 soc_reg_t reg_excep_list[]={MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr, 1677 MMU_RQE_REPL_PORT_AGG_MAPr}; 1678 int reg_index, num_regs, add_exception = 0; 1679 int stage_id; 1680 #endif 1681 1682 1683 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1684 soc_regaddrinfo_get(unit, ainfo, addr); 1685 return; 1686 } 1687 ainfo->addr = addr; 1688 ainfo->valid = 1; 1689 ainfo->reg = INVALIDr; 1690 portblktype = SOC_BLK_PORT; 1691 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype > 1 ? 1692 SOC_DRIVER(unit)->port_num_blktype : 1; 1693 pindex = addr & 0xff; 1694 1695 /* find the matching block */ 1696 /* we find the last matching block to make things work with cmic/cpic */ 1697 blk = -1; 1698 for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) { 1699 cmic = SOC_BLOCK_INFO(unit, i).cmic; 1700 if (cmic == block) { 1701 blk = i; 1702 /* break; */ 1703 } 1704 } 1705 1706 if (SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_GLB && 1707 SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_SC && 1708 SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_SED && 1709 SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_XPE && 1710 SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_ITM && 1711 SOC_BLOCK_INFO(unit, blk).type != SOC_BLK_MMU_EB && 1712 addr & 0x02000000) { 1713 offset = addr; 1714 } else { 1715 offset = addr & 0xffffff00; 1716 } 1717 1718 #if defined(BCM_SAND_SUPPORT) 1719 if (SOC_IS_SAND(unit)) { 1720 use_orig_address = 1; /* The register address of a soc_genreg does not end with 0x00 in DPP */ 1721 } 1722 #endif 1723 1724 actual_blk = blk; 1725 #ifdef BCM_JERICHO_SUPPORT 1726 /* handle broadcast blocks */ 1727 if (SOC_IS_JERICHO(unit) && SOC_BLOCK_IS_BROADCAST(unit, blk)) { 1728 actual_blk = SOC_BLOCK_BROADCAST_MEMBER(unit, blk, 0); 1729 } 1730 #endif /* BCM_JERICHO_SUPPORT */ 1731 1732 assert(actual_blk >= 0); 1733 for (reg = 0; reg < NUM_SOC_REG; reg++) { 1734 uint32 reg_offset; /* base address according to the checked register candidate */ 1735 if (!SOC_REG_IS_VALID(unit, reg)) { 1736 continue; 1737 } 1738 regtype = SOC_REG_INFO(unit, reg).regtype; 1739 regblktype = SOC_REG_INFO(unit, reg).block; 1740 #ifdef BCM_TOMAHAWK3_SUPPORT 1741 if (SOC_IS_TOMAHAWK3(unit)) { 1742 /* Since TH3 has the dummy blocks CDMAC defined in the regsfile, we need 1743 to assign them to the CDPORT block */ 1744 if (regblktype[0] == SOC_BLK_CDMAC) { 1745 regblktype[0] = SOC_BLK_CDPORT; 1746 } 1747 } 1748 #endif 1749 /* Base address decision of GH2 TAF block */ 1750 if (SOC_IS_GREYHOUND2(unit) && 1751 (SOC_REG_INFO(unit, reg).regtype == soc_genreg) && 1752 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_TAF)) { 1753 offset |= (1 << SOC_RT_BP); 1754 pindex = 0; 1755 } 1756 1757 #ifdef BCM_SAND_SUPPORT 1758 reg_offset = (use_orig_address && regtype == soc_genreg) ? addr : offset; 1759 if (SOC_IS_DNX(unit) && (SOC_BLOCK_TYPE(unit, actual_blk) == SOC_BLK_CDMAC || SOC_BLOCK_TYPE(unit, actual_blk) == SOC_BLK_CDPORT)) { 1760 reg_offset &= 0xf3ffff00; 1761 } 1762 #else 1763 reg_offset = offset; 1764 #endif 1765 #ifdef BCM_TOMAHAWK3_SUPPORT 1766 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 1767 stage does this port belong to for the per port registers. 1768 For CDPORT registers, the stage is 0 and CDMAC_0 registers, it is 1 1769 while for CDMAC_1 it is 2 */ 1770 if (SOC_IS_TOMAHAWK3(unit)) { 1771 if (SOC_BLOCK_IS(regblktype, SOC_BLK_CDPORT)) { 1772 if ((reg_offset & 0x000F0000) == 0x10000) { /* CDMAC_OFFSET_CNT */ 1773 reg_offset &= ~(0x04000000 | 0x08000000); 1774 } 1775 } 1776 } 1777 #endif 1778 if ((regtype == soc_cpureg) || (regtype == soc_mcsreg) || (regtype == soc_iprocreg)) { 1779 continue; 1780 } 1781 /* coverity[negative_returns:FALSE] */ 1782 if (!SOC_BLOCK_IS_TYPE(unit, actual_blk, regblktype)) { 1783 #ifdef BCM_DNX_SUPPORT 1784 if (SOC_IS_DNX(unit) && 1785 ((SOC_BLOCK_TYPE(unit, actual_blk) == SOC_BLK_CDPORT && *SOC_REG_INFO(unit, reg).block == SOC_BLK_CDMAC) || 1786 (SOC_BLOCK_TYPE(unit, actual_blk) == SOC_BLK_CDMAC && *SOC_REG_INFO(unit, reg).block == SOC_BLK_CDPORT))) { 1787 /* In Jer2 CDPORT and CDMAC are the same sbus blocks */ 1788 } else 1789 #endif 1790 continue; 1791 } 1792 1793 if ((acc_type != SOC_REG_ACC_TYPE(unit, reg)) && (acc_type >= 0) 1794 /* skip acc_type check when acc_type is -ve */ 1795 #ifdef BCM_SAND_SUPPORT 1796 && (!use_orig_address) 1797 #endif 1798 ) { 1799 continue; 1800 } 1801 1802 minadr = SOC_REG_INFO(unit, reg).offset; 1803 if (reg_offset < minadr) { 1804 continue; 1805 } 1806 1807 if (SOC_REG_IS_ARRAY(unit, reg)) { 1808 maxadr = minadr + (SOC_REG_NUMELS(unit, reg) - 1) * SOC_REG_ELEM_SKIP(unit, reg); 1809 if ( reg_offset > maxadr || ((reg_offset-minadr) % SOC_REG_ELEM_SKIP(unit, reg))) { 1810 continue; /* exit if address out of array range, or is not an exact multiple of element skip */ 1811 } 1812 ainfo->idx = (reg_offset-minadr) / SOC_REG_ELEM_SKIP(unit, reg); 1813 } else { 1814 /* handle other possible array types */ 1815 if (SOC_REG_ARRAY(unit, reg)) { 1816 aindex = (reg_offset - SOC_REG_BASE(unit, reg)) >> 8; 1817 if (SOC_REG_ARRAY2(unit, reg)) { 1818 ainfo->idx = aindex / (2 * SOC_REG_GRAN(unit, reg)); 1819 maxadr = minadr + 1820 ((2 * (SOC_REG_GRAN(unit, reg) * 1821 (SOC_REG_NUMELS(unit, reg) - 1))) << 8); 1822 } else if (SOC_REG_ARRAY4(unit, reg)) { 1823 ainfo->idx = aindex / (4 * SOC_REG_GRAN(unit, reg)); 1824 maxadr = minadr + 1825 ((4 * (SOC_REG_GRAN(unit, reg) * 1826 (SOC_REG_NUMELS(unit, reg) - 1))) << 8); 1827 } else { 1828 ainfo->idx = aindex / SOC_REG_GRAN(unit, reg); 1829 maxadr = minadr + 1830 (((SOC_REG_GRAN(unit, reg) * 1831 (SOC_REG_NUMELS(unit, reg) - 1))) << 8); 1832 } 1833 } else { 1834 ainfo->idx = -1; 1835 maxadr = minadr; 1836 } 1837 if (reg_offset > maxadr) { 1838 continue; 1839 } 1840 if (SOC_REG_ARRAY2(unit, reg)) { 1841 if ( (reg_offset & 0x100) != (minadr & 0x100) ) { 1842 /* make sure last bit are same as the base addr when array stride is 2 */ 1843 continue; 1844 } 1845 } 1846 } 1847 1848 ainfo->block = blk; 1849 ainfo->acc_type = acc_type; 1850 ainfo->reg = reg; 1851 ainfo->field = INVALIDf; 1852 ainfo->cos = -1; 1853 ainfo->port = REG_PORT_ANY; 1854 switch (regtype) { 1855 case soc_customreg: 1856 case soc_portreg: 1857 case soc_ppportreg: 1858 if (SOC_BLOCK_IN_LIST(regblktype, portblktype) && 1859 !(SOC_BLOCK_IS(regblktype, SOC_BLK_CDPORT))) { 1860 for (phy_port = 0; ; phy_port++) { 1861 if (soc_feature(unit, soc_feature_logical_port_num)) { 1862 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1863 if (port < 0) { 1864 continue; 1865 } 1866 } else { 1867 port = phy_port; 1868 } 1869 #ifdef BCM_KATANA2_SUPPORT 1870 /* Override port blocks with Linkphy Blocks.. */ 1871 if(SOC_IS_KATANA2(unit) && 1872 (regblktype[0] == SOC_BLK_TXLP) ) { 1873 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 1874 SOC_BLK_TXLP, &blk, &bindex) != SOC_E_NONE) { 1875 continue; 1876 } 1877 } else if(SOC_IS_KATANA2(unit) && 1878 (regblktype[0] == SOC_BLK_RXLP) ) { 1879 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 1880 SOC_BLK_RXLP, &blk, &bindex) != SOC_E_NONE) { 1881 continue; 1882 } 1883 1884 } else 1885 #endif 1886 #ifdef BCM_METROLITE_SUPPORT 1887 /* Override port blocks with Linkphy Blocks.. */ 1888 if (SOC_IS_METROLITE(unit) && 1889 (regblktype[0] == SOC_BLK_IECELL)) { 1890 if (soc_ml_iecell_port_reg_blk_idx_get(unit, port, 1891 SOC_BLK_IECELL, &blk, &bindex) != SOC_E_NONE) { 1892 continue; 1893 } 1894 } else 1895 #endif 1896 #if defined (BCM_SABER2_SUPPORT) 1897 /* Override port blocks with Linkphy Blocks.. */ 1898 if (SOC_IS_SABER2(unit) && 1899 (regblktype[0] == SOC_BLK_IECELL)) { 1900 if (soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 1901 SOC_BLK_IECELL, &blk, &bindex) != SOC_E_NONE) { 1902 continue; 1903 } 1904 } else 1905 #endif 1906 { 1907 blk = SOC_PORT_BLOCK(unit, phy_port); 1908 bindex = SOC_PORT_BINDEX(unit, phy_port); 1909 } 1910 if (blk < 0 && bindex < 0) { /* end of list */ 1911 break; 1912 } 1913 if (blk < 0) { /* empty slot */ 1914 continue; 1915 } 1916 1917 for (i = 0; i < port_num_blktype ; i++) { 1918 #ifdef BCM_KATANA2_SUPPORT 1919 /* Override port blocks with Linkphy Blocks.. */ 1920 if(SOC_IS_KATANA2(unit) && 1921 (regblktype[0] == SOC_BLK_TXLP)){ 1922 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 1923 SOC_BLK_TXLP, &blk, &bindex) != SOC_E_NONE) { 1924 continue; 1925 } 1926 } else if(SOC_IS_KATANA2(unit) && 1927 (regblktype[0] == SOC_BLK_RXLP) ) { 1928 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 1929 SOC_BLK_RXLP, &blk, &bindex) != SOC_E_NONE) { 1930 continue; 1931 } 1932 } else 1933 #endif 1934 #ifdef BCM_METROLITE_SUPPORT 1935 if ((SOC_IS_METROLITE(unit)) && 1936 (regblktype[0] == SOC_BLK_IECELL) ) { 1937 if (soc_ml_iecell_port_reg_blk_idx_get(unit, port, 1938 SOC_BLK_IECELL, &blk, &bindex) != SOC_E_NONE) { 1939 continue; 1940 } 1941 } else 1942 #endif 1943 #if defined (BCM_SABER2_SUPPORT) 1944 if ((SOC_IS_SABER2(unit)) && 1945 (regblktype[0] == SOC_BLK_IECELL) ) { 1946 if (soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 1947 SOC_BLK_IECELL, &blk, &bindex) != SOC_E_NONE) { 1948 continue; 1949 } 1950 } else 1951 #endif 1952 #if defined (BCM_TRIDENT3_SUPPORT) 1953 if ((SOC_IS_TRIDENT3X(unit)) && 1954 ((SOC_REG_INFO(unit, reg).block[0] == SOC_BLK_XLPORT) && 1955 (pindex == 2) && (phy_port == 128))) { 1956 blk = SOC_PORT_IDX_BLOCK(unit, 129, i); 1957 bindex = 2; 1958 } else 1959 #endif 1960 { 1961 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 1962 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 1963 } 1964 if ((uint32)blk != ainfo->block) { 1965 continue; 1966 } 1967 if (soc_feature(unit, 1968 soc_feature_pgw_mac_rsv_mask_remap) && 1969 reg == PGW_MAC_RSV_MASKr) { 1970 bindex = (phy_port - 1) & 0xf; 1971 } 1972 if (bindex == pindex) { 1973 ainfo->port = port; 1974 break; 1975 } 1976 } 1977 if (i == port_num_blktype) { 1978 continue; 1979 } 1980 if (blk >= 0) { 1981 break; 1982 } 1983 } 1984 if (ainfo->port == REG_PORT_ANY) { 1985 ainfo->reg = INVALIDr; 1986 } 1987 } else { 1988 if (soc_feature(unit, soc_feature_logical_port_num) && 1989 (regblktype[0] == SOC_BLK_MMU || 1990 regblktype[0] == SOC_BLK_MMU_GLB || 1991 regblktype[0] == SOC_BLK_MMU_XPE || 1992 regblktype[0] == SOC_BLK_MMU_SED || 1993 regblktype[0] == SOC_BLK_MMU_ITM || 1994 regblktype[0] == SOC_BLK_MMU_EB || 1995 regblktype[0] == SOC_BLK_MMU_SC)) { 1996 #ifdef BCM_TOMAHAWK3_SUPPORT 1997 /*MMU register with device port indexing*/ 1998 num_regs = sizeof(reg_excep_list) / sizeof(soc_reg_t); 1999 for (reg_index = 0;reg_index < num_regs; reg_index++) { 2000 if (reg_excep_list[reg_index] == reg) { 2001 add_exception = 1; 2002 break; 2003 } 2004 } 2005 if (add_exception) { 2006 ainfo->port = pindex; 2007 } else 2008 2009 #endif 2010 { 2011 phy_port = SOC_INFO(unit).port_m2p_mapping[pindex]; 2012 ainfo->port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 2013 } 2014 } else { 2015 ainfo->port = pindex; 2016 } 2017 #ifdef BCM_TOMAHAWK3_SUPPORT 2018 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 2019 * CDMAC/stage id does this register belong to. 2020 * For CDMAC_0 registers, it is 1, while for CDMAC_1 it is 2 */ 2021 if (SOC_IS_TOMAHAWK3(unit)) { 2022 phy_port = SOC_INFO(unit).port_m2p_mapping[pindex]; 2023 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CDPORT)) { 2024 if ((SOC_REG_INFO(unit, reg).offset & 0x000F0000) == 2025 CDMAC_OFFSET_CNT) { 2026 stage_id = ((((phy_port - 1) >> 2) & 1) == 0) ? 2027 CDMAC0_STAGE_ID : CDMAC1_STAGE_ID; 2028 if (stage_id == CDMAC0_STAGE_ID) { 2029 pindex = pindex | 0x04000000; 2030 break; 2031 } else { 2032 pindex = pindex | 0x08000000; 2033 break; 2034 } 2035 } 2036 } 2037 ainfo->port = pindex; 2038 } 2039 #endif 2040 } 2041 break; 2042 case soc_cosreg: 2043 if (pindex >= 0 && pindex <= NUM_COS(unit)) { 2044 ainfo->cos = pindex; 2045 } else { 2046 ainfo->reg = INVALIDr; 2047 } 2048 break; 2049 case soc_pipereg: 2050 if (pindex >= 0 && pindex < NUM_PIPE(unit)) { 2051 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2052 } else { 2053 ainfo->reg = INVALIDr; 2054 } 2055 break; 2056 case soc_xpereg: 2057 if (pindex >= 0 && pindex < NUM_XPE(unit)) { 2058 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2059 } else { 2060 ainfo->reg = INVALIDr; 2061 } 2062 break; 2063 case soc_itmreg: 2064 if (pindex >= 0 && pindex < NUM_ITM(unit)) { 2065 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2066 } else { 2067 ainfo->reg = INVALIDr; 2068 } 2069 break; 2070 case soc_ebreg: 2071 if (pindex >= 0 && pindex < NUM_EB(unit)) { 2072 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2073 } else { 2074 ainfo->reg = INVALIDr; 2075 } 2076 break; 2077 case soc_slicereg: 2078 if (pindex >= 0 && pindex < NUM_SLICE(unit)) { 2079 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2080 } else { 2081 ainfo->reg = INVALIDr; 2082 } 2083 break; 2084 case soc_layerreg: 2085 if (pindex >= 0 && pindex < NUM_LAYER(unit)) { 2086 ainfo->port = SOC_REG_ADDR_INSTANCE_MASK | pindex; 2087 } else { 2088 ainfo->reg = INVALIDr; 2089 } 2090 break; 2091 case soc_genreg: 2092 if (pindex != 0) { 2093 #ifdef BCM_SAND_SUPPORT 2094 if (!use_orig_address) 2095 #endif 2096 ainfo->reg = INVALIDr; 2097 } 2098 break; 2099 default: 2100 assert(0); 2101 } 2102 if (ainfo->idx != -1) { 2103 continue; 2104 } 2105 break; 2106 } 2107 } 2108 2109 /* port_types supported: -1(all), ETH_PORT, STK_PORT, INTLB_PORT */ 2110 int 2111 soc_pipe_port_get(int unit, uint32 port_type, int pipe, soc_pbmp_t *pbmp) 2112 { 2113 if (!soc_feature(unit, soc_feature_multi_pipe_mapped_ports)) { 2114 return SOC_E_UNAVAIL; 2115 } 2116 if (pipe > NUM_PIPE(unit)) { 2117 return SOC_E_PARAM; 2118 } 2119 SOC_PBMP_ASSIGN(*pbmp, PBMP_PIPE(unit, pipe)); 2120 SOC_PBMP_REMOVE(*pbmp, SOC_PORT_DISABLED_BITMAP(unit, all)); 2121 if (0xffffffff == port_type) { 2122 return SOC_E_NONE; 2123 } else { 2124 if (!(port_type & ETH_PORT)) { 2125 SOC_PBMP_REMOVE(*pbmp, PBMP_E_ALL(unit)); 2126 } 2127 if (!(port_type & STK_PORT)) { 2128 SOC_PBMP_REMOVE(*pbmp, PBMP_ST_ALL(unit)); 2129 } 2130 if (!(port_type & INTLB_PORT)) { 2131 SOC_PBMP_REMOVE(*pbmp, PBMP_LB_ALL(unit)); 2132 } 2133 } 2134 return SOC_E_NONE; 2135 } 2136 2137 int 2138 soc_port_pipe_get(int unit, int port, int *pipe) 2139 { 2140 if (!soc_feature(unit, soc_feature_multi_pipe_mapped_ports)) { 2141 return SOC_E_UNAVAIL; 2142 } 2143 if (port > MAX_PORT(unit)) { 2144 return SOC_E_PARAM; 2145 } 2146 *pipe = SOC_INFO(unit).port_pipe[port]; 2147 return SOC_E_NONE; 2148 } 2149 2150 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT)*/