2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * $Copyright Open Broadcom Corporation$
7 * $Id: aiutils.c 385510 2013-02-15 21:02:07Z $
19 #include "siutils_priv.h"
21 #define BCM47162_DMP() (0)
22 #define BCM5357_DMP() (0)
23 #define BCM4707_DMP() (0)
24 #define remap_coreid(sih, coreid) (coreid)
25 #define remap_corerev(sih, corerev) (corerev)
30 get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
33 uint inv = 0, nom = 0;
36 ent = R_REG(si_osh(sih), *eromptr);
42 if ((ent & ER_VALID) == 0) {
47 if (ent == (ER_END | ER_VALID))
50 if ((ent & mask) == match)
56 SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
58 SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom));
64 get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh,
65 uint32 *sizel, uint32 *sizeh)
69 asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
70 if (((asd & ER_TAG1) != ER_ADD) ||
71 (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
72 ((asd & AD_ST_MASK) != st)) {
77 *addrl = asd & AD_ADDR_MASK;
79 *addrh = get_erom_ent(sih, eromptr, 0, 0);
83 sz = asd & AD_SZ_MASK;
84 if (sz == AD_SZ_SZD) {
85 szd = get_erom_ent(sih, eromptr, 0, 0);
86 *sizel = szd & SD_SZ_MASK;
88 *sizeh = get_erom_ent(sih, eromptr, 0, 0);
90 *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
92 SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
93 sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
99 ai_hwfixup(si_info_t *sii)
106 ai_scan(si_t *sih, void *regs, uint devid)
108 si_info_t *sii = SI_INFO(sih);
109 chipcregs_t *cc = (chipcregs_t *)regs;
110 uint32 erombase, *eromptr, *eromlim;
112 erombase = R_REG(sii->osh, &cc->eromptr);
114 switch (BUSTYPE(sih->bustype)) {
116 eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
121 sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
124 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
130 eromptr = (uint32 *)(uintptr)erombase;
135 SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype));
139 eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
141 SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n",
142 regs, erombase, eromptr, eromlim));
143 while (eromptr < eromlim) {
144 uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
145 uint32 mpd, asd, addrl, addrh, sizel, sizeh;
152 cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
153 if (cia == (ER_END | ER_VALID)) {
154 SI_VMSG(("Found END of erom after %d cores\n", sii->numcores));
159 cib = get_erom_ent(sih, &eromptr, 0, 0);
161 if ((cib & ER_TAG) != ER_CI) {
162 SI_ERROR(("CIA not followed by CIB\n"));
166 cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
167 mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
168 crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
169 nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
170 nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
171 nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
172 nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
175 SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, "
176 "nsw = %d, nmp = %d & nsp = %d\n",
177 mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp));
182 if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
184 if ((nmw + nsw == 0)) {
186 if (cid == OOB_ROUTER_CORE_ID) {
187 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
188 &addrl, &addrh, &sizel, &sizeh);
190 sii->oob_router = addrl;
193 if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID)
201 sii->coreid[idx] = remap_coreid(sih, cid);
203 for (i = 0; i < nmp; i++) {
204 mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
205 if ((mpd & ER_TAG) != ER_MP) {
206 SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
209 SI_VMSG((" Master port %d, mp: %d id: %d\n", i,
210 (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
211 (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
215 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
219 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
227 else if ((addrh != 0) || (sizeh != 0) ||
228 (sizel != SI_CORE_SIZE)) {
229 SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 ="
230 "0x%x\n", addrh, sizeh, sizel));
231 SI_ERROR(("First Slave ASD for"
232 "core 0x%04x malformed "
233 "(0x%08x)\n", cid, asd));
239 sii->coresba[idx] = addrl;
240 sii->coresba_size[idx] = sizel;
244 asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
246 if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
247 sii->coresba2[idx] = addrl;
248 sii->coresba2_size[idx] = sizel;
254 for (i = 1; i < nsp; i++) {
257 asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
265 SI_ERROR((" SP %d has no address descriptors\n", i));
271 for (i = 0; i < nmw; i++) {
272 asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
275 SI_ERROR(("Missing descriptor for MW %d\n", i));
278 if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
279 SI_ERROR(("Master wrapper %d is not 4KB\n", i));
283 sii->wrapba[idx] = addrl;
287 for (i = 0; i < nsw; i++) {
288 uint fwp = (nsp == 1) ? 0 : 1;
289 asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
292 SI_ERROR(("Missing descriptor for SW %d\n", i));
295 if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
296 SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
299 if ((nmw == 0) && (i == 0))
300 sii->wrapba[idx] = addrl;
312 SI_ERROR(("Reached end of erom without finding END"));
321 ai_setcoreidx(si_t *sih, uint coreidx)
323 si_info_t *sii = SI_INFO(sih);
327 if (coreidx >= MIN(sii->numcores, SI_MAXCORES))
330 addr = sii->coresba[coreidx];
331 wrap = sii->wrapba[coreidx];
334 ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
336 switch (BUSTYPE(sih->bustype)) {
339 if (!sii->regs[coreidx]) {
340 sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
341 ASSERT(GOODREGS(sii->regs[coreidx]));
343 sii->curmap = regs = sii->regs[coreidx];
344 if (!sii->wrappers[coreidx] && (wrap != 0)) {
345 sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
346 ASSERT(GOODREGS(sii->wrappers[coreidx]));
348 sii->curwrap = sii->wrappers[coreidx];
354 sii->curmap = regs = (void *)((uintptr)addr);
355 sii->curwrap = (void *)((uintptr)wrap);
366 sii->curidx = coreidx;
372 ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
374 si_info_t *sii = SI_INFO(sih);
375 chipcregs_t *cc = NULL;
376 uint32 erombase, *eromptr, *eromlim;
378 uint32 cia, cib, nmp, nsp;
379 uint32 asd, addrl, addrh, sizel, sizeh;
381 for (i = 0; i < sii->numcores; i++) {
382 if (sii->coreid[i] == CC_CORE_ID) {
383 cc = (chipcregs_t *)sii->regs[i];
390 erombase = R_REG(sii->osh, &cc->eromptr);
391 eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
392 eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
395 cia = sii->cia[cidx];
396 cib = sii->cib[cidx];
398 nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
399 nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
402 while (eromptr < eromlim) {
403 if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) &&
404 (get_erom_ent(sih, &eromptr, 0, 0) == cib)) {
410 for (i = 0; i < nmp; i++)
411 get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
414 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
417 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
423 asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
429 for (i = 1; i < nsp; i++) {
432 asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
446 SI_ERROR((" SP %d has no address descriptors\n", i));
458 ai_numaddrspaces(si_t *sih)
465 ai_addrspace(si_t *sih, uint asidx)
474 return sii->coresba[cidx];
476 return sii->coresba2[cidx];
478 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
479 __FUNCTION__, asidx));
486 ai_addrspacesize(si_t *sih, uint asidx)
495 return sii->coresba_size[cidx];
497 return sii->coresba2_size[cidx];
499 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
500 __FUNCTION__, asidx));
512 if (BCM47162_DMP()) {
513 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
517 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
521 SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
527 return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
531 ai_flag_alt(si_t *sih)
537 if (BCM47162_DMP()) {
538 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
542 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
546 SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
552 return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
556 ai_setint(si_t *sih, int siflag)
561 ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
563 si_info_t *sii = SI_INFO(sih);
564 uint32 *map = (uint32 *) sii->curwrap;
567 uint32 w = R_REG(sii->osh, map+(offset/4));
570 W_REG(sii->osh, map+(offset/4), val);
573 return (R_REG(sii->osh, map+(offset/4)));
577 ai_corevendor(si_t *sih)
583 cia = sii->cia[sii->curidx];
584 return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
588 ai_corerev(si_t *sih)
594 cib = sii->cib[sii->curidx];
595 return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
599 ai_iscoreup(si_t *sih)
607 return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
608 ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
613 ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
624 ASSERT(GOODIDX(coreidx));
625 ASSERT(regoff < SI_CORE_SIZE);
626 ASSERT((val & ~mask) == 0);
628 if (coreidx >= SI_MAXCORES)
631 if (BUSTYPE(sih->bustype) == SI_BUS) {
635 if (!sii->regs[coreidx]) {
636 sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
638 ASSERT(GOODREGS(sii->regs[coreidx]));
640 r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff);
641 } else if (BUSTYPE(sih->bustype) == PCI_BUS) {
644 if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
648 r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
649 } else if (sii->pub.buscoreidx == coreidx) {
653 r = (uint32 *)((char *)sii->curmap +
654 PCI_16KB0_PCIREGS_OFFSET + regoff);
656 r = (uint32 *)((char *)sii->curmap +
657 ((regoff >= SBCONFIGOFF) ?
658 PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
664 INTR_OFF(sii, intr_val);
667 origidx = si_coreidx(&sii->pub);
670 r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
676 w = (R_REG(sii->osh, r) & ~mask) | val;
677 W_REG(sii->osh, r, w);
681 w = R_REG(sii->osh, r);
685 if (origidx != coreidx)
686 ai_setcoreidx(&sii->pub, origidx);
688 INTR_RESTORE(sii, intr_val);
695 ai_core_disable(si_t *sih, uint32 bits)
698 volatile uint32 dummy;
704 ASSERT(GOODREGS(sii->curwrap));
708 if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
712 SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
718 SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000);
723 W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
724 dummy = R_REG(sii->osh, &ai->resetctrl);
725 BCM_REFERENCE(dummy);
728 W_REG(sii->osh, &ai->ioctrl, bits);
729 dummy = R_REG(sii->osh, &ai->ioctrl);
730 BCM_REFERENCE(dummy);
736 ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
740 volatile uint32 dummy;
743 ASSERT(GOODREGS(sii->curwrap));
747 ai_core_disable(sih, (bits | resetbits));
750 W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
751 dummy = R_REG(sii->osh, &ai->ioctrl);
752 BCM_REFERENCE(dummy);
754 W_REG(sii->osh, &ai->resetctrl, 0);
755 dummy = R_REG(sii->osh, &ai->resetctrl);
756 BCM_REFERENCE(dummy);
759 W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
760 dummy = R_REG(sii->osh, &ai->ioctrl);
761 BCM_REFERENCE(dummy);
766 ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
774 if (BCM47162_DMP()) {
775 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
780 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
785 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
790 ASSERT(GOODREGS(sii->curwrap));
793 ASSERT((val & ~mask) == 0);
796 w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
797 W_REG(sii->osh, &ai->ioctrl, w);
802 ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
809 if (BCM47162_DMP()) {
810 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
815 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
820 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
825 ASSERT(GOODREGS(sii->curwrap));
828 ASSERT((val & ~mask) == 0);
831 w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
832 W_REG(sii->osh, &ai->ioctrl, w);
835 return R_REG(sii->osh, &ai->ioctrl);
839 ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
846 if (BCM47162_DMP()) {
847 SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
852 SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
857 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
862 ASSERT(GOODREGS(sii->curwrap));
865 ASSERT((val & ~mask) == 0);
866 ASSERT((mask & ~SISF_CORE_BITS) == 0);
869 w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
870 W_REG(sii->osh, &ai->iostatus, w);
873 return R_REG(sii->osh, &ai->iostatus);