2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2010, 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,v 1.27.2.5 2011-01-26 18:24:11 Exp $
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
;
272 /* Grok a component */
273 cia
= get_erom_ent(sih
, &eromptr
, ER_TAG
, ER_CI
);
274 if (cia
== (ER_END
| ER_VALID
)) {
275 SI_VMSG(("Found END of erom after %d cores\n", sii
->numcores
));
280 cib
= get_erom_ent(sih
, &eromptr
, 0, 0);
282 if ((cib
& ER_TAG
) != ER_CI
) {
283 SI_ERROR(("CIA not followed by CIB\n"));
287 cid
= (cia
& CIA_CID_MASK
) >> CIA_CID_SHIFT
;
288 mfg
= (cia
& CIA_MFG_MASK
) >> CIA_MFG_SHIFT
;
289 crev
= (cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
290 nmw
= (cib
& CIB_NMW_MASK
) >> CIB_NMW_SHIFT
;
291 nsw
= (cib
& CIB_NSW_MASK
) >> CIB_NSW_SHIFT
;
292 nmp
= (cib
& CIB_NMP_MASK
) >> CIB_NMP_SHIFT
;
293 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
, base
, nmw
, nsw
, nmp
, nsp
));
299 if (((mfg
== MFGID_ARM
) && (cid
== DEF_AI_COMP
)) || (nsp
== 0))
301 if ((nmw
+ nsw
== 0)) {
302 /* A component which is not a core */
303 if (cid
== OOB_ROUTER_CORE_ID
) {
304 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
,
305 &addrl
, &addrh
, &sizel
, &sizeh
);
307 sii
->oob_router
= addrl
;
310 if (cid
!= GMAC_COMMON_4706_CORE_ID
)
315 /* sii->eromptr[idx] = base; */
318 sii
->coreid
[idx
] = remap_coreid(sih
, cid
);
320 for (i
= 0; i
< nmp
; i
++) {
321 mpd
= get_erom_ent(sih
, &eromptr
, ER_VALID
, ER_VALID
);
322 if ((mpd
& ER_TAG
) != ER_MP
) {
323 SI_ERROR(("Not enough MP entries for component 0x%x\n", cid
));
326 SI_VMSG((" Master port %d, mp: %d id: %d\n", i
,
327 (mpd
& MPD_MP_MASK
) >> MPD_MP_SHIFT
,
328 (mpd
& MPD_MUI_MASK
) >> MPD_MUI_SHIFT
));
331 /* First Slave Address Descriptor should be port 0:
332 * the main register space for the core
334 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
, &addrl
, &addrh
, &sizel
, &sizeh
);
336 /* Try again to see if it is a bridge */
337 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_BRIDGE
, &addrl
, &addrh
,
342 if ((addrh
!= 0) || (sizeh
!= 0) || (sizel
!= SI_CORE_SIZE
)) {
343 SI_ERROR(("First Slave ASD for core 0x%04x malformed "
344 "(0x%08x)\n", cid
, asd
));
348 sii
->coresba
[idx
] = addrl
;
349 sii
->coresba_size
[idx
] = sizel
;
350 /* Get any more ASDs in port 0 */
353 asd
= get_asd(sih
, &eromptr
, 0, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
355 if ((asd
!= 0) && (j
== 1) && (sizel
== SI_CORE_SIZE
)) {
356 sii
->coresba2
[idx
] = addrl
;
357 sii
->coresba2_size
[idx
] = sizel
;
362 /* Go through the ASDs for other slave ports */
363 for (i
= 1; i
< nsp
; i
++) {
366 asd
= get_asd(sih
, &eromptr
, i
, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
374 SI_ERROR((" SP %d has no address descriptors\n", i
));
379 /* Now get master wrappers */
380 for (i
= 0; i
< nmw
; i
++) {
381 asd
= get_asd(sih
, &eromptr
, i
, 0, AD_ST_MWRAP
, &addrl
, &addrh
,
384 SI_ERROR(("Missing descriptor for MW %d\n", i
));
387 if ((sizeh
!= 0) || (sizel
!= SI_CORE_SIZE
)) {
388 SI_ERROR(("Master wrapper %d is not 4KB\n", i
));
392 sii
->wrapba
[idx
] = addrl
;
395 /* And finally slave wrappers */
396 for (i
= 0; i
< nsw
; i
++) {
397 uint fwp
= (nsp
== 1) ? 0 : 1;
398 asd
= get_asd(sih
, &eromptr
, fwp
+ i
, 0, AD_ST_SWRAP
, &addrl
, &addrh
,
401 SI_ERROR(("Missing descriptor for SW %d\n", i
));
404 if ((sizeh
!= 0) || (sizel
!= SI_CORE_SIZE
)) {
405 SI_ERROR(("Slave wrapper %d is not 4KB\n", i
));
408 if ((nmw
== 0) && (i
== 0))
409 sii
->wrapba
[idx
] = addrl
;
412 /* Don't record bridges */
420 SI_ERROR(("Reached end of erom without finding END"));
427 /* This function changes the logical "focus" to the indicated core.
428 * Return the current core's virtual address.
431 ai_setcoreidx(si_t
*sih
, uint coreidx
)
433 si_info_t
*sii
= SI_INFO(sih
);
434 uint32 addr
= sii
->coresba
[coreidx
];
435 uint32 wrap
= sii
->wrapba
[coreidx
];
438 if (coreidx
>= sii
->numcores
)
442 * If the user has provided an interrupt mask enabled function,
443 * then assert interrupts are disabled before switching the core.
445 ASSERT((sii
->intrsenabled_fn
== NULL
) || !(*(sii
)->intrsenabled_fn
)((sii
)->intr_arg
));
447 switch (BUSTYPE(sih
->bustype
)) {
450 if (!sii
->regs
[coreidx
]) {
451 sii
->regs
[coreidx
] = REG_MAP(addr
, SI_CORE_SIZE
);
452 ASSERT(GOODREGS(sii
->regs
[coreidx
]));
454 sii
->curmap
= regs
= sii
->regs
[coreidx
];
455 if (!sii
->wrappers
[coreidx
]) {
456 sii
->wrappers
[coreidx
] = REG_MAP(wrap
, SI_CORE_SIZE
);
457 ASSERT(GOODREGS(sii
->wrappers
[coreidx
]));
459 sii
->curwrap
= sii
->wrappers
[coreidx
];
463 /* point bar0 window */
464 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, 4, addr
);
466 /* point bar0 2nd 4KB window */
467 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, wrap
);
472 sii
->curmap
= regs
= (void *)((uintptr
)addr
);
473 sii
->curwrap
= (void *)((uintptr
)wrap
);
485 sii
->curidx
= coreidx
;
491 ai_coreaddrspaceX(si_t
*sih
, uint asidx
, uint32
*addr
, uint32
*size
)
493 si_info_t
*sii
= SI_INFO(sih
);
494 chipcregs_t
*cc
= NULL
;
495 uint32 erombase
, *eromptr
, *eromlim
;
497 uint32 cia
, cib
, nmp
, nsp
;
498 uint32 asd
, addrl
, addrh
, sizel
, sizeh
;
500 for (i
= 0; i
< sii
->numcores
; i
++) {
501 if (sii
->coreid
[i
] == CC_CORE_ID
) {
502 cc
= (chipcregs_t
*)sii
->regs
[i
];
509 erombase
= R_REG(sii
->osh
, &cc
->eromptr
);
510 eromptr
= (uint32
*)REG_MAP(erombase
, SI_CORE_SIZE
);
511 eromlim
= eromptr
+ (ER_REMAPCONTROL
/ sizeof(uint32
));
514 cia
= sii
->cia
[cidx
];
515 cib
= sii
->cib
[cidx
];
517 nmp
= (cib
& CIB_NMP_MASK
) >> CIB_NMP_SHIFT
;
518 nsp
= (cib
& CIB_NSP_MASK
) >> CIB_NSP_SHIFT
;
521 while (eromptr
< eromlim
) {
522 if ((get_erom_ent(sih
, &eromptr
, ER_TAG
, ER_CI
) == cia
) &&
523 (get_erom_ent(sih
, &eromptr
, 0, 0) == cib
)) {
528 /* skip master ports */
529 for (i
= 0; i
< nmp
; i
++)
530 get_erom_ent(sih
, &eromptr
, ER_VALID
, ER_VALID
);
532 /* Skip ASDs in port 0 */
533 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_SLAVE
, &addrl
, &addrh
, &sizel
, &sizeh
);
535 /* Try again to see if it is a bridge */
536 asd
= get_asd(sih
, &eromptr
, 0, 0, AD_ST_BRIDGE
, &addrl
, &addrh
,
542 asd
= get_asd(sih
, &eromptr
, 0, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
547 /* Go through the ASDs for other slave ports */
548 for (i
= 1; i
< nsp
; i
++) {
551 asd
= get_asd(sih
, &eromptr
, i
, j
, AD_ST_SLAVE
, &addrl
, &addrh
,
565 SI_ERROR((" SP %d has no address descriptors\n", i
));
575 /* Return the number of address spaces in current core */
577 ai_numaddrspaces(si_t
*sih
)
582 /* Return the address of the nth address space in the current core */
584 ai_addrspace(si_t
*sih
, uint asidx
)
593 return sii
->coresba
[cidx
];
595 return sii
->coresba2
[cidx
];
597 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
598 __FUNCTION__
, asidx
));
603 /* Return the size of the nth address space in the current core */
605 ai_addrspacesize(si_t
*sih
, uint asidx
)
614 return sii
->coresba_size
[cidx
];
616 return sii
->coresba2_size
[cidx
];
618 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
619 __FUNCTION__
, asidx
));
631 if (BCM47162_DMP()) {
632 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__
));
636 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__
));
641 return (R_REG(sii
->osh
, &ai
->oobselouta30
) & 0x1f);
645 ai_setint(si_t
*sih
, int siflag
)
650 ai_write_wrap_reg(si_t
*sih
, uint32 offset
, uint32 val
)
652 si_info_t
*sii
= SI_INFO(sih
);
653 uint32
*w
= (uint32
*) sii
->curwrap
;
654 W_REG(sii
->osh
, w
+(offset
/4), val
);
659 ai_corevendor(si_t
*sih
)
665 cia
= sii
->cia
[sii
->curidx
];
666 return ((cia
& CIA_MFG_MASK
) >> CIA_MFG_SHIFT
);
670 ai_corerev(si_t
*sih
)
676 cib
= sii
->cib
[sii
->curidx
];
677 return remap_corerev(sih
, (cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
);
681 ai_iscoreup(si_t
*sih
)
689 return (((R_REG(sii
->osh
, &ai
->ioctrl
) & (SICF_FGC
| SICF_CLOCK_EN
)) == SICF_CLOCK_EN
) &&
690 ((R_REG(sii
->osh
, &ai
->resetctrl
) & AIRC_RESET
) == 0));
694 * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
695 * switch back to the original core, and return the new value.
697 * When using the silicon backplane, no fiddling with interrupts or core switches is needed.
699 * Also, when using pci/pcie, we can optimize away the core switching for pci registers
700 * and (on newer pci cores) chipcommon registers.
703 ai_corereg(si_t
*sih
, uint coreidx
, uint regoff
, uint mask
, uint val
)
714 ASSERT(GOODIDX(coreidx
));
715 ASSERT(regoff
< SI_CORE_SIZE
);
716 ASSERT((val
& ~mask
) == 0);
718 if (coreidx
>= SI_MAXCORES
)
721 if (BUSTYPE(sih
->bustype
) == SI_BUS
) {
722 /* If internal bus, we can always get at everything */
724 /* map if does not exist */
725 if (!sii
->regs
[coreidx
]) {
726 sii
->regs
[coreidx
] = REG_MAP(sii
->coresba
[coreidx
],
728 ASSERT(GOODREGS(sii
->regs
[coreidx
]));
730 r
= (uint32
*)((uchar
*)sii
->regs
[coreidx
] + regoff
);
731 } else if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
732 /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
734 if ((sii
->coreid
[coreidx
] == CC_CORE_ID
) && SI_FAST(sii
)) {
735 /* Chipc registers are mapped at 12KB */
738 r
= (uint32
*)((char *)sii
->curmap
+ PCI_16KB0_CCREGS_OFFSET
+ regoff
);
739 } else if (sii
->pub
.buscoreidx
== coreidx
) {
740 /* pci registers are at either in the last 2KB of an 8KB window
741 * or, in pcie and pci rev 13 at 8KB
745 r
= (uint32
*)((char *)sii
->curmap
+
746 PCI_16KB0_PCIREGS_OFFSET
+ regoff
);
748 r
= (uint32
*)((char *)sii
->curmap
+
749 ((regoff
>= SBCONFIGOFF
) ?
750 PCI_BAR0_PCISBR_OFFSET
: PCI_BAR0_PCIREGS_OFFSET
) +
756 INTR_OFF(sii
, intr_val
);
758 /* save current core index */
759 origidx
= si_coreidx(&sii
->pub
);
762 r
= (uint32
*) ((uchar
*) ai_setcoreidx(&sii
->pub
, coreidx
) + regoff
);
768 w
= (R_REG(sii
->osh
, r
) & ~mask
) | val
;
769 W_REG(sii
->osh
, r
, w
);
773 w
= R_REG(sii
->osh
, r
);
776 /* restore core index */
777 if (origidx
!= coreidx
)
778 ai_setcoreidx(&sii
->pub
, origidx
);
780 INTR_RESTORE(sii
, intr_val
);
787 ai_core_disable(si_t
*sih
, uint32 bits
)
790 volatile uint32 dummy
;
795 ASSERT(GOODREGS(sii
->curwrap
));
798 /* if core is already in reset, just return */
799 if (R_REG(sii
->osh
, &ai
->resetctrl
) & AIRC_RESET
)
802 W_REG(sii
->osh
, &ai
->ioctrl
, bits
);
803 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
806 W_REG(sii
->osh
, &ai
->resetctrl
, AIRC_RESET
);
807 dummy
= R_REG(sii
->osh
, &ai
->resetctrl
);
811 /* reset and re-enable a core
813 * bits - core specific bits that are set during and after reset sequence
814 * resetbits - core specific bits that are set only during reset sequence
817 ai_core_reset(si_t
*sih
, uint32 bits
, uint32 resetbits
)
821 volatile uint32 dummy
;
824 ASSERT(GOODREGS(sii
->curwrap
));
828 * Must do the disable sequence first to work for arbitrary current core state.
830 ai_core_disable(sih
, (bits
| resetbits
));
833 * Now do the initialization sequence.
835 W_REG(sii
->osh
, &ai
->ioctrl
, (bits
| SICF_FGC
| SICF_CLOCK_EN
));
836 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
837 W_REG(sii
->osh
, &ai
->resetctrl
, 0);
840 W_REG(sii
->osh
, &ai
->ioctrl
, (bits
| SICF_CLOCK_EN
));
841 dummy
= R_REG(sii
->osh
, &ai
->ioctrl
);
847 ai_core_cflags_wo(si_t
*sih
, uint32 mask
, uint32 val
)
855 if (BCM47162_DMP()) {
856 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
861 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
866 ASSERT(GOODREGS(sii
->curwrap
));
869 ASSERT((val
& ~mask
) == 0);
872 w
= ((R_REG(sii
->osh
, &ai
->ioctrl
) & ~mask
) | val
);
873 W_REG(sii
->osh
, &ai
->ioctrl
, w
);
878 ai_core_cflags(si_t
*sih
, uint32 mask
, uint32 val
)
885 if (BCM47162_DMP()) {
886 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
891 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
896 ASSERT(GOODREGS(sii
->curwrap
));
899 ASSERT((val
& ~mask
) == 0);
902 w
= ((R_REG(sii
->osh
, &ai
->ioctrl
) & ~mask
) | val
);
903 W_REG(sii
->osh
, &ai
->ioctrl
, w
);
906 return R_REG(sii
->osh
, &ai
->ioctrl
);
910 ai_core_sflags(si_t
*sih
, uint32 mask
, uint32 val
)
917 if (BCM47162_DMP()) {
918 SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
923 SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
928 ASSERT(GOODREGS(sii
->curwrap
));
931 ASSERT((val
& ~mask
) == 0);
932 ASSERT((mask
& ~SISF_CORE_BITS
) == 0);
935 w
= ((R_REG(sii
->osh
, &ai
->iostatus
) & ~mask
) | val
);
936 W_REG(sii
->osh
, &ai
->iostatus
, w
);
939 return R_REG(sii
->osh
, &ai
->iostatus
);
942 #if defined(BCMDBG) || defined(BCMDBG_DUMP)
943 /* print interesting aidmp registers */
945 ai_dumpregs(si_t
*sih
, struct bcmstrbuf
*b
)
955 for (i
= 0; i
< sii
->numcores
; i
++) {
956 si_setcoreidx(&sii
->pub
, i
);
959 bcm_bprintf(b
, "core 0x%x: \n", sii
->coreid
[i
]);
960 if (BCM47162_DMP()) {
961 bcm_bprintf(b
, "Skipping mips74k in 47162a0\n");
965 bcm_bprintf(b
, "Skipping usb20h in 5357\n");
969 bcm_bprintf(b
, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
970 "ioctrlwidth 0x%x iostatuswidth 0x%x\n"
971 "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n"
972 "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
973 "errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
974 "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
975 "intstatus 0x%x config 0x%x itcr 0x%x\n",
976 R_REG(osh
, &ai
->ioctrlset
),
977 R_REG(osh
, &ai
->ioctrlclear
),
978 R_REG(osh
, &ai
->ioctrl
),
979 R_REG(osh
, &ai
->iostatus
),
980 R_REG(osh
, &ai
->ioctrlwidth
),
981 R_REG(osh
, &ai
->iostatuswidth
),
982 R_REG(osh
, &ai
->resetctrl
),
983 R_REG(osh
, &ai
->resetstatus
),
984 R_REG(osh
, &ai
->resetreadid
),
985 R_REG(osh
, &ai
->resetwriteid
),
986 R_REG(osh
, &ai
->errlogctrl
),
987 R_REG(osh
, &ai
->errlogdone
),
988 R_REG(osh
, &ai
->errlogstatus
),
989 R_REG(osh
, &ai
->errlogaddrlo
),
990 R_REG(osh
, &ai
->errlogaddrhi
),
991 R_REG(osh
, &ai
->errlogid
),
992 R_REG(osh
, &ai
->errloguser
),
993 R_REG(osh
, &ai
->errlogflags
),
994 R_REG(osh
, &ai
->intstatus
),
995 R_REG(osh
, &ai
->config
),
996 R_REG(osh
, &ai
->itcr
));
997 if ((sih
->chip
== BCM4331_CHIP_ID
) && (sii
->coreid
[i
] == PCIE_CORE_ID
)) {
998 /* point bar0 2nd 4KB window */
999 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN2
, 4, 0x18103000);
1000 bcm_bprintf(b
, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
1001 "ioctrlwidth 0x%x iostatuswidth 0x%x\n"
1002 "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x"
1003 " resetwriteid 0x%x\n"
1004 "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
1005 "errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
1006 "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
1007 "intstatus 0x%x config 0x%x itcr 0x%x\n",
1008 R_REG(osh
, &ai
->ioctrlset
),
1009 R_REG(osh
, &ai
->ioctrlclear
),
1010 R_REG(osh
, &ai
->ioctrl
),
1011 R_REG(osh
, &ai
->iostatus
),
1012 R_REG(osh
, &ai
->ioctrlwidth
),
1013 R_REG(osh
, &ai
->iostatuswidth
),
1014 R_REG(osh
, &ai
->resetctrl
),
1015 R_REG(osh
, &ai
->resetstatus
),
1016 R_REG(osh
, &ai
->resetreadid
),
1017 R_REG(osh
, &ai
->resetwriteid
),
1018 R_REG(osh
, &ai
->errlogctrl
),
1019 R_REG(osh
, &ai
->errlogdone
),
1020 R_REG(osh
, &ai
->errlogstatus
),
1021 R_REG(osh
, &ai
->errlogaddrlo
),
1022 R_REG(osh
, &ai
->errlogaddrhi
),
1023 R_REG(osh
, &ai
->errlogid
),
1024 R_REG(osh
, &ai
->errloguser
),
1025 R_REG(osh
, &ai
->errlogflags
),
1026 R_REG(osh
, &ai
->intstatus
),
1027 R_REG(osh
, &ai
->config
),
1028 R_REG(osh
, &ai
->itcr
));
1029 /* bar0 2nd 4KB window will be fixed in the next setcore */
1033 #endif /* BCMDBG || BCMDBG_DUMP */
1037 ai_view(si_t
*sih
, bool verbose
)
1047 if (BCM47162_DMP()) {
1048 SI_ERROR(("Cannot access mips74k DMP in 47162a0\n"));
1051 if (BCM5357_DMP()) {
1052 SI_ERROR(("Cannot access usb20h DMP in 5357\n"));
1056 SI_ERROR(("\nCore ID: 0x%x, config 0x%x\n", si_coreid(&sii
->pub
),
1057 (config
= R_REG(osh
, &ai
->config
))));
1059 if (config
& AICFG_RST
)
1060 SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n",
1061 R_REG(osh
, &ai
->resetctrl
), R_REG(osh
, &ai
->resetstatus
),
1062 R_REG(osh
, &ai
->resetreadid
), R_REG(osh
, &ai
->resetwriteid
)));
1064 if (config
& AICFG_IOC
)
1065 SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh
, &ai
->ioctrl
),
1066 R_REG(osh
, &ai
->ioctrlwidth
)));
1068 if (config
& AICFG_IOS
)
1069 SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh
, &ai
->iostatus
),
1070 R_REG(osh
, &ai
->iostatuswidth
)));
1072 if (config
& AICFG_ERRL
) {
1073 SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n",
1074 R_REG(osh
, &ai
->errlogctrl
), R_REG(osh
, &ai
->errlogdone
),
1075 R_REG(osh
, &ai
->errlogstatus
), R_REG(osh
, &ai
->intstatus
)));
1076 SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr "
1078 R_REG(osh
, &ai
->errlogid
), R_REG(osh
, &ai
->errloguser
),
1079 R_REG(osh
, &ai
->errlogflags
), R_REG(osh
, &ai
->errlogaddrhi
),
1080 R_REG(osh
, &ai
->errlogaddrlo
)));
1083 if (verbose
&& (config
& AICFG_OOB
)) {
1084 SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n",
1085 R_REG(osh
, &ai
->oobselina30
), R_REG(osh
, &ai
->oobselina74
)));
1086 SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n",
1087 R_REG(osh
, &ai
->oobselinb30
), R_REG(osh
, &ai
->oobselinb74
)));
1088 SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n",
1089 R_REG(osh
, &ai
->oobselinc30
), R_REG(osh
, &ai
->oobselinc74
)));
1090 SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n",
1091 R_REG(osh
, &ai
->oobselind30
), R_REG(osh
, &ai
->oobselind74
)));
1092 SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n",
1093 R_REG(osh
, &ai
->oobselouta30
), R_REG(osh
, &ai
->oobselouta74
)));
1094 SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n",
1095 R_REG(osh
, &ai
->oobseloutb30
), R_REG(osh
, &ai
->oobseloutb74
)));
1096 SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n",
1097 R_REG(osh
, &ai
->oobseloutc30
), R_REG(osh
, &ai
->oobseloutc74
)));
1098 SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n",
1099 R_REG(osh
, &ai
->oobseloutd30
), R_REG(osh
, &ai
->oobseloutd74
)));
1100 SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n",
1101 R_REG(osh
, &ai
->oobsynca
), R_REG(osh
, &ai
->oobseloutaen
)));
1102 SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n",
1103 R_REG(osh
, &ai
->oobsyncb
), R_REG(osh
, &ai
->oobseloutben
)));
1104 SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n",
1105 R_REG(osh
, &ai
->oobsyncc
), R_REG(osh
, &ai
->oobseloutcen
)));
1106 SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n",
1107 R_REG(osh
, &ai
->oobsyncd
), R_REG(osh
, &ai
->oobseloutden
)));
1108 SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n",
1109 R_REG(osh
, &ai
->oobaextwidth
), R_REG(osh
, &ai
->oobainwidth
),
1110 R_REG(osh
, &ai
->oobaoutwidth
)));
1111 SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n",
1112 R_REG(osh
, &ai
->oobbextwidth
), R_REG(osh
, &ai
->oobbinwidth
),
1113 R_REG(osh
, &ai
->oobboutwidth
)));
1114 SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n",
1115 R_REG(osh
, &ai
->oobcextwidth
), R_REG(osh
, &ai
->oobcinwidth
),
1116 R_REG(osh
, &ai
->oobcoutwidth
)));
1117 SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n",
1118 R_REG(osh
, &ai
->oobdextwidth
), R_REG(osh
, &ai
->oobdinwidth
),
1119 R_REG(osh
, &ai
->oobdoutwidth
)));