| .. | .. |
|---|
| 1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 2 | 1 | /* |
|---|
| 3 | 2 | * Misc utility routines for accessing chip-specific features |
|---|
| 4 | 3 | * of the SiliconBackplane-based Broadcom chips. |
|---|
| 5 | 4 | * |
|---|
| 6 | | - * Copyright (C) 1999-2019, Broadcom Corporation |
|---|
| 7 | | - * |
|---|
| 5 | + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation |
|---|
| 6 | + * |
|---|
| 7 | + * Copyright (C) 1999-2017, Broadcom Corporation |
|---|
| 8 | + * |
|---|
| 8 | 9 | * Unless you and Broadcom execute a separate written software license |
|---|
| 9 | 10 | * agreement governing use of this software, this software is licensed to you |
|---|
| 10 | 11 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
|---|
| 11 | 12 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
|---|
| 12 | 13 | * following added to such license: |
|---|
| 13 | | - * |
|---|
| 14 | + * |
|---|
| 14 | 15 | * As a special exception, the copyright holders of this software give you |
|---|
| 15 | 16 | * permission to link this software with independent modules, and to copy and |
|---|
| 16 | 17 | * distribute the resulting executable under terms of your choice, provided that |
|---|
| .. | .. |
|---|
| 18 | 19 | * the license of that module. An independent module is a module which is not |
|---|
| 19 | 20 | * derived from this software. The special exception does not apply to any |
|---|
| 20 | 21 | * modifications of the software. |
|---|
| 21 | | - * |
|---|
| 22 | + * |
|---|
| 22 | 23 | * Notwithstanding the above, under no circumstances may you combine this |
|---|
| 23 | 24 | * software in any way with any other Broadcom software provided under a license |
|---|
| 24 | 25 | * other than the GPL, without Broadcom's express prior written consent. |
|---|
| .. | .. |
|---|
| 26 | 27 | * |
|---|
| 27 | 28 | * <<Broadcom-WL-IPTag/Open:>> |
|---|
| 28 | 29 | * |
|---|
| 29 | | - * $Id: sbutils.c 514727 2014-11-12 03:02:48Z $ |
|---|
| 30 | + * $Id: sbutils.c 700323 2017-05-18 16:12:11Z $ |
|---|
| 30 | 31 | */ |
|---|
| 31 | 32 | |
|---|
| 32 | 33 | #include <bcm_cfg.h> |
|---|
| .. | .. |
|---|
| 43 | 44 | |
|---|
| 44 | 45 | #include "siutils_priv.h" |
|---|
| 45 | 46 | |
|---|
| 46 | | - |
|---|
| 47 | 47 | /* local prototypes */ |
|---|
| 48 | 48 | static uint _sb_coreidx(si_info_t *sii, uint32 sba); |
|---|
| 49 | | -static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, |
|---|
| 50 | | - uint ncores); |
|---|
| 49 | +static uint _sb_scan(si_info_t *sii, uint32 sba, volatile void *regs, uint bus, uint32 sbba, |
|---|
| 50 | + uint ncores, uint devid); |
|---|
| 51 | 51 | static uint32 _sb_coresba(si_info_t *sii); |
|---|
| 52 | | -static void *_sb_setcoreidx(si_info_t *sii, uint coreidx); |
|---|
| 52 | +static volatile void *_sb_setcoreidx(si_info_t *sii, uint coreidx); |
|---|
| 53 | 53 | #define SET_SBREG(sii, r, mask, val) \ |
|---|
| 54 | 54 | W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val))) |
|---|
| 55 | | -#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) |
|---|
| 55 | +#define REGS2SB(va) (sbconfig_t*) ((volatile int8*)(va) + SBCONFIGOFF) |
|---|
| 56 | 56 | |
|---|
| 57 | 57 | /* sonicsrev */ |
|---|
| 58 | 58 | #define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) |
|---|
| .. | .. |
|---|
| 66 | 66 | static uint32 |
|---|
| 67 | 67 | sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr) |
|---|
| 68 | 68 | { |
|---|
| 69 | | - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 70 | 69 | uint8 tmp; |
|---|
| 71 | 70 | uint32 val, intr_val = 0; |
|---|
| 72 | | - |
|---|
| 73 | 71 | |
|---|
| 74 | 72 | /* |
|---|
| 75 | 73 | * compact flash only has 11 bits address, while we needs 12 bits address. |
|---|
| .. | .. |
|---|
| 98 | 96 | static void |
|---|
| 99 | 97 | sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v) |
|---|
| 100 | 98 | { |
|---|
| 101 | | - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 102 | 99 | uint8 tmp; |
|---|
| 103 | 100 | volatile uint32 dummy; |
|---|
| 104 | 101 | uint32 intr_val = 0; |
|---|
| 105 | | - |
|---|
| 106 | 102 | |
|---|
| 107 | 103 | /* |
|---|
| 108 | 104 | * compact flash only has 11 bits address, while we needs 12 bits address. |
|---|
| .. | .. |
|---|
| 150 | 146 | sb_intflag(si_t *sih) |
|---|
| 151 | 147 | { |
|---|
| 152 | 148 | si_info_t *sii = SI_INFO(sih); |
|---|
| 153 | | - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 154 | | - void *corereg; |
|---|
| 149 | + volatile void *corereg; |
|---|
| 155 | 150 | sbconfig_t *sb; |
|---|
| 156 | 151 | uint origidx, intflag, intr_val = 0; |
|---|
| 157 | 152 | |
|---|
| .. | .. |
|---|
| 215 | 210 | { |
|---|
| 216 | 211 | uint32 sbaddr; |
|---|
| 217 | 212 | |
|---|
| 218 | | - |
|---|
| 219 | 213 | switch (BUSTYPE(sii->pub.bustype)) { |
|---|
| 220 | 214 | case SI_BUS: { |
|---|
| 221 | 215 | sbconfig_t *sb = REGS2SB(sii->curmap); |
|---|
| .. | .. |
|---|
| 243 | 237 | case SDIO_BUS: |
|---|
| 244 | 238 | sbaddr = (uint32)(uintptr)sii->curmap; |
|---|
| 245 | 239 | break; |
|---|
| 246 | | -#endif |
|---|
| 247 | | - |
|---|
| 240 | +#endif // endif |
|---|
| 248 | 241 | |
|---|
| 249 | 242 | default: |
|---|
| 250 | 243 | sbaddr = BADCOREADDR; |
|---|
| .. | .. |
|---|
| 377 | 370 | sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) |
|---|
| 378 | 371 | { |
|---|
| 379 | 372 | uint origidx = 0; |
|---|
| 380 | | - uint32 *r = NULL; |
|---|
| 373 | + volatile uint32 *r = NULL; |
|---|
| 381 | 374 | uint w; |
|---|
| 382 | 375 | uint intr_val = 0; |
|---|
| 383 | 376 | bool fast = FALSE; |
|---|
| .. | .. |
|---|
| 400 | 393 | SI_CORE_SIZE); |
|---|
| 401 | 394 | ASSERT(GOODREGS(cores_info->regs[coreidx])); |
|---|
| 402 | 395 | } |
|---|
| 403 | | - r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff); |
|---|
| 396 | + r = (volatile uint32 *)((volatile uchar *)cores_info->regs[coreidx] + regoff); |
|---|
| 404 | 397 | } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { |
|---|
| 405 | 398 | /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ |
|---|
| 406 | 399 | |
|---|
| .. | .. |
|---|
| 408 | 401 | /* Chipc registers are mapped at 12KB */ |
|---|
| 409 | 402 | |
|---|
| 410 | 403 | fast = TRUE; |
|---|
| 411 | | - r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); |
|---|
| 404 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 405 | + PCI_16KB0_CCREGS_OFFSET + regoff); |
|---|
| 412 | 406 | } else if (sii->pub.buscoreidx == coreidx) { |
|---|
| 413 | 407 | /* pci registers are at either in the last 2KB of an 8KB window |
|---|
| 414 | 408 | * or, in pcie and pci rev 13 at 8KB |
|---|
| 415 | 409 | */ |
|---|
| 416 | 410 | fast = TRUE; |
|---|
| 417 | 411 | if (SI_FAST(sii)) |
|---|
| 418 | | - r = (uint32 *)((char *)sii->curmap + |
|---|
| 412 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 419 | 413 | PCI_16KB0_PCIREGS_OFFSET + regoff); |
|---|
| 420 | 414 | else |
|---|
| 421 | | - r = (uint32 *)((char *)sii->curmap + |
|---|
| 415 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 422 | 416 | ((regoff >= SBCONFIGOFF) ? |
|---|
| 423 | 417 | PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + |
|---|
| 424 | 418 | regoff); |
|---|
| .. | .. |
|---|
| 432 | 426 | origidx = si_coreidx(&sii->pub); |
|---|
| 433 | 427 | |
|---|
| 434 | 428 | /* switch core */ |
|---|
| 435 | | - r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff); |
|---|
| 429 | + r = (volatile uint32*) ((volatile uchar*)sb_setcoreidx(&sii->pub, coreidx) + |
|---|
| 430 | + regoff); |
|---|
| 436 | 431 | } |
|---|
| 437 | 432 | ASSERT(r != NULL); |
|---|
| 438 | 433 | |
|---|
| .. | .. |
|---|
| 451 | 446 | if (regoff >= SBCONFIGOFF) |
|---|
| 452 | 447 | w = R_SBREG(sii, r); |
|---|
| 453 | 448 | else { |
|---|
| 454 | | - if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) && |
|---|
| 455 | | - (coreidx == SI_CC_IDX) && |
|---|
| 456 | | - (regoff == OFFSETOF(chipcregs_t, watchdog))) { |
|---|
| 457 | | - w = val; |
|---|
| 458 | | - } else |
|---|
| 459 | | - w = R_REG(sii->osh, r); |
|---|
| 449 | + w = R_REG(sii->osh, r); |
|---|
| 460 | 450 | } |
|---|
| 461 | 451 | |
|---|
| 462 | 452 | if (!fast) { |
|---|
| .. | .. |
|---|
| 479 | 469 | * For accessing registers that would need a core switch, this function will return |
|---|
| 480 | 470 | * NULL. |
|---|
| 481 | 471 | */ |
|---|
| 482 | | -uint32 * |
|---|
| 472 | +volatile uint32 * |
|---|
| 483 | 473 | sb_corereg_addr(si_t *sih, uint coreidx, uint regoff) |
|---|
| 484 | 474 | { |
|---|
| 485 | | - uint32 *r = NULL; |
|---|
| 475 | + volatile uint32 *r = NULL; |
|---|
| 486 | 476 | bool fast = FALSE; |
|---|
| 487 | 477 | si_info_t *sii = SI_INFO(sih); |
|---|
| 488 | 478 | si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| .. | .. |
|---|
| 502 | 492 | SI_CORE_SIZE); |
|---|
| 503 | 493 | ASSERT(GOODREGS(cores_info->regs[coreidx])); |
|---|
| 504 | 494 | } |
|---|
| 505 | | - r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff); |
|---|
| 495 | + r = (volatile uint32 *)((volatile uchar *)cores_info->regs[coreidx] + regoff); |
|---|
| 506 | 496 | } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { |
|---|
| 507 | 497 | /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ |
|---|
| 508 | 498 | |
|---|
| .. | .. |
|---|
| 510 | 500 | /* Chipc registers are mapped at 12KB */ |
|---|
| 511 | 501 | |
|---|
| 512 | 502 | fast = TRUE; |
|---|
| 513 | | - r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); |
|---|
| 503 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 504 | + PCI_16KB0_CCREGS_OFFSET + regoff); |
|---|
| 514 | 505 | } else if (sii->pub.buscoreidx == coreidx) { |
|---|
| 515 | 506 | /* pci registers are at either in the last 2KB of an 8KB window |
|---|
| 516 | 507 | * or, in pcie and pci rev 13 at 8KB |
|---|
| 517 | 508 | */ |
|---|
| 518 | 509 | fast = TRUE; |
|---|
| 519 | 510 | if (SI_FAST(sii)) |
|---|
| 520 | | - r = (uint32 *)((char *)sii->curmap + |
|---|
| 511 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 521 | 512 | PCI_16KB0_PCIREGS_OFFSET + regoff); |
|---|
| 522 | 513 | else |
|---|
| 523 | | - r = (uint32 *)((char *)sii->curmap + |
|---|
| 514 | + r = (volatile uint32 *)((volatile char *)sii->curmap + |
|---|
| 524 | 515 | ((regoff >= SBCONFIGOFF) ? |
|---|
| 525 | 516 | PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + |
|---|
| 526 | 517 | regoff); |
|---|
| .. | .. |
|---|
| 542 | 533 | */ |
|---|
| 543 | 534 | #define SB_MAXBUSES 2 |
|---|
| 544 | 535 | static uint |
|---|
| 545 | | -_sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores) |
|---|
| 536 | +_sb_scan(si_info_t *sii, uint32 sba, volatile void *regs, uint bus, |
|---|
| 537 | + uint32 sbba, uint numcores, uint devid) |
|---|
| 546 | 538 | { |
|---|
| 547 | 539 | uint next; |
|---|
| 548 | 540 | uint ncc = 0; |
|---|
| .. | .. |
|---|
| 588 | 580 | /* Older chips */ |
|---|
| 589 | 581 | uint chip = CHIPID(sii->pub.chip); |
|---|
| 590 | 582 | |
|---|
| 591 | | - if (chip == BCM4306_CHIP_ID) /* < 4306c0 */ |
|---|
| 592 | | - numcores = 6; |
|---|
| 593 | | - else if (chip == BCM4704_CHIP_ID) |
|---|
| 583 | + if (chip == BCM4704_CHIP_ID) |
|---|
| 594 | 584 | numcores = 9; |
|---|
| 595 | 585 | else if (chip == BCM5365_CHIP_ID) |
|---|
| 596 | 586 | numcores = 7; |
|---|
| .. | .. |
|---|
| 612 | 602 | |
|---|
| 613 | 603 | sii->numcores = next + 1; |
|---|
| 614 | 604 | |
|---|
| 615 | | - if ((nsbba & 0xfff00000) != SI_ENUM_BASE) |
|---|
| 605 | + if ((nsbba & 0xfff00000) != si_enum_base(devid)) |
|---|
| 616 | 606 | continue; |
|---|
| 617 | 607 | nsbba &= 0xfffff000; |
|---|
| 618 | 608 | if (_sb_coreidx(sii, nsbba) != BADIDX) |
|---|
| 619 | 609 | continue; |
|---|
| 620 | 610 | |
|---|
| 621 | 611 | nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16; |
|---|
| 622 | | - nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc); |
|---|
| 623 | | - if (sbba == SI_ENUM_BASE) |
|---|
| 612 | + nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc, devid); |
|---|
| 613 | + if (sbba == si_enum_base(devid)) |
|---|
| 624 | 614 | numcores -= nsbcc; |
|---|
| 625 | 615 | ncc += nsbcc; |
|---|
| 626 | 616 | } |
|---|
| .. | .. |
|---|
| 634 | 624 | |
|---|
| 635 | 625 | /* scan the sb enumerated space to identify all cores */ |
|---|
| 636 | 626 | void |
|---|
| 637 | | -sb_scan(si_t *sih, void *regs, uint devid) |
|---|
| 627 | +sb_scan(si_t *sih, volatile void *regs, uint devid) |
|---|
| 638 | 628 | { |
|---|
| 639 | 629 | uint32 origsba; |
|---|
| 640 | 630 | sbconfig_t *sb; |
|---|
| 641 | 631 | si_info_t *sii = SI_INFO(sih); |
|---|
| 632 | + BCM_REFERENCE(devid); |
|---|
| 642 | 633 | |
|---|
| 643 | 634 | sb = REGS2SB(sii->curmap); |
|---|
| 644 | 635 | |
|---|
| .. | .. |
|---|
| 649 | 640 | */ |
|---|
| 650 | 641 | origsba = _sb_coresba(sii); |
|---|
| 651 | 642 | |
|---|
| 652 | | - /* scan all SB(s) starting from SI_ENUM_BASE */ |
|---|
| 653 | | - sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1); |
|---|
| 643 | + /* scan all SB(s) starting from SI_ENUM_BASE_DEFAULT */ |
|---|
| 644 | + sii->numcores = _sb_scan(sii, origsba, regs, 0, si_enum_base(devid), 1, devid); |
|---|
| 654 | 645 | } |
|---|
| 655 | 646 | |
|---|
| 656 | 647 | /* |
|---|
| .. | .. |
|---|
| 658 | 649 | * must be called with interrupts off. |
|---|
| 659 | 650 | * Moreover, callers should keep interrupts off during switching out of and back to d11 core |
|---|
| 660 | 651 | */ |
|---|
| 661 | | -void * |
|---|
| 652 | +volatile void * |
|---|
| 662 | 653 | sb_setcoreidx(si_t *sih, uint coreidx) |
|---|
| 663 | 654 | { |
|---|
| 664 | 655 | si_info_t *sii = SI_INFO(sih); |
|---|
| .. | .. |
|---|
| 681 | 672 | /* This function changes the logical "focus" to the indicated core. |
|---|
| 682 | 673 | * Return the current core's virtual address. |
|---|
| 683 | 674 | */ |
|---|
| 684 | | -static void * |
|---|
| 675 | +static volatile void * |
|---|
| 685 | 676 | _sb_setcoreidx(si_info_t *sii, uint coreidx) |
|---|
| 686 | 677 | { |
|---|
| 687 | 678 | si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 688 | 679 | uint32 sbaddr = cores_info->coresba[coreidx]; |
|---|
| 689 | | - void *regs; |
|---|
| 680 | + volatile void *regs; |
|---|
| 690 | 681 | |
|---|
| 691 | 682 | switch (BUSTYPE(sii->pub.bustype)) { |
|---|
| 692 | 683 | case SI_BUS: |
|---|
| .. | .. |
|---|
| 725 | 716 | regs = cores_info->regs[coreidx]; |
|---|
| 726 | 717 | break; |
|---|
| 727 | 718 | #endif /* BCMSDIO */ |
|---|
| 728 | | - |
|---|
| 729 | 719 | |
|---|
| 730 | 720 | default: |
|---|
| 731 | 721 | ASSERT(0); |
|---|
| .. | .. |
|---|
| 806 | 796 | return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx)))); |
|---|
| 807 | 797 | } |
|---|
| 808 | 798 | |
|---|
| 809 | | - |
|---|
| 810 | 799 | /* do buffered registers update */ |
|---|
| 811 | 800 | void |
|---|
| 812 | 801 | sb_commit(si_t *sih) |
|---|
| 813 | 802 | { |
|---|
| 814 | 803 | si_info_t *sii = SI_INFO(sih); |
|---|
| 815 | | - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 816 | 804 | uint origidx; |
|---|
| 817 | 805 | uint intr_val = 0; |
|---|
| 818 | 806 | |
|---|
| .. | .. |
|---|
| 974 | 962 | sb_set_initiator_to(si_t *sih, uint32 to, uint idx) |
|---|
| 975 | 963 | { |
|---|
| 976 | 964 | si_info_t *sii = SI_INFO(sih); |
|---|
| 977 | | - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; |
|---|
| 978 | 965 | uint origidx; |
|---|
| 979 | 966 | uint intr_val = 0; |
|---|
| 980 | 967 | uint32 tmp, ret = 0xffffffff; |
|---|
| 981 | 968 | sbconfig_t *sb; |
|---|
| 982 | | - |
|---|
| 983 | 969 | |
|---|
| 984 | 970 | if ((to & ~TO_MASK) != 0) |
|---|
| 985 | 971 | return ret; |
|---|
| .. | .. |
|---|
| 996 | 982 | case PCMCIA_BUS: |
|---|
| 997 | 983 | #ifdef BCMSDIO |
|---|
| 998 | 984 | case SDIO_BUS: |
|---|
| 999 | | -#endif |
|---|
| 985 | +#endif // endif |
|---|
| 1000 | 986 | idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0); |
|---|
| 1001 | 987 | break; |
|---|
| 1002 | 988 | case SI_BUS: |
|---|
| .. | .. |
|---|
| 1106 | 1092 | sb_setcoreidx(sih, origidx); |
|---|
| 1107 | 1093 | INTR_RESTORE(sii, intr_val); |
|---|
| 1108 | 1094 | } |
|---|
| 1109 | | -#endif |
|---|
| 1095 | +#endif // endif |
|---|