reg.c (218062B)
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 * Register address and value manipulations. 8 */ 9 10 11 #include <shared/bsl.h> 12 13 #include <sal/core/libc.h> 14 #include <sal/core/boot.h> 15 16 #include <soc/debug.h> 17 #include <soc/cm.h> 18 #include <soc/drv.h> 19 #include <soc/error.h> 20 #include <soc/cmic.h> 21 #include <soc/register.h> 22 23 #if defined(BCM_PETRA_SUPPORT) 24 #include <soc/dpp/drv.h> 25 #include <soc/dpp/mbcm.h> 26 #endif /* BCM_PETRA_SUPPORT */ 27 #if defined(BCM_DFE_SUPPORT) 28 #include <soc/dfe/cmn/dfe_drv.h> 29 #endif /* BCM_DFE_SUPPORT */ 30 #if defined(BCM_DNX_SUPPORT) 31 #include <soc/dnx/drv.h> 32 #include <soc/dnx/dnx_data/auto_generated/dnx_data_device.h> 33 #endif 34 #if defined(BCM_DNXF_SUPPORT) 35 #include <soc/dnxf/cmn/dnxf_drv.h> 36 #endif /* BCM_DNXF_SUPPORT */ 37 #ifdef DNX_TEST_CHIPS_SUPPORT 38 #include <soc/dpp/dnxtestchip.h> 39 #endif 40 #ifdef BCM_CMICM_SUPPORT 41 #include <soc/cmicm.h> 42 #endif 43 #ifdef BCM_IPROC_SUPPORT 44 #include <soc/iproc.h> 45 #endif 46 #if defined(BCM_KATANA2_SUPPORT) 47 #include <soc/katana2.h> 48 #endif 49 #if defined(BCM_GREYHOUND_SUPPORT) 50 #include <soc/greyhound.h> 51 #endif 52 53 #ifdef CRASH_RECOVERY_SUPPORT 54 #include <soc/hwstate/hw_log.h> 55 #endif /* CRASH_RECOVERY_SUPPORT */ 56 57 #if defined(BCM_SABER2_SUPPORT) 58 #include <soc/saber2.h> 59 #endif 60 #if defined(BCM_METROLITE_SUPPORT) 61 #include <soc/metrolite.h> 62 #endif 63 64 #ifdef CANCUN_SUPPORT 65 #include <soc/esw/cancun.h> 66 #endif 67 68 #if defined(BCM_APACHE_SUPPORT) 69 #include <soc/apache.h> 70 #endif 71 #if defined(BCM_MONTEREY_SUPPORT) 72 #include <soc/monterey.h> 73 #endif 74 75 #ifdef BCM_SAND_SUPPORT 76 #include <soc/sand/sand_aux_access.h> 77 #endif 78 79 #include <soc/dnxc/multithread_analyzer.h> 80 81 #ifdef BCM_DNX_SUPPORT 82 #define CDMAC_OFFSET_CNT 0x10000 83 #endif 84 85 #ifdef BCM_TOMAHAWK3_SUPPORT 86 #define CDMAC_OFFSET_CNT 0x10000 87 #define CDMAC0_STAGE_ID 1 88 #define CDMAC1_STAGE_ID 2 89 #endif 90 91 /* 92 * Function: soc_reg_datamask 93 * Purpose: Generate data mask for the fields in a register 94 * whose flags match the flags parameter 95 * Returns: The data mask 96 * 97 * Notes: flags can be SOCF_RO, SOCF_WO, or zero (read/write) 98 */ 99 uint32 100 soc_reg_datamask(int unit, soc_reg_t reg, int flags) 101 { 102 int i, start, end; 103 soc_field_info_t *fieldp; 104 soc_reg_info_t *regp; 105 uint32 result, mask; 106 107 if (!SOC_REG_IS_VALID(unit, reg)) { 108 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 109 #if !defined(SOC_NO_NAMES) 110 LOG_CLI((BSL_META_U(unit, 111 "reg %s is invalid\n"), soc_reg_name[reg])); 112 #endif 113 #endif 114 assert(SOC_REG_IS_VALID(unit, reg)); 115 } 116 117 regp = &(SOC_REG_INFO(unit, reg)); 118 119 result = 0; 120 for (i = 0; i < (int)(regp->nFields); i++) { 121 fieldp = &(regp->fields[i]); 122 123 if ((fieldp->flags & flags) == flags) { 124 start = fieldp->bp; 125 if (start > 31) { 126 continue; 127 } 128 end = fieldp->bp + fieldp->len; 129 if (end < 32) { 130 mask = (1 << end) - 1; 131 } else { 132 mask = -1; 133 } 134 result |= ((uint32)-1 << start) & mask; 135 } 136 } 137 138 return result; 139 } 140 141 /* 142 * Function: soc_reg64_datamask 143 * Purpose: Generate data mask for the fields in a 64-bit register 144 * whose flags match the flags parameter 145 * Returns: The data mask 146 * 147 * Notes: flags can be SOCF_RO, SOCF_WO, or zero (read/write) 148 */ 149 uint64 150 soc_reg64_datamask(int unit, soc_reg_t reg, int flags) 151 { 152 int i, start, end; 153 soc_field_info_t *fieldp; 154 soc_reg_info_t *regp; 155 uint64 mask, tmp, result; 156 157 if (!SOC_REG_IS_VALID(unit, reg)) { 158 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 159 #if !defined(SOC_NO_NAMES) 160 LOG_CLI((BSL_META_U(unit, 161 "reg %s is invalid\n"), soc_reg_name[reg])); 162 #endif 163 #endif 164 assert(SOC_REG_IS_VALID(unit, reg)); 165 } 166 167 regp = &(SOC_REG_INFO(unit, reg)); 168 169 COMPILER_64_ZERO(result); 170 171 for (i = 0; i < (int)(regp->nFields); i++) { 172 fieldp = &(regp->fields[i]); 173 174 if ((fieldp->flags & flags) == flags) { 175 start = fieldp->bp; 176 end = fieldp->bp + fieldp->len; 177 COMPILER_64_SET(mask, 0, 1); 178 COMPILER_64_SHL(mask, end); 179 COMPILER_64_SUB_32(mask, 1); 180 COMPILER_64_ZERO(tmp); 181 /* coverity[overflow_assign] */ 182 COMPILER_64_SUB_32(tmp, 1); 183 COMPILER_64_SHL(tmp, start); 184 COMPILER_64_AND(tmp, mask); 185 COMPILER_64_OR(result, tmp); 186 } 187 } 188 189 return result; 190 } 191 192 /* 193 * Function: soc_reg_above_64_datamask 194 * Purpose: Generate data mask for the fields in above 64-bit register 195 * whose flags match the flags parameter 196 * 197 * Notes: flags can be SOCF_RO, SOCF_WO, or zero (read/write) 198 */ 199 void 200 soc_reg_above_64_datamask(int unit, soc_reg_t reg, int flags, soc_reg_above_64_val_t datamask) 201 { 202 int i; 203 soc_field_info_t *fieldp; 204 soc_reg_info_t *regp; 205 206 if (!SOC_REG_IS_VALID(unit, reg)) { 207 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 208 #if !defined(SOC_NO_NAMES) 209 LOG_CLI((BSL_META_U(unit, 210 "reg %s is invalid\n"), soc_reg_name[reg])); 211 #endif 212 #endif 213 assert(SOC_REG_IS_VALID(unit, reg)); 214 } 215 216 regp = &(SOC_REG_INFO(unit, reg)); 217 218 SOC_REG_ABOVE_64_CLEAR(datamask); 219 220 for (i = 0; i < (int)(regp->nFields); i++) { 221 fieldp = &(regp->fields[i]); 222 223 if ((fieldp->flags & flags) == flags) { 224 SOC_REG_ABOVE_64_CREATE_MASK(datamask, fieldp->len, fieldp->bp); 225 } 226 } 227 } 228 229 /************************************************************************/ 230 /* Routines for reading/writing SOC internal registers */ 231 /************************************************************************/ 232 233 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 234 235 STATIC 236 void _soc_snoop_reg(int unit, soc_block_t block, int acc, uint32 addr, 237 uint32 flag, uint32 data_hi, uint32 data_lo) { 238 soc_reg_info_t *reg_info_p; 239 soc_regaddrinfo_t ainfo; 240 soc_reg_t reg; 241 242 if (bsl_check(bslLayerSoc, bslSourceTests, bslSeverityNormal, unit) == 0) { 243 return; 244 } 245 soc_regaddrinfo_extended_get(unit, &ainfo, block, acc, addr); 246 reg = (int)ainfo.reg; 247 if (SOC_REG_IS_VALID(unit, reg)) { 248 reg_info_p = &SOC_REG_INFO(unit, reg); 249 /* (SOC_REG_SNOOP_READ & reg_info_p->snoop_flags)) */ 250 if (NULL != reg_info_p->snoop_cb) { 251 if (reg_info_p->snoop_flags & flag) { 252 reg_info_p->snoop_cb(unit, reg,&ainfo, flag, data_hi,data_lo, 253 reg_info_p->snoop_user_data); 254 } 255 } 256 } 257 return ; 258 } 259 #ifdef BROADCOM_DEBUG 260 261 void 262 _soc_reg_debug(int unit, int access_width, char *op_str, 263 uint32 addr, uint32 data_hi, uint32 data_lo) 264 { 265 soc_regaddrinfo_t ainfo; 266 char buf[80]; 267 268 ainfo.block = SOC_BLK_NONE; 269 soc_regaddrinfo_get(unit, &ainfo, addr); 270 271 if (!ainfo.valid || (int)ainfo.reg < 0) { 272 sal_strncpy(buf, "??", sizeof(buf)); 273 } else { 274 soc_reg_sprint_addr(unit, buf, &ainfo); 275 } 276 277 if (data_hi != 0) { 278 LOG_VERBOSE(BSL_LS_SOC_REG, 279 (BSL_META_U(unit, 280 "soc_reg%d_%s unit %d: " 281 "%s[0x%x] data=0x%08x_%08x\n"), 282 access_width, op_str, unit, 283 buf, addr, data_hi, data_lo)); 284 } else { 285 LOG_VERBOSE(BSL_LS_SOC_REG, 286 (BSL_META_U(unit, 287 "soc_reg%d_%s unit %d: " 288 "%s[0x%x] data=0x%08x\n"), 289 access_width, op_str, unit, 290 buf, addr, data_lo)); 291 } 292 } 293 294 STATIC void 295 _soc_reg_extended_debug(int unit, int access_width, char *op_str, 296 soc_block_t block, int acc, uint32 addr, 297 uint32 data_hi, uint32 data_lo) 298 { 299 soc_regaddrinfo_t ainfo; 300 char buf[80]; 301 302 soc_regaddrinfo_extended_get(unit, &ainfo, block, acc, addr); 303 304 if (!ainfo.valid || (int)ainfo.reg < 0) { 305 sal_strncpy(buf, "??", sizeof(buf)); 306 } else { 307 soc_reg_sprint_addr(unit, buf, &ainfo); 308 } 309 310 if (data_hi != 0) { 311 LOG_VERBOSE(BSL_LS_SOC_REG, 312 (BSL_META_U(unit, 313 "soc_reg%d_%s unit %d: " 314 "%s[%d][0x%x] data=0x%08x_%08x\n"), 315 access_width, op_str, unit, 316 buf, block, addr, data_hi, data_lo)); 317 } else { 318 LOG_VERBOSE(BSL_LS_SOC_REG, 319 (BSL_META_U(unit, 320 "soc_reg%d_%s unit %d: " 321 "%s[%d][0x%x] data=0x%08x\n"), 322 access_width, op_str, unit, 323 buf, block, addr, data_lo)); 324 } 325 } 326 327 void 328 _soc_reg_above_64_debug(int unit, char *op_str, soc_block_t block, 329 uint32 addr, soc_reg_above_64_val_t data) 330 { 331 soc_regaddrinfo_t ainfo; 332 char buf[80]; 333 int i, first_non_zero; 334 335 soc_regaddrinfo_extended_get(unit, &ainfo, block, 0, addr); 336 337 if (!ainfo.valid || (int)ainfo.reg < 0) { 338 sal_strncpy(buf, "??", sizeof(buf)); 339 } else { 340 soc_reg_sprint_addr(unit, buf, &ainfo); 341 } 342 343 LOG_VERBOSE(BSL_LS_SOC_REG, 344 (BSL_META_U(unit, 345 "soc_reg_above_64_%s unit %d: " 346 "%s[0x%x] data="), 347 op_str, unit, 348 buf, addr)); 349 350 first_non_zero = 0; 351 for(i=SOC_REG_ABOVE_64_MAX_SIZE_U32-1 ; i>=0 ; i--) { 352 if(0 == i) { 353 LOG_VERBOSE(BSL_LS_SOC_REG, 354 (BSL_META_U(unit, 355 "0x%08x\n"),data[i])); 356 } else { 357 if(data[i] != 0) { 358 first_non_zero = 1; 359 } 360 361 if(1 == first_non_zero) { 362 LOG_VERBOSE(BSL_LS_SOC_REG, 363 (BSL_META_U(unit, 364 "0x%08x_"),data[i])); 365 } 366 } 367 } 368 369 } 370 371 #endif /* BROADCOM_DEBUG */ 372 373 374 #ifdef BCM_BIGMAC_SUPPORT 375 376 /* List of registers that need iterative read/write operations */ 377 STATIC int 378 iterative_op_required(soc_reg_t reg) 379 { 380 switch (reg) { 381 case MAC_RXCTRLr: 382 case MAC_RXMACSAr: 383 case MAC_RXMAXSZr: 384 case MAC_RXLSSCTRLr: 385 case MAC_RXLSSSTATr: 386 case MAC_RXSPARE0r: 387 case IR64r: 388 case IR127r: 389 case IR255r: 390 case IR511r: 391 case IR1023r: 392 case IR1518r: 393 case IR2047r: 394 case IR4095r: 395 case IR9216r: 396 case IR16383r: 397 case IRMAXr: 398 case IRPKTr: 399 case IRFCSr: 400 case IRUCr: 401 case IRMCAr: 402 case IRBCAr: 403 case IRXPFr: 404 case IRXPPr: 405 case IRXUOr: 406 case IRJBRr: 407 case IROVRr: 408 case IRXCFr: 409 case IRFLRr: 410 case IRPOKr: 411 case IRMEGr: 412 case IRMEBr: 413 case IRBYTr: 414 case IRUNDr: 415 case IRFRGr: 416 case IRERBYTr: 417 case IRERPKTr: 418 case IRJUNKr: 419 case MAC_RXLLFCMSGCNTr: 420 case MAC_RXLLFCMSGFLDSr: 421 return TRUE; 422 break; 423 default: 424 return FALSE; 425 break; 426 } 427 } 428 429 /* 430 * Iterative read procedure for MAC registers on Hyperlite ports. 431 */ 432 STATIC int 433 soc_reg64_read_iterative(int unit, uint32 addr, soc_port_t port, 434 uint64 *data) 435 { 436 int rv, i, diff; 437 uint64 xgxs_stat; 438 uint32 locked; 439 sal_usecs_t t1 = 0, t2; 440 soc_timeout_t to; 441 for (i = 0; i < 100; i++) { 442 /* Read PLL lock status */ 443 soc_timeout_init(&to, 25 * MILLISECOND_USEC, 0); 444 do { 445 t1 = sal_time_usecs(); 446 rv = READ_MAC_XGXS_STATr(unit, port, &xgxs_stat); 447 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 448 TXPLL_LOCKf); 449 if (locked || SOC_FAILURE(rv)) { 450 break; 451 } 452 } while (!soc_timeout_check(&to)); 453 if (SOC_FAILURE(rv)) { 454 return rv; 455 } 456 if (!locked) { 457 continue; 458 } 459 /* Read register value */ 460 SOC_IF_ERROR_RETURN(soc_reg64_read(unit, addr, data)); 461 /* Read PLL lock status */ 462 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 463 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 464 TXPLL_LOCKf); 465 t2 = sal_time_usecs(); 466 diff = SAL_USECS_SUB(t2, t1); 467 if (locked && (diff < 20 * MILLISECOND_USEC)) { 468 return SOC_E_NONE; 469 } 470 LOG_VERBOSE(BSL_LS_SOC_COMMON, 471 (BSL_META_U(unit, 472 "soc_reg64_read_iterative: WARNING: " 473 "iteration %d PLL went out of lock"), 474 i)); 475 } 476 LOG_ERROR(BSL_LS_SOC_COMMON, 477 (BSL_META_U(unit, 478 "soc_reg64_read_iterative: " 479 "operation failed:\n"))); 480 return SOC_E_FAIL; 481 } 482 #endif /* BCM_BIGMAC_SUPPORT */ 483 484 /* 485 * Read an internal 64-bit SOC register through S-Channel messaging buffer. 486 */ 487 int 488 _soc_reg64_get(int unit, soc_block_t block, int acc, uint32 addr, uint64 *reg) 489 { 490 schan_msg_t schan_msg; 491 int rv, allow_intr = 0; 492 int data_byte_len; 493 int opcode, err; 494 495 /* 496 * Write message to S-Channel. 497 */ 498 schan_msg_clear(&schan_msg); 499 500 data_byte_len = 8; 501 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_REGISTER_CMD_MSG, 502 block, 0, acc, data_byte_len, 0, 0); 503 504 schan_msg.readcmd.address = addr; 505 506 if(SOC_IS_SAND(unit)) { 507 allow_intr = 1; 508 } 509 /* Write header word + address DWORD, read header word + data DWORD */ 510 rv = soc_schan_op(unit, &schan_msg, 2, 3, allow_intr); 511 if (SOC_FAILURE(rv)) { 512 #if defined(BCM_XGS_SUPPORT) 513 int rv1, port = 0, index; 514 #endif /* BCM_XGS_SUPPORT */ 515 soc_regaddrinfo_t ainfo; 516 517 if (!soc_feature(unit, soc_feature_ser_parity)) { 518 return rv; 519 } 520 soc_regaddrinfo_extended_get(unit, &ainfo, block, acc, addr); 521 if (ainfo.reg != INVALIDr) { 522 if (SOC_REG_IS_COUNTER(unit, ainfo.reg)) { 523 COMPILER_64_SET(*reg, 0, 0); 524 /* Force correct */ 525 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 526 rv = SOC_E_NONE; 527 } 528 } 529 #if defined(BCM_XGS_SUPPORT) 530 else if (soc_feature(unit, soc_feature_regs_as_mem)) { 531 if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_portreg) { 532 port = ainfo.port; 533 } else if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_cosreg) { 534 port = ainfo.cos; 535 } 536 index = ainfo.idx != -1 ? ainfo.idx : 0; 537 rv1 = soc_ser_reg_cache_get(unit, ainfo.reg, port, index, reg); 538 if (rv1 != SOC_E_NONE) { 539 if (SOC_REG_IS_DYNAMIC(unit, ainfo.reg)) { 540 COMPILER_64_SET(*reg, 0, 0); 541 } else { 542 return rv; 543 } 544 } 545 /* Force correct */ 546 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 547 rv = SOC_E_NONE; 548 } 549 } 550 #endif /* BCM_XGS_SUPPORT */ 551 } else { 552 return rv; 553 } 554 } 555 /* Check result */ 556 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 557 &err, NULL, NULL);; 558 if (opcode != READ_REGISTER_ACK_MSG || err != 0) { 559 { 560 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "_soc_reg64_get: " 561 "invalid S-Channel reply, expected READ_REG_ACK: got %d " 562 "block:%d address:0x%x\n"), opcode, block, addr)); 563 soc_schan_dump(unit, &schan_msg, 2); 564 return SOC_E_INTERNAL; 565 } 566 } 567 568 #ifdef BROADCOM_DEBUG 569 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 570 _soc_reg_extended_debug(unit, 64, "read", block, acc, addr, 571 schan_msg.readresp.data[1], 572 schan_msg.readresp.data[0]); 573 } 574 #endif /* BROADCOM_DEBUG */ 575 _soc_snoop_reg(unit, block, acc, addr,SOC_REG_SNOOP_READ, 576 schan_msg.readresp.data[1],schan_msg.readresp.data[0]); 577 578 COMPILER_64_SET(*reg, 579 schan_msg.readresp.data[1], 580 schan_msg.readresp.data[0]); 581 582 return SOC_E_NONE; 583 } 584 585 #ifdef BCM_BIGMAC_SUPPORT 586 587 /* 588 * Iterative read procedure for MAC registers on Hyperlite ports. 589 */ 590 STATIC int 591 soc_reg64_get_iterative(int unit, soc_block_t block, int acc, uint32 addr, 592 soc_port_t port, uint64 *data) 593 { 594 int rv, i, diff; 595 uint64 xgxs_stat; 596 uint32 locked; 597 sal_usecs_t t1 = 0, t2; 598 soc_timeout_t to; 599 for (i = 0; i < 100; i++) { 600 /* Read PLL lock status */ 601 soc_timeout_init(&to, 25 * MILLISECOND_USEC, 0); 602 do { 603 t1 = sal_time_usecs(); 604 rv = READ_MAC_XGXS_STATr(unit, port, &xgxs_stat); 605 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 606 TXPLL_LOCKf); 607 if (locked || SOC_FAILURE(rv)) { 608 break; 609 } 610 } while (!soc_timeout_check(&to)); 611 if (SOC_FAILURE(rv)) { 612 return rv; 613 } 614 if (!locked) { 615 continue; 616 } 617 /* Read register value */ 618 SOC_IF_ERROR_RETURN(_soc_reg64_get(unit, block, acc, addr, data)); 619 /* Read PLL lock status */ 620 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 621 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 622 TXPLL_LOCKf); 623 t2 = sal_time_usecs(); 624 diff = SAL_USECS_SUB(t2, t1); 625 if (locked && (diff < 20 * MILLISECOND_USEC)) { 626 return SOC_E_NONE; 627 } 628 LOG_VERBOSE(BSL_LS_SOC_COMMON, 629 (BSL_META_U(unit, 630 "soc_reg64_get_iterative: WARNING: " 631 "iteration %d PLL went out of lock"), 632 i)); 633 } 634 LOG_ERROR(BSL_LS_SOC_COMMON, 635 (BSL_META_U(unit, 636 "soc_reg64_get_iterative: " 637 "operation failed:\n"))); 638 return SOC_E_FAIL; 639 } 640 641 #endif /* BCM_BIGMAC_SUPPORT */ 642 643 /* 644 * Read an internal SOC register through S-Channel messaging buffer. 645 * Checks if the register is 32 or 64 bits. 646 */ 647 648 int 649 soc_reg_read(int unit, soc_reg_t reg, uint32 addr, uint64 *data) 650 { 651 if (!SOC_REG_IS_VALID(unit, reg)) { 652 return SOC_E_PARAM; 653 } 654 655 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, FALSE)); 656 657 #ifdef DNX_TEST_CHIPS_SUPPORT 658 if (SOC_IS_DNX_TEST_DEVICE(unit) 659 #if defined(PLISIM) 660 && !SAL_BOOT_PLISIM 661 #endif 662 ) { 663 return soc_dnxtestchip_reg_read(unit, reg, addr, data); 664 } 665 #endif /* DNX_TEST_CHIPS_SUPPORT */ 666 667 if (SOC_REG_IS_ABOVE_64(unit, reg)) { 668 LOG_ERROR(BSL_LS_SOC_COMMON, 669 (BSL_META_U(unit, 670 "soc_reg_read: " 671 "Use soc_reg_above_64_get \n"))); 672 673 return SOC_E_FAIL; 674 } 675 676 if (SOC_REG_IS_64(unit, reg)) { 677 soc_port_t port; 678 soc_block_types_t regblktype = SOC_REG_INFO(unit, reg).block; 679 int blk, pindex, bindex, block; 680 pindex = (addr >> SOC_REGIDX_BP) & 0x3f; 681 block = ((addr >> SOC_BLOCK_BP) & 0xf) | 682 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 683 if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT) 684 #ifdef BCM_SAND_SUPPORT 685 && !SOC_IS_SAND(unit) 686 #endif /* BCM_SAND_SUPPORT */ 687 #ifdef BCM_BIGMAC_SUPPORT 688 && iterative_op_required(reg) 689 #endif /* BCM_BIGMAC_SUPPORT */ 690 ) { 691 PBMP_HYPLITE_ITER(unit, port) { 692 blk = SOC_PORT_BLOCK(unit, port); 693 bindex = SOC_PORT_BINDEX(unit, port); 694 if ((SOC_BLOCK2SCH(unit, blk) == block) && (bindex == pindex)) { 695 break; 696 } 697 } 698 if (!IS_HYPLITE_PORT(unit, port)) { 699 return soc_reg64_read(unit, addr, data); 700 } 701 #ifdef BCM_BIGMAC_SUPPORT 702 else { 703 return soc_reg64_read_iterative(unit, addr, port, data); 704 } 705 #endif /* BCM_BIGMAC_SUPPORT */ 706 } else { 707 return soc_reg64_read(unit, addr, data); 708 } 709 } else { 710 uint32 data32; 711 712 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &data32)); 713 COMPILER_64_SET(*data, 0, data32); 714 } 715 716 return SOC_E_NONE; 717 } 718 719 /* 720 * Read an internal SOC register through S-Channel messaging buffer. 721 * 722 * block is cmic block id 723 */ 724 725 int 726 soc_direct_memreg_get(int unit, int cmic_block, uint32 addr, uint32 dwc_read, int is_mem, uint32 *data) 727 { 728 schan_msg_t schan_msg; 729 uint32 i; 730 int allow_intr = 0; 731 int data_byte_len; 732 int opcode, err; 733 734 /* 735 * Write message to S-Channel. 736 */ 737 schan_msg_clear(&schan_msg); 738 739 soc_schan_header_cmd_set(unit, &schan_msg.header, (is_mem? READ_MEMORY_CMD_MSG : READ_REGISTER_CMD_MSG), 740 cmic_block, SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)), 741 0, dwc_read * 4, 0, 0); 742 743 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 744 if(soc_feature(unit, soc_feature_cmicm) || soc_feature(unit, soc_feature_cmicx)) { 745 schan_msg.readcmd.address = addr; 746 } else 747 #endif 748 { 749 uint32 cmice_addr = addr; 750 if (cmic_block >= 0) { 751 cmice_addr |= ((cmic_block & 0xf) << SOC_BLOCK_BP) | 752 (((cmic_block >> 4) & 0x3) << SOC_BLOCK_MSB_BP); 753 } 754 755 schan_msg.readcmd.address = cmice_addr; 756 } 757 758 if (SOC_IS_SAND(unit)) { 759 allow_intr = 1; 760 } 761 762 /* Write header word + address DWORD, read header word + data DWORD */ 763 SOC_IF_ERROR_RETURN(soc_schan_op(unit, &schan_msg, 2, dwc_read+1, allow_intr)); 764 765 /* Check result */ 766 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, 767 &data_byte_len, &err, NULL, NULL); 768 if (opcode != (is_mem ? READ_MEMORY_ACK_MSG : READ_REGISTER_ACK_MSG) || err != 0) { 769 { 770 LOG_ERROR(BSL_LS_SOC_COMMON, 771 (BSL_META_U(unit, 772 "soc_direct_memreg_get(): block:%d address:%u " 773 "invalid S-Channel reply, expected %s and found %d err=%d\n"), 774 cmic_block, (unsigned)addr, (is_mem ? "READ_MEM_ACK" : "READ_REG_ACK"), opcode, err)); 775 soc_schan_dump(unit, &schan_msg, 2); 776 return SOC_E_INTERNAL; 777 } 778 } 779 780 for(i = 0; i < data_byte_len / 4; i++) { 781 data[i] = schan_msg.readresp.data[i]; 782 } 783 784 return SOC_E_NONE; 785 } 786 787 int 788 soc_direct_reg_get(int unit, int cmic_block, uint32 addr, uint32 dwc_read, uint32 *data) 789 { 790 return soc_direct_memreg_get(unit, cmic_block, addr, dwc_read, 0, data); 791 } 792 793 794 void soc_direct_mem_set_cache_update(int unit, int cmic_block, uint32 addr, uint32 *entry_data) 795 { 796 int rc; 797 soc_mem_t mem; 798 int blk; 799 int index; 800 unsigned array_index; 801 802 /* find the matching block by cmic_block */ 803 for (blk = 0; ; ++blk) 804 { 805 if (SOC_BLOCK_TYPE(unit, blk) < 0) 806 { 807 return; 808 } 809 else if (SOC_BLOCK_INFO(unit, blk).cmic == cmic_block) 810 { 811 break; 812 } 813 } 814 815 mem = soc_addr_to_mem_extended(unit, cmic_block, 0xff, addr); 816 if(mem == INVALIDm) 817 { 818 return; 819 } 820 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 821 rc = soc_mem_addr_to_array_element_and_index(unit, mem, addr, &array_index, &index); 822 if (rc != SOC_E_NONE) 823 { 824 return; 825 } 826 827 _soc_mem_write_cache_update(unit, mem, blk, 0, index, (int)array_index, entry_data, NULL, NULL, NULL); 828 829 return; 830 } 831 832 int 833 soc_direct_memreg_set(int unit, int cmic_block, uint32 addr, uint32 dwc_write, int is_mem, uint32 *data) 834 { 835 schan_msg_t schan_msg; 836 int i, allow_intr = 0; 837 838 if (is_mem) 839 { 840 soc_direct_mem_set_cache_update(unit, cmic_block, addr, data); 841 } 842 /* 843 * Setup S-Channel command packet 844 * 845 * NOTE: the datalen field matters only for the Write Memory and 846 * Write Register commands, where it is used only by the CMIC to 847 * determine how much data to send, and is in units of bytes. 848 */ 849 850 schan_msg_clear(&schan_msg); 851 852 soc_schan_header_cmd_set(unit, &schan_msg.header, (is_mem ? WRITE_MEMORY_CMD_MSG : WRITE_REGISTER_CMD_MSG), 853 cmic_block, SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)), 854 0, dwc_write * 4, 0, 0); 855 856 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 857 if(soc_feature(unit, soc_feature_cmicm) || soc_feature(unit, soc_feature_cmicx)) { 858 schan_msg.writecmd.address = addr; 859 } else 860 #endif 861 { 862 uint32 cmice_addr = addr; 863 if (cmic_block >= 0) { 864 cmice_addr |= ((cmic_block & 0xf) << SOC_BLOCK_BP) | 865 (((cmic_block >> 4) & 0x3) << SOC_BLOCK_MSB_BP); 866 } 867 868 schan_msg.readcmd.address = cmice_addr; 869 } 870 871 for(i=0 ; i<dwc_write ; i++) 872 schan_msg.writecmd.data[i] = data[i]; 873 874 875 if(SOC_IS_SAND(unit)) { 876 allow_intr = 1; 877 } 878 879 /* Write header word + address + data DWORD */ 880 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 881 882 883 884 return soc_schan_op(unit, &schan_msg, dwc_write+2, 0, allow_intr); 885 } 886 887 int 888 soc_direct_reg_set(int unit, int cmic_block, uint32 addr, uint32 dwc_write, uint32 *data) 889 { 890 #ifdef CRASH_RECOVERY_SUPPORT 891 /* Use crash recovery defined callback for access*/ 892 if (SOC_IS_DONE_INIT(unit)) 893 { 894 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 895 { 896 if(Hw_Log_List[unit].Access_cb.direct_reg_set) 897 { 898 return Hw_Log_List[unit].Access_cb.direct_reg_set(unit, cmic_block, addr, dwc_write, data); 899 } 900 } 901 } 902 903 #endif /* CRASH_RECOVERY_SUPPORT */ 904 return soc_direct_memreg_set(unit, cmic_block, addr, dwc_write, 0, data); 905 } 906 907 /* 908 * Read an internal SOC register through S-Channel messaging buffer. 909 * Use soc_reg32_get() if you know the port number, index 910 */ 911 912 int 913 _soc_reg32_get(int unit, soc_block_t block, int acc, uint32 addr, uint32 *data) 914 { 915 schan_msg_t schan_msg; 916 int rv, allow_intr = 0; 917 int data_byte_len; 918 int opcode, err; 919 #ifdef BCM_HELIX5_SUPPORT 920 soc_info_t *si = &SOC_INFO(unit); 921 #endif 922 923 /* 924 * Write message to S-Channel. 925 */ 926 schan_msg_clear(&schan_msg); 927 928 data_byte_len = 4; 929 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_REGISTER_CMD_MSG, 930 block, 0, acc, data_byte_len, 0, 0); 931 932 schan_msg.readcmd.address = addr; 933 934 if(SOC_IS_SAND(unit)) { 935 allow_intr = 1; 936 } 937 938 /* Write header word + address DWORD, read header word + data DWORD */ 939 rv = soc_schan_op(unit, &schan_msg, 2, 2, allow_intr); 940 if (SOC_FAILURE(rv)) { 941 #if defined(BCM_XGS_SUPPORT) 942 int rv1, port = 0, index; 943 #endif /* BCM_XGS_SUPPORT */ 944 soc_regaddrinfo_t ainfo; 945 946 if (!soc_feature(unit, soc_feature_ser_parity)) { 947 return rv; 948 } 949 soc_regaddrinfo_extended_get(unit, &ainfo, block, acc, addr); 950 if (ainfo.reg != INVALIDr) { 951 if (SOC_REG_IS_COUNTER(unit, ainfo.reg)) { 952 *data = 0; 953 /* Force correct */ 954 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 955 rv = SOC_E_NONE; 956 } 957 } 958 #if defined(BCM_XGS_SUPPORT) 959 else if (soc_feature(unit, soc_feature_regs_as_mem)) { 960 if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_portreg) { 961 port = ainfo.port; 962 } else if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_cosreg) { 963 port = ainfo.cos; 964 } 965 index = ainfo.idx != -1 ? ainfo.idx : 0; 966 rv1 = soc_ser_reg32_cache_get(unit, ainfo.reg, port, index, data); 967 if (rv1 != SOC_E_NONE) { 968 if (SOC_REG_IS_DYNAMIC(unit, ainfo.reg)) { 969 *data = 0; 970 } else { 971 return rv; 972 } 973 } 974 /* Force correct */ 975 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 976 rv = SOC_E_NONE; 977 } 978 } 979 #endif /* BCM_XGS_SUPPORT */ 980 } else { 981 return rv; 982 } 983 } 984 985 /* Check result */ 986 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 987 &err, NULL, NULL); 988 if (opcode != READ_REGISTER_ACK_MSG || err != 0) { 989 { 990 LOG_ERROR(BSL_LS_SOC_COMMON, 991 (BSL_META_U(unit, 992 "_soc_reg32_get: " 993 "invalid S-Channel reply, expected READ_REG_ACK(%d) and found %d err=%d\n"), 994 READ_REGISTER_ACK_MSG, opcode, err)); 995 soc_schan_dump(unit, &schan_msg, 2); 996 return SOC_E_INTERNAL; 997 } 998 } 999 1000 *data = schan_msg.readresp.data[0]; 1001 1002 #ifdef BCM_HELIX5_SUPPORT 1003 /* For HX5 A WAR is needed when reading 'CHIP_CONFIGr', since the fields 1004 PMD_PLL_CTRL_REFLK_DIV2f/PMD_PLL_CTRL_REFLK_DIV4f are swapped (Write 1005 into the register is fine) */ 1006 if (si->hx5_chip_config_war_enable) { 1007 uint32 pll_ctrl_ref_clk_div2 = 0, pll_ctrl_ref_clk_div4 = 0; 1008 if (addr == si->hx5_chip_config_address) { 1009 pll_ctrl_ref_clk_div2 = soc_reg_field_get(unit, CHIP_CONFIGr, 1010 *data, PMD_PLL_CTRL_REFCLK_DIV2f); 1011 pll_ctrl_ref_clk_div4 = soc_reg_field_get(unit, CHIP_CONFIGr, 1012 *data, PMD_PLL_CTRL_REFCLK_DIV4f); 1013 soc_reg_field_set(unit, CHIP_CONFIGr, data, PMD_PLL_CTRL_REFCLK_DIV2f, 1014 pll_ctrl_ref_clk_div4); 1015 soc_reg_field_set(unit, CHIP_CONFIGr, data, PMD_PLL_CTRL_REFCLK_DIV4f, 1016 pll_ctrl_ref_clk_div2); 1017 } 1018 } 1019 #endif /* BCM_HELIX5_SUPPORT */ 1020 1021 #ifdef BROADCOM_DEBUG 1022 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1023 _soc_reg_extended_debug(unit, 32, "read", block, acc, addr, 0, *data); 1024 } 1025 #endif /* BROADCOM_DEBUG */ 1026 _soc_snoop_reg(unit, block, acc, addr,SOC_REG_SNOOP_READ, 0,*data); 1027 1028 return SOC_E_NONE; 1029 } 1030 1031 /* 1032 * Read an internal SOC register through S-Channel messaging buffer. 1033 * Checks if the register is 32 or 64 bits. 1034 */ 1035 1036 int 1037 soc_reg_get(int unit, soc_reg_t reg, int port, int index, uint64 *data) 1038 { 1039 uint32 addr; 1040 int block; 1041 int pindex = port; 1042 int rv = SOC_E_NONE; 1043 uint8 acc_type = 0; 1044 1045 if (!SOC_REG_IS_VALID(unit, reg)) { 1046 return SOC_E_PARAM; 1047 } 1048 1049 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, FALSE)); 1050 1051 #ifdef CRASH_RECOVERY_SUPPORT 1052 /* Use crash recovery defined callback for access*/ 1053 if (SOC_IS_DONE_INIT(unit) && BCM_UNIT_DO_HW_READ_WRITE(unit) && Hw_Log_List[unit].Access_cb.soc_reg_get) { 1054 rv = Hw_Log_List[unit].Access_cb.soc_reg_get(unit, reg, port, index, data); 1055 } else 1056 #endif /* CRASH_RECOVERY_SUPPORT */ 1057 /* Use user defined callback for access */ 1058 if (SOC_INFO(unit).reg_access.reg64_get) { 1059 rv = SOC_INFO(unit).reg_access.reg64_get(unit, reg, port, index, data); 1060 } else 1061 1062 if (SOC_REG_IS_ABOVE_64(unit, reg)) { 1063 LOG_ERROR(BSL_LS_SOC_COMMON, 1064 (BSL_META_U(unit, 1065 "soc_reg_get: " 1066 "Use soc_reg_above_64_get \n"))); 1067 1068 return SOC_E_FAIL; 1069 } else 1070 1071 #ifdef CANCUN_SUPPORT 1072 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 1073 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE) && 1074 SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1075 rv = soc_cancun_pseudo_reg_get(unit, reg, data); 1076 } else 1077 #endif 1078 1079 #ifdef DNX_TEST_CHIPS_SUPPORT 1080 if (SOC_IS_DNX_TEST_DEVICE(unit) 1081 #if defined(PLISIM) 1082 && !SAL_BOOT_PLISIM 1083 #endif 1084 ) { 1085 rv = soc_dnxtestchip_reg_get(unit, reg, port, data); 1086 } else 1087 #endif /* DNX_TEST_CHIPS_SUPPORT */ 1088 { 1089 addr = soc_reg_addr_get(unit, reg, port, index, SOC_REG_ADDR_OPTION_NONE, &block, &acc_type); 1090 if (SOC_REG_IS_64(unit, reg)) { 1091 soc_port_t _port; 1092 soc_block_types_t regblktype = SOC_REG_INFO(unit, reg).block; 1093 int blk, bindex; 1094 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1095 rv = soc_reg_read(unit, reg, addr, data); 1096 } 1097 1098 else if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT) 1099 #ifdef BCM_SAND_SUPPORT 1100 && !SOC_IS_SAND(unit) 1101 #endif /* BCM_SAND_SUPPORT */ 1102 #ifdef BCM_BIGMAC_SUPPORT 1103 && iterative_op_required(reg) 1104 #endif /* BCM_BIGMAC_SUPPORT */ 1105 ) { 1106 PBMP_HYPLITE_ITER(unit, _port) { 1107 blk = SOC_PORT_BLOCK(unit, _port); 1108 bindex = SOC_PORT_BINDEX(unit, _port); 1109 if ((SOC_BLOCK2SCH(unit, blk) == block) && (bindex == pindex)) { 1110 break; 1111 } 1112 } 1113 if (!IS_HYPLITE_PORT(unit, port)) { 1114 rv = _soc_reg64_get(unit, block, acc_type, addr, data); 1115 } 1116 #ifdef BCM_BIGMAC_SUPPORT 1117 else 1118 { 1119 rv = soc_reg64_get_iterative(unit, block, acc_type, addr, port, data); 1120 } 1121 #endif 1122 } else { 1123 rv = _soc_reg64_get(unit, block, acc_type, addr, data); 1124 } 1125 } else { 1126 uint32 data32; 1127 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1128 rv = soc_reg32_read(unit, addr, &data32); 1129 } else { 1130 rv = _soc_reg32_get(unit, block, acc_type, addr, &data32); 1131 } 1132 if (rv == SOC_E_NONE) { 1133 COMPILER_64_SET(*data, 0, data32); 1134 } 1135 } 1136 } 1137 1138 if (rv != SOC_E_NONE) { 1139 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1140 "soc_reg_get failed for %s\n"), SOC_REG_NAME(unit, reg))); 1141 } 1142 return rv; 1143 } 1144 1145 /* 1146 * Read an internal SOC register through S-Channel messaging buffer. 1147 * Handle register at any size 1148 */ 1149 1150 int 1151 soc_reg_above_64_get(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t data) 1152 { 1153 uint32 addr; 1154 int block; 1155 uint8 at; 1156 uint64 data64; 1157 int rc; 1158 int reg_size; 1159 1160 if (!SOC_REG_IS_VALID(unit, reg)) { 1161 return SOC_E_PARAM; 1162 } 1163 1164 SOC_REG_ABOVE_64_CLEAR(data); 1165 1166 #ifdef CRASH_RECOVERY_SUPPORT 1167 1168 /* Use crash recovery defined callback for access*/ 1169 if (SOC_IS_DONE_INIT(unit)) 1170 { 1171 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 1172 { 1173 if(Hw_Log_List[unit].Access_cb.reg_above64_get) 1174 { 1175 return Hw_Log_List[unit].Access_cb.reg_above64_get(unit, reg, port, index, data); 1176 } 1177 } 1178 } 1179 1180 #endif /* CRASH_RECOVERY_SUPPORT */ 1181 1182 #ifdef DNX_TEST_CHIPS_SUPPORT 1183 if (SOC_IS_DNX_TEST_DEVICE(unit) 1184 #if defined(PLISIM) 1185 && !SAL_BOOT_PLISIM 1186 #endif 1187 ) { 1188 return soc_dnxtestchip_reg_above_64_get(unit, reg, port, data); 1189 } 1190 #endif /* DNX_TEST_CHIPS_SUPPORT */ 1191 1192 /* Use user defined callback for access */ 1193 if(SOC_INFO(unit).reg_access.reg_above64_get) { 1194 return SOC_INFO(unit).reg_access.reg_above64_get(unit, reg, port, index, data); 1195 } 1196 1197 if (SOC_REG_IS_ABOVE_64(unit, reg)) 1198 { 1199 reg_size = SOC_REG_ABOVE_64_INFO(unit, reg).size; 1200 addr = soc_reg_addr_get(unit, reg, port, index, 1201 SOC_REG_ADDR_OPTION_NONE, &block, &at); 1202 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1203 block = ((addr >> SOC_BLOCK_BP) & 0xf) | (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 1204 } 1205 rc = soc_direct_reg_get(unit, block, addr, reg_size, data); 1206 1207 #ifdef BROADCOM_DEBUG 1208 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1209 _soc_reg_above_64_debug(unit, "get", block, addr, data); 1210 } 1211 #endif /* BROADCOM_DEBUG */ 1212 1213 if (rc != SOC_E_NONE) { 1214 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1215 "soc_reg_above_64_get failed for %s\n"), SOC_REG_NAME(unit, reg))); 1216 } 1217 return rc; 1218 1219 } 1220 else if (SOC_REG_IS_64(unit, reg)) { 1221 COMPILER_64_SET(data64, data[1], data[0]); 1222 rc = soc_reg_get(unit, reg, port, index, &data64); 1223 data[0] = COMPILER_64_LO(data64); 1224 data[1] = COMPILER_64_HI(data64); 1225 return rc; 1226 } 1227 else { 1228 rc = soc_reg_get(unit, reg, port, index, &data64); 1229 data[0] = COMPILER_64_LO(data64); 1230 return rc; 1231 } 1232 } 1233 1234 /* 1235 * Read an internal SOC register through S-Channel messaging buffer. 1236 * Uses sbusv1 format, before CMICm 1237 * SHOULD not be called from other files, use soc_reg32_get() instead 1238 */ 1239 1240 int 1241 soc_reg32_read(int unit, 1242 uint32 addr, 1243 uint32 *data) 1244 { 1245 schan_msg_t schan_msg; 1246 int rv, allow_intr = 0; 1247 int dst_blk, src_blk, data_byte_len; 1248 int opcode, err; 1249 1250 #ifdef BCM_CMICM_SUPPORT 1251 uint32 fsdata = 0; 1252 int cmc = SOC_PCI_CMC(unit); 1253 #endif 1254 1255 #ifdef DNX_TEST_CHIPS_SUPPORT 1256 if (SOC_IS_DNX_TEST_DEVICE(unit) 1257 #if defined(PLISIM) 1258 && !SAL_BOOT_PLISIM 1259 #endif 1260 ) { 1261 return soc_dnxtestchip_reg32_read(unit, addr, data); 1262 } 1263 #endif /* DNX_TEST_CHIPS_SUPPORT */ 1264 1265 #ifdef BCM_CMICM_SUPPORT 1266 if(soc_feature(unit, soc_feature_cmicm) && 1267 (NULL != SOC_CONTROL(unit)->fschanMutex)) { 1268 FSCHAN_LOCK(unit); 1269 soc_pci_write(unit, CMIC_CMCx_FSCHAN_ADDRESS_OFFSET(cmc), addr); 1270 fsdata = soc_pci_read(unit, CMIC_CMCx_FSCHAN_DATA32_OFFSET(cmc)); 1271 FSCHAN_UNLOCK(unit); 1272 *data = fsdata; 1273 } else 1274 #endif 1275 { 1276 /* 1277 * Write message to S-Channel. 1278 */ 1279 schan_msg_clear(&schan_msg); 1280 1281 dst_blk = ((addr >> SOC_BLOCK_BP) & 0xf) | 1282 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 1283 { 1284 src_blk = SOC_IS_SHADOW(unit) ? 1285 0 : SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 1286 data_byte_len = SOC_IS_XGS12_FABRIC(unit) ? 8 : 4; 1287 } 1288 soc_schan_header_cmd_set(unit, &schan_msg.header, 1289 READ_REGISTER_CMD_MSG, dst_blk, src_blk, 0, 1290 data_byte_len, 0, 0); 1291 1292 schan_msg.readcmd.address = addr; 1293 1294 if(SOC_IS_SAND(unit)) { 1295 allow_intr = 1; 1296 } 1297 1298 /* Write header word + address DWORD, read header word + data DWORD */ 1299 rv = soc_schan_op(unit, &schan_msg, 2, 2, allow_intr); 1300 if (SOC_FAILURE(rv)) { 1301 #if defined(BCM_XGS_SUPPORT) 1302 int rv1, port = 0, index; 1303 #endif /* BCM_XGS_SUPPORT */ 1304 soc_regaddrinfo_t ainfo; 1305 1306 if (!soc_feature(unit, soc_feature_ser_parity)) { 1307 return rv; 1308 } 1309 soc_regaddrinfo_get(unit, &ainfo, addr); 1310 if (ainfo.reg != INVALIDr) { 1311 if (SOC_REG_IS_COUNTER(unit, ainfo.reg)) { 1312 *data = 0; 1313 /* Force correct */ 1314 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 1315 rv = SOC_E_NONE; 1316 } 1317 } 1318 #if defined(BCM_XGS_SUPPORT) 1319 else if (soc_feature(unit, soc_feature_regs_as_mem)) { 1320 if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_portreg) { 1321 port = ainfo.port; 1322 } else if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_cosreg) { 1323 port = ainfo.cos; 1324 } 1325 index = ainfo.idx != -1 ? ainfo.idx : 0; 1326 rv1 = soc_ser_reg32_cache_get(unit, ainfo.reg, port, index, data); 1327 if (rv1 != SOC_E_NONE) { 1328 if (SOC_REG_IS_DYNAMIC(unit, ainfo.reg)) { 1329 *data = 0; 1330 } else { 1331 return rv; 1332 } 1333 } 1334 /* Force correct */ 1335 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 1336 rv = SOC_E_NONE; 1337 } 1338 } 1339 #endif /* BCM_XGS_SUPPORT */ 1340 } else { 1341 return rv; 1342 } 1343 } 1344 1345 /* Check result */ 1346 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, 1347 NULL, &err, NULL, NULL); 1348 if (!SOC_FAILURE(rv) && 1349 (opcode != READ_REGISTER_ACK_MSG || err != 0)) { 1350 LOG_ERROR(BSL_LS_SOC_COMMON, 1351 (BSL_META_U(unit, 1352 "soc_reg32_read: " 1353 "invalid S-Channel reply, expected READ_REG_ACK:\n"))); 1354 soc_schan_dump(unit, &schan_msg, 2); 1355 return SOC_E_INTERNAL; 1356 } 1357 *data = schan_msg.readresp.data[0]; 1358 } 1359 #ifdef BROADCOM_DEBUG 1360 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1361 _soc_reg_debug(unit, 32, "read", addr, 0, *data); 1362 } 1363 #endif /* BROADCOM_DEBUG */ 1364 _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_READ, 0, *data); 1365 return SOC_E_NONE; 1366 } 1367 1368 /* 1369 * Read an internal SOC register through S-Channel messaging buffer. 1370 */ 1371 1372 int 1373 soc_reg32_get(int unit, soc_reg_t reg, int port, int index, uint32 *data) 1374 { 1375 uint32 addr; 1376 int block = 0; 1377 uint8 acc_type = 0; 1378 1379 if (!SOC_REG_IS_VALID(unit, reg)) { 1380 return SOC_E_PARAM; 1381 } 1382 1383 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, FALSE)); 1384 1385 if (SOC_REG_IS_ABOVE_32(unit, reg)) { 1386 #if !defined(SOC_NO_NAMES) 1387 LOG_CLI((BSL_META_U(unit, 1388 "reg %s is > 32 bit , but called with soc_reg32_get\n"), soc_reg_name[reg])); 1389 #endif 1390 } 1391 assert(!SOC_REG_IS_ABOVE_32(unit, reg)); 1392 1393 /* Use crash recovery defined callback for access*/ 1394 #ifdef CRASH_RECOVERY_SUPPORT 1395 if (SOC_IS_DONE_INIT(unit)) 1396 { 1397 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 1398 { 1399 if(Hw_Log_List[unit].Access_cb.reg32_get) 1400 { 1401 return Hw_Log_List[unit].Access_cb.reg32_get(unit, reg, port, index, data); 1402 } 1403 } 1404 } 1405 1406 #endif /* CRASH_RECOVERY_SUPPORT */ 1407 1408 /* Use user defined callback for access */ 1409 if(SOC_INFO(unit).reg_access.reg32_get) { 1410 return SOC_INFO(unit).reg_access.reg32_get(unit, reg, port, index, data); 1411 } 1412 1413 #ifdef CANCUN_SUPPORT 1414 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 1415 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 1416 uint64 rval64; 1417 int rv; 1418 1419 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1420 rv = soc_cancun_pseudo_reg_get(unit, reg, &rval64); 1421 if(rv == SOC_E_NONE) { 1422 *data = COMPILER_64_LO(rval64); 1423 } 1424 return rv; 1425 } 1426 } 1427 #endif 1428 1429 addr = soc_reg_addr_get(unit, reg, port, index, 1430 SOC_REG_ADDR_OPTION_NONE, &block, &acc_type); 1431 1432 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1433 return soc_reg32_read(unit, addr, data); 1434 } 1435 return _soc_reg32_get(unit, block, acc_type, addr, data); 1436 } 1437 1438 /* 1439 * Read an internal 64-bit SOC register through S-Channel messaging buffer. 1440 */ 1441 int 1442 soc_reg64_read(int unit, 1443 uint32 addr, 1444 uint64 *reg) 1445 { 1446 schan_msg_t schan_msg; 1447 int rv, allow_intr = 0; 1448 int dst_blk, src_blk, data_byte_len; 1449 int opcode, err; 1450 1451 #ifdef BCM_CMICM_SUPPORT 1452 uint32 fsdatal = 0, fsdatah = 0; 1453 int cmc = SOC_PCI_CMC(unit); 1454 #endif 1455 1456 #ifdef DNX_TEST_CHIPS_SUPPORT 1457 if (SOC_IS_DNX_TEST_DEVICE(unit) 1458 #if defined(PLISIM) 1459 && !SAL_BOOT_PLISIM 1460 #endif 1461 ) { 1462 return soc_dnxtestchip_reg64_read(unit, addr, reg); 1463 } 1464 #endif /* DNX_TEST_CHIPS_SUPPORT */ 1465 1466 #ifdef BCM_CMICM_SUPPORT 1467 if(soc_feature(unit, soc_feature_cmicm) && 1468 (NULL != SOC_CONTROL(unit)->fschanMutex)) { 1469 FSCHAN_LOCK(unit); 1470 soc_pci_write(unit, CMIC_CMCx_FSCHAN_ADDRESS_OFFSET(cmc), addr); 1471 fsdatal = soc_pci_read(unit, CMIC_CMCx_FSCHAN_DATA64_LO_OFFSET(cmc)); 1472 fsdatah = soc_pci_read(unit, CMIC_CMCx_FSCHAN_DATA64_HI_OFFSET(cmc)); 1473 FSCHAN_UNLOCK(unit); 1474 COMPILER_64_SET(*reg, fsdatah, fsdatal); 1475 } else 1476 #endif 1477 { 1478 /* 1479 * Write message to S-Channel. 1480 */ 1481 schan_msg_clear(&schan_msg); 1482 1483 dst_blk = ((addr >> SOC_BLOCK_BP) & 0xf) | 1484 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 1485 { 1486 src_blk = SOC_IS_SHADOW(unit) ? 1487 0 : SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 1488 data_byte_len = 8; 1489 } 1490 soc_schan_header_cmd_set(unit, &schan_msg.header, 1491 READ_REGISTER_CMD_MSG, dst_blk, src_blk, 0, 1492 data_byte_len, 0, 0); 1493 1494 schan_msg.readcmd.address = addr; 1495 1496 if(SOC_IS_SAND(unit)) { 1497 allow_intr = 1; 1498 } 1499 1500 /* Write header word + address DWORD, read header word + data DWORD */ 1501 rv = soc_schan_op(unit, &schan_msg, 2, 3, allow_intr); 1502 if (SOC_FAILURE(rv)) { 1503 #if defined(BCM_XGS_SUPPORT) 1504 int rv1, port = 0, index; 1505 #endif /* BCM_XGS_SUPPORT */ 1506 soc_regaddrinfo_t ainfo; 1507 1508 if (!soc_feature(unit, soc_feature_ser_parity)) { 1509 return rv; 1510 } 1511 soc_regaddrinfo_get(unit, &ainfo, addr); 1512 if (ainfo.reg != INVALIDr) { 1513 if (SOC_REG_IS_COUNTER(unit, ainfo.reg)) { 1514 COMPILER_64_SET(*reg, 0, 0); 1515 /* Force correct */ 1516 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 1517 rv = SOC_E_NONE; 1518 } 1519 } 1520 #if defined(BCM_XGS_SUPPORT) 1521 else if (soc_feature(unit, soc_feature_regs_as_mem)) { 1522 if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_portreg) { 1523 port = ainfo.port; 1524 } else if (SOC_REG_INFO(unit, ainfo.reg).regtype == soc_cosreg) { 1525 port = ainfo.cos; 1526 } 1527 index = ainfo.idx != -1 ? ainfo.idx : 0; 1528 rv1 = soc_ser_reg_cache_get(unit, ainfo.reg, port, index, reg); 1529 if (rv1 != SOC_E_NONE) { 1530 if (SOC_REG_IS_DYNAMIC(unit, ainfo.reg)) { 1531 COMPILER_64_SET(*reg, 0, 0); 1532 } else { 1533 return rv; 1534 } 1535 } 1536 /* Force correct */ 1537 if (!SOC_REG_RETURN_SER_ERROR(unit)) { 1538 rv = SOC_E_NONE; 1539 } 1540 } 1541 #endif /* BCM_XGS_SUPPORT */ 1542 } else { 1543 return rv; 1544 } 1545 } 1546 1547 /* Check result */ 1548 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, 1549 NULL, &err, NULL, NULL); 1550 if (opcode != READ_REGISTER_ACK_MSG || err != 0) { 1551 LOG_ERROR(BSL_LS_SOC_COMMON, 1552 (BSL_META_U(unit, 1553 "soc_reg64_read: " 1554 "invalid S-Channel reply, expected READ_REG_ACK:\n"))); 1555 soc_schan_dump(unit, &schan_msg, 2); 1556 return SOC_E_INTERNAL; 1557 } 1558 COMPILER_64_SET(*reg, schan_msg.readresp.data[1], 1559 schan_msg.readresp.data[0]); 1560 } 1561 1562 #ifdef BROADCOM_DEBUG 1563 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1564 _soc_reg_debug(unit, 64, "read", addr, 1565 schan_msg.readresp.data[1], 1566 schan_msg.readresp.data[0]); 1567 } 1568 #endif /* BROADCOM_DEBUG */ 1569 _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_READ, 1570 schan_msg.readresp.data[1], schan_msg.readresp.data[0]); 1571 1572 return SOC_E_NONE; 1573 } 1574 1575 /* 1576 * Read an internal 64-bit SOC register through S-Channel messaging buffer. 1577 */ 1578 int 1579 soc_reg64_get(int unit, soc_reg_t reg, int port, int index, uint64 *data) 1580 { 1581 uint32 addr; 1582 int block = 0; 1583 uint8 acc_type = 0; 1584 1585 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, FALSE)); 1586 1587 #ifdef CANCUN_SUPPORT 1588 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 1589 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 1590 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1591 return(soc_cancun_pseudo_reg_get(unit, reg, data)); 1592 } 1593 } 1594 #endif 1595 1596 #ifdef CRASH_RECOVERY_SUPPORT 1597 /* Use crash recovery defined callback for access*/ 1598 if (SOC_IS_DONE_INIT(unit)) 1599 { 1600 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 1601 { 1602 if(Hw_Log_List[unit].Access_cb.reg64_get) 1603 { 1604 return Hw_Log_List[unit].Access_cb.reg64_get(unit, reg, port, index, data); 1605 } 1606 } 1607 } 1608 #endif /* CRASH_RECOVERY_SUPPORT */ 1609 1610 /* Use user defined callback for access */ 1611 if(SOC_INFO(unit).reg_access.reg64_get) { 1612 return SOC_INFO(unit).reg_access.reg64_get(unit, reg, port, index, data); 1613 } 1614 1615 addr = soc_reg_addr_get(unit, reg, port, index, 1616 SOC_REG_ADDR_OPTION_NONE, &block, &acc_type); 1617 assert(SOC_REG_IS_64(unit, reg)); 1618 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1619 return soc_reg64_read(unit, addr, data); 1620 } 1621 return _soc_reg64_get(unit, block, acc_type, addr, data); 1622 } 1623 1624 /* 1625 * Read an internal SOC register through S-Channel messaging buffer 1626 * with Raw Port Number. 1627 */ 1628 int 1629 soc_reg_rawport_get(int unit, soc_reg_t reg, int port, int index, uint64 *data) 1630 { 1631 uint32 addr; 1632 int block = 0; 1633 uint8 acc_type; 1634 1635 if (!SOC_REG_IS_VALID(unit, reg)) { 1636 return SOC_E_PARAM; 1637 } 1638 1639 if ((REG_PORT_ANY != port) && 1640 (port & (SOC_REG_ADDR_INSTANCE_MASK | SOC_REG_ADDR_BLOCK_ID_MASK | 1641 SOC_REG_ADDR_SCHAN_ID_MASK | SOC_REG_ADDR_PHY_ACC_MASK))) { 1642 LOG_ERROR(BSL_LS_SOC_COMMON, 1643 (BSL_META_U(unit, 1644 "This function is only for Raw Port Numbers \n"))); 1645 return SOC_E_FAIL; 1646 } 1647 #ifdef CRASH_RECOVERY_SUPPORT 1648 /* Don't handle Special Accesses */ 1649 if((SOC_INFO(unit).reg_access.reg64_get) || /* User defined */ 1650 (SOC_REG_IS_ABOVE_64(unit, reg)) || 1651 (SOC_IS_DONE_INIT(unit) && BCM_UNIT_DO_HW_READ_WRITE(unit) && 1652 Hw_Log_List[unit].Access_cb.soc_reg_get)) { 1653 LOG_ERROR(BSL_LS_SOC_COMMON, 1654 (BSL_META_U(unit, 1655 "Use soc_reg_get \n"))); 1656 return SOC_E_FAIL; 1657 } 1658 #else 1659 if((SOC_INFO(unit).reg_access.reg64_get) || /* User defined */ 1660 (SOC_REG_IS_ABOVE_64(unit, reg))) { 1661 LOG_ERROR(BSL_LS_SOC_COMMON, 1662 (BSL_META_U(unit, 1663 "Use soc_reg_get \n"))); 1664 return SOC_E_FAIL; 1665 } 1666 #endif /* CRASH_RECOVERY_SUPPORT */ 1667 1668 addr = soc_reg_addr_get(unit, reg, port, index, 1669 SOC_REG_ADDR_OPTION_PRESERVE_PORT, 1670 &block, &acc_type); 1671 1672 if (SOC_REG_IS_64(unit, reg)) { 1673 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1674 return soc_reg_read(unit, reg, addr, data); 1675 } else { 1676 return _soc_reg64_get(unit, block, acc_type, addr, data); 1677 } 1678 } else { 1679 uint32 data32; 1680 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 1681 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &data32)); 1682 } else { 1683 SOC_IF_ERROR_RETURN 1684 (_soc_reg32_get(unit, block, acc_type, addr, &data32)); 1685 } 1686 COMPILER_64_SET(*data, 0, data32); 1687 } 1688 return SOC_E_NONE; 1689 } 1690 1691 int 1692 soc_reg32_rawport_get(int unit, soc_reg_t reg, int port, int index, uint32 *data) 1693 { 1694 int rv; 1695 uint64 d64; 1696 1697 rv = soc_reg_rawport_get(unit, reg, port, index, &d64); 1698 *data = COMPILER_64_LO(d64); 1699 return rv; 1700 } 1701 1702 #ifdef BCM_BIGMAC_SUPPORT 1703 /* 1704 * Iterative write procedure for MAC registers on Hyperlite ports. 1705 */ 1706 STATIC int 1707 soc_reg64_write_iterative(int unit, uint32 addr, soc_port_t port, 1708 uint64 data) 1709 { 1710 int rv, i, diff; 1711 uint64 xgxs_stat; 1712 uint32 locked; 1713 sal_usecs_t t1 = 0, t2; 1714 soc_timeout_t to; 1715 for (i = 0; i < 100; i++) { 1716 /* Read PLL lock status */ 1717 soc_timeout_init(&to, 25 * MILLISECOND_USEC, 0); 1718 do { 1719 t1 = sal_time_usecs(); 1720 rv = READ_MAC_XGXS_STATr(unit, port, &xgxs_stat); 1721 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 1722 TXPLL_LOCKf); 1723 if (locked || SOC_FAILURE(rv)) { 1724 break; 1725 } 1726 } while (!soc_timeout_check(&to)); 1727 if (SOC_FAILURE(rv)) { 1728 return rv; 1729 } 1730 if (!locked) { 1731 continue; 1732 } 1733 /* Write register value */ 1734 SOC_IF_ERROR_RETURN(soc_reg64_write(unit, addr, data)); 1735 /* Read PLL lock status */ 1736 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 1737 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 1738 TXPLL_LOCKf); 1739 t2 = sal_time_usecs(); 1740 diff = SAL_USECS_SUB(t2, t1); 1741 if (locked && (diff < 20 * MILLISECOND_USEC)) { 1742 return SOC_E_NONE; 1743 } 1744 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1745 (BSL_META_U(unit, 1746 "soc_reg64_write_iterative: WARNING: " 1747 "iteration %d PLL went out of lock"), 1748 i)); 1749 } 1750 LOG_ERROR(BSL_LS_SOC_COMMON, 1751 (BSL_META_U(unit, 1752 "soc_reg64_write_iterative: " 1753 "operation failed:\n"))); 1754 return SOC_E_FAIL; 1755 } 1756 1757 #endif /* BCM_BIGMAC_SUPPORT */ 1758 1759 #ifdef BCM_TOMAHAWK3_SUPPORT 1760 /* 1761 * Write an internal 64-bit TH3 SOC register through S-Channel messaging buffer. 1762 */ 1763 int 1764 _soc_th3_reg64_set(int unit, soc_block_t block, int acc, uint32 addr, uint64 data) 1765 { 1766 schan_msg_t schan_msg; 1767 int allow_intr = 0; 1768 1769 /* 1770 * Setup S-Channel command packet 1771 * 1772 * NOTE: the datalen field matters only for the Write Memory and 1773 * Write Register commands, where it is used only by the CMIC to 1774 * determine how much data to send, and is in units of bytes. 1775 */ 1776 1777 schan_msg_clear(&schan_msg); 1778 1779 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_REGISTER_CMD_MSG, 1780 block, 0, acc, 8, 0, 0); 1781 1782 schan_msg.writecmd.address = addr; 1783 schan_msg.writecmd.data[0] = COMPILER_64_LO(data); 1784 schan_msg.writecmd.data[1] = COMPILER_64_HI(data); 1785 1786 #ifdef BROADCOM_DEBUG 1787 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1788 _soc_reg_extended_debug(unit, 64, "write", block, acc, addr, 1789 schan_msg.writecmd.data[1], 1790 schan_msg.writecmd.data[0]); 1791 } 1792 #endif /* BROADCOM_DEBUG */ 1793 _soc_snoop_reg(unit, block, acc, addr,SOC_REG_SNOOP_WRITE, 1794 schan_msg.writecmd.data[1],schan_msg.writecmd.data[0]); 1795 1796 if(SOC_IS_SAND(unit)) { 1797 allow_intr = 1; 1798 } 1799 1800 /* Write header word + address + 2*data DWORD */ 1801 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 1802 1803 1804 1805 return soc_schan_op(unit, &schan_msg, 4, 0, allow_intr); 1806 1807 1808 } 1809 #endif 1810 1811 /* 1812 * Write an internal 64-bit SOC register through S-Channel messaging buffer. 1813 */ 1814 int 1815 _soc_reg64_set(int unit, soc_block_t block, int acc, uint32 addr, uint64 data) 1816 { 1817 schan_msg_t schan_msg; 1818 int allow_intr = 0, rv = 0; 1819 #ifdef BCM_TOMAHAWK3_SUPPORT 1820 uint16 dev_id; 1821 uint8 rev_id; 1822 int j; 1823 1824 soc_cm_get_id(unit, &dev_id, &rev_id); 1825 if ((acc == 9 || acc == 14) && (dev_id == BCM56983_DEVICE_ID)) { 1826 1827 for (j = 0; j< 4; j++) { 1828 switch(j) { 1829 case 0 : acc = 0; 1830 break; 1831 case 1 : acc = 1; 1832 break; 1833 case 2 : acc = 6; 1834 break; 1835 case 3 : acc = 7; 1836 break; 1837 } 1838 rv = _soc_th3_reg64_set(unit, block, acc, addr, data); 1839 if ( rv < 0 ) { 1840 return rv; 1841 } 1842 } 1843 1844 } else if (acc == 15 && (dev_id == BCM56983_DEVICE_ID)) { 1845 for (j = 0; j < 2; j++) { 1846 switch(j) { 1847 case 0 : acc = 0; 1848 break; 1849 case 1 : acc = 6; 1850 break; 1851 } 1852 rv = _soc_th3_reg64_set(unit, block, acc, addr, data); 1853 if ( rv < 0 ) { 1854 return rv; 1855 } 1856 } 1857 } else if (acc == 16 && (dev_id == BCM56983_DEVICE_ID)) { 1858 acc = 0; 1859 rv = _soc_th3_reg64_set(unit, block, acc, addr, data); 1860 if ( rv < 0 ) { 1861 return rv; 1862 } 1863 } else 1864 #endif 1865 { 1866 /* 1867 * Setup S-Channel command packet 1868 * 1869 * NOTE: the datalen field matters only for the Write Memory and 1870 * Write Register commands, where it is used only by the CMIC to 1871 * determine how much data to send, and is in units of bytes. 1872 */ 1873 1874 schan_msg_clear(&schan_msg); 1875 1876 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_REGISTER_CMD_MSG, 1877 block, 0, acc, 8, 0, 0); 1878 1879 schan_msg.writecmd.address = addr; 1880 schan_msg.writecmd.data[0] = COMPILER_64_LO(data); 1881 schan_msg.writecmd.data[1] = COMPILER_64_HI(data); 1882 1883 #ifdef BROADCOM_DEBUG 1884 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 1885 _soc_reg_extended_debug(unit, 64, "write", block, acc, addr, 1886 schan_msg.writecmd.data[1], 1887 schan_msg.writecmd.data[0]); 1888 } 1889 #endif /* BROADCOM_DEBUG */ 1890 _soc_snoop_reg(unit, block, acc, addr,SOC_REG_SNOOP_WRITE, 1891 schan_msg.writecmd.data[1],schan_msg.writecmd.data[0]); 1892 1893 if(SOC_IS_SAND(unit)) { 1894 allow_intr = 1; 1895 } 1896 1897 /* Write header word + address + 2*data DWORD */ 1898 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 1899 1900 1901 1902 rv = soc_schan_op(unit, &schan_msg, 4, 0, allow_intr); 1903 } 1904 return rv; 1905 } 1906 1907 void 1908 soc_reg_watch_set(int unit, int value) 1909 { 1910 SOC_CONTROL(unit)->soc_reg_watch = value; 1911 LOG_CLI((BSL_META("regwatch delta %s\n"), 1912 value ? "on" : "off")); 1913 } 1914 1915 #ifdef BCM_BIGMAC_SUPPORT 1916 1917 /* 1918 * Iterative write procedure for MAC registers on Hyperlite ports. 1919 */ 1920 STATIC int 1921 soc_reg64_set_iterative(int unit, soc_block_t block, int acc, uint32 addr, 1922 soc_port_t port, uint64 data) 1923 { 1924 int rv, i, diff; 1925 uint64 xgxs_stat; 1926 uint32 locked; 1927 sal_usecs_t t1 = 0, t2; 1928 soc_timeout_t to; 1929 for (i = 0; i < 100; i++) { 1930 /* Read PLL lock status */ 1931 soc_timeout_init(&to, 25 * MILLISECOND_USEC, 0); 1932 do { 1933 t1 = sal_time_usecs(); 1934 rv = READ_MAC_XGXS_STATr(unit, port, &xgxs_stat); 1935 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 1936 TXPLL_LOCKf); 1937 if (locked || SOC_FAILURE(rv)) { 1938 break; 1939 } 1940 } while (!soc_timeout_check(&to)); 1941 if (SOC_FAILURE(rv)) { 1942 return rv; 1943 } 1944 if (!locked) { 1945 continue; 1946 } 1947 /* Write register value */ 1948 SOC_IF_ERROR_RETURN(_soc_reg64_set(unit, block, acc, addr, data)); 1949 /* Read PLL lock status */ 1950 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 1951 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 1952 TXPLL_LOCKf); 1953 t2 = sal_time_usecs(); 1954 diff = SAL_USECS_SUB(t2, t1); 1955 if (locked && (diff < 20 * MILLISECOND_USEC)) { 1956 return SOC_E_NONE; 1957 } 1958 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1959 (BSL_META_U(unit, 1960 "soc_reg64_set_iterative: WARNING: " 1961 "iteration %d PLL went out of lock"), 1962 i)); 1963 } 1964 LOG_ERROR(BSL_LS_SOC_COMMON, 1965 (BSL_META_U(unit, 1966 "soc_reg64_set_iterative: " 1967 "operation failed:\n"))); 1968 return SOC_E_FAIL; 1969 } 1970 1971 #endif /* BCM_BIGMAC_SUPPORT */ 1972 1973 /* 1974 * Write an internal SOC register through S-Channel messaging buffer. 1975 * Checks if the register is 32 or 64 bits. 1976 */ 1977 1978 int 1979 soc_reg_write(int unit, soc_reg_t reg, uint32 addr, uint64 data) 1980 { 1981 1982 if (!SOC_REG_IS_VALID(unit, reg)) { 1983 return SOC_E_PARAM; 1984 } 1985 1986 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, TRUE)); 1987 1988 if (SOC_REG_IS_ABOVE_64(unit, reg)) { 1989 LOG_ERROR(BSL_LS_SOC_COMMON, 1990 (BSL_META_U(unit, 1991 "soc_reg_write: " 1992 "Use soc_reg_above_64_set \n"))); 1993 1994 return SOC_E_FAIL; 1995 } 1996 1997 #ifdef DNX_TEST_CHIPS_SUPPORT 1998 if (SOC_IS_DNX_TEST_DEVICE(unit) 1999 #if defined(PLISIM) 2000 && !SAL_BOOT_PLISIM 2001 #endif 2002 ) { 2003 return soc_dnxtestchip_reg_write(unit, reg, addr, data); 2004 } 2005 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2006 2007 if (SOC_REG_IS_64(unit, reg)) { 2008 soc_port_t port; 2009 soc_block_types_t regblktype = SOC_REG_INFO(unit, reg).block; 2010 int blk, pindex, bindex, block; 2011 pindex = (addr >> SOC_REGIDX_BP) & 0x3f; 2012 block = ((addr >> SOC_BLOCK_BP) & 0xf) | 2013 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 2014 if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT) 2015 #ifdef BCM_SAND_SUPPORT 2016 && !SOC_IS_SAND(unit) 2017 #endif /* BCM_SAND_SUPPORT */ 2018 #ifdef BCM_BIGMAC_SUPPORT 2019 && iterative_op_required(reg) 2020 #endif /* BCM_BIGMAC_SUPPORT */ 2021 ) { 2022 PBMP_HYPLITE_ITER(unit, port) { 2023 blk = SOC_PORT_BLOCK(unit, port); 2024 bindex = SOC_PORT_BINDEX(unit, port); 2025 if ((SOC_BLOCK2SCH(unit, blk) == block) && (bindex == pindex)) { 2026 break; 2027 } 2028 } 2029 if (!IS_HYPLITE_PORT(unit, port)) { 2030 return soc_reg64_write(unit, addr, data); 2031 } 2032 #ifdef BCM_BIGMAC_SUPPORT 2033 else { 2034 return soc_reg64_write_iterative(unit, addr, port, data); 2035 } 2036 #endif /* BCM_BIGMAC_SUPPORT */ 2037 } else { 2038 return soc_reg64_write(unit, addr, data); 2039 } 2040 } else { 2041 if (COMPILER_64_HI(data)) { 2042 LOG_WARN(BSL_LS_SOC_COMMON, 2043 (BSL_META_U(unit, 2044 "soc_reg_write: WARNING: " 2045 "write to 32-bit reg %s with hi order data, 0x%x\n"), 2046 SOC_REG_NAME(unit, reg), 2047 COMPILER_64_HI(data))); 2048 } 2049 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, 2050 COMPILER_64_LO(data))); 2051 } 2052 2053 return SOC_E_NONE; 2054 } 2055 2056 /* 2057 * Write an internal SOC register through S-Channel messaging buffer. 2058 */ 2059 int 2060 _soc_reg32_set(int unit, soc_block_t block, int acc, uint32 addr, uint32 data) 2061 { 2062 schan_msg_t schan_msg; 2063 int allow_intr=0; 2064 2065 /* 2066 * Setup S-Channel command packet 2067 * 2068 * NOTE: the datalen field matters only for the Write Memory and 2069 * Write Register commands, where it is used only by the CMIC to 2070 * determine how much data to send, and is in units of bytes. 2071 */ 2072 2073 schan_msg_clear(&schan_msg); 2074 2075 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_REGISTER_CMD_MSG, 2076 block, 0, acc, 4, 0, 0); 2077 2078 schan_msg.writecmd.address = addr; 2079 schan_msg.writecmd.data[0] = data; 2080 2081 #ifdef BROADCOM_DEBUG 2082 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 2083 _soc_reg_extended_debug(unit, 32, "write", block, acc, addr, 0, data); 2084 } 2085 #endif /* BROADCOM_DEBUG */ 2086 _soc_snoop_reg(unit, block, acc, addr,SOC_REG_SNOOP_WRITE, 0,data); 2087 2088 if(SOC_IS_SAND(unit)) { 2089 allow_intr = 1; 2090 } 2091 2092 /* Write header word + address + data DWORD */ 2093 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 2094 2095 2096 2097 return soc_schan_op(unit, &schan_msg, 3, 0, allow_intr); 2098 } 2099 2100 /* 2101 * Write an internal SOC register through S-Channel messaging buffer. 2102 * Checks if the register is 32 or 64 bits. 2103 */ 2104 2105 int 2106 soc_reg_set(int unit, soc_reg_t reg, int port, int index, uint64 data) 2107 { 2108 uint32 addr; 2109 int block; 2110 soc_reg_access_info_t access_info; 2111 int rv; 2112 int pindex = port; 2113 if (!SOC_REG_IS_VALID(unit, reg)) { 2114 return SOC_E_PARAM; 2115 } 2116 2117 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, TRUE)); 2118 2119 if (SOC_REG_IS_ABOVE_64(unit, reg)) { 2120 LOG_ERROR(BSL_LS_SOC_COMMON, 2121 (BSL_META_U(unit, 2122 "soc_reg_set: " 2123 "Use soc_reg_above_64_set \n"))); 2124 2125 return SOC_E_FAIL; 2126 } 2127 2128 /* if reloading, don't write to register */ 2129 if (SOC_IS_RELOADING(unit)) 2130 { 2131 return SOC_E_NONE; 2132 } 2133 2134 #ifdef CRASH_RECOVERY_SUPPORT 2135 2136 /* Use crash recovery defined callback for access*/ 2137 if (SOC_IS_DONE_INIT(unit)) 2138 { 2139 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 2140 { 2141 if(Hw_Log_List[unit].Access_cb.soc_reg_set) 2142 { 2143 return Hw_Log_List[unit].Access_cb.soc_reg_set(unit, reg, port, index, data); 2144 } 2145 } 2146 } 2147 2148 #endif /* CRASH_RECOVERY_SUPPORT */ 2149 2150 /* Use user defined callback for access */ 2151 if(SOC_INFO(unit).reg_access.reg64_set) { 2152 return SOC_INFO(unit).reg_access.reg64_set(unit, reg, port, index, data); 2153 } 2154 2155 #ifdef CANCUN_SUPPORT 2156 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 2157 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 2158 soc_cancun_cch_reg_set(unit, reg, index, data); 2159 2160 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 2161 return(soc_cancun_pseudo_reg_set(unit, reg, data)); 2162 } 2163 } 2164 #endif 2165 2166 #ifdef DNX_TEST_CHIPS_SUPPORT 2167 if (SOC_IS_DNX_TEST_DEVICE(unit) 2168 #if defined(PLISIM) 2169 && !SAL_BOOT_PLISIM 2170 #endif 2171 ) { 2172 return soc_dnxtestchip_reg_set(unit, reg, port, data); 2173 } 2174 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2175 rv = soc_reg_xaddr_get(unit, reg, port, index, 2176 SOC_REG_ADDR_OPTION_WRITE, &access_info); 2177 if (rv != SOC_E_NONE) { 2178 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2179 "soc_reg_set: failed to get register address"))); 2180 return rv; 2181 } 2182 addr = access_info.offset; 2183 block = access_info.blk_list[0]; 2184 if (SOC_REG_IS_64(unit, reg)) { 2185 soc_port_t _port; 2186 soc_block_types_t regblktype = SOC_REG_INFO(unit, reg).block; 2187 int blk, bindex; 2188 2189 #if defined(BCM_XGS_SUPPORT) 2190 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2191 (void)soc_ser_reg_cache_set(unit, reg, port, index, data); 2192 } 2193 #endif /* BCM_XGS_SUPPORT */ 2194 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2195 return soc_reg_write(unit, reg, addr, data); 2196 } 2197 if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT) 2198 #ifdef BCM_SAND_SUPPORT 2199 && !SOC_IS_SAND(unit) 2200 #endif /* BCM_SAND_SUPPORT */ 2201 #ifdef BCM_BIGMAC_SUPPORT 2202 && iterative_op_required(reg) 2203 #endif /* BCM_BIGMAC_SUPPORT */ 2204 ) { 2205 PBMP_HYPLITE_ITER(unit, _port) { 2206 blk = SOC_PORT_BLOCK(unit, _port); 2207 bindex = SOC_PORT_BINDEX(unit, _port); 2208 if ((SOC_BLOCK2SCH(unit, blk) == block) && (bindex == pindex)) { 2209 break; 2210 } 2211 } 2212 if (!IS_HYPLITE_PORT(unit, port)) { 2213 return _soc_reg64_set(unit, block, access_info.acc_type, addr, data); 2214 } 2215 #ifdef BCM_BIGMAC_SUPPORT 2216 else { 2217 return soc_reg64_set_iterative(unit, block, access_info.acc_type, addr, 2218 port, data); 2219 } 2220 #endif /* BCM_BIGMAC_SUPPORT */ 2221 } else { 2222 for (block = 0; block < access_info.num_blks && rv == SOC_E_NONE; ++block) { 2223 rv = _soc_reg64_set(unit, access_info.blk_list[block], access_info.acc_type, addr, data); 2224 } 2225 } 2226 } else { 2227 uint32 data32; 2228 if (COMPILER_64_HI(data)) { 2229 LOG_WARN(BSL_LS_SOC_COMMON, 2230 (BSL_META_U(unit, 2231 "soc_reg_set: WARNING: " 2232 "write to 32-bit reg %s with hi order data, 0x%x\n"), 2233 SOC_REG_NAME(unit, reg), 2234 COMPILER_64_HI(data))); 2235 } 2236 data32 = COMPILER_64_LO(data); 2237 #if defined(BCM_XGS_SUPPORT) 2238 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2239 (void)soc_ser_reg32_cache_set(unit, reg, port, index, data32); 2240 } 2241 #endif /* BCM_XGS_SUPPORT */ 2242 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2243 return soc_reg32_write(unit, addr, data32); 2244 } 2245 for (block = 0; block < access_info.num_blks && rv == SOC_E_NONE; ++block) { 2246 rv = _soc_reg32_set(unit, access_info.blk_list[block], access_info.acc_type, addr, data32); 2247 } 2248 } 2249 2250 if (rv != SOC_E_NONE) { 2251 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2252 "soc_reg_set failed for %s\n"), SOC_REG_NAME(unit, reg))); 2253 } 2254 return rv; 2255 } 2256 2257 /* Write to h/w - do not update reg cache */ 2258 int 2259 soc_reg_set_nocache(int unit, soc_reg_t reg, int port, int index, uint64 data) 2260 { 2261 uint32 addr; 2262 int block, rv; 2263 int pindex = port; 2264 soc_reg_access_info_t access_info; 2265 if (!SOC_REG_IS_VALID(unit, reg)) { 2266 return SOC_E_PARAM; 2267 } 2268 2269 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, TRUE)); 2270 2271 if (SOC_REG_IS_ABOVE_64(unit, reg)) { 2272 LOG_ERROR(BSL_LS_SOC_COMMON, 2273 (BSL_META_U(unit, 2274 "soc_reg_set: " 2275 "Use soc_reg_above_64_set \n"))); 2276 2277 return SOC_E_FAIL; 2278 } 2279 2280 /* if reloading, don't write to register */ 2281 if (SOC_IS_RELOADING(unit)) 2282 { 2283 return SOC_E_NONE; 2284 } 2285 2286 #ifdef CRASH_RECOVERY_SUPPORT 2287 /* Use crash recovery defined callback for access*/ 2288 if (SOC_IS_DONE_INIT(unit)) 2289 { 2290 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 2291 { 2292 if(Hw_Log_List[unit].Access_cb.soc_reg_set_nocache) 2293 { 2294 return Hw_Log_List[unit].Access_cb.soc_reg_set_nocache(unit, reg, port, index, data); 2295 } 2296 } 2297 } 2298 #endif /* CRASH_RECOVERY_SUPPORT */ 2299 2300 #ifdef CANCUN_SUPPORT 2301 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 2302 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 2303 SOC_IF_ERROR_RETURN(soc_cancun_cch_reg_set(unit, reg, index, data)); 2304 2305 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 2306 return(soc_cancun_pseudo_reg_set(unit, reg, data)); 2307 } 2308 } 2309 #endif 2310 2311 rv = soc_reg_xaddr_get(unit, reg, port, index, 2312 SOC_REG_ADDR_OPTION_WRITE, &access_info); 2313 if (rv != SOC_E_NONE) { 2314 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2315 "soc_reg_set_nocache: failed to get register address"))); 2316 return rv; 2317 } 2318 addr = access_info.offset; 2319 block = access_info.blk_list[0]; 2320 2321 if (SOC_REG_IS_64(unit, reg)) { 2322 soc_port_t _port; 2323 soc_block_types_t regblktype = SOC_REG_INFO(unit, reg).block; 2324 int blk, bindex; 2325 2326 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2327 return soc_reg_write(unit, reg, addr, data); 2328 } 2329 if (SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_PORT) 2330 #ifdef BCM_SAND_SUPPORT 2331 && !SOC_IS_SAND(unit) 2332 #endif /* BCM_SAND_SUPPORT */ 2333 #ifdef BCM_BIGMAC_SUPPORT 2334 && iterative_op_required(reg) 2335 #endif /* BCM_BIGMAC_SUPPORT */ 2336 ) { 2337 PBMP_HYPLITE_ITER(unit, _port) { 2338 blk = SOC_PORT_BLOCK(unit, _port); 2339 bindex = SOC_PORT_BINDEX(unit, _port); 2340 if ((SOC_BLOCK2SCH(unit, blk) == block) && (bindex == pindex)) { 2341 break; 2342 } 2343 } 2344 if (!IS_HYPLITE_PORT(unit, port)) { 2345 return _soc_reg64_set(unit, block, access_info.acc_type, addr, data); 2346 } 2347 #ifdef BCM_BIGMAC_SUPPORT 2348 else { 2349 return soc_reg64_set_iterative(unit, block, access_info.acc_type, addr, 2350 port, data); 2351 } 2352 #endif /* BCM_BIGMAC_SUPPORT */ 2353 } else { 2354 for (block = 0; block < access_info.num_blks && rv == SOC_E_NONE; ++block) { 2355 rv = _soc_reg64_set(unit, access_info.blk_list[block], access_info.acc_type, addr, data); 2356 } 2357 } 2358 } else { 2359 uint32 data32; 2360 if (COMPILER_64_HI(data)) { 2361 LOG_WARN(BSL_LS_SOC_COMMON, 2362 (BSL_META_U(unit, 2363 "soc_reg_set: WARNING: " 2364 "write to 32-bit reg %s with hi order data, 0x%x\n"), 2365 SOC_REG_NAME(unit, reg), 2366 COMPILER_64_HI(data))); 2367 } 2368 data32 = COMPILER_64_LO(data); 2369 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2370 return soc_reg32_write(unit, addr, data32); 2371 } 2372 for (block = 0; block < access_info.num_blks && rv == SOC_E_NONE; ++block) { 2373 rv = _soc_reg32_set(unit, access_info.blk_list[block], access_info.acc_type, addr, data32); 2374 } 2375 } 2376 2377 return rv; 2378 } 2379 2380 /* 2381 * Write an internal SOC register through S-Channel messaging buffer. 2382 * Handle register at any size 2383 */ 2384 2385 int 2386 soc_reg_above_64_set(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t data) 2387 { 2388 uint32 addr; 2389 int i, rv, reg_size; 2390 uint64 data64; 2391 soc_reg_access_info_t access_info; 2392 2393 /* if reloading, don't write to register */ 2394 if (SOC_IS_RELOADING(unit)) 2395 { 2396 return SOC_E_NONE; 2397 } 2398 2399 if (!SOC_REG_IS_VALID(unit, reg)) { 2400 return SOC_E_PARAM; 2401 } 2402 2403 /* Use crash recovery defined callback for access*/ 2404 #ifdef CRASH_RECOVERY_SUPPORT 2405 2406 if (SOC_IS_DONE_INIT(unit)) 2407 { 2408 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 2409 { 2410 if(Hw_Log_List[unit].Access_cb.reg_above64_set) 2411 { 2412 return Hw_Log_List[unit].Access_cb.reg_above64_set(unit, reg, port, index, data); 2413 } 2414 } 2415 } 2416 2417 #endif /* CRASH_RECOVERY_SUPPORT */ 2418 2419 /* Use user defined callback for access */ 2420 if(SOC_INFO(unit).reg_access.reg_above64_set) { 2421 return SOC_INFO(unit).reg_access.reg_above64_set(unit, reg, port, index, data); 2422 } 2423 2424 #ifdef DNX_TEST_CHIPS_SUPPORT 2425 if (SOC_IS_DNX_TEST_DEVICE(unit) 2426 #if defined(PLISIM) 2427 && !SAL_BOOT_PLISIM 2428 #endif 2429 ) { 2430 return soc_dnxtestchip_reg_above_64_set(unit, reg, port, data); 2431 } 2432 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2433 2434 if (SOC_REG_IS_ABOVE_64(unit, reg)) 2435 { 2436 reg_size = SOC_REG_ABOVE_64_INFO(unit, reg).size; 2437 rv = soc_reg_xaddr_get(unit, reg, port, index, 2438 SOC_REG_ADDR_OPTION_WRITE, &access_info); 2439 if (rv != SOC_E_NONE) { 2440 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2441 "soc_reg64_set: failed to get register address"))); 2442 return rv; 2443 } 2444 addr = access_info.offset; 2445 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2446 access_info.blk_list[0] = ((addr >> SOC_BLOCK_BP) & 0xf) | (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 2447 access_info.num_blks = 1; 2448 } 2449 2450 for (i = 0; i < access_info.num_blks && rv == SOC_E_NONE; ++i) { 2451 #ifdef BROADCOM_DEBUG 2452 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 2453 _soc_reg_above_64_debug(unit, "set", access_info.blk_list[i], addr, data); 2454 } 2455 #endif /* BROADCOM_DEBUG */ 2456 2457 rv = soc_direct_reg_set(unit, access_info.blk_list[i], addr, reg_size, data); 2458 } 2459 if (rv != SOC_E_NONE) { 2460 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2461 "soc_reg_above_64_set failed for %s\n"), SOC_REG_NAME(unit, reg))); 2462 } 2463 return rv; 2464 } 2465 else if (SOC_REG_IS_64(unit, reg)) { 2466 COMPILER_64_SET(data64, data[1], data[0]); 2467 return soc_reg_set(unit, reg, port, index, data64); 2468 } 2469 else { 2470 COMPILER_64_SET(data64, 0, data[0]); 2471 return soc_reg_set(unit, reg, port, index, data64); 2472 } 2473 } 2474 2475 /* 2476 * Write an internal SOC register through S-Channel messaging buffer. 2477 */ 2478 2479 int 2480 soc_reg32_write(int unit, 2481 uint32 addr, 2482 uint32 data) 2483 { 2484 schan_msg_t schan_msg; 2485 int allow_intr=0; 2486 int dst_blk, src_blk, data_byte_len; 2487 #ifdef BCM_CMICM_SUPPORT 2488 int cmc = SOC_PCI_CMC(unit); 2489 #endif 2490 2491 #ifdef BROADCOM_DEBUG 2492 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 2493 _soc_reg_debug(unit, 32, "write", addr, 0, data); 2494 } 2495 #endif /* BROADCOM_DEBUG */ 2496 _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_WRITE, 0, data); 2497 2498 #ifdef DNX_TEST_CHIPS_SUPPORT 2499 if (SOC_IS_DNX_TEST_DEVICE(unit) 2500 #if defined(PLISIM) 2501 && !SAL_BOOT_PLISIM 2502 #endif 2503 ) { 2504 return soc_dnxtestchip_reg32_write(unit, addr, data); 2505 } 2506 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2507 2508 #ifdef BCM_CMICM_SUPPORT 2509 if(soc_feature(unit, soc_feature_cmicm) && 2510 (NULL != SOC_CONTROL(unit)->fschanMutex)) { 2511 FSCHAN_LOCK(unit); 2512 soc_pci_write(unit, CMIC_CMCx_FSCHAN_ADDRESS_OFFSET(cmc), addr); 2513 soc_pci_write(unit, CMIC_CMCx_FSCHAN_DATA32_OFFSET(cmc), data); 2514 fschan_wait_idle(unit); 2515 FSCHAN_UNLOCK(unit); 2516 return SOC_E_NONE; 2517 } 2518 #endif /* CMICM */ 2519 /* 2520 * Setup S-Channel command packet 2521 * 2522 * NOTE: the datalen field matters only for the Write Memory and 2523 * Write Register commands, where it is used only by the CMIC to 2524 * determine how much data to send, and is in units of bytes. 2525 */ 2526 2527 schan_msg_clear(&schan_msg); 2528 2529 dst_blk = ((addr >> SOC_BLOCK_BP) & 0xf) | 2530 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 2531 data_byte_len = SOC_IS_XGS12_FABRIC(unit) ? 8 : 4; 2532 { 2533 src_blk = SOC_IS_SHADOW(unit) ? 2534 0 : SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 2535 } 2536 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_REGISTER_CMD_MSG, 2537 dst_blk, src_blk, 0, data_byte_len, 0, 0); 2538 2539 schan_msg.writecmd.address = addr; 2540 schan_msg.writecmd.data[0] = data; 2541 2542 if(SOC_IS_SAND(unit)) { 2543 allow_intr = 1; 2544 } 2545 2546 /* Write header word + address + data DWORD */ 2547 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 2548 2549 2550 2551 return soc_schan_op(unit, &schan_msg, 3, 0, allow_intr); 2552 2553 } 2554 2555 /* 2556 * Write an internal SOC register through S-Channel messaging buffer. 2557 */ 2558 2559 int 2560 soc_reg32_set(int unit, soc_reg_t reg, int port, int index, uint32 data) 2561 { 2562 uint32 addr; 2563 int i, rv = 0; 2564 soc_reg_access_info_t access_info; 2565 #ifdef BCM_TOMAHAWK3_SUPPORT 2566 int j=0, acc=0; 2567 uint16 dev_id; 2568 uint8 rev_id; 2569 #endif 2570 /* if reloading, don't write to register */ 2571 if (SOC_IS_RELOADING(unit)) 2572 { 2573 return SOC_E_NONE; 2574 } 2575 #ifdef BCM_TOMAHAWK3_SUPPORT 2576 soc_cm_get_id (unit, &dev_id, &rev_id); 2577 #endif 2578 2579 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, TRUE)); 2580 2581 #ifdef CRASH_RECOVERY_SUPPORT 2582 /* Use crash recovery defined callback for access*/ 2583 2584 if (SOC_IS_DONE_INIT(unit)) 2585 { 2586 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 2587 { 2588 if(Hw_Log_List[unit].Access_cb.reg32_set) 2589 { 2590 return Hw_Log_List[unit].Access_cb.reg32_set(unit, reg, port, index, data); 2591 } 2592 } 2593 } 2594 #endif /* CRASH_RECOVERY_SUPPORT */ 2595 2596 2597 /* Use user defined callback for access */ 2598 if(SOC_INFO(unit).reg_access.reg32_set) { 2599 return SOC_INFO(unit).reg_access.reg32_set(unit, reg, port, index, data); 2600 } 2601 2602 #ifdef CANCUN_SUPPORT 2603 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 2604 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 2605 uint64 data64; 2606 COMPILER_64_SET(data64, 0, data); 2607 SOC_IF_ERROR_RETURN( 2608 soc_cancun_cch_reg_set(unit, reg, index, data64)); 2609 2610 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 2611 return(soc_cancun_pseudo_reg_set(unit, reg, data64)); 2612 } 2613 } 2614 #endif 2615 2616 #ifdef DNX_TEST_CHIPS_SUPPORT 2617 if (SOC_IS_DNX_TEST_DEVICE(unit) 2618 #if defined(PLISIM) 2619 && !SAL_BOOT_PLISIM 2620 #endif 2621 ) { 2622 return soc_dnxtestchip_reg32_set(unit, reg, port, data); 2623 } 2624 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2625 2626 rv = soc_reg_xaddr_get(unit, reg, port, index, 2627 SOC_REG_ADDR_OPTION_WRITE, &access_info); 2628 if (rv != SOC_E_NONE) { 2629 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2630 "soc_reg32_set: failed to get register address"))); 2631 return rv; 2632 } 2633 addr = access_info.offset; 2634 if (SOC_REG_IS_ABOVE_32(unit, reg)) { 2635 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 2636 #if !defined(SOC_NO_NAMES) 2637 LOG_CLI((BSL_META_U(unit, 2638 "reg %s is not 32 bit\n"), soc_reg_name[reg])); 2639 #endif 2640 #endif 2641 2642 } 2643 assert(!SOC_REG_IS_ABOVE_32(unit, reg)); 2644 #if defined(BCM_XGS_SUPPORT) 2645 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2646 (void)soc_ser_reg32_cache_set(unit, reg, port, index, data); 2647 } 2648 #endif /* BCM_XGS_SUPPORT */ 2649 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2650 return soc_reg32_write(unit, addr, data); 2651 } 2652 2653 for (i = 0; i < access_info.num_blks && rv == SOC_E_NONE; ++i) { 2654 #ifdef BCM_TOMAHAWK3_SUPPORT 2655 /* For 56983 Lower die SKU, we make sure DATA_SPLIT and DUPL writes get 2656 converted into 4 unique writes since the OTP settings are not 2657 available 2658 */ 2659 if ((access_info.acc_type == 9 || access_info.acc_type == 14) && 2660 (dev_id == BCM56983_DEVICE_ID)) { 2661 for (j = 0; j < 4; j++) { 2662 switch(j) { 2663 case 0 : acc = 0; 2664 break; 2665 case 1 : acc = 1; 2666 break; 2667 case 2 : acc = 6; 2668 break; 2669 case 3 : acc = 7; 2670 break; 2671 } 2672 rv = _soc_reg32_set(unit, access_info.blk_list[i], acc, addr, data); 2673 } 2674 } else if (access_info.acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) { 2675 acc = 0; 2676 rv = _soc_reg32_set(unit, access_info.blk_list[i], acc, addr, data); 2677 } else if (access_info.acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) { 2678 for (j = 0; j < 2; j++) { 2679 switch(j) { 2680 case 0 : acc = 0; 2681 break; 2682 case 1 : acc = 6; 2683 break; 2684 } 2685 rv = _soc_reg32_set(unit, access_info.blk_list[i], acc, addr, data); 2686 } 2687 } else 2688 #endif 2689 { 2690 rv = _soc_reg32_set(unit, access_info.blk_list[i], access_info.acc_type, addr, data); 2691 } 2692 if (rv != SOC_E_NONE) { 2693 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2694 "soc_reg32_set failed for %s failed\n"), SOC_REG_NAME(unit, reg))); 2695 } 2696 } 2697 return rv; 2698 } 2699 2700 /* 2701 * Write an internal 64-bit SOC register through S-Channel messaging buffer. 2702 */ 2703 int 2704 soc_reg64_write(int unit, 2705 uint32 addr, 2706 uint64 data) 2707 { 2708 schan_msg_t schan_msg; 2709 int allow_intr=0; 2710 int dst_blk, src_blk; 2711 #ifdef BCM_CMICM_SUPPORT 2712 int cmc = SOC_PCI_CMC(unit); 2713 #endif 2714 2715 #ifdef DNX_TEST_CHIPS_SUPPORT 2716 if (SOC_IS_DNX_TEST_DEVICE(unit) 2717 #if defined(PLISIM) 2718 && !SAL_BOOT_PLISIM 2719 #endif 2720 ) { 2721 return soc_dnxtestchip_reg64_write(unit, addr, data); 2722 } 2723 #endif /* DNX_TEST_CHIPS_SUPPORT */ 2724 2725 #ifdef BCM_CMICM_SUPPORT 2726 if(soc_feature(unit, soc_feature_cmicm) && 2727 (NULL != SOC_CONTROL(unit)->fschanMutex)) { 2728 FSCHAN_LOCK(unit); 2729 soc_pci_write(unit, CMIC_CMCx_FSCHAN_ADDRESS_OFFSET(cmc), addr); 2730 /* coverity[result_independent_of_operands] */ 2731 SOC_IF_ERROR_RETURN(soc_pci_write(unit, 2732 CMIC_CMCx_FSCHAN_DATA64_HI_OFFSET(cmc), 2733 COMPILER_64_HI(data))); 2734 SOC_IF_ERROR_RETURN(soc_pci_write(unit, 2735 CMIC_CMCx_FSCHAN_DATA64_LO_OFFSET(cmc), 2736 COMPILER_64_LO(data))); 2737 2738 fschan_wait_idle(unit); 2739 FSCHAN_UNLOCK(unit); 2740 return SOC_E_NONE; 2741 } 2742 #endif /* CMICM */ 2743 /* 2744 * Setup S-Channel command packet 2745 * 2746 * NOTE: the datalen field matters only for the Write Memory and 2747 * Write Register commands, where it is used only by the CMIC to 2748 * determine how much data to send, and is in units of bytes. 2749 */ 2750 2751 schan_msg_clear(&schan_msg); 2752 2753 dst_blk = ((addr >> SOC_BLOCK_BP) & 0xf) | 2754 (((addr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 2755 { 2756 src_blk = SOC_IS_SHADOW(unit) ? 2757 0 : SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 2758 } 2759 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_REGISTER_CMD_MSG, 2760 dst_blk, src_blk, 0, 8, 0, 0); 2761 2762 schan_msg.writecmd.address = addr; 2763 schan_msg.writecmd.data[0] = COMPILER_64_LO(data); 2764 schan_msg.writecmd.data[1] = COMPILER_64_HI(data); 2765 2766 #ifdef BROADCOM_DEBUG 2767 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 2768 _soc_reg_debug(unit, 64, "write", addr, 2769 schan_msg.writecmd.data[1], 2770 schan_msg.writecmd.data[0]); 2771 } 2772 #endif /* BROADCOM_DEBUG */ 2773 _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_WRITE, 2774 schan_msg.writecmd.data[1],schan_msg.writecmd.data[0]); 2775 2776 if(SOC_IS_SAND(unit)) { 2777 allow_intr = 1; 2778 } 2779 2780 /* Write header word + address + 2*data DWORD */ 2781 /* Note: The hardware does not send WRITE_REGISTER_ACK_MSG. */ 2782 2783 2784 2785 return soc_schan_op(unit, &schan_msg, 4, 0, allow_intr); 2786 2787 } 2788 2789 /* 2790 * Write an internal 64-bit SOC register through S-Channel messaging buffer. 2791 */ 2792 int 2793 soc_reg64_set(int unit, soc_reg_t reg, int port, int index, uint64 data) 2794 { 2795 uint32 addr; 2796 int i, rv; 2797 soc_reg_access_info_t access_info; 2798 #ifdef CRASH_RECOVERY_SUPPORT 2799 2800 /* Use crash recovery defined callback for access*/ 2801 if (SOC_IS_DONE_INIT(unit)) 2802 { 2803 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 2804 { 2805 if(Hw_Log_List[unit].Access_cb.reg64_set) 2806 { 2807 return Hw_Log_List[unit].Access_cb.reg64_set(unit, reg, port, index, data); 2808 } 2809 } 2810 } 2811 2812 #endif /* CRASH_RECOVERY_SUPPORT */ 2813 2814 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_REG, reg, TRUE)); 2815 2816 #ifdef CANCUN_SUPPORT 2817 if (SOC_REG_IS_CCH(unit, reg) && !(soc_property_get(unit, 2818 "skip_cancun_cch_reg_check", 0) ? TRUE : FALSE)) { 2819 soc_cancun_cch_reg_set(unit, reg, index, data); 2820 2821 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 2822 return(soc_cancun_pseudo_reg_set(unit, reg, data)); 2823 } 2824 } 2825 #endif 2826 2827 /* Use user defined callback for access */ 2828 if(SOC_INFO(unit).reg_access.reg64_set) { 2829 return SOC_INFO(unit).reg_access.reg64_set(unit, reg, port, index, data); 2830 } 2831 2832 rv = soc_reg_xaddr_get(unit, reg, port, index, 2833 SOC_REG_ADDR_OPTION_WRITE, &access_info); 2834 if (rv != SOC_E_NONE) { 2835 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2836 "soc_reg64_set: failed to get register address"))); 2837 return rv; 2838 } 2839 addr = access_info.offset; 2840 assert(SOC_REG_IS_64(unit, reg)); 2841 #if defined(BCM_XGS_SUPPORT) 2842 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2843 (void)soc_ser_reg_cache_set(unit, reg, port, index, data); 2844 } 2845 #endif /* BCM_XGS_SUPPORT */ 2846 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2847 return soc_reg64_write(unit, addr, data); 2848 } 2849 for (i = 0; i < access_info.num_blks && rv == SOC_E_NONE; ++i) { 2850 rv = _soc_reg64_set(unit, access_info.blk_list[i], access_info.acc_type, addr, data); 2851 } 2852 return rv; 2853 } 2854 2855 /* 2856 * Write an internal SOC register through S-Channel messaging buffer 2857 * with Raw Port Number. 2858 */ 2859 int 2860 soc_reg_rawport_set(int unit, soc_reg_t reg, int port, int index, uint64 data) 2861 { 2862 uint32 addr; 2863 int i, rv; 2864 soc_reg_access_info_t access_info; 2865 2866 if (!SOC_REG_IS_VALID(unit, reg)) { 2867 return SOC_E_PARAM; 2868 } 2869 2870 if ((REG_PORT_ANY != port) && 2871 (port & (SOC_REG_ADDR_INSTANCE_MASK | SOC_REG_ADDR_BLOCK_ID_MASK | 2872 SOC_REG_ADDR_SCHAN_ID_MASK | SOC_REG_ADDR_PHY_ACC_MASK))) { 2873 LOG_ERROR(BSL_LS_SOC_COMMON, 2874 (BSL_META_U(unit, 2875 "This function is only for Raw Port Numbers \n"))); 2876 return SOC_E_FAIL; 2877 } 2878 2879 #ifdef CRASH_RECOVERY_SUPPORT 2880 /* Don't handle Special Accesses */ 2881 if((SOC_INFO(unit).reg_access.reg64_set) || /* User defined */ 2882 (SOC_REG_IS_ABOVE_64(unit, reg)) || 2883 (SOC_IS_DONE_INIT(unit) && BCM_UNIT_DO_HW_READ_WRITE(unit) && 2884 Hw_Log_List[unit].Access_cb.soc_reg_set)) { 2885 LOG_ERROR(BSL_LS_SOC_COMMON, 2886 (BSL_META_U(unit, 2887 "Use soc_reg_set \n"))); 2888 return SOC_E_FAIL; 2889 } 2890 #else 2891 /* Don't handle Special Accesses */ 2892 if((SOC_INFO(unit).reg_access.reg64_set) || /* User defined */ 2893 (SOC_REG_IS_ABOVE_64(unit, reg))) { 2894 LOG_ERROR(BSL_LS_SOC_COMMON, 2895 (BSL_META_U(unit, 2896 "Use soc_reg_set \n"))); 2897 return SOC_E_FAIL; 2898 } 2899 #endif /* CRASH_RECOVERY_SUPPORT */ 2900 2901 rv = soc_reg_xaddr_get(unit, reg, port, index, SOC_REG_ADDR_OPTION_WRITE | 2902 SOC_REG_ADDR_OPTION_PRESERVE_PORT, &access_info); 2903 if (rv != SOC_E_NONE) { 2904 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2905 "soc_reg_rawport_set: failed to get register address"))); 2906 return rv; 2907 } 2908 addr = access_info.offset; 2909 if (SOC_REG_IS_64(unit, reg)) { 2910 #if defined(BCM_XGS_SUPPORT) 2911 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2912 (void)soc_ser_reg_cache_set(unit, reg, port, index, data); 2913 } 2914 #endif /* BCM_XGS_SUPPORT */ 2915 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2916 return soc_reg_write(unit, reg, addr, data); 2917 } else { 2918 for (i = 0; i < access_info.num_blks && rv == SOC_E_NONE; ++i) { 2919 rv = _soc_reg64_set(unit, access_info.blk_list[i], access_info.acc_type, addr, data); 2920 } 2921 } 2922 } else { 2923 uint32 data32; 2924 if (COMPILER_64_HI(data)) { 2925 LOG_WARN(BSL_LS_SOC_COMMON, 2926 (BSL_META_U(unit, 2927 "WARNING: " 2928 "write to 32-bit reg %s with hi order data, 0x%x\n"), 2929 SOC_REG_NAME(unit, reg), 2930 COMPILER_64_HI(data))); 2931 } 2932 data32 = COMPILER_64_LO(data); 2933 #if defined(BCM_XGS_SUPPORT) 2934 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2935 (void)soc_ser_reg32_cache_set(unit, reg, port, index, data32); 2936 } 2937 #endif /* BCM_XGS_SUPPORT */ 2938 2939 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 2940 return soc_reg32_write(unit, addr, data32); 2941 } else { 2942 for (i = 0; i < access_info.num_blks && rv == SOC_E_NONE; ++i) { 2943 rv = _soc_reg32_set(unit, access_info.blk_list[i], access_info.acc_type, addr, data32); 2944 } 2945 } 2946 } 2947 return rv; 2948 } 2949 2950 int 2951 soc_reg32_rawport_set(int unit, soc_reg_t reg, int port, int index, uint32 data) 2952 { 2953 uint64 d64; 2954 2955 COMPILER_64_SET(d64, 0, data); 2956 return soc_reg_rawport_set(unit, reg, port, index, d64); 2957 } 2958 2959 /* 2960 * Write internal register for a group of ports. 2961 * The specified register must be a port reg (type soc_portreg). 2962 */ 2963 2964 int 2965 soc_reg_write_ports(int unit, 2966 soc_reg_t reg, 2967 pbmp_t pbmp, 2968 uint32 value) 2969 { 2970 soc_port_t port; 2971 soc_block_t ptype; 2972 soc_block_types_t rtype; 2973 2974 /* assert(reg is a port register) */ 2975 if (!SOC_REG_IS_VALID(unit, reg) || 2976 SOC_REG_INFO(unit, reg).regtype != soc_portreg) { 2977 return SOC_E_UNAVAIL; 2978 } 2979 2980 rtype = SOC_REG_INFO(unit, reg).block; 2981 2982 /* 2983 * each port block type must match one of the register block types 2984 * or the register block type can be the MMU 2985 */ 2986 PBMP_ITER(pbmp, port) { 2987 ptype = SOC_PORT_TYPE(unit, port); 2988 if (SOC_BLOCK_IN_LIST(rtype, ptype) || SOC_BLOCK_IN_LIST(rtype, SOC_BLK_MMU)) { 2989 if (soc_feature(unit, soc_feature_new_sbus_format)) { 2990 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 2991 port, 0, value)); 2992 } else { 2993 #if defined(BCM_XGS_SUPPORT) 2994 if (soc_feature(unit, soc_feature_regs_as_mem)) { 2995 (void)soc_ser_reg32_cache_set(unit, reg, port, 0, value); 2996 } 2997 #endif /* BCM_XGS_SUPPORT */ 2998 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, 2999 soc_reg_addr(unit, reg, port, 0), value)); 3000 } 3001 } 3002 } 3003 return SOC_E_NONE; 3004 } 3005 3006 /* 3007 * Write internal register for a block or group of blocks. 3008 * The specified register must be a generic reg (type soc_genreg). 3009 * 3010 * This routine will write to all possible blocks for the given 3011 * register. 3012 */ 3013 int 3014 soc_reg64_write_all_blocks(int unit, 3015 soc_reg_t reg, 3016 uint64 value) 3017 { 3018 int blk, port; 3019 soc_block_types_t rtype; 3020 3021 /* assert(reg is not a port or cos register) */ 3022 if (!SOC_REG_IS_VALID(unit, reg) || 3023 SOC_REG_INFO(unit, reg).regtype != soc_genreg) { 3024 return SOC_E_UNAVAIL; 3025 } 3026 3027 rtype = SOC_REG_INFO(unit, reg).block; 3028 3029 SOC_BLOCKS_ITER(unit, blk, rtype) { 3030 port = SOC_BLOCK_PORT(unit, blk); 3031 #if defined(BCM_XGS_SUPPORT) 3032 if (soc_feature(unit, soc_feature_regs_as_mem)) { 3033 (void)soc_ser_reg_cache_set(unit, reg, port, 0, value); 3034 } 3035 #endif /* BCM_XGS_SUPPORT */ 3036 if (soc_feature(unit, soc_feature_new_sbus_format)) { 3037 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, value)); 3038 } else { 3039 SOC_IF_ERROR_RETURN(soc_reg_write(unit, reg, 3040 soc_reg_addr(unit, reg, port, 0), value)); 3041 } 3042 } 3043 return SOC_E_NONE; 3044 } 3045 3046 /* 3047 * Write internal register for a block or group of blocks. 3048 * The specified register must be a generic reg (type soc_genreg). 3049 * 3050 * This routine will write to all possible blocks for the given 3051 * register. 3052 */ 3053 int 3054 soc_reg_write_all_blocks(int unit, 3055 soc_reg_t reg, 3056 uint32 value) 3057 { 3058 uint64 val64; 3059 3060 if (!SOC_REG_IS_VALID(unit, reg)) { 3061 return SOC_E_PARAM; 3062 } 3063 3064 COMPILER_64_SET(val64, 0, value); 3065 return soc_reg64_write_all_blocks(unit, reg, val64); 3066 } 3067 3068 /* 3069 * Read a general register from any block that has a copy 3070 */ 3071 int 3072 soc_reg64_read_any_block(int unit, 3073 soc_reg_t reg, 3074 uint64 *datap) 3075 { 3076 int blk, port; 3077 soc_block_types_t rtype; 3078 #ifdef CRASH_RECOVERY_SUPPORT 3079 if (SOC_IS_DONE_INIT(unit)) 3080 { 3081 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 3082 { 3083 LOG_WARN(BSL_LS_SOC_COMMON, 3084 (BSL_META_U(unit, "soc_reg64_read_any_block: WARNING: " 3085 "HW Log feature in unexpected function!!!\n"))); 3086 } 3087 } 3088 #endif /* CRASH_RECOVERY_SUPPORT */ 3089 3090 /* assert(reg is not a port or cos register) */ 3091 if (!SOC_REG_IS_VALID(unit, reg) || 3092 SOC_REG_INFO(unit, reg).regtype != soc_genreg) { 3093 return SOC_E_UNAVAIL; 3094 } 3095 3096 rtype = SOC_REG_INFO(unit, reg).block; 3097 SOC_BLOCKS_ITER(unit, blk, rtype) { 3098 port = SOC_BLOCK_PORT(unit, blk); 3099 if (soc_feature(unit, soc_feature_new_sbus_format)) { 3100 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, datap)); 3101 } else { 3102 SOC_IF_ERROR_RETURN 3103 (soc_reg_read(unit, reg, soc_reg_addr(unit, reg, port, 0), 3104 datap)); 3105 } 3106 break; 3107 } 3108 return SOC_E_NONE; 3109 } 3110 3111 /* 3112 * Read a general register from any block that has a copy 3113 */ 3114 int 3115 soc_reg_read_any_block(int unit, 3116 soc_reg_t reg, 3117 uint32 *datap) 3118 { 3119 uint64 val64; 3120 3121 SOC_IF_ERROR_RETURN(soc_reg64_read_any_block(unit, reg, &val64)); 3122 COMPILER_64_TO_32_LO(*datap, val64); 3123 3124 return SOC_E_NONE; 3125 } 3126 3127 /**************************************************************** 3128 * Register field manipulation functions 3129 */ 3130 3131 /* Define a macro so the assertion printout is informative. */ 3132 #define REG_FIELD_IS_VALID finfop 3133 3134 /* 3135 * Function: soc_reg_field_length 3136 * Purpose: Return the length of a register field in bits. 3137 * Value is 0 if field is not found. 3138 * Returns: bits in field 3139 */ 3140 int 3141 soc_reg_field_length(int unit, soc_reg_t reg, soc_field_t field) 3142 { 3143 soc_field_info_t *finfop; 3144 3145 if (!SOC_REG_IS_VALID(unit, reg)) { 3146 return 0; 3147 } 3148 3149 SOC_FIND_FIELD(field, 3150 SOC_REG_INFO(unit, reg).fields, 3151 SOC_REG_INFO(unit, reg).nFields, 3152 finfop); 3153 if (finfop == NULL) { 3154 return 0; 3155 } 3156 return finfop->len; 3157 } 3158 3159 /* 3160 * Function: soc_reg_field_valid 3161 * Purpose: Determine if a field in a register is valid. 3162 * Returns: Returns TRUE if field is found. 3163 * Returns FALSE if field is not found. 3164 */ 3165 int 3166 soc_reg_field_valid(int unit, soc_reg_t reg, soc_field_t field) 3167 { 3168 soc_field_info_t *finfop; 3169 3170 if (!SOC_REG_IS_VALID(unit, reg)) { 3171 return FALSE; 3172 } 3173 3174 SOC_FIND_FIELD(field, 3175 SOC_REG_INFO(unit, reg).fields, 3176 SOC_REG_INFO(unit, reg).nFields, 3177 finfop); 3178 return (finfop != NULL); 3179 } 3180 3181 3182 /* 3183 * Function: soc_reg_field_get 3184 * Purpose: Get the value of a field from a register 3185 * Parameters: 3186 * Returns: Value of field 3187 */ 3188 uint32 3189 soc_reg_field_get(int unit, soc_reg_t reg, uint32 regval, soc_field_t field) 3190 { 3191 soc_field_info_t *finfop; 3192 uint32 val; 3193 3194 if (!SOC_REG_IS_VALID(unit, reg)) { 3195 #if !defined(SOC_NO_NAMES) 3196 LOG_CLI((BSL_META_U(unit, 3197 "reg %s is invalid\n"), soc_reg_name[reg])); 3198 #endif 3199 assert(SOC_REG_IS_VALID(unit, reg)); 3200 } 3201 3202 SOC_FIND_FIELD(field, 3203 SOC_REG_INFO(unit, reg).fields, 3204 SOC_REG_INFO(unit, reg).nFields, 3205 finfop); 3206 3207 if (finfop == NULL) { 3208 #if !defined(SOC_NO_NAMES) 3209 LOG_CLI((BSL_META_U(unit, 3210 "reg %s field %s is invalid\n"), 3211 soc_reg_name[reg], soc_fieldnames[field])); 3212 #endif 3213 assert(finfop); 3214 } 3215 3216 /* 3217 * COVERITY 3218 * 3219 * assert validates the input for NULL 3220 */ 3221 /* coverity[var_deref_op : FALSE] */ 3222 val = regval >> finfop->bp; 3223 if (finfop->len < 32) { 3224 return val & ((1 << finfop->len) - 1); 3225 } else { 3226 return val; 3227 } 3228 } 3229 3230 /* 3231 * Function: soc_ftmh_cfg_get 3232 * Purpose: Get the value of FTMH_LB_KEY_EXT_ENf, FTMH_STACKING_EXT_ENABLEf into the given int pointers 3233 */ 3234 int 3235 soc_ftmh_cfg_get(int unit, int * p_cfg_ftmh_lb_key_ext_en, int * p_cfg_ftmh_stacking_ext_enable) 3236 { 3237 uint32 3238 reg_val32; 3239 int 3240 rv = SOC_E_NONE; 3241 3242 rv = READ_ECI_GLOBALFr(unit, ®_val32); 3243 *p_cfg_ftmh_lb_key_ext_en = soc_reg_field_get(unit, ECI_GLOBALFr, reg_val32, FTMH_LB_KEY_EXT_ENf); 3244 *p_cfg_ftmh_stacking_ext_enable = soc_reg_field_get(unit, ECI_GLOBALFr, reg_val32, FTMH_STACKING_EXT_ENABLEf); 3245 3246 return rv; 3247 } 3248 3249 /* 3250 * Function: soc_reg64_field_get 3251 * Purpose: Get the value of a field from a 64-bit register 3252 * Parameters: 3253 * Returns: Value of field (64 bits) 3254 */ 3255 uint64 3256 soc_reg64_field_get(int unit, soc_reg_t reg, uint64 regval, soc_field_t field) 3257 { 3258 soc_field_info_t *finfop; 3259 uint64 mask; 3260 3261 if (!SOC_REG_IS_VALID(unit, reg)) { 3262 #if !defined(SOC_NO_NAMES) 3263 LOG_CLI((BSL_META_U(unit, 3264 "reg %s is invalid\n"), soc_reg_name[reg])); 3265 #endif 3266 assert(SOC_REG_IS_VALID(unit, reg)); 3267 } 3268 3269 SOC_FIND_FIELD(field, 3270 SOC_REG_INFO(unit, reg).fields, 3271 SOC_REG_INFO(unit, reg).nFields, 3272 finfop); 3273 if (finfop == NULL) { 3274 #if !defined(SOC_NO_NAMES) 3275 LOG_CLI((BSL_META_U(unit, 3276 "reg %s field %s is invalid\n"), 3277 soc_reg_name[reg], soc_fieldnames[field])); 3278 #endif 3279 assert(finfop); 3280 } 3281 3282 /* 3283 * COVERITY 3284 * 3285 * assert validates the input for NULL 3286 */ 3287 /* coverity[var_deref_op : FALSE] */ 3288 COMPILER_64_MASK_CREATE(mask, finfop->len, 0); 3289 COMPILER_64_SHR(regval, finfop->bp); 3290 COMPILER_64_AND(regval, mask); 3291 3292 return regval; 3293 } 3294 3295 /* 3296 * Function: soc_reg64_field32_get 3297 * Purpose: Get the value of a field from a 64-bit register 3298 * Parameters: 3299 * Returns: Value of field (32 bits) 3300 */ 3301 uint32 3302 soc_reg64_field32_get(int unit, soc_reg_t reg, uint64 regval, 3303 soc_field_t field) 3304 { 3305 soc_field_info_t *finfop; 3306 uint32 val32; 3307 3308 if (!SOC_REG_IS_VALID(unit, reg)) { 3309 #if !defined(SOC_NO_NAMES) 3310 LOG_CLI((BSL_META_U(unit, 3311 "reg %s is invalid\n"), soc_reg_name[reg])); 3312 #endif 3313 assert(SOC_REG_IS_VALID(unit, reg)); 3314 } 3315 3316 SOC_FIND_FIELD(field, 3317 SOC_REG_INFO(unit, reg).fields, 3318 SOC_REG_INFO(unit, reg).nFields, 3319 finfop); 3320 if (finfop == NULL) { 3321 #if !defined(SOC_NO_NAMES) 3322 LOG_CLI((BSL_META_U(unit, 3323 "reg %s field %s is invalid\n"), 3324 soc_reg_name[reg], soc_fieldnames[field])); 3325 #endif 3326 assert(finfop); 3327 } 3328 3329 /* 3330 * COVERITY 3331 * 3332 * assert validates the input for NULL 3333 */ 3334 /* coverity[var_deref_op : FALSE] */ 3335 COMPILER_64_SHR(regval, finfop->bp); 3336 COMPILER_64_TO_32_LO(val32, regval); 3337 if (finfop->len < 32) { 3338 return val32 & ((1 << finfop->len) - 1); 3339 } else { 3340 return val32; 3341 } 3342 } 3343 3344 /* 3345 * Function: soc_reg_above_64_field_get 3346 * Purpose: Get the value of a field from a register 3347 * Parameters: 3348 * Returns: Value of field 3349 */ 3350 void 3351 soc_reg_above_64_field_get(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3352 soc_field_t field, soc_reg_above_64_val_t field_val) 3353 { 3354 soc_field_info_t *finfop; 3355 3356 if (!SOC_REG_IS_VALID(unit, reg)) { 3357 #if !defined(SOC_NO_NAMES) 3358 LOG_CLI((BSL_META_U(unit, 3359 "reg %s is invalid\n"), soc_reg_name[reg])); 3360 #endif 3361 assert(SOC_REG_IS_VALID(unit, reg)); 3362 } 3363 3364 SOC_FIND_FIELD(field, 3365 SOC_REG_INFO(unit, reg).fields, 3366 SOC_REG_INFO(unit, reg).nFields, 3367 finfop); 3368 3369 if (finfop == NULL) { 3370 #if !defined(SOC_NO_NAMES) 3371 LOG_CLI((BSL_META_U(unit, 3372 "reg %s field %s is invalid\n"), 3373 soc_reg_name[reg], soc_fieldnames[field])); 3374 #endif 3375 assert(finfop); 3376 } 3377 3378 3379 SOC_REG_ABOVE_64_CLEAR(field_val); 3380 /* 3381 * COVERITY 3382 * 3383 * assert validates the input for NULL 3384 */ 3385 /* coverity[var_deref_op : FALSE] */ 3386 SHR_BITCOPY_RANGE(field_val, 0, regval, finfop->bp, finfop->len); 3387 3388 } 3389 /* 3390 * Function: soc_reg_above_64_field_read 3391 * Purpose: Read a register of any size, and get the value of a field sized up to any size. 3392 * Parameters: 3393 * Returns: Value of field (32 bits) 3394 */ 3395 int 3396 soc_reg_above_64_field_read(int unit, soc_reg_t reg, soc_port_t port, int index, soc_field_t field, soc_reg_above_64_val_t out_field_val) 3397 { 3398 int rc = SOC_E_NONE; 3399 soc_reg_above_64_val_t data; 3400 SOC_REG_ABOVE_64_CLEAR(data); 3401 rc = soc_reg_above_64_get(unit, reg, port, index, data); 3402 if (rc != SOC_E_NONE){ 3403 return rc; 3404 } 3405 soc_reg_above_64_field_get(unit, reg, data, field, out_field_val); 3406 return rc; 3407 } 3408 /* 3409 * Function: soc_reg_above_64_field32_get 3410 * Purpose: Get the value of a field sized up to 32 bit from a register of any size 3411 * Parameters: 3412 * Returns: Value of field (32 bits) 3413 */ 3414 uint32 3415 soc_reg_above_64_field32_get(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3416 soc_field_t field) 3417 { 3418 soc_field_info_t *finfop; 3419 uint32 field_val = 0; 3420 3421 if (!SOC_REG_IS_VALID(unit, reg)) { 3422 #if !defined(SOC_NO_NAMES) 3423 LOG_CLI((BSL_META_U(unit, 3424 "reg %s is invalid\n"), soc_reg_name[reg])); 3425 #endif 3426 assert(SOC_REG_IS_VALID(unit, reg)); 3427 } 3428 3429 SOC_FIND_FIELD(field, 3430 SOC_REG_INFO(unit, reg).fields, 3431 SOC_REG_INFO(unit, reg).nFields, 3432 finfop); 3433 3434 if (finfop == NULL) { 3435 #if !defined(SOC_NO_NAMES) 3436 LOG_CLI((BSL_META_U(unit, 3437 "reg %s field %s is invalid\n"), 3438 soc_reg_name[reg], soc_fieldnames[field])); 3439 #endif 3440 assert(finfop); 3441 } else if (finfop->len > 32) { 3442 #if !defined(SOC_NO_NAMES) 3443 LOG_CLI((BSL_META_U(unit, 3444 "reg %s field %s has a size of %u bits which is greater than 32\n"), 3445 soc_reg_name[reg], soc_fieldnames[field], (unsigned)finfop->len)); 3446 #endif 3447 assert(0); 3448 } else { 3449 3450 SHR_BITCOPY_RANGE(&field_val, 0, regval, finfop->bp, finfop->len); /* get the field value */ 3451 3452 } 3453 return field_val; 3454 } 3455 /* 3456 * Function: soc_reg_above_64_field32_read 3457 * Purpose: Read a register of any size, and get the value of a field sized up to 32 bit from it. 3458 * Parameters: 3459 * Returns: Value of field (32 bits) 3460 */ 3461 3462 int 3463 soc_reg_above_64_field32_read(int unit, soc_reg_t reg, soc_port_t port, int index, soc_field_t field, uint32* out_field_val) 3464 { 3465 int rc = SOC_E_NONE; 3466 soc_reg_above_64_val_t data; 3467 SOC_REG_ABOVE_64_CLEAR(data); 3468 rc = soc_reg_above_64_get(unit, reg, port, index, data); 3469 if (rc != SOC_E_NONE){ 3470 return rc; 3471 } 3472 *out_field_val = soc_reg_above_64_field32_get(unit,reg, data, field); 3473 return rc; 3474 } 3475 /* 3476 * Function: soc_reg_above_64_field64_get 3477 * Purpose: Get the value of a field sized up to 32 bit from a register of any size 3478 * Parameters: 3479 * Returns: Value of field (32 bits) 3480 */ 3481 3482 uint64 3483 soc_reg_above_64_field64_get(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3484 soc_field_t field) 3485 { 3486 soc_field_info_t *finfop; 3487 uint64 fieldval; 3488 3489 COMPILER_64_ZERO(fieldval); 3490 if (!SOC_REG_IS_VALID(unit, reg)) { 3491 #if !defined(SOC_NO_NAMES) 3492 LOG_CLI((BSL_META_U(unit, 3493 "reg %s is invalid\n"), soc_reg_name[reg])); 3494 #endif 3495 assert(SOC_REG_IS_VALID(unit, reg)); 3496 } 3497 3498 SOC_FIND_FIELD(field, 3499 SOC_REG_INFO(unit, reg).fields, 3500 SOC_REG_INFO(unit, reg).nFields, 3501 finfop); 3502 /* coverity[var_compare_op] */ 3503 if (finfop == NULL) { 3504 #if !defined(SOC_NO_NAMES) 3505 LOG_CLI((BSL_META_U(unit, 3506 "reg %s field %s is invalid\n"), 3507 soc_reg_name[reg], soc_fieldnames[field])); 3508 #endif 3509 assert(finfop); 3510 } else if (finfop->len > 64) { 3511 #if !defined(SOC_NO_NAMES) 3512 LOG_CLI((BSL_META_U(unit, 3513 "reg %s field %s has a size of %u bits which is greater than 32\n"), 3514 soc_reg_name[reg], soc_fieldnames[field], (unsigned)finfop->len)); 3515 #endif 3516 assert(0); 3517 } else { 3518 uint32 low = 0, hi = 0; 3519 if (finfop->len > 32) { 3520 SHR_BITCOPY_RANGE(&low, 0, regval, finfop->bp, 32); /* get the field value lsb word */ 3521 SHR_BITCOPY_RANGE(&hi, 0, regval, finfop->bp + 32, finfop->len - 32); /* get the field value msb word */ 3522 } else { 3523 SHR_BITCOPY_RANGE(&low, 0, regval, finfop->bp, finfop->len); /* get the field value */ 3524 } 3525 COMPILER_64_SET(fieldval, hi, low); 3526 } 3527 return fieldval; 3528 } 3529 /* 3530 * Function: soc_reg_above_64_field64_read 3531 * Purpose: Read a register of any size, and get the value of a field sized up to 64 bit from it. 3532 * Parameters: 3533 * Returns: Value of field (32 bits) 3534 */ 3535 int 3536 soc_reg_above_64_field64_read(int unit, soc_reg_t reg, soc_port_t port, int index, soc_field_t field, uint64* out_field_val) 3537 { 3538 int rc = SOC_E_NONE; 3539 soc_reg_above_64_val_t data; 3540 SOC_REG_ABOVE_64_CLEAR(data); 3541 rc = soc_reg_above_64_get(unit, reg, port, index, data); 3542 if (rc != SOC_E_NONE){ 3543 return rc; 3544 } 3545 *out_field_val = soc_reg_above_64_field64_get(unit,reg, data, field); 3546 return rc; 3547 } 3548 3549 /* Define a macro so the assertion printout is informative. */ 3550 #define VALUE_TOO_BIG_FOR_FIELD ((value & ~mask) != 0) 3551 3552 /* 3553 * Function: soc_reg_field_validate 3554 * Purpose: Validate the value of a register's field. 3555 * Parameters: 3556 * Returns: SOC_E_XXX 3557 */ 3558 int 3559 soc_reg_field_validate(int unit, soc_reg_t reg, soc_field_t field, uint32 value) 3560 { 3561 soc_field_info_t *finfop; 3562 uint32 mask; 3563 3564 if (!SOC_REG_IS_VALID(unit, reg)) { 3565 #if !defined(SOC_NO_NAMES) 3566 LOG_CLI((BSL_META_U(unit, 3567 "reg %s is invalid\n"), soc_reg_name[reg])); 3568 #endif 3569 assert(SOC_REG_IS_VALID(unit, reg)); 3570 } 3571 3572 SOC_FIND_FIELD(field, 3573 SOC_REG_INFO(unit, reg).fields, 3574 SOC_REG_INFO(unit, reg).nFields, 3575 finfop); 3576 3577 if (finfop == NULL) { 3578 #if !defined(SOC_NO_NAMES) 3579 LOG_CLI((BSL_META_U(unit, 3580 "reg %s field %s is invalid\n"), 3581 soc_reg_name[reg], soc_fieldnames[field])); 3582 #endif 3583 assert(finfop); 3584 } 3585 3586 /* 3587 * COVERITY 3588 * 3589 * assert validates the input for NULL 3590 */ 3591 /* coverity[var_deref_op : FALSE] */ 3592 if (finfop->len < 32) { 3593 mask = (1 << finfop->len) - 1; 3594 if (VALUE_TOO_BIG_FOR_FIELD) { 3595 return SOC_E_PARAM; 3596 } 3597 } 3598 3599 return SOC_E_NONE; 3600 } 3601 3602 /* 3603 * Function: soc_reg_signed_field_mask 3604 * Purpose: Chops high bits of signed value to fit in register field 3605 * Parameters: 3606 * Returns: SOC_E_XXX 3607 */ 3608 int 3609 soc_reg_signed_field_mask(int unit, soc_reg_t reg, soc_field_t field, int32 value_in, uint32 *value_out) 3610 { 3611 soc_field_info_t *finfop; 3612 int32 max_valid; 3613 int32 min_valid; 3614 uint32 mask; 3615 3616 if (!SOC_REG_IS_VALID(unit, reg)) { 3617 #if !defined(SOC_NO_NAMES) 3618 LOG_CLI((BSL_META_U(unit, 3619 "reg %s is invalid\n"), soc_reg_name[reg])); 3620 #endif 3621 assert(SOC_REG_IS_VALID(unit, reg)); 3622 } 3623 3624 SOC_FIND_FIELD(field, 3625 SOC_REG_INFO(unit, reg).fields, 3626 SOC_REG_INFO(unit, reg).nFields, 3627 finfop); 3628 3629 if (finfop == NULL) { 3630 #if !defined(SOC_NO_NAMES) 3631 LOG_CLI((BSL_META_U(unit, 3632 "reg %s field %s is invalid\n"), 3633 soc_reg_name[reg], soc_fieldnames[field])); 3634 #endif 3635 assert(finfop); 3636 } 3637 3638 /* 3639 * COVERITY 3640 * 3641 * assert validates the input for NULL 3642 */ 3643 /* coverity[var_deref_op : FALSE] */ 3644 if (finfop->len < 32) { 3645 mask = (1 << finfop->len) - 1; 3646 3647 *value_out = (((uint32)value_in) & mask); 3648 3649 max_valid = (1 << (finfop->len-1)) - 1; 3650 min_valid = -max_valid; 3651 3652 if (value_in > max_valid || value_in < min_valid) { 3653 return SOC_E_PARAM; 3654 } 3655 } else { 3656 *value_out = (uint32) value_in; 3657 } 3658 3659 return SOC_E_NONE; 3660 } 3661 3662 /* 3663 * Function: soc_reg_unsigned_field_mask 3664 * Purpose: Chops high bits of unsigned value to fit in register field 3665 * Parameters: 3666 * Returns: SOC_E_XXX 3667 */ 3668 int 3669 soc_reg_unsigned_field_mask(int unit, soc_reg_t reg, soc_field_t field, int32 value_in, uint32 *value_out) 3670 { 3671 soc_field_info_t *finfop; 3672 uint32 max_valid; 3673 uint32 min_valid; 3674 uint32 mask; 3675 3676 if (!SOC_REG_IS_VALID(unit, reg)) { 3677 #if !defined(SOC_NO_NAMES) 3678 LOG_CLI((BSL_META_U(unit, 3679 "reg %s is invalid\n"), soc_reg_name[reg])); 3680 #endif 3681 assert(SOC_REG_IS_VALID(unit, reg)); 3682 } 3683 3684 SOC_FIND_FIELD(field, 3685 SOC_REG_INFO(unit, reg).fields, 3686 SOC_REG_INFO(unit, reg).nFields, 3687 finfop); 3688 3689 if (finfop == NULL) { 3690 #if !defined(SOC_NO_NAMES) 3691 LOG_CLI((BSL_META_U(unit, 3692 "reg %s field %s is invalid\n"), 3693 soc_reg_name[reg], soc_fieldnames[field])); 3694 #endif 3695 assert(finfop); 3696 } 3697 3698 if (finfop->len < 32) { 3699 mask = (1 << finfop->len) - 1; 3700 3701 *value_out = (((uint32)value_in) & mask); 3702 3703 max_valid = (1 << finfop->len) - 1; 3704 min_valid = 0; 3705 3706 if (value_in > max_valid || value_in < min_valid) { 3707 return SOC_E_PARAM; 3708 } 3709 } else { 3710 *value_out = (uint32) value_in; 3711 } 3712 3713 return SOC_E_NONE; 3714 } 3715 3716 /* 3717 * Function: soc_reg_field_set 3718 * Purpose: Set the value of a register's field. 3719 * Parameters: 3720 * Returns: void 3721 */ 3722 void 3723 soc_reg_field_set(int unit, soc_reg_t reg, uint32 *regval, 3724 soc_field_t field, uint32 value) 3725 { 3726 soc_field_info_t *finfop; 3727 uint32 mask; 3728 3729 if (!SOC_REG_IS_VALID(unit, reg)) { 3730 #if !defined(SOC_NO_NAMES) 3731 LOG_CLI((BSL_META_U(unit, 3732 "reg %s is invalid\n"), soc_reg_name[reg])); 3733 #endif 3734 assert(SOC_REG_IS_VALID(unit, reg)); 3735 } 3736 3737 SOC_FIND_FIELD(field, 3738 SOC_REG_INFO(unit, reg).fields, 3739 SOC_REG_INFO(unit, reg).nFields, 3740 finfop); 3741 if (finfop == NULL) { 3742 #if !defined(SOC_NO_NAMES) 3743 LOG_CLI((BSL_META_U(unit, 3744 "reg %s field %s is invalid\n"), 3745 soc_reg_name[reg], soc_fieldnames[field])); 3746 #endif 3747 assert(finfop); 3748 } 3749 3750 if (finfop->len < 32) { 3751 mask = (1 << finfop->len) - 1; 3752 if (VALUE_TOO_BIG_FOR_FIELD) { 3753 #if !defined(SOC_NO_NAMES) 3754 LOG_CLI((BSL_META_U(unit, 3755 "reg %s field %s is too big\n"), 3756 soc_reg_name[reg], soc_fieldnames[field])); 3757 #endif 3758 assert(!VALUE_TOO_BIG_FOR_FIELD); 3759 } 3760 } else { 3761 mask = -1; 3762 } 3763 3764 *regval = (*regval & ~(mask << finfop->bp)) | value << finfop->bp; 3765 } 3766 3767 /* 3768 * Function: soc_reg_field_set 3769 * Purpose: Set the value of a register's field. 3770 * Parameters: 3771 * Returns: void 3772 */ 3773 void 3774 soc_reg_above_64_field_set(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3775 soc_field_t field, CONST soc_reg_above_64_val_t value) 3776 { 3777 soc_field_info_t *finfop; 3778 3779 if (!SOC_REG_IS_VALID(unit, reg)) { 3780 #if !defined(SOC_NO_NAMES) 3781 LOG_CLI((BSL_META_U(unit, 3782 "reg %s is invalid\n"), soc_reg_name[reg])); 3783 #endif 3784 assert(SOC_REG_IS_VALID(unit, reg)); 3785 } 3786 3787 SOC_FIND_FIELD(field, 3788 SOC_REG_INFO(unit, reg).fields, 3789 SOC_REG_INFO(unit, reg).nFields, 3790 finfop); 3791 if (finfop == NULL) { 3792 #if !defined(SOC_NO_NAMES) 3793 LOG_CLI((BSL_META_U(unit, 3794 "reg %s field %s is invalid\n"), 3795 soc_reg_name[reg], soc_fieldnames[field])); 3796 #endif 3797 assert(finfop); 3798 } 3799 { /* Check if the field value will fit into the field: Verify that value's bits that do not fit in the field are all zeroes. */ 3800 3801 /* 3802 * COVERITY 3803 * 3804 * assert validates the input for NULL 3805 */ 3806 /* coverity[var_deref_op : FALSE] */ 3807 unsigned msb_bits = finfop->len % 32; /* Bits in msb word of field value */ 3808 unsigned idx = finfop->len / 32; /* word Iteration index, starts with msb word of field. */ 3809 3810 if (msb_bits) { /* if the msb vaule word has left over bits unused */ 3811 assert (!(value[idx] & (((uint32)0xffffffff) << msb_bits))); /* verify the left over bits are zeros */ 3812 ++idx; 3813 } 3814 for (; idx < SOC_REG_ABOVE_64_MAX_SIZE_U32; ++idx) { /* verify the remaining words are zeros */ 3815 assert (!(value[idx])); 3816 } 3817 } 3818 3819 SHR_BITCOPY_RANGE(regval, finfop->bp, value, 0, finfop->len); 3820 3821 } 3822 3823 /* 3824 * Function: soc_reg_above_64_field32_set 3825 * Purpose: Set the value of a register's field; field must be <= 32 bits, any register size supported 3826 * Parameters: 3827 * Returns: void 3828 */ 3829 void 3830 soc_reg_above_64_field32_set(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3831 soc_field_t field, uint32 value) 3832 { 3833 soc_field_info_t *finfop; 3834 3835 if (!SOC_REG_IS_VALID(unit, reg)) { 3836 #if !defined(SOC_NO_NAMES) 3837 LOG_CLI((BSL_META_U(unit, 3838 "reg %s is invalid\n"), soc_reg_name[reg])); 3839 #endif 3840 assert(SOC_REG_IS_VALID(unit, reg)); 3841 } 3842 3843 SOC_FIND_FIELD(field, 3844 SOC_REG_INFO(unit, reg).fields, 3845 SOC_REG_INFO(unit, reg).nFields, 3846 finfop); 3847 if (finfop == NULL) { 3848 #if !defined(SOC_NO_NAMES) 3849 LOG_CLI((BSL_META_U(unit, 3850 "reg %s field %s is invalid\n"), 3851 soc_reg_name[reg], soc_fieldnames[field])); 3852 #endif 3853 assert(finfop); 3854 /* Check if the field value will fit into the field: Verify that value's bits that do not fit in the field are all zeroes. */ 3855 } else if (finfop->len > 32) { 3856 SHR_BITCLR_RANGE(regval, finfop->bp + 32, finfop->len - 32); 3857 SHR_BITCOPY_RANGE(regval, finfop->bp, &value, 0, 32); 3858 } else { 3859 if (finfop->len < 32 && value >= (((uint32)1) << finfop->len)) { 3860 #if !defined(SOC_NO_NAMES) 3861 LOG_CLI((BSL_META_U(unit, 3862 "reg %s field %s is too small for value 0x%lx\n"), 3863 soc_reg_name[reg], soc_fieldnames[field],(unsigned long)value)); 3864 #endif 3865 assert (0); 3866 } 3867 SHR_BITCOPY_RANGE(regval, finfop->bp, &value, 0, finfop->len); 3868 } 3869 3870 } 3871 3872 3873 /* 3874 * Function: soc_reg_above_64_field64_set 3875 * Purpose: Set the value of a register's field; field must be <= 64 bits, any register size supported 3876 * Parameters: 3877 * Returns: void 3878 */ 3879 void 3880 soc_reg_above_64_field64_set(int unit, soc_reg_t reg, soc_reg_above_64_val_t regval, 3881 soc_field_t field, uint64 value) 3882 { 3883 soc_field_info_t *finfop; 3884 uint32 value32; 3885 3886 if (!SOC_REG_IS_VALID(unit, reg)) { 3887 #if !defined(SOC_NO_NAMES) 3888 LOG_CLI((BSL_META_U(unit, 3889 "reg %s is invalid\n"), soc_reg_name[reg])); 3890 #endif 3891 assert(SOC_REG_IS_VALID(unit, reg)); 3892 } 3893 3894 SOC_FIND_FIELD(field, 3895 SOC_REG_INFO(unit, reg).fields, 3896 SOC_REG_INFO(unit, reg).nFields, 3897 finfop); 3898 if (finfop == NULL) { 3899 #if !defined(SOC_NO_NAMES) 3900 LOG_CLI((BSL_META_U(unit, 3901 "reg %s field %s is invalid\n"), 3902 soc_reg_name[reg], soc_fieldnames[field])); 3903 #endif 3904 assert(finfop); 3905 /* Check if the field value will fit into the field: Verify that value's bits that do not fit in the field are all zeroes. */ 3906 } else if (finfop->len > 64) { 3907 SHR_BITCLR_RANGE(regval, finfop->bp + 64, finfop->len - 64); 3908 3909 value32 = COMPILER_64_LO(value); 3910 SHR_BITCOPY_RANGE(regval, finfop->bp, &value32, 0, 32); 3911 3912 value32 = COMPILER_64_HI(value); 3913 SHR_BITCOPY_RANGE(regval, finfop->bp + 32, &value32, 0, 32); 3914 3915 } else if (finfop->len <= 32 ) { 3916 if (finfop->len < 32 && COMPILER_64_LO(value) >= (((uint32)1) << finfop->len)) { 3917 #if !defined(SOC_NO_NAMES) 3918 LOG_CLI((BSL_META_U(unit, 3919 "reg %s field %s is too small for value 0x%lx\n"), 3920 soc_reg_name[reg], soc_fieldnames[field],(unsigned long)COMPILER_64_LO(value))); 3921 #endif 3922 assert (0); 3923 } 3924 value32 = COMPILER_64_LO(value); 3925 SHR_BITCOPY_RANGE(regval, finfop->bp, &value32, 0, finfop->len); 3926 } else { /*32<field lengh<=64*/ 3927 if (finfop->len < 64 && COMPILER_64_HI(value) >= (((uint32)1) << (finfop->len - 32))) { 3928 #if !defined(SOC_NO_NAMES) 3929 LOG_CLI((BSL_META_U(unit, 3930 "reg %s field %s is too small for value 0x%lx\n"), 3931 soc_reg_name[reg], soc_fieldnames[field],(unsigned long)COMPILER_64_HI(value))); 3932 #endif 3933 assert (0); 3934 } 3935 value32 = COMPILER_64_LO(value); 3936 SHR_BITCOPY_RANGE(regval, finfop->bp, &value32, 0, 32); 3937 3938 value32 = COMPILER_64_HI(value); 3939 SHR_BITCOPY_RANGE(regval, finfop->bp + 32, &value32, 0, finfop->len - 32); 3940 3941 } 3942 3943 } 3944 #define VALUE_TOO_BIG_FOR_FIELD64(mask) (!COMPILER_64_IS_ZERO(mask)) 3945 3946 /* 3947 * Function: soc_reg64_field_validate 3948 * Purpose: Validate the value of a register's field. 3949 * Parameters: 3950 * Returns: SOC_E_XXX 3951 */ 3952 int 3953 soc_reg64_field_validate(int unit, soc_reg_t reg, soc_field_t field, uint64 value) 3954 { 3955 soc_field_info_t *finfop; 3956 uint64 mask; 3957 3958 if (!SOC_REG_IS_VALID(unit, reg)) { 3959 #if !defined(SOC_NO_NAMES) 3960 LOG_CLI((BSL_META_U(unit, 3961 "reg %s is invalid\n"), soc_reg_name[reg])); 3962 #endif 3963 assert(SOC_REG_IS_VALID(unit, reg)); 3964 } 3965 3966 SOC_FIND_FIELD(field, 3967 SOC_REG_INFO(unit, reg).fields, 3968 SOC_REG_INFO(unit, reg).nFields, 3969 finfop); 3970 3971 if (finfop == NULL) { 3972 #if !defined(SOC_NO_NAMES) 3973 LOG_CLI((BSL_META_U(unit, 3974 "reg %s field %s is invalid\n"), 3975 soc_reg_name[reg], soc_fieldnames[field])); 3976 #endif 3977 assert(finfop); 3978 } 3979 3980 /* 3981 * COVERITY 3982 * 3983 * assert validates the input for NULL 3984 */ 3985 /* coverity[var_deref_op : FALSE] */ 3986 if (finfop->len < 64) { 3987 COMPILER_64_ZERO(mask); 3988 COMPILER_64_ADD_32(mask, 1); 3989 COMPILER_64_SHL(mask, finfop->len); 3990 COMPILER_64_SUB_32(mask, 1); 3991 COMPILER_64_NOT(mask); 3992 COMPILER_64_AND(mask, value); 3993 if(VALUE_TOO_BIG_FOR_FIELD64(mask)) 3994 return SOC_E_PARAM; 3995 3996 } 3997 3998 return SOC_E_NONE; 3999 } 4000 4001 /* 4002 * Function: soc_reg64_field_set 4003 * Purpose: Set the value of a register's field. 4004 * Parameters: 4005 * Returns: void 4006 */ 4007 void 4008 soc_reg64_field_set(int unit, soc_reg_t reg, uint64 *regval, 4009 soc_field_t field, uint64 value) 4010 { 4011 soc_field_info_t *finfop; 4012 uint64 mask, tmp; 4013 4014 if (!SOC_REG_IS_VALID(unit, reg)) { 4015 #if !defined(SOC_NO_NAMES) 4016 LOG_CLI((BSL_META_U(unit, 4017 "reg %s is invalid\n"), soc_reg_name[reg])); 4018 #endif 4019 assert(SOC_REG_IS_VALID(unit, reg)); 4020 } 4021 4022 SOC_FIND_FIELD(field, 4023 SOC_REG_INFO(unit, reg).fields, 4024 SOC_REG_INFO(unit, reg).nFields, 4025 finfop); 4026 if (finfop == NULL) { 4027 #if !defined(SOC_NO_NAMES) 4028 LOG_CLI((BSL_META_U(unit, 4029 "reg %s field %s is invalid\n"), 4030 soc_reg_name[reg], soc_fieldnames[field])); 4031 #endif 4032 assert(finfop); 4033 } 4034 4035 /* 4036 * COVERITY 4037 * 4038 * assert validates the input for NULL 4039 */ 4040 /* coverity[var_deref_op : FALSE] */ 4041 if (finfop->len < 64) { 4042 COMPILER_64_SET(mask, 0, 1); 4043 COMPILER_64_SHL(mask, finfop->len); 4044 COMPILER_64_SUB_32(mask, 1); 4045 #ifndef NDEBUG 4046 /* assert(!VALUE_TOO_BIG_FOR_FIELD); */ 4047 tmp = mask; 4048 COMPILER_64_NOT(tmp); 4049 COMPILER_64_AND(tmp, value); 4050 assert(!VALUE_TOO_BIG_FOR_FIELD64(tmp)); 4051 #endif 4052 } else { 4053 COMPILER_64_SET(mask, -1, -1); 4054 } 4055 4056 /* *regval = (*regval & ~(mask << finfop->bp)) | value << finfop->bp; */ 4057 tmp = mask; 4058 COMPILER_64_SHL(tmp, finfop->bp); 4059 COMPILER_64_NOT(tmp); 4060 COMPILER_64_AND(*regval, tmp); 4061 COMPILER_64_SHL(value, finfop->bp); 4062 COMPILER_64_OR(*regval, value); 4063 } 4064 4065 /* 4066 * Function: soc_reg64_field32_set 4067 * Purpose: Set the value of a register's field; field must be < 32 bits 4068 * Parameters: 4069 * Returns: void 4070 */ 4071 void 4072 soc_reg64_field32_set(int unit, soc_reg_t reg, uint64 *regval, 4073 soc_field_t field, uint32 value) 4074 { 4075 soc_field_info_t *finfop; 4076 uint64 mask, tmp; 4077 4078 if (!SOC_REG_IS_VALID(unit, reg)) { 4079 #if !defined(SOC_NO_NAMES) 4080 LOG_CLI((BSL_META_U(unit, 4081 "reg %s is invalid\n"), soc_reg_name[reg])); 4082 #endif 4083 assert(SOC_REG_IS_VALID(unit, reg)); 4084 } 4085 4086 SOC_FIND_FIELD(field, 4087 SOC_REG_INFO(unit, reg).fields, 4088 SOC_REG_INFO(unit, reg).nFields, 4089 finfop); 4090 if (finfop == NULL) { 4091 #if !defined(SOC_NO_NAMES) 4092 LOG_CLI((BSL_META_U(unit, 4093 "reg %s field %s is invalid\n"), 4094 soc_reg_name[reg], soc_fieldnames[field])); 4095 #endif 4096 assert(finfop); 4097 } 4098 4099 /* 4100 * COVERITY 4101 * 4102 * assert validates the input for NULL 4103 */ 4104 /* coverity[var_deref_op : FALSE] */ 4105 if (finfop->len < 64) { 4106 COMPILER_64_SET(mask, 0, 1); 4107 COMPILER_64_SHL(mask, finfop->len); 4108 COMPILER_64_SUB_32(mask, 1); 4109 } else { 4110 COMPILER_64_SET(mask, -1, -1); 4111 } 4112 4113 /* Mask value to fit in field. Needed if passed-in value was signed. */ 4114 value &= COMPILER_64_LO(mask); 4115 4116 /* *regval = (*regval & ~(mask << finfop->bp)) | value << finfop->bp; */ 4117 COMPILER_64_SHL(mask, finfop->bp); 4118 COMPILER_64_NOT(mask); 4119 COMPILER_64_AND(*regval, mask); 4120 if (value != 0) { 4121 COMPILER_64_SET(tmp, 0, value); 4122 COMPILER_64_SHL(tmp, finfop->bp); 4123 COMPILER_64_OR(*regval, tmp); 4124 } 4125 } 4126 4127 /* 4128 * Function: soc_reg_addr 4129 * Purpose: calculate the address of a register 4130 * Parameters: 4131 * unit switch unit 4132 * reg register number 4133 * port port number or REG_PORT_ANY 4134 * index array index (or cos number) 4135 * Returns: register address suitable for soc_reg_read and friends 4136 * Notes: the block number to access is determined by the register 4137 * and the port number 4138 * 4139 * cpureg 00SSSSSS 00000000 0000RRRR RRRRRRRR 4140 * genreg 00SSSSSS BBBB1000 0000RRRR RRRRRRRR 4141 * portreg 00SSSSSS BBBB00PP PPPPRRRR RRRRRRRR 4142 * cosreg 00SSSSSS BBBB01CC CCCCRRRR RRRRRRRR 4143 * 4144 * all regs of bcm88230 4145 * 00000000 00001000 0000RRRR RRRRRRRR 4146 * 4147 * where B+ is the 4 bit block number 4148 * P+ is the 6 bit port number (within a block or chip wide) 4149 * C+ is the 6 bit class of service 4150 * R+ is the 12 bit register number 4151 * S+ is the 6 bit Pipe stage 4152 */ 4153 uint32 4154 soc_reg_addr(int unit, soc_reg_t reg, int port, int index) 4155 { 4156 uint32 base; /* base address from reg_info */ 4157 int block = -1; /* block number */ 4158 int pindex = -1; /* register port/cos field */ 4159 int gransh; /* index granularity shift */ 4160 soc_block_types_t regblktype; 4161 soc_block_t portblktype; 4162 int phy_port; 4163 int instance_mask = 0; 4164 int instance = -1; 4165 4166 4167 #ifdef BCM_TOMAHAWK3_SUPPORT 4168 soc_reg_t reg_excep_list[]={MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr, 4169 MMU_RQE_REPL_PORT_AGG_MAPr}; 4170 int reg_index, num_regs, add_exception = 0; 4171 #endif 4172 4173 if (SOC_CONTROL(unit)->soc_reg_watch) { 4174 if (SOC_CONTROL(unit)->prev_reg != reg) { 4175 LOG_CLI((BSL_META_U(unit, "%d:%s REG: %s\n"), 4176 unit, BSL_FUNC, SOC_REG_NAME(unit, reg))); 4177 SOC_CONTROL(unit)->prev_reg = reg; 4178 } 4179 } 4180 4181 if (!SOC_REG_IS_VALID(unit, reg)) { 4182 #if !defined(SOC_NO_NAMES) 4183 LOG_CLI((BSL_META_U(unit, 4184 "reg %s is invalid\n"), soc_reg_name[reg])); 4185 #endif 4186 assert(SOC_REG_IS_VALID(unit, reg)); 4187 } 4188 4189 #ifdef DNX_TEST_CHIPS_SUPPORT 4190 if (SOC_IS_DNX_TEST_DEVICE(unit) 4191 #if defined(PLISIM) 4192 && !SAL_BOOT_PLISIM 4193 #endif 4194 ) { 4195 return soc_dnxtestchip_reg_addr(unit, reg, port, index); 4196 } 4197 #endif /* DNX_TEST_CHIPS_SUPPORT */ 4198 4199 #define SOC_REG_ADDR_INVALID_PORT 0 /* for asserts */ 4200 4201 { 4202 portblktype = SOC_BLK_PORT; 4203 } 4204 4205 regblktype = SOC_REG_INFO(unit, reg).block; 4206 if(REG_PORT_ANY != port) { 4207 instance_mask = port & SOC_REG_ADDR_INSTANCE_MASK; 4208 port &= (~SOC_REG_ADDR_INSTANCE_MASK); 4209 } 4210 4211 4212 if(!instance_mask) { 4213 if (port >= 0) { 4214 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 4215 assert(SOC_PORT_VALID(unit, port)); 4216 if (soc_feature(unit, soc_feature_logical_port_num)) { 4217 /* 4218 * COVERITY 4219 * 4220 * assert validates the port 4221 */ 4222 /* coverity[overrun-local : FALSE] */ 4223 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4224 } else { 4225 phy_port = port; 4226 } 4227 block = SOC_PORT_BLOCK(unit, phy_port); 4228 pindex = SOC_PORT_BINDEX(unit, phy_port); 4229 } else { 4230 block = pindex = -1; /* multiple non-port block */ 4231 } 4232 } else if (port == REG_PORT_ANY) { 4233 block = pindex = -1; 4234 if(soc_portreg == SOC_REG_INFO(unit, reg).regtype ) { 4235 PBMP_ALL_ITER(unit, port) { /* try enabled ports */ 4236 if (soc_feature(unit, soc_feature_logical_port_num)) { 4237 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4238 } else { 4239 phy_port = port; 4240 } 4241 block = SOC_PORT_BLOCK(unit, phy_port); 4242 pindex = SOC_PORT_BINDEX(unit, phy_port); 4243 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { /* match reg type */ 4244 if (SOC_BLOCK_IS_TYPE(unit, block, regblktype)) { 4245 break; 4246 } 4247 block = -1; 4248 } else { /* match any port */ 4249 break; 4250 } 4251 } 4252 if (block < 0) { 4253 assert(SOC_REG_ADDR_INVALID_PORT); /* invalid port */ 4254 } 4255 } 4256 } else { 4257 port &= ~SOC_REG_ADDR_INSTANCE_MASK; 4258 block = pindex = -1; 4259 } 4260 } 4261 4262 if (REG_PORT_ANY == port ||instance_mask || !SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 4263 switch (SOC_REG_FIRST_BLK_TYPE(regblktype)) { 4264 case SOC_BLK_ARL: 4265 block = ARL_BLOCK(unit); 4266 break; 4267 case SOC_BLK_IPIPE: 4268 block = IPIPE_BLOCK(unit); 4269 break; 4270 case SOC_BLK_IPIPE_HI: 4271 block = IPIPE_HI_BLOCK(unit); 4272 break; 4273 case SOC_BLK_EPIPE: 4274 block = EPIPE_BLOCK(unit); 4275 break; 4276 case SOC_BLK_EPIPE_HI: 4277 block = EPIPE_HI_BLOCK(unit); 4278 break; 4279 case SOC_BLK_IGR: 4280 block = IGR_BLOCK(unit); 4281 break; 4282 case SOC_BLK_EGR: 4283 block = EGR_BLOCK(unit); 4284 break; 4285 case SOC_BLK_BSE: 4286 block = BSE_BLOCK(unit); 4287 break; 4288 case SOC_BLK_CSE: 4289 block = CSE_BLOCK(unit); 4290 break; 4291 case SOC_BLK_HSE: 4292 block = HSE_BLOCK(unit); 4293 break; 4294 case SOC_BLK_BSAFE: 4295 block = BSAFE_BLOCK(unit); 4296 break; 4297 case SOC_BLK_OTPC: 4298 instance = 0; 4299 block = OTPC_BLOCK(unit, instance); 4300 break; 4301 case SOC_BLK_MMU: 4302 block = MMU_BLOCK(unit); 4303 break; 4304 case SOC_BLK_MCU: 4305 block = MCU_BLOCK(unit); 4306 break; 4307 case SOC_BLK_CMIC: 4308 block = CMIC_BLOCK(unit); 4309 break; 4310 case SOC_BLK_IPROC: 4311 block = IPROC_BLOCK(unit); 4312 break; 4313 case SOC_BLK_CRYPTO: 4314 block = CRYPTO_BLOCK(unit); 4315 break; 4316 case SOC_BLK_ESM: 4317 block = ESM_BLOCK(unit); 4318 break; 4319 case SOC_BLK_PORT_GROUP4: 4320 block = PG4_BLOCK(unit, port); 4321 break; 4322 case SOC_BLK_PORT_GROUP5: 4323 block = PG5_BLOCK(unit, port); 4324 break; 4325 case SOC_BLK_TOP: 4326 block = TOP_BLOCK(unit); 4327 break; 4328 case SOC_BLK_LLS: 4329 block = LLS_BLOCK(unit); 4330 break; 4331 case SOC_BLK_CES: 4332 block = CES_BLOCK(unit); 4333 break; 4334 case SOC_BLK_CI: 4335 if (port >= 3) { 4336 assert(SOC_REG_ADDR_INVALID_PORT); /* invalid instance */ 4337 } else { 4338 block = CI_BLOCK(unit, port); 4339 } 4340 break; 4341 case SOC_BLK_IL: 4342 if (SOC_IS_SHADOW(unit)) { 4343 if (port == 9) { 4344 block = IL0_BLOCK(unit); 4345 } else if (port == 13) { 4346 block = IL1_BLOCK(unit); 4347 } 4348 pindex = 0; 4349 } 4350 break; 4351 case SOC_BLK_MS_ISEC: 4352 if (SOC_IS_SHADOW(unit)) { 4353 if (port >= 1 && port <= 4) { 4354 block = MS_ISEC0_BLOCK(unit); 4355 pindex = port - 1; 4356 } else { 4357 block = MS_ISEC1_BLOCK(unit); 4358 pindex = port - 5; 4359 } 4360 } 4361 break; 4362 case SOC_BLK_MS_ESEC: 4363 if (SOC_IS_SHADOW(unit)) { 4364 if (port >= 1 && port <= 4) { 4365 block = MS_ESEC0_BLOCK(unit); 4366 pindex = port - 1; 4367 } else { 4368 block = MS_ESEC1_BLOCK(unit); 4369 pindex = port - 5; 4370 } 4371 } 4372 break; 4373 case SOC_BLK_IECELL: 4374 #if defined(BCM_METROLITE_SUPPORT) 4375 if (SOC_IS_METROLITE(unit)) { 4376 soc_ml_iecell_port_reg_blk_idx_get(unit, port, 4377 SOC_BLK_IECELL, &block, &pindex); 4378 } else 4379 #endif 4380 #if defined (BCM_SABER2_SUPPORT) 4381 if (SOC_IS_SABER2(unit)) { 4382 soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 4383 SOC_BLK_IECELL, &block, &pindex); 4384 } 4385 #endif 4386 break; 4387 case SOC_BLK_TXLP: 4388 #if defined(BCM_KATANA2_SUPPORT) 4389 if (SOC_IS_KATANA2(unit)) { 4390 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 4391 SOC_BLK_TXLP, &block, &pindex); 4392 } 4393 #endif 4394 break; 4395 case SOC_BLK_RXLP: 4396 #if defined(BCM_KATANA2_SUPPORT) 4397 if (SOC_IS_KATANA2(unit)) { 4398 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 4399 SOC_BLK_RXLP, &block, &pindex); 4400 } 4401 #endif 4402 break; 4403 case SOC_BLK_OAMP: 4404 #if defined(BCM_SABER2_SUPPORT) || defined (BCM_METROLITE_SUPPORT) 4405 block = OAMP_BLOCK(unit); 4406 #endif 4407 break; 4408 4409 case SOC_BLK_CW: 4410 if (SOC_IS_SHADOW(unit)) { 4411 block = CW_BLOCK(unit); 4412 } 4413 break; 4414 case SOC_BLK_ECI: 4415 block = ECI_BLOCK(unit); 4416 break; 4417 case SOC_BLK_OCCG: 4418 block = OCCG_BLOCK(unit); 4419 break; 4420 case SOC_BLK_DCH: 4421 if(REG_PORT_ANY != port) 4422 block = DCH_BLOCK(unit, port); 4423 else 4424 block = DCH_BLOCK(unit, 0); 4425 break; 4426 case SOC_BLK_DCL: 4427 if(REG_PORT_ANY != port) 4428 block = DCL_BLOCK(unit, port); 4429 else 4430 block = DCL_BLOCK(unit, 0); 4431 break; 4432 case SOC_BLK_DCMA: 4433 if(REG_PORT_ANY != port) 4434 block = DCMA_BLOCK(unit, port); 4435 else 4436 block = DCMA_BLOCK(unit, 0); 4437 break; 4438 case SOC_BLK_DCMB: 4439 if(REG_PORT_ANY != port) 4440 block = DCMB_BLOCK(unit, port); 4441 else 4442 block = DCMB_BLOCK(unit, 0); 4443 break; 4444 case SOC_BLK_DCMC: 4445 block = DCMC_BLOCK(unit); 4446 break; 4447 case SOC_BLK_CCS: 4448 if(REG_PORT_ANY != port) 4449 block = CCS_BLOCK(unit, port); 4450 else 4451 block = CCS_BLOCK(unit, 0); 4452 break; 4453 case SOC_BLK_RTP: 4454 block = RTP_BLOCK(unit); 4455 break; 4456 case SOC_BLK_MESH_TOPOLOGY: 4457 block = MESH_TOPOLOGY_BLOCK(unit); 4458 break; 4459 case SOC_BLK_FMAC: 4460 if(REG_PORT_ANY != port) 4461 block = FMAC_BLOCK(unit, port); 4462 else 4463 block = FMAC_BLOCK(unit, 0); 4464 break; 4465 case SOC_BLK_IPSEC_SPU_WRAPPER_TOP: 4466 if(REG_PORT_ANY != port) 4467 block = IPSEC_SPU_WRAPPER_TOP_BLOCK(unit, port); 4468 else 4469 block = IPSEC_SPU_WRAPPER_TOP_BLOCK(unit, 0); 4470 break; 4471 case SOC_BLK_FSRD: 4472 if(REG_PORT_ANY != port) 4473 block = FSRD_BLOCK(unit, port); 4474 else 4475 block = FSRD_BLOCK(unit, 0); 4476 break; 4477 case SOC_BLK_HBC: 4478 if(REG_PORT_ANY != port) 4479 block = HBC_BLOCK(unit, port); 4480 else 4481 block = HBC_BLOCK(unit, 0); 4482 break; 4483 case SOC_BLK_BRDC_FMACH: 4484 block = BRDC_FMACH_BLOCK(unit); 4485 break; 4486 case SOC_BLK_BRDC_FMACL: 4487 block = BRDC_FMACL_BLOCK(unit); 4488 break; 4489 case SOC_BLK_BRDC_FSRD: 4490 block = BRDC_FSRD_BLOCK(unit); 4491 break; 4492 case SOC_BLK_BRDC_HBC: 4493 block = BRDC_HBC_BLOCK(unit); 4494 break; 4495 case SOC_BLK_MXQ: 4496 if(REG_PORT_ANY != port) 4497 block = MXQ_BLOCK(unit, port); 4498 else 4499 block = MXQ_BLOCK(unit, 0); 4500 break; 4501 case SOC_BLK_PLL: 4502 block = PLL_BLOCK(unit); 4503 break; 4504 case SOC_BLK_NIF: 4505 block = NIF_BLOCK(unit); 4506 break; 4507 default: 4508 block = -1; /* unknown non-port block */ 4509 break; 4510 } 4511 } 4512 4513 assert(block >= 0); /* block must be valid */ 4514 4515 /* determine final block, pindex, and index */ 4516 gransh = 0; 4517 switch (SOC_REG_INFO(unit, reg).regtype) { 4518 case soc_cpureg: 4519 case soc_mcsreg: 4520 case soc_iprocreg: 4521 block = -1; 4522 pindex = 0; 4523 gransh = 2; /* 4 byte granularity */ 4524 break; 4525 case soc_portreg: 4526 if (!SOC_BLOCK_IN_LIST(regblktype, portblktype) && 4527 !(SOC_IS_SHADOW(unit) && 4528 (SOC_BLOCK_IS(regblktype, SOC_BLK_MS_ISEC) || 4529 SOC_BLOCK_IS(regblktype, SOC_BLK_MS_ESEC))) 4530 #if defined(BCM_KATANA2_SUPPORT) 4531 && !(SOC_IS_KATANA2(unit) && 4532 (SOC_BLOCK_IS(regblktype, SOC_BLK_TXLP) || 4533 SOC_BLOCK_IS(regblktype, SOC_BLK_RXLP))) 4534 #endif 4535 /* Need to check : SABER2 */ 4536 #if defined(BCM_SABER2_SUPPORT) 4537 && !(SOC_IS_SABER2(unit) && 4538 (SOC_BLOCK_IS(regblktype, SOC_BLK_IECELL))) 4539 #endif 4540 ) { 4541 if (soc_feature(unit, soc_feature_logical_port_num) && 4542 block == MMU_BLOCK(unit)) { 4543 #ifdef BCM_TOMAHAWK3_SUPPORT 4544 /*MMU register with device port indexing*/ 4545 num_regs = sizeof(reg_excep_list) / sizeof(soc_reg_t); 4546 for (reg_index = 0;reg_index < num_regs; reg_index++) { 4547 if (reg_excep_list[reg_index] == reg) { 4548 add_exception = 1; 4549 break; 4550 } 4551 } 4552 if (add_exception) { 4553 pindex = port; 4554 } else 4555 #endif 4556 { 4557 /* coverity[negative_returns : FALSE] */ 4558 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4559 pindex = SOC_INFO(unit).port_p2m_mapping[phy_port]; 4560 } 4561 } else { 4562 pindex = port; 4563 } 4564 } 4565 break; 4566 case soc_cosreg: 4567 assert(index >= 0 && index < NUM_COS(unit)); 4568 pindex = index; 4569 index = 0; 4570 break; 4571 case soc_customreg: 4572 case soc_genreg: 4573 pindex = 0; 4574 break; 4575 default: 4576 assert(0); /* unknown register type */ 4577 break; 4578 } 4579 4580 /* put together address: base|block|pindex + index */ 4581 base = SOC_REG_INFO(unit, reg).offset; 4582 LOG_VERBOSE(BSL_LS_SOC_REG, 4583 (BSL_META_U(unit, 4584 "base: %x "), base)); 4585 4586 if (block >= 0) { 4587 base |= ((SOC_BLOCK2OFFSET(unit, block) & 0xf) << SOC_BLOCK_BP) | 4588 (((SOC_BLOCK2OFFSET(unit, block) >> 4) & 0x3) << 4589 SOC_BLOCK_MSB_BP); 4590 } 4591 4592 if (pindex) { 4593 base |= pindex << SOC_REGIDX_BP; 4594 } 4595 4596 if (SOC_REG_IS_ARRAY(unit, reg)) { 4597 assert(index >= SOC_REG_INFO(unit, reg).first_array_index && index < SOC_REG_NUMELS(unit, reg) + SOC_REG_INFO(unit, reg).first_array_index); 4598 #if defined(BCM_SABER2_SUPPORT) 4599 if (SOC_IS_SABER2(unit) && block == OAMP_BLOCK(unit)) { 4600 base += (index - SOC_REG_INFO(unit, reg).first_array_index)*(SOC_REG_ELEM_SKIP(unit, reg) << 8); 4601 } else 4602 #endif 4603 { 4604 base += (index - SOC_REG_INFO(unit, reg).first_array_index)*SOC_REG_ELEM_SKIP(unit, reg); 4605 } 4606 } else if (index && SOC_REG_ARRAY(unit, reg)) { 4607 assert(index >= 0 && index < SOC_REG_NUMELS(unit, reg)); 4608 if (index && SOC_REG_ARRAY2(unit, reg)) { 4609 base += ((index*2) << gransh); 4610 } else if (index && SOC_REG_ARRAY4(unit, reg)) { 4611 base += ((index * 4) << gransh); 4612 } else { 4613 base += (index << gransh); 4614 } 4615 } 4616 LOG_VERBOSE(BSL_LS_SOC_REG, 4617 (BSL_META_U(unit, 4618 "addr: %x, block: %d, index: %d, pindex: %d, gransh: %d\n"), 4619 base, block, index, pindex, gransh)); 4620 return base; 4621 } 4622 4623 /* 4624 * Function: soc_reg_xaddr_get 4625 * Purpose: calculate the address of a register 4626 * Parameters: 4627 * unit - SOC unit number 4628 * reg - Register number 4629 * port - Port number or REG_PORT_ANY or SOC_CORE_ALL for DNX blockswith an instance per core 4630 * index - Array index (or cos number) 4631 * options - Flag to indicate special handling to calculate 4632 * the HW register address: SOC_REG_ADDR_OPTION_xxx 4633 * access_info- (OUT) Register access info: address, schan block IDs, access type 4634 * 4635 * Returns: success 4636 * Notes: the block number/s to access is determined by the register 4637 * and the port number 4638 */ 4639 int soc_reg_xaddr_get(int unit, soc_reg_t reg, int port, int index, 4640 uint32 options, soc_reg_access_info_t *access_info) 4641 { 4642 uint32 base; /* base address from reg_info */ 4643 int block = -1; /* block number */ 4644 int pindex = -1; /* register port/cos field */ 4645 int gransh; /* index granularity shift */ 4646 soc_block_types_t regblktype; 4647 soc_block_t portblktype; 4648 uint32 phy_port = 0; 4649 int instance = -1, i; 4650 int instance_mask = 0, block_id_mask = 0, schan_id_mask = 0, phy_acc_mask = 0; 4651 int port_num_blktype; 4652 int block_core = 0; 4653 int is_write; 4654 int preserve_port; 4655 int *soc_blocks = NULL; 4656 #ifdef BCM_TOMAHAWK3_SUPPORT 4657 soc_reg_t reg_excep_list[]={MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr, 4658 MMU_RQE_REPL_PORT_AGG_MAPr}; 4659 int reg_index, num_regs, add_exception = 0; 4660 int stage_id; 4661 #endif 4662 4663 COMPILER_REFERENCE(is_write); 4664 4665 if (SOC_CONTROL(unit)->soc_reg_watch) { 4666 if (SOC_CONTROL(unit)->prev_reg != reg) { 4667 LOG_CLI((BSL_META_U(unit, "%d:%s REG: %s\n"), 4668 unit, BSL_FUNC, SOC_REG_NAME(unit, reg))); 4669 SOC_CONTROL(unit)->prev_reg = reg; 4670 } 4671 } 4672 4673 4674 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 4675 access_info->offset = soc_reg_addr(unit, reg, port, index); 4676 access_info->num_blks = 0; 4677 return SOC_E_NONE; 4678 } 4679 access_info->num_blks = 1; 4680 4681 if (!SOC_REG_IS_VALID(unit, reg)) { 4682 #if !defined(SOC_NO_NAMES) 4683 LOG_CLI((BSL_META_U(unit, 4684 "reg %s is invalid\n"), soc_reg_name[reg])); 4685 #endif 4686 assert(SOC_REG_IS_VALID(unit, reg)); 4687 } 4688 4689 #define SOC_REG_ADDR_INVALID_PORT 0 /* for asserts */ 4690 4691 access_info->acc_type = SOC_REG_ACC_TYPE(unit, reg); 4692 4693 portblktype = SOC_BLK_PORT; 4694 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype > 1 ? 4695 SOC_DRIVER(unit)->port_num_blktype : 1; 4696 4697 access_info->blk_list[0] = 0;/* not really needed, just to avoid coverity defect */ 4698 4699 /* Get options */ 4700 is_write = options & SOC_REG_ADDR_OPTION_WRITE; 4701 preserve_port = options & SOC_REG_ADDR_OPTION_PRESERVE_PORT; 4702 4703 if ((REG_PORT_ANY != port) && (SOC_CORE_ALL != port)) { 4704 instance_mask = port & SOC_REG_ADDR_INSTANCE_MASK; 4705 block_id_mask = port & SOC_REG_ADDR_BLOCK_ID_MASK; 4706 schan_id_mask = port & SOC_REG_ADDR_SCHAN_ID_MASK; 4707 phy_acc_mask = port & SOC_REG_ADDR_PHY_ACC_MASK; 4708 port &= (~ (SOC_REG_ADDR_INSTANCE_MASK | SOC_REG_ADDR_BLOCK_ID_MASK 4709 | SOC_REG_ADDR_SCHAN_ID_MASK | SOC_REG_ADDR_PHY_ACC_MASK)); 4710 } 4711 4712 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 4713 /* Use core broadcast writes when possible for more efficient writes */ 4714 if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) { 4715 instance = block_core = (port == SOC_CORE_ALL || port == REG_PORT_ANY) ? 4716 (is_write ? SOC_CORE_ALL : 0) : port; 4717 } 4718 #endif /* BCM_PETRA_SUPPORT || BCM_DNX_SUPPORT */ 4719 4720 regblktype = SOC_REG_INFO(unit, reg).block; 4721 4722 #ifdef BCM_DNX_SUPPORT 4723 if (SOC_IS_DNX(unit) && (soc_customreg == SOC_REG_INFO(unit,reg).regtype) 4724 && (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_ILE) 4725 && (port != SOC_CORE_ALL) && (port != SOC_BLOCK_ALL)) { 4726 /* for custom register, ILKN, the instance is meaningless */ 4727 instance = block_core = 0; 4728 } 4729 #endif 4730 4731 #ifdef BCM_TOMAHAWK3_SUPPORT 4732 if (SOC_IS_TOMAHAWK3(unit)) { 4733 /* Since TH3 has the dummy blocks CDMAC defined in the regsfile, we need 4734 to assign them to the CDPORT block */ 4735 if (regblktype[0] == SOC_BLK_CDMAC) { 4736 regblktype[0] = SOC_BLK_CDPORT; 4737 } 4738 } 4739 #endif 4740 4741 if (!block_id_mask && !schan_id_mask && !instance_mask && port >= 0) { 4742 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 4743 if (preserve_port || phy_acc_mask) { 4744 phy_port = port; 4745 4746 #ifdef BCM_JERICHO_SUPPORT 4747 if (SOC_IS_JERICHO(unit)) { 4748 /* translate phy port to phy port with qsgmii offset */ 4749 SOC_IF_ERROR_RETURN(MBCM_DPP_SOC_DRIVER_CALL(unit, mbcm_dpp_qsgmii_offsets_add, (unit, phy_port, &phy_port))); 4750 } 4751 #endif /* BCM_JERICHO_SUPPORT */ 4752 4753 } else { 4754 assert(SOC_PORT_VALID(unit, port)); 4755 if (soc_feature(unit, soc_feature_logical_port_num)) { 4756 /* 4757 * COVERITY 4758 * 4759 * assert validates the port 4760 */ 4761 /* coverity[overrun-local : FALSE] */ 4762 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4763 } else { 4764 phy_port = port; 4765 } 4766 } 4767 for (i = 0; i < port_num_blktype; i++) { 4768 #ifdef BCM_KATANA2_SUPPORT 4769 /* Override port blocks with Linkphy Blocks.. */ 4770 if(SOC_IS_KATANA2(unit) && 4771 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_TXLP) ) { 4772 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 4773 SOC_BLK_TXLP, &block, &pindex); 4774 break; 4775 } else if(SOC_IS_KATANA2(unit) && 4776 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_RXLP) ) { 4777 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 4778 SOC_BLK_RXLP, &block, &pindex); 4779 break; 4780 #ifdef BCM_METROLITE_SUPPORT 4781 } else if((SOC_IS_METROLITE(unit)) && 4782 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_IECELL)) { 4783 soc_ml_iecell_port_reg_blk_idx_get(unit, port, 4784 SOC_BLK_IECELL, &block, &pindex); 4785 break; 4786 #endif 4787 #if defined (BCM_SABER2_SUPPORT) 4788 } else if((SOC_IS_SABER2(unit)) && 4789 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_IECELL)) { 4790 soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 4791 SOC_BLK_IECELL, &block, &pindex); 4792 break; 4793 #endif 4794 } 4795 #endif 4796 #ifdef BCM_GREYHOUND_SUPPORT 4797 if(SOC_IS_GREYHOUND(unit) && 4798 (SOC_REG_FIRST_BLK_TYPE(regblktype) == SOC_BLK_XLPORT) ) { 4799 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, NULL, 4800 &block, &pindex, 0) > 0){ 4801 break; 4802 } 4803 } 4804 #endif 4805 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 4806 4807 #ifdef BCM_APACHE_SUPPORT 4808 if (SOC_IS_APACHE(unit)) { 4809 SOC_IF_ERROR_RETURN(soc_apache_port_reg_blk_index_get 4810 (unit, port, SOC_REG_FIRST_BLK_TYPE(regblktype), &block)); 4811 } 4812 #endif 4813 if (block < 0) { 4814 break; 4815 } 4816 if (SOC_BLOCK_IN_LIST(regblktype, 4817 SOC_BLOCK_TYPE(unit, block))) { 4818 pindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 4819 break; 4820 } 4821 4822 else if (SOC_IS_JERICHO(unit) && SOC_PORT_IDX_BLOCK(unit, phy_port, i + 1) == -1) { 4823 break; 4824 } 4825 else if (SOC_IS_DNX(unit)) { 4826 if( (regblktype[0] == SOC_BLK_CDMAC) && (SOC_BLOCK_TYPE(unit, block) == SOC_BLK_CDPORT) ) { 4827 /* 4828 * DNX only: get pindex, in case of CDMAC. 4829 * SOC_PORT_IDX_BLOCK returns CDPORT, therefore check type of block is CDPORT. 4830 */ 4831 pindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 4832 break; 4833 } 4834 } 4835 } 4836 } else { 4837 block = pindex = -1; /* multiple non-port block */ 4838 } 4839 } else if (port == REG_PORT_ANY) { 4840 block = pindex = -1; 4841 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 4842 PBMP_ALL_ITER(unit, port) { /* try enabled ports */ 4843 if (soc_feature(unit, soc_feature_logical_port_num)) { 4844 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4845 } else { 4846 phy_port = port; 4847 } 4848 for (i = 0; i < port_num_blktype; i++) { 4849 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 4850 if (block < 0) { 4851 break; 4852 } 4853 if (SOC_BLOCK_IN_LIST 4854 (regblktype, SOC_BLOCK_TYPE(unit, block))) { 4855 pindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 4856 i); 4857 break; 4858 } 4859 } 4860 if (i == port_num_blktype) { 4861 continue; 4862 } 4863 if (block >= 0) { 4864 break; 4865 } 4866 } 4867 if (block < 0) { 4868 assert(SOC_REG_ADDR_INVALID_PORT); /* invalid port */ 4869 } 4870 } else { /* match any port */ 4871 if (!SOC_IS_SAND(unit)) { 4872 PBMP_ALL_ITER(unit, port) { /* try enabled ports */ 4873 break; 4874 } 4875 } 4876 } 4877 } else if (port != SOC_CORE_ALL){ 4878 port &= ~(SOC_REG_ADDR_INSTANCE_MASK | SOC_REG_ADDR_BLOCK_ID_MASK | SOC_REG_ADDR_SCHAN_ID_MASK); 4879 instance = port; 4880 block = pindex = -1; 4881 } 4882 4883 #if defined (BCM_KATANA2_SUPPORT) 4884 if (SOC_IS_KATANA2(unit)) { 4885 if (((SOC_BLK_RXLP == SOC_REG_FIRST_BLK_TYPE(regblktype)) || 4886 (SOC_BLK_TXLP == SOC_REG_FIRST_BLK_TYPE(regblktype))) && 4887 (soc_portreg != SOC_REG_INFO(unit, reg).regtype)) { 4888 instance_mask = 1; 4889 } 4890 } 4891 #endif 4892 #if defined (BCM_SABER2_SUPPORT) 4893 if (SOC_IS_SABER2(unit)) { 4894 if ((SOC_BLK_IECELL == SOC_REG_FIRST_BLK_TYPE(regblktype)) && 4895 (soc_portreg != SOC_REG_INFO(unit, reg).regtype)) { 4896 instance_mask = 1; 4897 } 4898 } 4899 #endif 4900 4901 if ((!block_id_mask) && (!schan_id_mask) && (REG_PORT_ANY == port || instance_mask || !SOC_BLOCK_IN_LIST(regblktype, portblktype))) { 4902 int blkport = port; 4903 if (port == REG_PORT_ANY || port == SOC_CORE_ALL) { 4904 blkport = 0; 4905 } 4906 switch (SOC_REG_FIRST_BLK_TYPE(regblktype)) { 4907 case SOC_BLK_ARL: 4908 block = ARL_BLOCK(unit); 4909 break; 4910 case SOC_BLK_IPIPE: 4911 block = IPIPE_BLOCK(unit); 4912 break; 4913 case SOC_BLK_IPIPE_HI: 4914 block = IPIPE_HI_BLOCK(unit); 4915 break; 4916 case SOC_BLK_EPIPE: 4917 block = EPIPE_BLOCK(unit); 4918 break; 4919 case SOC_BLK_EPIPE_HI: 4920 block = EPIPE_HI_BLOCK(unit); 4921 break; 4922 case SOC_BLK_IGR: 4923 block = IGR_BLOCK(unit); 4924 break; 4925 case SOC_BLK_EGR: 4926 block = EGR_BLOCK(unit); 4927 break; 4928 case SOC_BLK_BSE: 4929 block = BSE_BLOCK(unit); 4930 break; 4931 case SOC_BLK_CSE: 4932 block = CSE_BLOCK(unit); 4933 break; 4934 case SOC_BLK_HSE: 4935 block = HSE_BLOCK(unit); 4936 break; 4937 case SOC_BLK_SYS: 4938 break; 4939 case SOC_BLK_BSAFE: 4940 block = BSAFE_BLOCK(unit); 4941 break; 4942 case SOC_BLK_OTPC: 4943 block = OTPC_BLOCK(unit, blkport); 4944 break; 4945 case SOC_BLK_MMU: 4946 block = MMU_BLOCK(unit); 4947 break; 4948 case SOC_BLK_MMU_SED: 4949 block = MMU_SED_BLOCK(unit); 4950 break; 4951 case SOC_BLK_MMU_GLB: 4952 block = MMU_GLB_BLOCK(unit); 4953 break; 4954 case SOC_BLK_MMU_XPE: 4955 block = MMU_XPE_BLOCK(unit); 4956 break; 4957 case SOC_BLK_MMU_SC: 4958 block = MMU_SC_BLOCK(unit); 4959 break; 4960 case SOC_BLK_MCU: 4961 block = MCU_BLOCK(unit); 4962 break; 4963 case SOC_BLK_CMIC: 4964 block = CMIC_BLOCK(unit); 4965 break; 4966 case SOC_BLK_IPROC: 4967 block = IPROC_BLOCK(unit); 4968 break; 4969 case SOC_BLK_CRYPTO: 4970 block = CRYPTO_BLOCK(unit); 4971 break; 4972 case SOC_BLK_ESM: 4973 block = ESM_BLOCK(unit); 4974 break; 4975 case SOC_BLK_PORT_GROUP4: 4976 block = PG4_BLOCK(unit, port); 4977 break; 4978 case SOC_BLK_PORT_GROUP5: 4979 block = PG5_BLOCK(unit, port); 4980 break; 4981 case SOC_BLK_TOP: 4982 block = TOP_BLOCK(unit); 4983 break; 4984 case SOC_BLK_SER: 4985 block = SER_BLOCK(unit); 4986 break; 4987 case SOC_BLK_AVS: 4988 block = AVS_BLOCK(unit); 4989 break; 4990 case SOC_BLK_AXP: 4991 block = AXP_BLOCK(unit); 4992 break; 4993 case SOC_BLK_ISM: 4994 block = ISM_BLOCK(unit); 4995 break; 4996 case SOC_BLK_ETU: 4997 block = ETU_BLOCK(unit); 4998 break; 4999 case SOC_BLK_ETU_WRAP: 5000 block = ETU_WRAP_BLOCK(unit); 5001 break; 5002 case SOC_BLK_IBOD: 5003 block = IBOD_BLOCK(unit); 5004 break; 5005 case SOC_BLK_LLS: 5006 block = LLS_BLOCK(unit); 5007 break; 5008 case SOC_BLK_CES: 5009 block = CES_BLOCK(unit); 5010 break; 5011 case SOC_BLK_PGW_CL: 5012 if (instance_mask) { 5013 instance = port; 5014 } else{ 5015 /* coverity[overrun-local : FALSE] */ 5016 instance = SOC_INFO(unit).port_group[port]; 5017 } 5018 block = PGW_CL_BLOCK(unit, instance); 5019 break; 5020 case SOC_BLK_PMQPORT: 5021 case SOC_BLK_PMQ: 5022 /* coverity[overrun-local : FALSE] */ 5023 block = PMQ_BLOCK(unit, blkport); 5024 break; 5025 case SOC_BLK_PGW_GE: 5026 block = PGW_GE_BLOCK(unit, instance); 5027 break; 5028 case SOC_BLK_IL: 5029 if (SOC_IS_SHADOW(unit)) { 5030 if (port == 9) { 5031 block = IL0_BLOCK(unit); 5032 } else if (port == 13) { 5033 block = IL1_BLOCK(unit); 5034 } 5035 pindex = 0; 5036 } 5037 break; 5038 case SOC_BLK_MS_ISEC: 5039 if (SOC_IS_SHADOW(unit)) { 5040 if (port >= 1 && port <= 4) { 5041 block = MS_ISEC0_BLOCK(unit); 5042 pindex = port - 1; 5043 } else { 5044 block = MS_ISEC1_BLOCK(unit); 5045 pindex = port - 5; 5046 } 5047 } 5048 break; 5049 case SOC_BLK_MS_ESEC: 5050 if (SOC_IS_SHADOW(unit)) { 5051 if (port >= 1 && port <= 4) { 5052 block = MS_ESEC0_BLOCK(unit); 5053 pindex = port - 1; 5054 } else { 5055 block = MS_ESEC1_BLOCK(unit); 5056 pindex = port - 5; 5057 } 5058 } 5059 break; 5060 case SOC_BLK_CW: 5061 if (SOC_IS_SHADOW(unit)) { 5062 block = CW_BLOCK(unit); 5063 } 5064 break; 5065 case SOC_BLK_CM: 5066 break; 5067 case SOC_BLK_CO: 5068 break; 5069 case SOC_BLK_CI: 5070 if (SOC_IS_KATANA2(unit)) { 5071 block = CI_BLOCK(unit, port); 5072 } 5073 break; 5074 case SOC_BLK_CX: 5075 break; 5076 case SOC_BLK_LRA: 5077 break; 5078 case SOC_BLK_LRB: 5079 break; 5080 case SOC_BLK_OC: 5081 break; 5082 case SOC_BLK_PB: 5083 break; 5084 case SOC_BLK_PD: 5085 break; 5086 case SOC_BLK_PP: 5087 break; 5088 case SOC_BLK_PR: 5089 break; 5090 case SOC_BLK_PT: 5091 break; 5092 case SOC_BLK_QM: 5093 break; 5094 case SOC_BLK_RC: 5095 break; 5096 case SOC_BLK_TMA: 5097 break; 5098 case SOC_BLK_TMB: 5099 break; 5100 case SOC_BLK_TM_QE: 5101 break; 5102 case SOC_BLK_TP: 5103 break; 5104 #if defined(BCM_KATANA2_SUPPORT) 5105 case SOC_BLK_TXLP: 5106 if (SOC_IS_KATANA2(unit)) { 5107 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 5108 SOC_BLK_TXLP, &block, &pindex); 5109 } 5110 break; 5111 case SOC_BLK_RXLP: 5112 if (SOC_IS_KATANA2(unit)) { 5113 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 5114 SOC_BLK_RXLP, &block, &pindex); 5115 } 5116 break; 5117 #endif 5118 case SOC_BLK_IECELL: 5119 #if defined(BCM_METROLITE_SUPPORT) 5120 if (SOC_IS_METROLITE(unit)) { 5121 soc_ml_iecell_port_reg_blk_idx_get(unit, port, 5122 SOC_BLK_IECELL, &block, &pindex); 5123 } 5124 #endif 5125 #if defined (BCM_SABER2_SUPPORT) 5126 if (SOC_IS_SABER2(unit)) { 5127 soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 5128 SOC_BLK_IECELL, &block, &pindex); 5129 } 5130 #endif 5131 break; 5132 /* DPP */ 5133 case SOC_BLK_CFC: 5134 #ifdef BCM_DNX_SUPPORT 5135 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5136 block = SOC_CORE_ALL; 5137 soc_blocks = SOC_INFO(unit).cfc_block; 5138 } else 5139 #endif 5140 { 5141 block = CFC_BLOCK(unit, blkport); 5142 } 5143 break; 5144 case SOC_BLK_OCB: 5145 block = OCB_BLOCK(unit, block_core); 5146 soc_blocks = SOC_INFO(unit).ocb_blocks; 5147 break; 5148 case SOC_BLK_CRPS: 5149 #ifdef BCM_DNX_SUPPORT 5150 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5151 block = SOC_CORE_ALL; 5152 soc_blocks = SOC_INFO(unit).crps_blocks; 5153 } else 5154 #endif 5155 { 5156 block = CRPS_BLOCK(unit, blkport); 5157 } 5158 break; 5159 case SOC_BLK_EPRE: 5160 block = EPRE_BLOCK(unit, block_core); 5161 soc_blocks = SOC_INFO(unit).epre_blocks; 5162 break; 5163 case SOC_BLK_IPPF: 5164 block = IPPF_BLOCK(unit, block_core); 5165 soc_blocks = SOC_INFO(unit).ippf_blocks; 5166 break; 5167 case SOC_BLK_MDB_ARM: 5168 block = MDB_ARM_BLOCK(unit); 5169 break; 5170 case SOC_BLK_CDPORT: 5171 block = CDPORT_BLOCK(unit, blkport); 5172 break; 5173 #ifdef BCM_DNX_SUPPORT 5174 case SOC_BLK_CLPORT: 5175 block = CLPORT_BLOCK(unit, blkport); 5176 break; 5177 #endif 5178 case SOC_BLK_CDMAC: 5179 block = CDMAC_BLOCK(unit, blkport); 5180 break; 5181 case SOC_BLK_FDTL: 5182 block = FDTL_BLOCK(unit); 5183 break; 5184 case SOC_BLK_ECI: 5185 block = ECI_BLOCK(unit); 5186 break; 5187 case SOC_BLK_EGQ: 5188 block = EGQ_BLOCK(unit, block_core); 5189 break; 5190 case SOC_BLK_FCR: 5191 block = FCR_BLOCK(unit); 5192 break; 5193 case SOC_BLK_FCT: 5194 block = FCT_BLOCK(unit); 5195 break; 5196 case SOC_BLK_FDR: 5197 #ifdef BCM_DNX_SUPPORT 5198 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5199 block = SOC_CORE_ALL; 5200 soc_blocks = SOC_INFO(unit).fdr_blocks; 5201 } else 5202 #endif 5203 { 5204 block = FDR_BLOCK(unit, blkport); 5205 } 5206 break; 5207 case SOC_BLK_FDA: 5208 block = FDA_BLOCK(unit); 5209 break; 5210 case SOC_BLK_FDT: 5211 block = FDT_BLOCK(unit); 5212 break; 5213 case SOC_BLK_MESH_TOPOLOGY: 5214 block = MESH_TOPOLOGY_BLOCK(unit); 5215 break; 5216 case SOC_BLK_IDR: 5217 block = IDR_BLOCK(unit); 5218 break; 5219 case SOC_BLK_IHB: 5220 block = IHB_BLOCK(unit, block_core); 5221 break; 5222 case SOC_BLK_IHP: 5223 block = IHP_BLOCK(unit, block_core); 5224 break; 5225 case SOC_BLK_IPS: 5226 block = IPS_BLOCK(unit, block_core); 5227 soc_blocks = SOC_INFO(unit).ips_blocks; 5228 break; 5229 case SOC_BLK_IPT: 5230 #ifdef BCM_DNX_SUPPORT 5231 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5232 block = SOC_CORE_ALL; 5233 soc_blocks = SOC_INFO(unit).ipt_blocks; 5234 } else 5235 #endif 5236 { 5237 block = IPT_BLOCK(unit, blkport); 5238 } 5239 break; 5240 case SOC_BLK_IQM: 5241 block = IQM_BLOCK(unit, block_core); 5242 soc_blocks = SOC_INFO(unit).iqm_blocks; 5243 break; 5244 case SOC_BLK_PQP: 5245 block = PQP_BLOCK(unit, block_core); 5246 soc_blocks = SOC_INFO(unit).pqp_blocks; 5247 break; 5248 case SOC_BLK_KAPS: 5249 block = KAPS_BLOCK(unit, blkport); 5250 break; 5251 case SOC_BLK_KAPS_BBS: 5252 block = KAPS_BBS_BLOCK(unit,instance); 5253 break; 5254 case SOC_BLK_ILB: 5255 block = ILB_BLOCK(unit); 5256 break; 5257 case SOC_BLK_IEP: 5258 block = IEP_BLOCK(unit); 5259 break; 5260 case SOC_BLK_IMP: 5261 block = IMP_BLOCK(unit); 5262 break; 5263 case SOC_BLK_SPB: 5264 block = SPB_BLOCK(unit, block_core); 5265 soc_blocks = SOC_INFO(unit).spb_blocks; 5266 break; 5267 case SOC_BLK_ITE: 5268 block = ITE_BLOCK(unit); 5269 break; 5270 case SOC_BLK_DDP: 5271 #ifdef BCM_DNX_SUPPORT 5272 if (block_core == SOC_CORE_ALL && SOC_IS_DNX(unit)) { 5273 block = SOC_CORE_ALL; 5274 soc_blocks = SOC_INFO(unit).ddp_blocks; 5275 } else 5276 #endif 5277 { 5278 block = DDP_BLOCK(unit, blkport); 5279 } 5280 break; 5281 case SOC_BLK_TXQ: 5282 block = TXQ_BLOCK(unit); 5283 break; 5284 case SOC_BLK_TAR: 5285 block = TAR_BLOCK(unit); 5286 break; 5287 case SOC_BLK_PTS: 5288 block = PTS_BLOCK(unit); 5289 break; 5290 case SOC_BLK_SQM: 5291 block = SQM_BLOCK(unit, blkport); 5292 break; 5293 case SOC_BLK_IPSEC: 5294 block = IPSEC_BLOCK(unit); 5295 break; 5296 case SOC_BLK_IPSEC_SPU_WRAPPER_TOP: 5297 block = IPSEC_SPU_WRAPPER_TOP_BLOCK(unit, instance); 5298 break; 5299 case SOC_BLK_DQM: 5300 block = DQM_BLOCK(unit, block_core); 5301 soc_blocks = SOC_INFO(unit).dqm_blocks; 5302 break; 5303 case SOC_BLK_ECGM: 5304 block = ECGM_BLOCK(unit, block_core); 5305 soc_blocks = SOC_INFO(unit).ecgm_blocks; 5306 break; 5307 case SOC_BLK_IDB: 5308 block = IDB_BLOCK(unit); 5309 break; 5310 case SOC_BLK_PEM: 5311 block = PEM_BLOCK(unit, blkport); 5312 break; 5313 5314 case SOC_BLK_IRE: 5315 #ifdef BCM_DNX_SUPPORT 5316 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5317 block = SOC_CORE_ALL; 5318 soc_blocks = SOC_INFO(unit).ire_blocks; 5319 } else 5320 #endif 5321 { 5322 block = IRE_BLOCK(unit, blkport); 5323 } 5324 break; 5325 case SOC_BLK_IRR: 5326 block = IRR_BLOCK(unit); 5327 break; 5328 case SOC_BLK_FMAC: 5329 block = FMAC_BLOCK(unit, blkport); 5330 break; 5331 case SOC_BLK_XLP: 5332 block = XLP_BLOCK(unit, blkport); 5333 break; 5334 case SOC_BLK_CLP: 5335 block = CLP_BLOCK(unit, blkport); 5336 break; 5337 case SOC_BLK_NBI: 5338 block = NBI_BLOCK(unit); 5339 break; 5340 case SOC_BLK_CGM: 5341 block = CGM_BLOCK(unit, block_core); 5342 soc_blocks = SOC_INFO(unit).cgm_blocks; 5343 break; 5344 case SOC_BLK_OAMP: 5345 block = OAMP_BLOCK(unit); 5346 break; 5347 case SOC_BLK_OLP: 5348 block = OLP_BLOCK(unit); 5349 break; 5350 case SOC_BLK_SIF: 5351 block = SIF_BLOCK(unit, block_core); 5352 soc_blocks = SOC_INFO(unit).sif_blocks; 5353 break; 5354 case SOC_BLK_MCP: 5355 block = MCP_BLOCK(unit, block_core); 5356 soc_blocks = SOC_INFO(unit).mcp_blocks; 5357 break; 5358 case SOC_BLK_ITPP: 5359 block = ITPP_BLOCK(unit, block_core); 5360 soc_blocks = SOC_INFO(unit).itpp_blocks; 5361 break; 5362 case SOC_BLK_ITPPD: 5363 block = ITPPD_BLOCK(unit, block_core); 5364 soc_blocks = SOC_INFO(unit).itppd_blocks; 5365 break; 5366 case SOC_BLK_PDM: 5367 block = PDM_BLOCK(unit, block_core); 5368 soc_blocks = SOC_INFO(unit).pdm_blocks; 5369 break; 5370 case SOC_BLK_BDM: 5371 block = BDM_BLOCK(unit, block_core); 5372 soc_blocks = SOC_INFO(unit).bdm_blocks; 5373 break; 5374 case SOC_BLK_CDU: 5375 block = CDU_BLOCK(unit, blkport); 5376 break; 5377 case SOC_BLK_CDUM: 5378 block = CDUM_BLOCK(unit, block_core); 5379 soc_blocks = SOC_INFO(unit).cdum_blocks; 5380 break; 5381 case SOC_BLK_EPS: 5382 block = EPS_BLOCK(unit, block_core); 5383 soc_blocks = SOC_INFO(unit).eps_blocks; 5384 break; 5385 5386 case SOC_BLK_DDHA: 5387 block = DDHA_BLOCK(unit, blkport); 5388 break; 5389 5390 case SOC_BLK_DDHB: 5391 block = DDHB_BLOCK(unit, blkport); 5392 break; 5393 5394 case SOC_BLK_DHC: 5395 block = DHC_BLOCK(unit, blkport); 5396 break; 5397 5398 case SOC_BLK_DMU: 5399 block = DMU_BLOCK(unit, blkport); 5400 break; 5401 5402 case SOC_BLK_ETPPC: 5403 block = ETPPC_BLOCK(unit, block_core); 5404 soc_blocks = SOC_INFO(unit).etppc_blocks; 5405 break; 5406 5407 case SOC_BLK_EVNT: 5408 block = EVNT_BLOCK(unit, blkport); 5409 break; 5410 5411 case SOC_BLK_HBC: 5412 block = HBC_BLOCK(unit, blkport); 5413 break; 5414 5415 case SOC_BLK_ILE: 5416 block = ILE_BLOCK(unit, block_core); 5417 soc_blocks = SOC_INFO(unit).ile_blocks; 5418 break; 5419 case SOC_BLK_CLU: 5420 block = CLU_BLOCK(unit, block_core); 5421 soc_blocks = SOC_INFO(unit).clu_blocks; 5422 break; 5423 case SOC_BLK_CLUP: 5424 block = CLUP_BLOCK(unit, block_core); 5425 soc_blocks = SOC_INFO(unit).clup_blocks; 5426 break; 5427 case SOC_BLK_CLMAC: 5428 block = CLMAC_BLOCK(unit, block_core); 5429 soc_blocks = SOC_INFO(unit).clmac_blocks; 5430 break; 5431 case SOC_BLK_ESB: 5432 block = ESB_BLOCK(unit); 5433 break; 5434 case SOC_BLK_ILU: 5435 block = ILU_BLOCK(unit, blkport); 5436 break; 5437 case SOC_BLK_NMG: 5438 block = NMG_BLOCK(unit, block_core); 5439 soc_blocks = SOC_INFO(unit).nmg_blocks; 5440 break; 5441 5442 case SOC_BLK_IPPE: 5443 block = IPPE_BLOCK(unit, block_core); 5444 soc_blocks = SOC_INFO(unit).ippe_blocks; 5445 break; 5446 5447 case SOC_BLK_TCAM: 5448 block = TCAM_BLOCK(unit, block_core); 5449 soc_blocks = SOC_INFO(unit).tcam_blocks; 5450 break; 5451 5452 case SOC_BLK_TDU: 5453 block = TDU_BLOCK(unit, block_core); 5454 soc_blocks = SOC_INFO(unit).tdu_blocks; 5455 break; 5456 5457 case SOC_BLK_MTM: 5458 block = MTM_BLOCK(unit); 5459 break; 5460 case SOC_BLK_HBM: 5461 block = HBM_BLOCK(unit, blkport); 5462 break; 5463 case SOC_BLK_RQP: 5464 block = RQP_BLOCK(unit, block_core); 5465 soc_blocks = SOC_INFO(unit).rqp_blocks; 5466 break; 5467 case SOC_BLK_FQP: 5468 block = FQP_BLOCK(unit, block_core); 5469 soc_blocks = SOC_INFO(unit).fqp_blocks; 5470 break; 5471 case SOC_BLK_HBMC: 5472 block = HBMC_BLOCK(unit, blkport); 5473 break; 5474 case SOC_BLK_MDB: 5475 block = MDB_BLOCK(unit); 5476 break; 5477 case SOC_BLK_ERPP: 5478 block = ERPP_BLOCK(unit, block_core); 5479 soc_blocks = SOC_INFO(unit).erpp_blocks; 5480 break; 5481 case SOC_BLK_ETPPA: 5482 block = ETPPA_BLOCK(unit, block_core); 5483 soc_blocks = SOC_INFO(unit).etppa_blocks; 5484 break; 5485 case SOC_BLK_ETPPB: 5486 block = ETPPB_BLOCK(unit, block_core); 5487 soc_blocks = SOC_INFO(unit).etppb_blocks; 5488 break; 5489 case SOC_BLK_MACT: 5490 block = MACT_BLOCK(unit); 5491 break; 5492 case SOC_BLK_IPPA: 5493 block = IPPA_BLOCK(unit, block_core); 5494 soc_blocks = SOC_INFO(unit).ippa_blocks; 5495 break; 5496 case SOC_BLK_IPPB: 5497 block = IPPB_BLOCK(unit, block_core); 5498 soc_blocks = SOC_INFO(unit).ippb_blocks; 5499 break; 5500 case SOC_BLK_IPPC: 5501 block = IPPC_BLOCK(unit, block_core); 5502 soc_blocks = SOC_INFO(unit).ippc_blocks; 5503 break; 5504 case SOC_BLK_IPPD: 5505 block = IPPD_BLOCK(unit, block_core); 5506 soc_blocks = SOC_INFO(unit).ippd_blocks; 5507 break; 5508 case SOC_BLK_FSRD: 5509 block = FSRD_BLOCK(unit, blkport); 5510 break; 5511 case SOC_BLK_RTP: 5512 block = RTP_BLOCK(unit); 5513 break; 5514 case SOC_BLK_SCH: 5515 block = SCH_BLOCK(unit, block_core); 5516 soc_blocks = SOC_INFO(unit).sch_blocks; 5517 break; 5518 case SOC_BLK_EPNI: 5519 block = EPNI_BLOCK(unit, block_core); 5520 soc_blocks = SOC_INFO(unit).epni_blocks; 5521 break; 5522 case SOC_BLK_DRCA: 5523 block = DRCA_BLOCK(unit); 5524 break; 5525 case SOC_BLK_DRCB: 5526 block = DRCB_BLOCK(unit); 5527 break; 5528 case SOC_BLK_DRCC: 5529 block = DRCC_BLOCK(unit); 5530 break; 5531 case SOC_BLK_DRCD: 5532 block = DRCD_BLOCK(unit); 5533 break; 5534 case SOC_BLK_DRCE: 5535 block = DRCE_BLOCK(unit); 5536 break; 5537 case SOC_BLK_DRCF: 5538 block = DRCF_BLOCK(unit); 5539 break; 5540 case SOC_BLK_DRCG: 5541 block = DRCG_BLOCK(unit); 5542 break; 5543 case SOC_BLK_DRCH: 5544 block = DRCH_BLOCK(unit); 5545 break; 5546 case SOC_BLK_EDB: 5547 #ifdef BCM_DNX_SUPPORT 5548 if (SOC_IS_DNX(unit) && block_core == SOC_CORE_ALL) { 5549 block = SOC_CORE_ALL; 5550 soc_blocks = SOC_INFO(unit).edb_blocks; 5551 } else 5552 #endif 5553 { 5554 block = EDB_BLOCK(unit, blkport); 5555 } 5556 break; 5557 case SOC_BLK_ILKN_PMH: 5558 block = ILKN_PMH_BLOCK(unit); 5559 break; 5560 case SOC_BLK_IPST: 5561 block = IPST_BLOCK(unit); 5562 break; 5563 case SOC_BLK_IQMT: 5564 block = IQMT_BLOCK(unit); 5565 break; 5566 case SOC_BLK_PPDB_A: 5567 block = PPDB_A_BLOCK(unit); 5568 break; 5569 case SOC_BLK_PPDB_B: 5570 block = PPDB_B_BLOCK(unit); 5571 break; 5572 case SOC_BLK_ILKN_PML: 5573 block = ILKN_PML_BLOCK(unit, blkport); 5574 break; 5575 case SOC_BLK_MRPS: 5576 block = MRPS_BLOCK(unit, instance); 5577 soc_blocks = SOC_INFO(unit).mrps_blocks; 5578 break; 5579 case SOC_BLK_MTRPS_EM: 5580 block = MTRPS_EM_BLOCK(unit, instance); 5581 break; 5582 case SOC_BLK_NBIL: 5583 block = NBIL_BLOCK(unit, blkport); 5584 break; 5585 case SOC_BLK_NBIH: 5586 block = NBIH_BLOCK(unit); 5587 break; 5588 case SOC_BLK_DRCBROADCAST: 5589 block = DRCBROADCAST_BLOCK(unit); 5590 break; 5591 case SOC_BLK_BRDC_FSRD: 5592 block = BRDC_FSRD_BLOCK(unit); 5593 break; 5594 case SOC_BLK_BRDC_FMAC: 5595 block = BRDC_FMAC_BLOCK(unit); 5596 break; 5597 case SOC_BLK_BRDC_HBC: 5598 block = BRDC_HBC_BLOCK(unit); 5599 break; 5600 case SOC_BLK_BRDC_CCH: 5601 block = BRDC_CCH_BLOCK(unit); 5602 break; 5603 case SOC_BLK_BRDC_CGM: 5604 block = BRDC_CGM_BLOCK(unit); 5605 break; 5606 case SOC_BLK_BRDC_EGQ: 5607 block = BRDC_EGQ_BLOCK(unit); 5608 break; 5609 case SOC_BLK_BRDC_EPNI: 5610 block = BRDC_EPNI_BLOCK(unit); 5611 break; 5612 case SOC_BLK_BRDC_IHB: 5613 block = BRDC_IHB_BLOCK(unit); 5614 break; 5615 case SOC_BLK_BRDC_IHP: 5616 block = BRDC_IHP_BLOCK(unit); 5617 break; 5618 case SOC_BLK_BRDC_IPS: 5619 block = BRDC_IPS_BLOCK(unit); 5620 break; 5621 case SOC_BLK_BRDC_IQM: 5622 block = BRDC_IQM_BLOCK(unit); 5623 break; 5624 case SOC_BLK_BRDC_SCH: 5625 block = BRDC_SCH_BLOCK(unit); 5626 break; 5627 #ifdef DNX_TEST_CHIPS_SUPPORT 5628 case SOC_BLK_PRM: 5629 block = PRM_BLOCK(unit); 5630 break; 5631 case SOC_BLK_BLH: 5632 block = BLH_BLOCK(unit, blkport); 5633 break; 5634 case SOC_BLK_AM_TOP: 5635 block = AM_TOP_BLOCK(unit); 5636 break; 5637 #endif /* DNX_TEST_CHIPS_SUPPORT */ 5638 /* DFE blocks*/ 5639 case SOC_BLK_DCH: 5640 block=DCH_BLOCK(unit,blkport); 5641 break; 5642 case SOC_BLK_DCL: 5643 block=DCL_BLOCK(unit,blkport); 5644 break; 5645 case SOC_BLK_OCCG: 5646 block=OCCG_BLOCK(unit); 5647 break; 5648 case SOC_BLK_DCM: 5649 block=DCM_BLOCK(unit,blkport); 5650 break; 5651 case SOC_BLK_DCMC: 5652 block = DCMC_BLOCK(unit); 5653 break; 5654 case SOC_BLK_CCS: 5655 block=CCS_BLOCK(unit,blkport); 5656 break; 5657 case SOC_BLK_BRDC_FMAC_AC: 5658 block=BRDC_FMAC_AC_BLOCK(unit); 5659 break; 5660 case SOC_BLK_BRDC_FMAC_BD: 5661 block=BRDC_FMAC_BD_BLOCK(unit); 5662 break; 5663 case SOC_BLK_BRDC_DCH: 5664 block=BRDC_DCH_BLOCK(unit); 5665 break; 5666 case SOC_BLK_BRDC_DCL: 5667 block=BRDC_DCL_BLOCK(unit); 5668 break; 5669 case SOC_BLK_BRDC_DCM: 5670 block=BRDC_DCM_BLOCK(unit); 5671 break; 5672 case SOC_BLK_BRDC_CCS: 5673 block=BRDC_CCS_BLOCK(unit); 5674 break; 5675 case SOC_BLK_DCML: 5676 block=DCML_BLOCK(unit, blkport); 5677 break; 5678 case SOC_BLK_MCT: 5679 block=MCT_BLOCK(unit); 5680 break; 5681 case SOC_BLK_QRH: 5682 block=QRH_BLOCK(unit, blkport); 5683 break; 5684 case SOC_BLK_CCH: 5685 block=CCH_BLOCK(unit, blkport); 5686 break; 5687 case SOC_BLK_LCM: 5688 block=LCM_BLOCK(unit, blkport); 5689 break; 5690 case SOC_BLK_BRDC_DCML: 5691 block=BRDC_DCML_BLOCK(unit); 5692 break; 5693 case SOC_BLK_BRDC_QRH: 5694 block=BRDC_QRH_BLOCK(unit); 5695 break; 5696 case SOC_BLK_BRDC_LCM: 5697 block=BRDC_LCM_BLOCK(unit); 5698 break; 5699 case SOC_BLK_GPORT: 5700 block=GPORT_BLOCK(unit, blkport); 5701 break; 5702 case SOC_BLK_MXQ: 5703 block=MXQ_BLOCK(unit, blkport); 5704 break; 5705 case SOC_BLK_PLL: 5706 block=PLL_BLOCK(unit); 5707 break; 5708 case SOC_BLK_NIF: 5709 block=NIF_BLOCK(unit); 5710 break; 5711 case SOC_BLK_MMU_ITM: 5712 block = MMU_ITM_BLOCK(unit); 5713 break; 5714 case SOC_BLK_MMU_EB: 5715 block = MMU_EB_BLOCK(unit); 5716 break; 5717 case SOC_BLK_CEV: 5718 block = CEV_BLOCK(unit); 5719 break; 5720 case SOC_BLK_MACSEC : 5721 block = MACSEC_BLOCK(unit); 5722 break; 5723 case SOC_BLK_TAF: 5724 block = TAF_BLOCK(unit); 5725 break; 5726 default: 5727 block = -1; /* unknown non-port block */ 5728 break; 5729 } 5730 } else if(block_id_mask) { 5731 block = port; 5732 } 5733 5734 if(!schan_id_mask) { 5735 if(block < 0) { 5736 assert(block == SOC_CORE_ALL); /* block must be valid */ 5737 } 5738 } 5739 5740 /* determine final block, pindex, and index */ 5741 gransh = 0; 5742 switch (SOC_REG_INFO(unit, reg).regtype) { 5743 case soc_cpureg: 5744 case soc_mcsreg: 5745 case soc_iprocreg: 5746 block = -1; 5747 pindex = 0; 5748 gransh = 2; /* 4 byte granularity */ 5749 break; 5750 case soc_ppportreg: 5751 case soc_portreg: 5752 if (!SOC_BLOCK_IN_LIST(regblktype, portblktype) && 5753 !(SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_MS_ISEC)) && 5754 !(SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_MS_ESEC)) && 5755 !(SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_TXLP)) && 5756 !(SOC_BLOCK_IN_LIST(regblktype, SOC_BLK_RXLP))) { 5757 if (soc_feature(unit, soc_feature_logical_port_num) && 5758 (block == MMU_BLOCK(unit) || 5759 block == MMU_SED_BLOCK(unit) || 5760 block == MMU_GLB_BLOCK(unit) || 5761 block == MMU_XPE_BLOCK(unit) || 5762 block == MMU_SED_BLOCK(unit) || 5763 block == MMU_ITM_BLOCK(unit) || 5764 block == MMU_EB_BLOCK(unit) || 5765 block == MMU_SC_BLOCK(unit))) { 5766 if (preserve_port) { 5767 phy_port = port; 5768 pindex = port; 5769 } else { 5770 #ifdef BCM_TOMAHAWK3_SUPPORT 5771 /*MMU register with device port indexing*/ 5772 num_regs = sizeof(reg_excep_list) / sizeof(soc_reg_t); 5773 for (reg_index = 0;reg_index < num_regs; reg_index++) { 5774 if (reg_excep_list[reg_index] == reg) { 5775 add_exception = 1; 5776 break; 5777 } 5778 } 5779 if (add_exception) { 5780 pindex = port; 5781 } else 5782 5783 #endif 5784 { 5785 /* coverity[overrun-local : FALSE] */ 5786 /* coverity[negative_returns : FALSE] */ 5787 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 5788 pindex = SOC_INFO(unit).port_p2m_mapping[phy_port]; 5789 if (pindex < 0) { 5790 pindex = SOC_INFO(unit).max_port_p2m_mapping[phy_port]; 5791 } 5792 assert(pindex >= 0); 5793 } 5794 } 5795 #ifdef BCM_TRIUMPH3_SUPPORT 5796 /* We do not want any more of these exceptions in the code */ 5797 if (SOC_IS_TRIUMPH3(unit) && (reg == MMU_INTFO_CONGST_STr)) { 5798 pindex = port; 5799 } 5800 #endif 5801 } else { 5802 pindex = port; 5803 #if defined(BCM_METROLITE_SUPPORT) 5804 METROLITE_GET_REG_THDI_PORT(unit, port, reg, pindex) 5805 #endif 5806 } 5807 gransh = 8; 5808 } 5809 #ifdef BCM_TOMAHAWK3_SUPPORT 5810 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 5811 stage does this port belong to for the per port registers. 5812 For CDPORT registers, the stage is 0 and CDMAC_0 registers, it is 1 5813 while for CDMAC_1 it is 2 */ 5814 if (SOC_IS_TOMAHAWK3(unit)) { 5815 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CDPORT)) { 5816 if ((SOC_REG_INFO(unit, reg).offset & 0x000F0000) == 5817 CDMAC_OFFSET_CNT) { 5818 stage_id = ((((phy_port - 1) >> 2) & 1) == 0) ? 5819 CDMAC0_STAGE_ID : CDMAC1_STAGE_ID; 5820 if (stage_id == CDMAC0_STAGE_ID) { 5821 pindex = pindex | 0x04000000; 5822 break; 5823 } else { 5824 pindex = pindex & 3; 5825 pindex = pindex | 0x08000000; 5826 break; 5827 } 5828 } 5829 } 5830 } 5831 #endif 5832 #ifdef BCM_DNX_SUPPORT 5833 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 5834 stage does this port belong to for the per port registers. 5835 For CDPORT registers, the stage is 0 and CDMAC_0 registers, it is 1 5836 while for CDMAC_1 it is 2 */ 5837 if (SOC_IS_DNX(unit) && SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CDMAC) && 5838 (SOC_REG_INFO(unit, reg).offset & 0x000F0000) == CDMAC_OFFSET_CNT) { 5839 if ((phy_port & 4) == 0) { /* is it CDMAC0_STAGE_ID */ 5840 pindex = pindex | 0x04000000; 5841 } else { 5842 pindex = pindex & 3; 5843 pindex = pindex | 0x08000000; 5844 } 5845 } 5846 #endif 5847 5848 break; 5849 case soc_cosreg: 5850 assert(index >= 0 && index < NUM_COS(unit)); 5851 pindex = index; 5852 index = 0; 5853 break; 5854 case soc_pipereg: 5855 case soc_xpereg: 5856 case soc_itmreg: 5857 case soc_ebreg: 5858 case soc_slicereg: 5859 case soc_layerreg: 5860 gransh = 8; 5861 pindex = port; 5862 break; 5863 case soc_customreg: 5864 case soc_genreg: 5865 gransh = 8; 5866 pindex = 0; 5867 #ifdef BCM_TOMAHAWK3_SUPPORT 5868 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 5869 * CDMAC/stage id does this register belong to. 5870 * For CDMAC_0 registers, it is 1, while for CDMAC_1 it is 2 */ 5871 if (SOC_IS_TOMAHAWK3(unit)) { 5872 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CDPORT)) { 5873 if ((SOC_REG_INFO(unit, reg).offset & 0x000F0000) == 5874 CDMAC_OFFSET_CNT) { 5875 stage_id = ((((phy_port - 1) >> 2) & 1) == 0) ? 5876 CDMAC0_STAGE_ID : CDMAC1_STAGE_ID; 5877 if (stage_id == CDMAC0_STAGE_ID) { 5878 pindex = pindex | 0x04000000; 5879 break; 5880 } else { 5881 pindex = pindex | 0x08000000; 5882 break; 5883 } 5884 } 5885 } 5886 } 5887 #endif 5888 if (SOC_IS_GREYHOUND2(unit) && 5889 (block == TAF_BLOCK(unit))) { 5890 /* Base address decision of GH2 TAF block */ 5891 gransh = 0; 5892 pindex = index; 5893 index = 0; 5894 } else { 5895 gransh = 8; 5896 pindex = 0; 5897 #ifdef BCM_DNX_SUPPORT 5898 /* Since there are two CDMAC0 and CDMAC1, we need to determine which 5899 * CDMAC/stage id does this register belong to. 5900 * For CDMAC_0 registers, it is 1, while for CDMAC_1 it is 2 */ 5901 if (SOC_IS_DNX(unit) && SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CDMAC)) { 5902 if ((SOC_REG_INFO(unit, reg).offset & 0x000F0000) == CDMAC_OFFSET_CNT) { 5903 5904 if (instance_mask) 5905 { 5906 /* use the block instance for selecting CDMAC stage */ 5907 pindex = ((port & 1) == 0) ? 0x04000000 : 0x08000000; 5908 } 5909 else 5910 { 5911 if ((phy_port & 4) == 0) { /* is it CDMAC0_STAGE_ID */ 5912 pindex = pindex | 0x04000000; 5913 } else { 5914 pindex = pindex | 0x08000000; 5915 } 5916 } 5917 5918 } 5919 } 5920 #endif 5921 } 5922 break; 5923 default: 5924 assert(0); /* unknown register type */ 5925 break; 5926 } 5927 5928 /* put together address: base|block|pindex + index */ 5929 base = SOC_REG_INFO(unit, reg).offset; 5930 5931 /* Base address decision of GH2 TAF block */ 5932 if (SOC_IS_GREYHOUND2(unit) && 5933 (SOC_REG_INFO(unit, reg).regtype == soc_genreg) && 5934 (block == TAF_BLOCK(unit)) && 5935 (SOC_REG_NUMELS(unit, reg) == 128)) { 5936 base &= ~(1 << SOC_RT_BP); 5937 } 5938 5939 LOG_VERBOSE(BSL_LS_SOC_REG, 5940 (BSL_META_U(unit, 5941 "base: %x "), base)); 5942 5943 if(schan_id_mask) { 5944 access_info->blk_list[0] = port; 5945 } else if (block >= 0) { 5946 access_info->blk_list[0] = SOC_BLOCK_INFO(unit, block).cmic; 5947 } else if (block == SOC_CORE_ALL) { 5948 if (SOC_IS_DNX(unit)) { 5949 /* Fill the output s-channel block ID list */ 5950 #ifdef BCM_DNX_SUPPORT 5951 /* Get the number of active cores */ 5952 access_info->num_blks = dnx_data_device.general.nof_cores_get(unit); 5953 for (block_core = 0; block_core < access_info->num_blks; ++block_core) { 5954 access_info->blk_list[block_core] = soc_blocks != NULL ? SOC_BLOCK_INFO(unit, soc_blocks[block_core]).cmic : -1; 5955 } 5956 #endif /* BCM_DNX_SUPPORT */ 5957 } else { 5958 access_info->blk_list[0] = soc_blocks != NULL ? SOC_BLOCK_INFO(unit, soc_blocks[0]).cmic : -1; 5959 } 5960 5961 } 5962 if (pindex != -1) { 5963 base |= pindex; 5964 } 5965 5966 if (SOC_REG_IS_ARRAY(unit, reg)) { 5967 assert(index >= SOC_REG_INFO(unit, reg).first_array_index && index < SOC_REG_NUMELS(unit, reg) + SOC_REG_INFO(unit, reg).first_array_index); 5968 #if defined(BCM_SABER2_SUPPORT) 5969 if (SOC_IS_SABER2(unit) && block == OAMP_BLOCK(unit)) { 5970 base += (index - SOC_REG_INFO(unit, reg).first_array_index)*(SOC_REG_ELEM_SKIP(unit, reg) << 8); 5971 } else 5972 #endif 5973 { 5974 base += (index - SOC_REG_INFO(unit, reg).first_array_index)*SOC_REG_ELEM_SKIP(unit, reg); 5975 } 5976 } else if (index && SOC_REG_ARRAY(unit, reg)) { 5977 if (index && SOC_REG_ARRAY2(unit, reg)) { 5978 assert(index >= 0 && index < 2 * SOC_REG_NUMELS(unit, reg)); 5979 base += ((index*2) << gransh); 5980 } else if (index && SOC_REG_ARRAY4(unit, reg)) { 5981 assert(index >= 0 && index < 4 * SOC_REG_NUMELS(unit, reg)); 5982 base += ((index * 4) << gransh); 5983 } else { 5984 assert(index >= 0 && index < SOC_REG_NUMELS(unit, reg)); 5985 base += (index << gransh); 5986 } 5987 } 5988 LOG_VERBOSE(BSL_LS_SOC_REG, 5989 (BSL_META_U(unit, 5990 "addr new: %x, block: %d, index: %d, pindex: %d, gransh: %d\n"), 5991 base, access_info->blk_list[0], index, pindex, gransh)); 5992 access_info->offset = base; 5993 return SOC_E_NONE; 5994 } 5995 5996 5997 /* 5998 * Function: soc_reg_addr_get 5999 * Purpose: calculate the address of a register 6000 * Parameters: 6001 * unit - SOC unit number 6002 * reg - Register number 6003 * port - Port number or REG_PORT_ANY 6004 * index - Array index (or cos number) 6005 * options - Flag to indicate special handling to calculate 6006 * the HW register address: SOC_REG_ADDR_OPTION_xxx 6007 * blk - (OUT) ... 6008 * acc_type - (OUT) Register access type 6009 * 6010 * Returns: register address suitable for soc_reg_get and friends 6011 * Notes: the block number to access is determined by the register 6012 * and the port number 6013 * 6014 * cpureg 00SSSSSS 00000000 0000RRRR RRRRRRRR 6015 * genreg 00SSSSSS BBBB1000 0000RRRR RRRRRRRR 6016 * portreg 00SSSSSS BBBB00PP PPPPRRRR RRRRRRRR 6017 * cosreg 00SSSSSS BBBB01CC CCCCRRRR RRRRRRRR 6018 * 6019 * all regs of bcm88230 6020 * 00000000 00001000 0000RRRR RRRRRRRR 6021 * 6022 * where B+ is the 4 bit block number 6023 * P+ is the 6 bit port number (within a block or chip wide) 6024 * C+ is the 6 bit class of service 6025 * R+ is the 12 bit register number 6026 * S+ is the 6 bit Pipe stage 6027 */ 6028 uint32 6029 soc_reg_addr_get(int unit, soc_reg_t reg, int port, int index, uint32 options, 6030 int *blk, uint8 *acc_type) 6031 { 6032 soc_reg_access_info_t access_info; 6033 6034 if (soc_reg_xaddr_get(unit, reg, port, index, options, &access_info) == SOC_E_NONE) { 6035 if (access_info.num_blks > 0) { 6036 *blk = access_info.blk_list[0]; /* (single) s-channel block ID */ 6037 *acc_type = access_info.acc_type; /* access type */ 6038 } 6039 return access_info.offset; /* register offset/address in its block */ 6040 } 6041 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 6042 "soc_reg_addr_get: failed to get register address"))); 6043 return -1; /* invalid address */ 6044 } 6045 6046 int 6047 soc_regaddrlist_alloc(soc_regaddrlist_t *addrlist) 6048 { 6049 if ((addrlist->ainfo = sal_alloc(_SOC_MAX_REGLIST * 6050 sizeof(soc_regaddrinfo_t), "regaddrlist")) == NULL) { 6051 return SOC_E_MEMORY; 6052 } 6053 addrlist->count = 0; 6054 memset(addrlist->ainfo, 0, sizeof(soc_regaddrinfo_t)); 6055 6056 return SOC_E_NONE; 6057 } 6058 6059 int 6060 soc_regaddrlist_free(soc_regaddrlist_t *addrlist) 6061 { 6062 if (addrlist->ainfo) { 6063 sal_free(addrlist->ainfo); 6064 } 6065 6066 return SOC_E_NONE; 6067 } 6068 6069 /* 6070 * Function: soc_reg_fields32_modify 6071 * Purpose: Modify the value of a fields in a register. 6072 * Parameters: 6073 * unit - (IN) SOC unit number. 6074 * reg - (IN) Register. 6075 * port - (IN) Port number. 6076 * field_count - (IN) Number of fields to modify. 6077 * fields - (IN) Modified fields array. 6078 * values - (IN) New value for each member of fields array. 6079 * Returns: 6080 * BCM_E_XXX 6081 */ 6082 int 6083 soc_reg_fields32_modify(int unit, soc_reg_t reg, soc_port_t port, 6084 int field_count, soc_field_t *fields, uint32 *values) 6085 { 6086 uint64 data64; /* Current 64 bit register data. */ 6087 uint64 odata64; /* Original 64 bit register data. */ 6088 uint32 data32; /* Current 32 bit register data. */ 6089 uint32 odata32; /* Original 32 bit register data. */ 6090 uint32 reg_addr; /* Register address. */ 6091 int idx; /* Iteration index. */ 6092 uint32 max_val; /* Max value to fit the field */ 6093 int field_len; /* Bit length of the field */ 6094 6095 /* Check that register is a valid one for this unit. */ 6096 if (!SOC_REG_IS_VALID(unit, reg)) { 6097 return SOC_E_PARAM; 6098 } 6099 6100 if ((NULL == fields) || (NULL == values)) { 6101 return SOC_E_PARAM; 6102 } 6103 6104 /* Fields & values sanity check. */ 6105 for (idx = 0; idx < field_count; idx++) { 6106 6107 /* Make sure field is present in register. */ 6108 if (!soc_reg_field_valid(unit, reg, fields[idx])) { 6109 return SOC_E_PARAM; 6110 } 6111 /* Make sure value can fit into field */ 6112 field_len = soc_reg_field_length(unit, reg, fields[idx]); 6113 max_val = (field_len < 32) ? ((1 << field_len) - 1) : 0xffffffff; 6114 if (values[idx] > max_val) { 6115 return SOC_E_PARAM; 6116 } 6117 } 6118 6119 if (soc_feature(unit, soc_feature_new_sbus_format)) { 6120 if (SOC_REG_IS_64(unit, reg)) { 6121 6122 /* Read current register value. */ 6123 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &data64)); 6124 odata64 = data64; 6125 6126 /* Update fields with new values. */ 6127 for (idx = 0; idx < field_count; idx ++) { 6128 soc_reg64_field32_set(unit, reg, &data64, fields[idx], values[idx]); 6129 } 6130 if (COMPILER_64_NE(data64, odata64)) { 6131 /* Write new register value back to hw. */ 6132 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, port, 0, data64)); 6133 } 6134 } else { 6135 if (soc_cpureg == SOC_REG_TYPE(unit, reg)) { 6136 reg_addr = soc_reg_addr(unit, reg, REG_PORT_ANY, port); 6137 /* Read PCI register value. */ 6138 SOC_IF_ERROR_RETURN(soc_pci_getreg(unit, reg_addr, &data32)); 6139 #ifdef BCM_IPROC_SUPPORT 6140 } else if (soc_iprocreg == SOC_REG_TYPE(unit, reg)) { 6141 reg_addr = soc_reg_addr(unit, reg, REG_PORT_ANY, port); 6142 SOC_IF_ERROR_RETURN(soc_iproc_getreg(unit, reg_addr, &data32)); 6143 #endif 6144 } else { 6145 reg_addr = 0; /* Compiler warning defense. */ 6146 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &data32)); 6147 } 6148 odata32 = data32; 6149 6150 for (idx = 0; idx < field_count; idx ++) { 6151 soc_reg_field_set(unit, reg, &data32, fields[idx], values[idx]); 6152 } 6153 if (data32 != odata32) { 6154 /* Write new register value back to hw. */ 6155 if (soc_cpureg == SOC_REG_TYPE(unit, reg)) { 6156 SOC_IF_ERROR_RETURN(soc_pci_write(unit, reg_addr, data32)); 6157 #ifdef BCM_IPROC_SUPPORT 6158 } else if (soc_iprocreg == SOC_REG_TYPE(unit, reg)) { 6159 SOC_IF_ERROR_RETURN(soc_iproc_setreg(unit, reg_addr, data32)); 6160 #endif 6161 } else { 6162 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, data32)); 6163 } 6164 } 6165 } 6166 } else { 6167 /* Calculate register address. */ 6168 reg_addr = soc_reg_addr(unit, reg, port, 0); 6169 6170 if (SOC_REG_IS_64(unit, reg)) { 6171 6172 /* Read current register value. */ 6173 SOC_IF_ERROR_RETURN(soc_reg64_read(unit, reg_addr, &data64)); 6174 odata64 = data64; 6175 6176 /* Update fields with new values. */ 6177 for (idx = 0; idx < field_count; idx ++) { 6178 soc_reg64_field32_set(unit, reg, &data64, fields[idx], values[idx]); 6179 } 6180 if (COMPILER_64_NE(data64, odata64)) { 6181 #if defined(BCM_XGS_SUPPORT) 6182 if (soc_feature(unit, soc_feature_regs_as_mem)) { 6183 (void)soc_ser_reg_cache_set(unit, reg, port, 0, data64); 6184 } 6185 #endif /* BCM_XGS_SUPPORT */ 6186 /* Write new register value back to hw. */ 6187 SOC_IF_ERROR_RETURN(soc_reg64_write(unit, reg_addr, data64)); 6188 } 6189 } else { 6190 if (soc_cpureg == SOC_REG_TYPE(unit, reg)) { 6191 reg_addr = soc_reg_addr(unit, reg, REG_PORT_ANY, port); 6192 /* Read PCI register value. */ 6193 /* coverity[result_independent_of_operands] */ 6194 SOC_IF_ERROR_RETURN(soc_pci_getreg(unit, reg_addr, &data32)); 6195 } else { 6196 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, reg_addr, &data32)); 6197 } 6198 6199 odata32 = data32; 6200 6201 for (idx = 0; idx < field_count; idx ++) { 6202 soc_reg_field_set(unit, reg, &data32, fields[idx], values[idx]); 6203 } 6204 if (data32 != odata32) { 6205 /* Write new register value back to hw. */ 6206 if (soc_cpureg == SOC_REG_TYPE(unit, reg)) { 6207 /* coverity[result_independent_of_operands] */ 6208 SOC_IF_ERROR_RETURN(soc_pci_write(unit, reg_addr, data32)); 6209 } else { 6210 #if defined(BCM_XGS_SUPPORT) 6211 if (soc_feature(unit, soc_feature_regs_as_mem)) { 6212 (void)soc_ser_reg32_cache_set(unit, reg, port, 0, data32); 6213 } 6214 #endif /* BCM_XGS_SUPPORT */ 6215 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, reg_addr, data32)); 6216 } 6217 } 6218 } 6219 } 6220 return (SOC_E_NONE); 6221 } 6222 6223 /* 6224 * Function: soc_reg_field32_modify 6225 * Purpose: Modify the value of a field in a register. 6226 * Parameters: 6227 * unit - (IN) SOC unit number. 6228 * reg - (IN) Register. 6229 * port - (IN) Port number. 6230 * field - (IN) Modified field. 6231 * value - (IN) New field value. 6232 * Returns: 6233 * SOC_E_XXX 6234 */ 6235 int 6236 soc_reg_field32_modify(int unit, soc_reg_t reg, soc_port_t port, 6237 soc_field_t field, uint32 value) 6238 { 6239 return soc_reg_fields32_modify(unit, reg, port, 1, &field, &value); 6240 } 6241 6242 int 6243 soc_reg_port_valid(int unit, soc_reg_t reg, soc_port_t port) { 6244 if (SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_XLPORT) && 6245 SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MXQPORT)) { 6246 /* This register is valid for both port blocks */ 6247 if (!IS_XL_PORT(unit, port) && !IS_MXQ_PORT(unit, port)) { 6248 return FALSE; 6249 } 6250 } else if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_XLPORT) && 6251 !IS_XL_PORT(unit, port)) { 6252 return FALSE; 6253 } else if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_MXQPORT) && 6254 !IS_MXQ_PORT(unit, port)) { 6255 return FALSE; 6256 } 6257 return TRUE; 6258 } 6259 6260 6261 /* 6262 * Function: soc_reg_above_64_field32_modify 6263 * Purpose: Modify the value of a 32 bit field in any size register. 6264 * Parameters: 6265 * unit - (IN) SOC unit number. 6266 * reg - (IN) Register. 6267 * port - (IN) Port number. 6268 * index - (IN) instance index 6269 * field - (IN) Modified field. 6270 * value - (IN) New field value. 6271 * Returns: 6272 * SOC_E_XXX 6273 */ 6274 int 6275 soc_reg_above_64_field32_modify(int unit, soc_reg_t reg, soc_port_t port, 6276 int index, soc_field_t field, uint32 value) 6277 { 6278 int rc; 6279 soc_reg_above_64_val_t data; 6280 SOC_REG_ABOVE_64_CLEAR(data); 6281 rc = soc_reg_above_64_get(unit, reg, port, index, data); 6282 if (rc != SOC_E_NONE){ 6283 return rc; 6284 } 6285 soc_reg_above_64_field32_set(unit, reg, data, field, value); 6286 rc = soc_reg_above_64_set(unit, reg, port, index, data); 6287 if (rc != SOC_E_NONE){ 6288 return rc; 6289 } 6290 return SOC_E_NONE; 6291 } 6292 6293 /* 6294 * Function: soc_reg_above_64_field32_modify 6295 * Purpose: Modify the value of a 32 bit field in any size register. 6296 * Parameters: 6297 * unit - (IN) SOC unit number. 6298 * reg - (IN) Register. 6299 * port - (IN) Port number. 6300 * index - (IN) instance index 6301 * field - (IN) Modified field. 6302 * value - (IN) New field value. 6303 * Returns: 6304 * SOC_E_XXX 6305 */ 6306 int 6307 soc_reg_above_64_field64_modify(int unit, soc_reg_t reg, soc_port_t port, 6308 int index, soc_field_t field, uint64 value) 6309 { 6310 int rc; 6311 soc_reg_above_64_val_t 6312 data; 6313 SOC_REG_ABOVE_64_CLEAR(data); 6314 rc = soc_reg_above_64_get(unit, reg, port, index, data); 6315 if (rc != SOC_E_NONE){ 6316 return rc; 6317 } 6318 soc_reg_above_64_field64_set(unit, reg, data, field, value); 6319 rc = soc_reg_above_64_set(unit, reg, port, index, data); 6320 if (rc != SOC_E_NONE){ 6321 return rc; 6322 } 6323 return SOC_E_NONE; 6324 } 6325 6326 /* 6327 * Function: soc_reg_port_idx_valid 6328 * Purpose: Determine if a register of a given 6329 * index and port is valid. 6330 * Returns: Returns TRUE if register is valid. 6331 * Returns FALSE if register is not valid. 6332 */ 6333 int 6334 soc_reg_port_idx_valid(int unit, soc_reg_t reg, soc_port_t port, int idx) 6335 { 6336 soc_numelport_set_t *numelports; 6337 uint32 *portslist; 6338 int i, numellist_idx, indx; 6339 6340 6341 if (!SOC_REG_IS_VALID(unit, reg)) { 6342 return FALSE; 6343 } 6344 6345 /* idx is -1 means "any/all indexes..". so, check for Index 0 */ 6346 indx = (idx == -1) ? 0 : idx; 6347 6348 #ifdef BCM_KATANA2_SUPPORT 6349 if (SOC_IS_KATANA2(unit)) { 6350 6351 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_TXLP)) { 6352 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 6353 SOC_BLK_TXLP, NULL, NULL) != SOC_E_NONE) { 6354 /* Not a TXLP Port */ 6355 return FALSE; 6356 } 6357 } else if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_RXLP)) { 6358 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 6359 SOC_BLK_RXLP, NULL, NULL) != SOC_E_NONE) { 6360 /* Not a RXLP Port */ 6361 return FALSE; 6362 } 6363 #ifdef BCM_METROLITE_SUPPORT 6364 } else if (SOC_IS_METROLITE(unit) && (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_IECELL))) { 6365 if (soc_ml_iecell_port_reg_blk_idx_get(unit, port, 6366 SOC_BLK_IECELL, NULL, NULL) != SOC_E_NONE) { 6367 /* Not a IECELL Port */ 6368 return FALSE; 6369 } 6370 #endif 6371 #if defined (BCM_SABER2_SUPPORT) 6372 } else if (SOC_IS_SABER2(unit) && (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_IECELL))) { 6373 if (soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 6374 SOC_BLK_IECELL, NULL, NULL) != SOC_E_NONE) { 6375 /* Not a IECELL Port */ 6376 return FALSE; 6377 } 6378 #endif 6379 } 6380 } 6381 #endif 6382 6383 numellist_idx = SOC_REG_NUMELPORTLIST_IDX(unit, reg); 6384 if (numellist_idx == -1) { 6385 /* No PORTLIST or NUMEL_PERPORT */ 6386 #ifdef BCM_SABER2_SUPPORT 6387 if (SOC_IS_SABER2(unit)) { 6388 return soc_reg_port_valid(unit, reg, port); 6389 } 6390 #endif 6391 return TRUE; 6392 } 6393 6394 #ifdef BCM_GREYHOUND2_SUPPORT 6395 /* GREYHOUND2 should use MMU port rather than logical port while checking PERPort MMU register */ 6396 if(SOC_IS_GREYHOUND2(unit) && (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU))) { 6397 if (soc_feature(unit, soc_feature_logical_port_num)) { 6398 port = SOC_INFO(unit).port_l2p_mapping[port]; 6399 port = SOC_INFO(unit).port_p2m_mapping[port]; 6400 } 6401 } 6402 #endif 6403 6404 numelports = soc_numelports_list[numellist_idx]; 6405 i=0; 6406 while (numelports[i].f_idx != -1) { 6407 if ((indx >= numelports[i].f_idx) && (indx <= numelports[i].l_idx)) { 6408 portslist = soc_ports_list[numelports[i].pl_idx]; 6409 if (portslist[port /32] & (1 << (port % 32))) { 6410 return TRUE; 6411 } else { 6412 return FALSE; 6413 } 6414 } 6415 i++; 6416 } 6417 /* If idx is not found in the numel list, then it is just PORTLIST, not NUMELS_PERPORT */ 6418 portslist = soc_ports_list[numelports[0].pl_idx]; 6419 if (portslist[port /32] & (1 << (port % 32))) { 6420 return TRUE; 6421 } else { 6422 return FALSE; 6423 } 6424 } 6425 6426 /* 6427 * Function: soc_reg_egress_cell_count_get 6428 * Purpose: Retrieves the number of egress cells for a <port, cos> pair. 6429 * Parameters: 6430 * unit - (IN) SOC unit number. 6431 * port - (IN) Port number. 6432 * cos - (IN) COS queue. 6433 * data - (OUT) Cell count. 6434 * Returns: 6435 * SOC_E_XXX 6436 */ 6437 int 6438 soc_reg_egress_cell_count_get(int unit, soc_port_t port, int cos, uint32 *data) 6439 { 6440 if (!SOC_PORT_VALID(unit, port) || cos < 0 || cos >= NUM_COS(unit)) { 6441 return SOC_E_PARAM; 6442 } 6443 SOC_IF_ERROR_RETURN(READ_COSLCCOUNTr(unit, port, cos, data)); 6444 return SOC_E_NONE; 6445 } 6446 6447 #ifdef BCM_CMICM_SUPPORT 6448 6449 soc_cmicm_reg_t cmicm_regs[] = CMICM_REG_INIT; 6450 6451 STATIC soc_cmicm_reg_t 6452 *soc_cmicm_srch (uint32 addr) { 6453 int start = 0; 6454 int end = NUM_CMICM_REGS - 1; 6455 int mid = (start + end) >> 1; 6456 while (start <= end && cmicm_regs[mid].addr != addr) { 6457 if (cmicm_regs[mid].addr > addr) { 6458 end = mid - 1; 6459 } else { 6460 start = mid + 1; 6461 } 6462 mid = (start + end) >> 1; 6463 } 6464 return (cmicm_regs[mid].addr == addr) ? &(cmicm_regs[mid]) : NULL; 6465 } 6466 6467 soc_cmicm_reg_t 6468 *soc_cmicm_reg_get (uint32 idx) { 6469 return &(cmicm_regs[idx]); 6470 } 6471 6472 soc_reg_t 6473 soc_cmicm_addr_reg (uint32 addr) { 6474 soc_cmicm_reg_t *cmreg = soc_cmicm_srch(addr); 6475 return (cmreg == NULL)?INVALIDr:cmreg->reg; 6476 } 6477 6478 char * 6479 soc_cmicm_addr_name (uint32 addr) { 6480 soc_cmicm_reg_t *cmreg = soc_cmicm_srch(addr); 6481 return (cmreg == NULL)?"???":cmreg->name; 6482 } 6483 #endif 6484 6485 6486 uint32 6487 soc_pci_mcs_read(int unit, uint32 addr) { 6488 6489 #ifdef BCM_CMICM_SUPPORT 6490 uint32 page = (addr & 0xffff8000); 6491 uint32 off = (addr & 0x00007fff); 6492 uint32 data = 0; 6493 6494 if (soc_feature(unit, soc_feature_cmicm)) { 6495 soc_pci_write(unit, CMIC_PIO_MCS_ACCESS_PAGE_OFFSET, page); 6496 6497 /* Read back to ensure write is complete */ 6498 page = soc_pci_read(unit, CMIC_PIO_MCS_ACCESS_PAGE_OFFSET); 6499 6500 /* Hardcoded for now.. use reg addr if & when available in regfile */ 6501 data = soc_pci_read(unit, (0x38000 + off)); 6502 #ifdef BROADCOM_DEBUG 6503 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 6504 _soc_reg_debug(unit, 32, "read", addr, 0, data); 6505 } 6506 #endif /* BROADCOM_DEBUG */ 6507 /* _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_READ,0,data); */ 6508 return data; 6509 } 6510 #endif /* BCM_CMICM_SUPPORT */ 6511 6512 return 0; 6513 } 6514 6515 int 6516 soc_pci_mcs_getreg(int unit, uint32 addr, uint32 *data_ptr) { 6517 *data_ptr = soc_pci_mcs_read(unit, addr); 6518 return SOC_E_NONE; 6519 } 6520 6521 int 6522 soc_pci_mcs_write(int unit, uint32 addr, uint32 data) { 6523 #ifdef BCM_CMICM_SUPPORT 6524 uint32 page = (addr & 0xffff8000); 6525 uint32 off = (addr & 0x00007fff); 6526 6527 if (soc_feature(unit, soc_feature_cmicm)) { 6528 #ifdef BROADCOM_DEBUG 6529 if (bsl_check(bslLayerSoc, bslSourceReg, bslSeverityNormal, unit)) { 6530 _soc_reg_debug(unit, 32, "write", addr, 0, data); 6531 } 6532 #endif /* BROADCOM_DEBUG */ 6533 /* _soc_snoop_reg(unit, 0, 0, addr,SOC_REG_SNOOP_WRITE,0,data); */ 6534 6535 soc_pci_write(unit, CMIC_PIO_MCS_ACCESS_PAGE_OFFSET, page); 6536 6537 /* Read back to ensure write is complete */ 6538 page = soc_pci_read(unit, CMIC_PIO_MCS_ACCESS_PAGE_OFFSET); 6539 6540 /* Hardcoded for now.. use reg addr if & when available in regfile */ 6541 return soc_pci_write(unit, (0x38000 + off), data); 6542 } 6543 #endif /* BCM_CMICM_SUPPORT */ 6544 6545 return 0; 6546 } 6547 6548 /* Get register length in bytes */ 6549 int 6550 soc_reg_bytes(int unit, soc_reg_t reg) { 6551 6552 int bits = 0; 6553 soc_reg_info_t *regp; 6554 int i, bytes; 6555 soc_field_info_t *fieldp; 6556 6557 if (!SOC_REG_IS_VALID(unit, reg)) { 6558 #if !defined(SOC_NO_NAMES) 6559 LOG_CLI((BSL_META_U(unit, 6560 "reg %s is invalid\n"), soc_reg_name[reg])); 6561 #endif /* !SOC_NO_NAMES */ 6562 assert(SOC_REG_IS_VALID(unit, reg)); 6563 } 6564 regp = &(SOC_REG_INFO(unit, reg)); 6565 6566 for (i = 0; i < (int)(regp->nFields); i++) { 6567 fieldp = &(regp->fields[i]); 6568 bits = ((fieldp->len + fieldp->bp) > bits)? 6569 (fieldp->len + fieldp->bp): bits; 6570 } 6571 bytes = BITS2BYTES(bits); 6572 return bytes; 6573 } 6574 6575 /* Get register length in bits */ 6576 int 6577 soc_reg_bits(int unit, soc_reg_t reg) { 6578 6579 int bits = 0; 6580 soc_reg_info_t *regp; 6581 int i; 6582 soc_field_info_t *fieldp; 6583 6584 if (!SOC_REG_IS_VALID(unit, reg)) { 6585 #if !defined(SOC_NO_NAMES) 6586 LOG_CLI((BSL_META_U(unit, 6587 "reg %s is invalid\n"), soc_reg_name[reg])); 6588 #endif /* !SOC_NO_NAMES */ 6589 return 0; 6590 } 6591 regp = &(SOC_REG_INFO(unit, reg)); 6592 6593 for (i = 0; i < (int)(regp->nFields); i++) { 6594 fieldp = &(regp->fields[i]); 6595 bits = ((fieldp->len + fieldp->bp) > bits)? 6596 (fieldp->len + fieldp->bp): bits; 6597 } 6598 6599 return bits; 6600 } 6601 6602 /* 6603 * Function: 6604 * soc_reg_snoop_register 6605 * Purpose: 6606 * Registers a snooping call back for specific memory. 6607 * Call back will be called on Read or Write operations 6608 * on the register according to specified flags 6609 * Parameters: 6610 * unit - (IN) BCM device number. 6611 * reg - (IN) Register to register a call back for. 6612 * flags - (IN) SOC_REGS_SNOOP_XXX flags. 6613 * snoop_cv - (IN) User provided call back, NULL for unregister 6614 * user_data - (IN) user provided data to be passed to call back function 6615 * Returns: 6616 * None 6617 */ 6618 void 6619 soc_reg_snoop_register(int unit, soc_reg_t reg, uint32 flags, 6620 soc_reg_snoop_cb_t snoop_cb, void *user_data) 6621 { 6622 soc_reg_info_t *reg_info_p; 6623 6624 if (!SOC_REG_IS_VALID(unit, reg)) { 6625 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 6626 LOG_CLI((BSL_META_U(unit, 6627 "reg %s is invalid\n"), soc_reg_name[reg])); 6628 #endif 6629 assert(SOC_REG_IS_VALID(unit, reg)); 6630 } 6631 6632 reg_info_p = &SOC_REG_INFO(unit, reg); 6633 6634 assert(NULL != snoop_cb); 6635 6636 reg_info_p->snoop_cb = snoop_cb; 6637 reg_info_p->snoop_user_data = user_data; 6638 reg_info_p->snoop_flags = flags; 6639 6640 return; 6641 } 6642 6643 /* 6644 * Function: 6645 * soc_reg_snoop_unregister 6646 * Purpose: 6647 * Unregisters a snooping call back for specific register. 6648 * this function will not fail even if call back was not previously 6649 * registered. 6650 * Parameters: 6651 * unit - (IN) BCM device number. 6652 * reg - (IN) Register to register a call back for. 6653 * Returns: 6654 * None 6655 */ 6656 void 6657 soc_reg_snoop_unregister(int unit, soc_reg_t reg) 6658 { 6659 soc_reg_info_t *reg_info_p; 6660 6661 if (!SOC_REG_IS_VALID(unit, reg)) { 6662 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 6663 LOG_CLI((BSL_META_U(unit, 6664 "reg %s is invalid\n"), soc_reg_name[reg])); 6665 #endif 6666 assert(SOC_REG_IS_VALID(unit, reg)); 6667 } 6668 6669 reg_info_p = &SOC_REG_INFO(unit, reg); 6670 6671 reg_info_p->snoop_cb = NULL; 6672 reg_info_p->snoop_user_data = NULL; 6673 reg_info_p->snoop_flags = 0; 6674 6675 return; 6676 } 6677 6678 /* 6679 * This function allows registration of user defined callbacks for 6680 * registers and memories operations. 6681 */ 6682 int 6683 soc_reg_access_func_register(int unit, soc_reg_access_t* reg_access) 6684 { 6685 SOC_INFO(unit).reg_access = *reg_access; 6686 6687 return SOC_E_NONE; 6688 } 6689 6690 6691 int 6692 soc_custom_reg32_get(int unit, soc_reg_t reg, int port, int index, uint32 *data) 6693 { 6694 soc_reg32_get_f custom_reg32_get = SOC_INFO(unit).custom_reg_access.custom_reg32_get; 6695 6696 if (!custom_reg32_get) { 6697 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6698 return SOC_E_FAIL; 6699 } 6700 6701 return custom_reg32_get(unit, reg, port, index, data); 6702 } 6703 6704 int 6705 soc_custom_reg32_set(int unit, soc_reg_t reg, int port, int index, uint32 data) 6706 { 6707 soc_reg32_set_f custom_reg32_set = SOC_INFO(unit).custom_reg_access.custom_reg32_set; 6708 6709 if (!custom_reg32_set) { 6710 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6711 return SOC_E_FAIL; 6712 } 6713 6714 return custom_reg32_set(unit, reg, port, index, data); 6715 } 6716 6717 int 6718 soc_custom_reg64_get(int unit, soc_reg_t reg, int port, int index, uint64 *data) 6719 { 6720 soc_reg64_get_f custom_reg64_get = SOC_INFO(unit).custom_reg_access.custom_reg64_get; 6721 6722 if (!custom_reg64_get) { 6723 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6724 return SOC_E_FAIL; 6725 } 6726 6727 return custom_reg64_get(unit, reg, port, index, data); 6728 } 6729 6730 int 6731 soc_custom_reg64_set(int unit, soc_reg_t reg, int port, int index, uint64 data) 6732 { 6733 soc_reg64_set_f custom_reg64_set = SOC_INFO(unit).custom_reg_access.custom_reg64_set; 6734 6735 if (!custom_reg64_set) { 6736 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6737 return SOC_E_FAIL; 6738 } 6739 6740 return custom_reg64_set(unit, reg, port, index, data); 6741 } 6742 6743 int 6744 soc_custom_reg_above_64_get(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t data) 6745 { 6746 soc_reg_above64_get_f custom_reg_above64_get = SOC_INFO(unit).custom_reg_access.custom_reg_above64_get; 6747 6748 if (!custom_reg_above64_get) { 6749 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6750 return SOC_E_FAIL; 6751 } 6752 6753 return custom_reg_above64_get(unit, reg, port, index, data); 6754 } 6755 6756 int 6757 soc_custom_reg_above_64_set(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t data) 6758 { 6759 soc_reg_above64_set_f custom_reg_above64_set = SOC_INFO(unit).custom_reg_access.custom_reg_above64_set; 6760 6761 if (!custom_reg_above64_set) { 6762 LOG_CLI((BSL_META_U(unit, "custom function not defined\n"))); 6763 return SOC_E_FAIL; 6764 } 6765 6766 return custom_reg_above64_set(unit, reg, port, index, data); 6767 } 6768 6769 6770 /* 6771 * Function: 6772 * soc_reg_field_acc_mode_get 6773 * Purpose: 6774 * indicate if a register or a field is readonly/writeonly. 6775 * Parameters: 6776 * unit - (IN) BCM device number. 6777 * reg - (IN) Register 6778 * field - (IN) field, if invalid then check readonly/writeonly on the register 6779 * is_read_only - (OUT) read only indication for the register or the field 6780 * is_write_only - (OUT) write only indication for the register or the field 6781 * Returns: 6782 * None 6783 */ 6784 void 6785 soc_reg_field_acc_mode_get( 6786 int unit, 6787 soc_reg_t reg, 6788 soc_field_t field, 6789 uint32 *is_read_only, 6790 uint32 *is_write_only) 6791 { 6792 soc_field_info_t *finfop; 6793 6794 *is_read_only = 0; 6795 *is_write_only = 0; 6796 6797 if (!SOC_REG_IS_VALID(unit, reg)) 6798 { 6799 #if !defined(SOC_NO_NAMES) 6800 LOG_CLI((BSL_META_U(unit, "reg %s is invalid\n"), soc_reg_name[reg])); 6801 #endif 6802 assert(SOC_REG_IS_VALID(unit, reg)); 6803 } 6804 6805 if (field == INVALIDf) 6806 { 6807 if (SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_RO) 6808 { 6809 *is_read_only = 1; 6810 } 6811 return; 6812 } 6813 6814 SOC_FIND_FIELD(field, SOC_REG_INFO(unit, reg).fields, SOC_REG_INFO(unit, reg).nFields, finfop); 6815 if (finfop == NULL) 6816 { 6817 #if !defined(SOC_NO_NAMES) 6818 LOG_CLI((BSL_META_U(unit, "reg %s field %s is invalid\n"), soc_reg_name[reg], soc_fieldnames[field])); 6819 #endif 6820 assert(finfop); 6821 } 6822 6823 if (finfop->flags & SOCF_RO) 6824 { 6825 *is_read_only = 1; 6826 } 6827 6828 if (finfop->flags & SOCF_WO) 6829 { 6830 *is_write_only = 1; 6831 } 6832 6833 } 6834 6835 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT)*/ 6836 6837