2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: aiutils.c 321248 2012-03-14 21:17:30Z $
31 #include "siutils_priv.h"
35 #define BCM47162_DMP() ((CHIPID(sih->chip) == BCM47162_CHIP_ID) && \
36 (CHIPREV(sih->chiprev) == 0) && \
37 (sii->coreid[sii->curidx] == MIPS74K_CORE_ID))
39 #define BCM5357_DMP() (((CHIPID(sih->chip) == BCM5357_CHIP_ID) || \
40 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && \
41 (sih->chippkg == BCM5357_PKG_ID) && \
42 (sii->coreid[sii->curidx] == USB20H_CORE_ID))
47 get_erom_ent(si_t
*sih
, uint32
**eromptr
, uint32 mask
, uint32 match
)
50 uint inv
= 0, nom
= 0;
53 ent
= R_REG(si_osh(sih
), *eromptr
);
59 if ((ent
& ER_VALID
) == 0) {
64 if (ent
== (ER_END
| ER_VALID
))
67 if ((ent
& mask
) == match
)
73 SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__
, ent
));
75 SI_VMSG((" after %d invalid and %d non-matching entries\n", inv
, nom
));
81 get_asd(si_t
*sih
, uint32
**eromptr
, uint sp
, uint ad
, uint st
, uint32
*addrl
, uint32
*addrh
,
82 uint32
*sizel
, uint32
*sizeh
)
86 asd
= get_erom_ent(sih
, eromptr
, ER_VALID
, ER_VALID
);
87 if (((asd
& ER_TAG1
) != ER_ADD
) ||
88 (((asd
& AD_SP_MASK
) >> AD_SP_SHIFT
) != sp
) ||
89 ((asd
& AD_ST_MASK
) != st
)) {
90 /* This is not what we want, "push" it back */
94 *addrl
= asd
& AD_ADDR_MASK
;
96 *addrh
= get_erom_ent(sih
, eromptr
, 0, 0);
100 sz
= asd
& AD_SZ_MASK
;
101 if (sz
== AD_SZ_SZD
) {
102 szd
= get_erom_ent(sih
, eromptr
, 0, 0);
103 *sizel
= szd
& SD_SZ_MASK
;
105 *sizeh
= get_erom_ent(sih
, eromptr
, 0, 0);
107 *sizel
= AD_SZ_BASE
<< (sz
>> AD_SZ_SHIFT
);
109 SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
110 sp
, ad
, st
, *sizeh
, *sizel
, *addrh
, *addrl
));
116 ai_hwfixup(si_info_t
*sii
)
119 /* Fixup the interrupts in 4716 for i2s core so that ai_flag
120 * works without having to look at the core sinking the
121 * interrupt. We should have done this as the hardware default.
123 * Future chips should allocate interrupt lines in order (meaning
124 * no line should be skipped), without regard for core index.
126 if (BUSTYPE(sii
->pub
.bustype
) == SI_BUS
&&
127 ((CHIPID(sii
->pub
.chip
) == BCM4716_CHIP_ID
) ||
128 (CHIPID(sii
->pub
.chip
) == BCM4748_CHIP_ID
))) {
129 aidmp_t
*i2s
, *pcie
, *cpu
;
131 ASSERT(sii
->coreid
[3] == MIPS74K_CORE_ID
);
132 cpu
= REG_MAP(sii
->wrapba
[3], SI_CORE_SIZE
);
133 ASSERT(sii
->coreid
[5] == PCIE_CORE_ID
);
134 pcie
= REG_MAP(sii
->wrapba
[5], SI_CORE_SIZE
);
135 ASSERT(sii
->coreid
[8] == I2S_CORE_ID
);
136 i2s
= REG_MAP(sii
->wrapba
[8], SI_CORE_SIZE
);
137 if ((R_REG(sii
->osh
, &cpu
->oobselina74
) != 0x08060504) ||
138 (R_REG(sii
->osh
, &pcie
->oobselina74
) != 0x08060504) ||
139 (R_REG(sii
->osh
, &i2s
->oobselouta30
) != 0x88)) {
140 SI_VMSG(("Unexpected oob values, not fixing i2s interrupt\n"));
142 /* Move i2s interrupt to oob line 7 instead of 8 */
143 W_REG(sii
->osh
, &cpu
->oobselina74
, 0x07060504);
144 W_REG(sii
->osh
, &pcie
->oobselina74
, 0x07060504);
145 W_REG(sii
->osh
, &i2s
->oobselouta30
, 0x87);
146 SI_VMSG(("Changed i2s interrupt to use oob line 7 instead of 8\n"));
152 struct _corerev_entry
{
156 static struct _corerev_entry bcm4706_corerev_cc
[] = {
157 { 0x1f, CC_4706B0_CORE_REV
},
160 static struct _corerev_entry bcm4706_corerev_socsram
[] = {
161 { 0x05, SOCRAM_4706B0_CORE_REV
},
164 static struct _corerev_entry bcm4706_corerev_gmac
[] = {
165 { 0x00, GMAC_4706B0_CORE_REV
},
169 struct _coreid_entry
{
173 static struct _coreid_entry bcm4706_coreid_table
[] = {
174 { CC_4706_CORE_ID
, CC_CORE_ID
},
175 { SOCRAM_4706_CORE_ID
, SOCRAM_CORE_ID
},
176 { GMAC_4706_CORE_ID
, GMAC_CORE_ID
},
181 remap_coreid(si_t
*sih
, uint coreid
)
183 struct _coreid_entry
*coreid_table
= NULL
;
185 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
)
186 coreid_table
= &bcm4706_coreid_table
[0];
188 if (coreid_table
!= NULL
) {
191 for (i
= 0; coreid_table
[i
].coreid
; i
++)
192 if (coreid_table
[i
].coreid
== coreid
)
193 return coreid_table
[i
].coreid_alias
;
200 remap_corerev(si_t
*sih
, uint corerev
)
202 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
) {
203 si_info_t
*sii
= SI_INFO(sih
);
204 uint i
, coreid
= sii
->coreid
[sii
->curidx
];
205 struct _corerev_entry
*corerev_table
= NULL
;
207 if (coreid
== CC_CORE_ID
)
208 corerev_table
= bcm4706_corerev_cc
;
209 else if (coreid
== GMAC_CORE_ID
)
210 corerev_table
= bcm4706_corerev_gmac
;
211 else if (coreid
== SOCRAM_CORE_ID
)
212 corerev_table
= bcm4706_corerev_socsram
;
213 if (corerev_table
!= NULL
) {
214 for (i
= 0; corerev_table
[i
].corerev_alias
; i
++)
215 if (corerev_table
[i
].corerev
== corerev
)
216 return corerev_table
[i
].corerev_alias
;
223 /* parse the enumeration rom to identify all cores */
225 BCMATTACHFN(ai_scan
)(si_t
*sih
, void *regs
, uint devid
)
227 si_info_t
*sii
= SI_INFO(sih
);
228 chipcregs_t
*cc
= (chipcregs_t
*)regs
;
229 uint32 erombase
, *eromptr
, *eromlim
;
231 erombase
= R_REG(sii
->osh
, &cc
->eromptr
);
233 switch (BUSTYPE(sih
->bustype
)) {
235 eromptr
= (uint32
*)REG_MAP(erombase
, SI_CORE_SIZE
);
239 /* Set wrappers address */
240 sii
->curwrap
= (void *)((uintptr
)regs
+ SI_CORE_SIZE
);
242 /* Now point the window at the erom */
243 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, 4, erombase
);
249 eromptr
= (uint32
*)(uintptr
)erombase
;
255 SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih
->bustype
));
259 eromlim
= eromptr
+ (ER_REMAPCONTROL
/ sizeof(uint32
));
261 SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n",
262 regs
, erombase
, eromptr
, eromlim
));
263 while (eromptr
< eromlim
) {
264 uint32 cia
, cib
, cid
, mfg
, crev
, nmw
, nsw
, nmp
, nsp
;
265 uint32 mpd
, asd
, addrl
, addrh
, sizel
, sizeh
;
271 /* Grok a component */
272 cia
= get_erom_ent(sih
, &eromptr
, ER_TAG
, ER_CI
);
273 if (cia
== (ER_END
| ER_VALID
)) {
274 SI_VMSG(("Found END of erom after %d cores\n", sii
->numcores
));
279 cib
= get_erom_ent(sih
, &eromptr
, 0, 0);
281 if ((cib
& ER_TAG
) != ER_CI
) {
282 SI_ERROR(("CIA not followed by CIB\n"));
286 cid
= (cia
& CIA_CID_MASK
) >> CIA_CID_SHIFT
;
287 mfg
= (cia
& CIA_MFG_MASK
) >> CIA_MFG_SHIFT
;
288 crev
= (cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
289 nmw
= (cib
& CIB_NMW_MASK
) >> CIB_NMW_SHIFT
;
290 nsw
= (cib
& CIB_NSW_MASK
) >> CIB_NSW_SHIFT
;
291 nmp
= (cib
& CIB_NMP_MASK
) >> CIB_NMP_SHIFT
;
292 nsp
= (cib
& CIB_NSP_MASK
) >> CIB_NSP_SHIFT
;
295 SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, "
296 "nsw = %d, nmp = %d & nsp = %d\n",
297 mfg
, cid
, crev
, eromptr
- 1, nmw
, nsw
, nmp
, nsp
));
302 if (((mfg
== MFGID_ARM
) && (cid
== DEF_AI_COMP
)) || (nsp
== 0))
304 if ((nmw
+ nsw
== 0)) {
305 /* A component which is not a core */
306 if (cid
== OOB_ROUTER_CORE_ID
) {
307 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
,
308 &addrl
, &addrh
, &sizel
, &sizeh
);
310 sii
->oob_router
= addrl
;
313 if (cid
!= GMAC_COMMON_4706_CORE_ID
)
321 sii
->coreid
[idx
] = remap_coreid(sih
, cid
);
323 for (i
= 0; i
< nmp
; i
++) {
324 mpd
= get_erom_ent(sih
, &eromptr
, ER_VALID
, ER_VALID
);
325 if ((mpd
& ER_TAG
) != ER_MP
) {
326 SI_ERROR(("Not enough MP entries for component 0x%x\n", cid
));
329 SI_VMSG((" Master port %d, mp: %d id: %d\n", i
,
330 (mpd
& MPD_MP_MASK
) >> MPD_MP_SHIFT
,
331 (mpd
& MPD_MUI_MASK
) >> MPD_MUI_SHIFT
));
334 /* First Slave Address Descriptor should be port 0:
335 * the main register space for the core
337 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
, &addrl
, &addrh
, &sizel
, &sizeh
);
340 /* Try again to see if it is a bridge */
341 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_BRIDGE
, &addrl
, &addrh
,
349 else if ((addrh
!= 0) || (sizeh
!= 0) ||
350 (sizel
!= SI_CORE_SIZE
)) {
351 SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 ="
352 "0x%x\n", addrh
, sizeh
, sizel
));
353 SI_ERROR(("First Slave ASD for"
354 "core 0x%04x malformed "
355 "(0x%08x)\n", cid
, asd
));
361 sii
->coresba
[idx
] = addrl
;
362 sii
->coresba_size
[idx
] = sizel
;
363 /* Get any more ASDs in port 0 */
366 asd
= get_asd(sih
, &eromptr
, 0, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
368 if ((asd
!= 0) && (j
== 1) && (sizel
== SI_CORE_SIZE
)) {
369 sii
->coresba2
[idx
] = addrl
;
370 sii
->coresba2_size
[idx
] = sizel
;
375 /* Go through the ASDs for other slave ports */
376 for (i
= 1; i
< nsp
; i
++) {
379 asd
= get_asd(sih
, &eromptr
, i
, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
387 SI_ERROR((" SP %d has no address descriptors\n", i
));
392 /* Now get master wrappers */
393 for (i
= 0; i
< nmw
; i
++) {
394 asd
= get_asd(sih
, &eromptr
, i
, 0, AD_ST_MWRAP
, &addrl
, &addrh
,
397 SI_ERROR(("Missing descriptor for MW %d\n", i
));
400 if ((sizeh
!= 0) || (sizel
!= SI_CORE_SIZE
)) {
401 SI_ERROR(("Master wrapper %d is not 4KB\n", i
));
405 sii
->wrapba
[idx
] = addrl
;
408 /* And finally slave wrappers */
409 for (i
= 0; i
< nsw
; i
++) {
410 uint fwp
= (nsp
== 1) ? 0 : 1;
411 asd
= get_asd(sih
, &eromptr
, fwp
+ i
, 0, AD_ST_SWRAP
, &addrl
, &addrh
,
414 SI_ERROR(("Missing descriptor for SW %d\n", i
));
417 if ((sizeh
!= 0) || (sizel
!= SI_CORE_SIZE
)) {
418 SI_ERROR(("Slave wrapper %d is not 4KB\n", i
));
421 if ((nmw
== 0) && (i
== 0))
422 sii
->wrapba
[idx
] = addrl
;
425 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
) {
426 /* Check if it's a low cost package */
427 i
= (R_REG(sii
->osh
, &cc
->chipid
) & CID_PKG_MASK
) >> CID_PKG_SHIFT
;
428 if (i
== BCM4706L_PKG_ID
) {
429 /* bcm4706L: only one GMAC */
430 if (cid
== GMAC_4706_CORE_ID
) {
431 for (j
= 0; j
< sii
->numcores
; j
++) {
432 if (sii
->coreid
[j
] == GMAC_CORE_ID
)
435 if (j
!= sii
->numcores
) {
436 /* Found one GMAC already, ignore this one */
443 /* Don't record bridges */
451 SI_ERROR(("Reached end of erom without finding END"));
458 /* This function changes the logical "focus" to the indicated core.
459 * Return the current core's virtual address.
462 ai_setcoreidx(si_t
*sih
, uint coreidx
)
464 si_info_t
*sii
= SI_INFO(sih
);
468 if (coreidx
>= MIN(sii
->numcores
, SI_MAXCORES
))
471 addr
= sii
->coresba
[coreidx
];
472 wrap
= sii
->wrapba
[coreidx
];
475 * If the user has provided an interrupt mask enabled function,
476 * then assert interrupts are disabled before switching the core.
478 ASSERT((sii
->intrsenabled_fn
== NULL
) || !(*(sii
)->intrsenabled_fn
)((sii
)->intr_arg
));
480 switch (BUSTYPE(sih
->bustype
)) {
483 if (!sii
->regs
[coreidx
]) {
484 sii
->regs
[coreidx
] = REG_MAP(addr
, SI_CORE_SIZE
);
485 ASSERT(GOODREGS(sii
->regs
[coreidx
]));
487 sii
->curmap
= regs
= sii
->regs
[coreidx
];
488 if (!sii
->wrappers
[coreidx
]) {
489 sii
->wrappers
[coreidx
] = REG_MAP(wrap
, SI_CORE_SIZE
);
490 ASSERT(GOODREGS(sii
->wrappers
[coreidx
]));
492 sii
->curwrap
= sii
->wrappers
[coreidx
];
496 /* point bar0 window */
497 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, 4, addr
);
499 /* point bar0 2nd 4KB window to the primary wrapper */
501 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCIE2_BAR0_WIN2
, 4, wrap
);
503 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, wrap
);
508 sii
->curmap
= regs
= (void *)((uintptr
)addr
);
509 sii
->curwrap
= (void *)((uintptr
)wrap
);
521 sii
->curidx
= coreidx
;
527 ai_coreaddrspaceX(si_t
*sih
, uint asidx
, uint32
*addr
, uint32
*size
)
529 si_info_t
*sii
= SI_INFO(sih
);
530 chipcregs_t
*cc
= NULL
;
531 uint32 erombase
, *eromptr
, *eromlim
;
533 uint32 cia
, cib
, nmp
, nsp
;
534 uint32 asd
, addrl
, addrh
, sizel
, sizeh
;
536 for (i
= 0; i
< sii
->numcores
; i
++) {
537 if (sii
->coreid
[i
] == CC_CORE_ID
) {
538 cc
= (chipcregs_t
*)sii
->regs
[i
];
545 erombase
= R_REG(sii
->osh
, &cc
->eromptr
);
546 eromptr
= (uint32
*)REG_MAP(erombase
, SI_CORE_SIZE
);
547 eromlim
= eromptr
+ (ER_REMAPCONTROL
/ sizeof(uint32
));
550 cia
= sii
->cia
[cidx
];
551 cib
= sii
->cib
[cidx
];
553 nmp
= (cib
& CIB_NMP_MASK
) >> CIB_NMP_SHIFT
;
554 nsp
= (cib
& CIB_NSP_MASK
) >> CIB_NSP_SHIFT
;
557 while (eromptr
< eromlim
) {
558 if ((get_erom_ent(sih
, &eromptr
, ER_TAG
, ER_CI
) == cia
) &&
559 (get_erom_ent(sih
, &eromptr
, 0, 0) == cib
)) {
564 /* skip master ports */
565 for (i
= 0; i
< nmp
; i
++)
566 get_erom_ent(sih
, &eromptr
, ER_VALID
, ER_VALID
);
568 /* Skip ASDs in port 0 */
569 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
, &addrl
, &addrh
, &sizel
, &sizeh
);
571 /* Try again to see if it is a bridge */
572 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_BRIDGE
, &addrl
, &addrh
,
578 asd
= get_asd(sih
, &eromptr
, 0, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
583 /* Go through the ASDs for other slave ports */
584 for (i
= 1; i
< nsp
; i
++) {
587 asd
= get_asd(sih
, &eromptr
, i
, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
601 SI_ERROR((" SP %d has no address descriptors\n", i
));
611 /* Return the number of address spaces in current core */
613 ai_numaddrspaces(si_t
*sih
)
618 /* Return the address of the nth address space in the current core */
620 ai_addrspace(si_t
*sih
, uint asidx
)
629 return sii
->coresba
[cidx
];
631 return sii
->coresba2
[cidx
];
633 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
634 __FUNCTION__
, asidx
));
639 /* Return the size of the nth address space in the current core */
641 ai_addrspacesize(si_t
*sih
, uint asidx
)
650 return sii
->coresba_size
[cidx
];
652 return sii
->coresba2_size
[cidx
];
654 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
655 __FUNCTION__
, asidx
));
667 if (BCM47162_DMP()) {
668 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__
));
672 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__
));
677 return (R_REG(sii
->osh
, &ai
->oobselouta30
) & 0x1f);
681 ai_setint(si_t
*sih
, int siflag
)
686 ai_wrap_reg(si_t
*sih
, uint32 offset
, uint32 mask
, uint32 val
)
688 si_info_t
*sii
= SI_INFO(sih
);
689 uint32
*map
= (uint32
*) sii
->curwrap
;
692 uint32 w
= R_REG(sii
->osh
, map
+(offset
/4));
695 W_REG(sii
->osh
, map
+(offset
/4), val
);
698 return (R_REG(sii
->osh
, map
+(offset
/4)));
702 ai_corevendor(si_t
*sih
)
708 cia
= sii
->cia
[sii
->curidx
];
709 return ((cia
& CIA_MFG_MASK
) >> CIA_MFG_SHIFT
);
713 ai_corerev(si_t
*sih
)
719 cib
= sii
->cib
[sii
->curidx
];
720 return remap_corerev(sih
, (cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
);
724 ai_iscoreup(si_t
*sih
)
732 return (((R_REG(sii
->osh
, &ai
->ioctrl
) & (SICF_FGC
| SICF_CLOCK_EN
)) == SICF_CLOCK_EN
) &&
733 ((R_REG(sii
->osh
, &ai
->resetctrl
) & AIRC_RESET
) == 0));
737 * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
738 * switch back to the original core, and return the new value.
740 * When using the silicon backplane, no fiddling with interrupts or core switches is needed.
742 * Also, when using pci/pcie, we can optimize away the core switching for pci registers
743 * and (on newer pci cores) chipcommon registers.
746 ai_corereg(si_t
*sih
, uint coreidx
, uint regoff
, uint mask
, uint val
)
757 ASSERT(GOODIDX(coreidx
));
758 ASSERT(regoff
< SI_CORE_SIZE
);
759 ASSERT((val
& ~mask
) == 0);
761 if (coreidx
>= SI_MAXCORES
)
764 if (BUSTYPE(sih
->bustype
) == SI_BUS
) {
765 /* If internal bus, we can always get at everything */
767 /* map if does not exist */
768 if (!sii
->regs
[coreidx
]) {
769 sii
->regs
[coreidx
] = REG_MAP(sii
->coresba
[coreidx
],
771 ASSERT(GOODREGS(sii
->regs
[coreidx
]));
773 r
= (uint32
*)((uchar
*)sii
->regs
[coreidx
] + regoff
);
774 } else if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
775 /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
777 if ((sii
->coreid
[coreidx
] == CC_CORE_ID
) && SI_FAST(sii
)) {
778 /* Chipc registers are mapped at 12KB */
781 r
= (uint32
*)((char *)sii
->curmap
+ PCI_16KB0_CCREGS_OFFSET
+ regoff
);
782 } else if (sii
->pub
.buscoreidx
== coreidx
) {
783 /* pci registers are at either in the last 2KB of an 8KB window
784 * or, in pcie and pci rev 13 at 8KB
788 r
= (uint32
*)((char *)sii
->curmap
+
789 PCI_16KB0_PCIREGS_OFFSET
+ regoff
);
791 r
= (uint32
*)((char *)sii
->curmap
+
792 ((regoff
>= SBCONFIGOFF
) ?
793 PCI_BAR0_PCISBR_OFFSET
: PCI_BAR0_PCIREGS_OFFSET
) +
799 INTR_OFF(sii
, intr_val
);
801 /* save current core index */
802 origidx
= si_coreidx(&sii
->pub
);
805 r
= (uint32
*) ((uchar
*) ai_setcoreidx(&sii
->pub
, coreidx
) + regoff
);
811 w
= (R_REG(sii
->osh
, r
) & ~mask
) | val
;
812 W_REG(sii
->osh
, r
, w
);
816 w
= R_REG(sii
->osh
, r
);
819 /* restore core index */
820 if (origidx
!= coreidx
)
821 ai_setcoreidx(&sii
->pub
, origidx
);
823 INTR_RESTORE(sii
, intr_val
);
830 ai_core_disable(si_t
*sih
, uint32 bits
)
833 volatile uint32 dummy
;
839 ASSERT(GOODREGS(sii
->curwrap
));
842 /* if core is already in reset, just return */
843 if (R_REG(sii
->osh
, &ai
->resetctrl
) & AIRC_RESET
)
846 /* ensure there are no pending backplane operations */
847 SPINWAIT(((status
= R_REG(sii
->osh
, &ai
->resetstatus
)) != 0), 300);
849 /* if pending backplane ops still, try waiting longer */
851 /* 300usecs was sufficient to allow backplane ops to clear for big hammer */
852 /* during driver load we may need more time */
853 SPINWAIT(((status
= R_REG(sii
->osh
, &ai
->resetstatus
)) != 0), 10000);
854 /* if still pending ops, continue on and try disable anyway */
855 /* this is in big hammer path, so don't call wl_reinit in this case... */
858 printf("%s: WARN: resetstatus=%0x on core disable\n", __FUNCTION__
, status
);
863 W_REG(sii
->osh
, &ai
->ioctrl
, bits
);
864 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
865 BCM_REFERENCE(dummy
);
868 W_REG(sii
->osh
, &ai
->resetctrl
, AIRC_RESET
);
869 dummy
= R_REG(sii
->osh
, &ai
->resetctrl
);
870 BCM_REFERENCE(dummy
);
874 /* reset and re-enable a core
876 * bits - core specific bits that are set during and after reset sequence
877 * resetbits - core specific bits that are set only during reset sequence
880 ai_core_reset(si_t
*sih
, uint32 bits
, uint32 resetbits
)
884 volatile uint32 dummy
;
887 ASSERT(GOODREGS(sii
->curwrap
));
891 * Must do the disable sequence first to work for arbitrary current core state.
893 ai_core_disable(sih
, (bits
| resetbits
));
896 * Now do the initialization sequence.
898 W_REG(sii
->osh
, &ai
->ioctrl
, (bits
| SICF_FGC
| SICF_CLOCK_EN
));
899 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
900 BCM_REFERENCE(dummy
);
902 W_REG(sii
->osh
, &ai
->resetctrl
, 0);
903 dummy
= R_REG(sii
->osh
, &ai
->resetctrl
);
904 BCM_REFERENCE(dummy
);
907 W_REG(sii
->osh
, &ai
->ioctrl
, (bits
| SICF_CLOCK_EN
));
908 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
909 BCM_REFERENCE(dummy
);
914 ai_core_cflags_wo(si_t
*sih
, uint32 mask
, uint32 val
)
922 if (BCM47162_DMP()) {
923 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
928 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
933 ASSERT(GOODREGS(sii
->curwrap
));
936 ASSERT((val
& ~mask
) == 0);
939 w
= ((R_REG(sii
->osh
, &ai
->ioctrl
) & ~mask
) | val
);
940 W_REG(sii
->osh
, &ai
->ioctrl
, w
);
945 ai_core_cflags(si_t
*sih
, uint32 mask
, uint32 val
)
952 if (BCM47162_DMP()) {
953 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
958 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
963 ASSERT(GOODREGS(sii
->curwrap
));
966 ASSERT((val
& ~mask
) == 0);
969 w
= ((R_REG(sii
->osh
, &ai
->ioctrl
) & ~mask
) | val
);
970 W_REG(sii
->osh
, &ai
->ioctrl
, w
);
973 return R_REG(sii
->osh
, &ai
->ioctrl
);
977 ai_core_sflags(si_t
*sih
, uint32 mask
, uint32 val
)
984 if (BCM47162_DMP()) {
985 SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
990 SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
995 ASSERT(GOODREGS(sii
->curwrap
));
998 ASSERT((val
& ~mask
) == 0);
999 ASSERT((mask
& ~SISF_CORE_BITS
) == 0);
1002 w
= ((R_REG(sii
->osh
, &ai
->iostatus
) & ~mask
) | val
);
1003 W_REG(sii
->osh
, &ai
->iostatus
, w
);
1006 return R_REG(sii
->osh
, &ai
->iostatus
);
1010 /* print interesting aidmp registers */
1012 ai_dumpregs(si_t
*sih
, struct bcmstrbuf
*b
)
1022 for (i
= 0; i
< sii
->numcores
; i
++) {
1023 si_setcoreidx(&sii
->pub
, i
);
1026 bcm_bprintf(b
, "core 0x%x: \n", sii
->coreid
[i
]);
1027 if (BCM47162_DMP()) {
1028 bcm_bprintf(b
, "Skipping mips74k in 47162a0\n");
1031 if (BCM5357_DMP()) {
1032 bcm_bprintf(b
, "Skipping usb20h in 5357\n");
1036 bcm_bprintf(b
, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
1037 "ioctrlwidth 0x%x iostatuswidth 0x%x\n"
1038 "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n"
1039 "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
1040 "errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
1041 "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
1042 "intstatus 0x%x config 0x%x itcr 0x%x\n",
1043 R_REG(osh
, &ai
->ioctrlset
),
1044 R_REG(osh
, &ai
->ioctrlclear
),
1045 R_REG(osh
, &ai
->ioctrl
),
1046 R_REG(osh
, &ai
->iostatus
),
1047 R_REG(osh
, &ai
->ioctrlwidth
),
1048 R_REG(osh
, &ai
->iostatuswidth
),
1049 R_REG(osh
, &ai
->resetctrl
),
1050 R_REG(osh
, &ai
->resetstatus
),
1051 R_REG(osh
, &ai
->resetreadid
),
1052 R_REG(osh
, &ai
->resetwriteid
),
1053 R_REG(osh
, &ai
->errlogctrl
),
1054 R_REG(osh
, &ai
->errlogdone
),
1055 R_REG(osh
, &ai
->errlogstatus
),
1056 R_REG(osh
, &ai
->errlogaddrlo
),
1057 R_REG(osh
, &ai
->errlogaddrhi
),
1058 R_REG(osh
, &ai
->errlogid
),
1059 R_REG(osh
, &ai
->errloguser
),
1060 R_REG(osh
, &ai
->errlogflags
),
1061 R_REG(osh
, &ai
->intstatus
),
1062 R_REG(osh
, &ai
->config
),
1063 R_REG(osh
, &ai
->itcr
));
1064 if ((sih
->chip
== BCM4331_CHIP_ID
) && (sii
->coreid
[i
] == PCIE_CORE_ID
)) {
1065 /* point bar0 2nd 4KB window */
1066 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, 0x18103000);
1067 bcm_bprintf(b
, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
1068 "ioctrlwidth 0x%x iostatuswidth 0x%x\n"
1069 "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x"
1070 " resetwriteid 0x%x\n"
1071 "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
1072 "errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
1073 "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
1074 "intstatus 0x%x config 0x%x itcr 0x%x\n",
1075 R_REG(osh
, &ai
->ioctrlset
),
1076 R_REG(osh
, &ai
->ioctrlclear
),
1077 R_REG(osh
, &ai
->ioctrl
),
1078 R_REG(osh
, &ai
->iostatus
),
1079 R_REG(osh
, &ai
->ioctrlwidth
),
1080 R_REG(osh
, &ai
->iostatuswidth
),
1081 R_REG(osh
, &ai
->resetctrl
),
1082 R_REG(osh
, &ai
->resetstatus
),
1083 R_REG(osh
, &ai
->resetreadid
),
1084 R_REG(osh
, &ai
->resetwriteid
),
1085 R_REG(osh
, &ai
->errlogctrl
),
1086 R_REG(osh
, &ai
->errlogdone
),
1087 R_REG(osh
, &ai
->errlogstatus
),
1088 R_REG(osh
, &ai
->errlogaddrlo
),
1089 R_REG(osh
, &ai
->errlogaddrhi
),
1090 R_REG(osh
, &ai
->errlogid
),
1091 R_REG(osh
, &ai
->errloguser
),
1092 R_REG(osh
, &ai
->errlogflags
),
1093 R_REG(osh
, &ai
->intstatus
),
1094 R_REG(osh
, &ai
->config
),
1095 R_REG(osh
, &ai
->itcr
));
1096 /* bar0 2nd 4KB window will be fixed in the next setcore */
1104 _ai_view(osl_t
*osh
, aidmp_t
*ai
, uint32 cid
, uint32 addr
, bool verbose
)
1108 config
= R_REG(osh
, &ai
->config
);
1109 SI_ERROR(("\nCore ID: 0x%x, addr 0x%x, config 0x%x\n", cid
, addr
, config
));
1111 if (config
& AICFG_RST
)
1112 SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n",
1113 R_REG(osh
, &ai
->resetctrl
), R_REG(osh
, &ai
->resetstatus
),
1114 R_REG(osh
, &ai
->resetreadid
), R_REG(osh
, &ai
->resetwriteid
)));
1116 if (config
& AICFG_IOC
)
1117 SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh
, &ai
->ioctrl
),
1118 R_REG(osh
, &ai
->ioctrlwidth
)));
1120 if (config
& AICFG_IOS
)
1121 SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh
, &ai
->iostatus
),
1122 R_REG(osh
, &ai
->iostatuswidth
)));
1124 if (config
& AICFG_ERRL
) {
1125 SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n",
1126 R_REG(osh
, &ai
->errlogctrl
), R_REG(osh
, &ai
->errlogdone
),
1127 R_REG(osh
, &ai
->errlogstatus
), R_REG(osh
, &ai
->intstatus
)));
1128 SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr "
1130 R_REG(osh
, &ai
->errlogid
), R_REG(osh
, &ai
->errloguser
),
1131 R_REG(osh
, &ai
->errlogflags
), R_REG(osh
, &ai
->errlogaddrhi
),
1132 R_REG(osh
, &ai
->errlogaddrlo
)));
1135 if (verbose
&& (config
& AICFG_OOB
)) {
1136 SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n",
1137 R_REG(osh
, &ai
->oobselina30
), R_REG(osh
, &ai
->oobselina74
)));
1138 SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n",
1139 R_REG(osh
, &ai
->oobselinb30
), R_REG(osh
, &ai
->oobselinb74
)));
1140 SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n",
1141 R_REG(osh
, &ai
->oobselinc30
), R_REG(osh
, &ai
->oobselinc74
)));
1142 SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n",
1143 R_REG(osh
, &ai
->oobselind30
), R_REG(osh
, &ai
->oobselind74
)));
1144 SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n",
1145 R_REG(osh
, &ai
->oobselouta30
), R_REG(osh
, &ai
->oobselouta74
)));
1146 SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n",
1147 R_REG(osh
, &ai
->oobseloutb30
), R_REG(osh
, &ai
->oobseloutb74
)));
1148 SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n",
1149 R_REG(osh
, &ai
->oobseloutc30
), R_REG(osh
, &ai
->oobseloutc74
)));
1150 SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n",
1151 R_REG(osh
, &ai
->oobseloutd30
), R_REG(osh
, &ai
->oobseloutd74
)));
1152 SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n",
1153 R_REG(osh
, &ai
->oobsynca
), R_REG(osh
, &ai
->oobseloutaen
)));
1154 SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n",
1155 R_REG(osh
, &ai
->oobsyncb
), R_REG(osh
, &ai
->oobseloutben
)));
1156 SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n",
1157 R_REG(osh
, &ai
->oobsyncc
), R_REG(osh
, &ai
->oobseloutcen
)));
1158 SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n",
1159 R_REG(osh
, &ai
->oobsyncd
), R_REG(osh
, &ai
->oobseloutden
)));
1160 SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n",
1161 R_REG(osh
, &ai
->oobaextwidth
), R_REG(osh
, &ai
->oobainwidth
),
1162 R_REG(osh
, &ai
->oobaoutwidth
)));
1163 SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n",
1164 R_REG(osh
, &ai
->oobbextwidth
), R_REG(osh
, &ai
->oobbinwidth
),
1165 R_REG(osh
, &ai
->oobboutwidth
)));
1166 SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n",
1167 R_REG(osh
, &ai
->oobcextwidth
), R_REG(osh
, &ai
->oobcinwidth
),
1168 R_REG(osh
, &ai
->oobcoutwidth
)));
1169 SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n",
1170 R_REG(osh
, &ai
->oobdextwidth
), R_REG(osh
, &ai
->oobdinwidth
),
1171 R_REG(osh
, &ai
->oobdoutwidth
)));
1176 ai_view(si_t
*sih
, bool verbose
)
1186 if (BCM47162_DMP()) {
1187 SI_ERROR(("Cannot access mips74k DMP in 47162a0\n"));
1190 if (BCM5357_DMP()) {
1191 SI_ERROR(("Cannot access usb20h DMP in 5357\n"));
1194 cid
= sii
->coreid
[sii
->curidx
];
1195 addr
= sii
->wrapba
[sii
->curidx
];
1196 _ai_view(osh
, ai
, cid
, addr
, verbose
);
1200 ai_viewall(si_t
*sih
, bool verbose
)
1210 for (i
= 0; i
< sii
->numcores
; i
++) {
1211 si_setcoreidx(sih
, i
);
1212 if (BCM47162_DMP()) {
1213 SI_ERROR(("Skipping mips74k DMP in 47162a0\n"));
1216 if (BCM5357_DMP()) {
1217 SI_ERROR(("Skipping usb20h DMP in 5357\n"));
1221 cid
= sii
->coreid
[sii
->curidx
];
1222 addr
= sii
->wrapba
[sii
->curidx
];
1223 _ai_view(osh
, ai
, cid
, addr
, verbose
);
1224 if ((sih
->chip
== BCM4331_CHIP_ID
) && (sii
->coreid
[i
] == PCIE_CORE_ID
)) {
1225 /* point bar0 2nd 4KB window */
1226 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, 0x18103000);
1227 _ai_view(osh
, ai
, cid
, 0x18103000, verbose
);
1228 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, 0x18104000);
1229 _ai_view(osh
, ai
, 0x135, 0x18104000, verbose
);
1230 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, 0x18105000);
1231 _ai_view(osh
, ai
, 0x135, 0x18105000, verbose
);
1232 /* bar0 2nd 4KB window will be fixed in the next setcore */