/* initialize the sdio core */ void si_sdio_init(si_t *sih) { si_info_t *sii = SI_INFO(sih); if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || (sih->buscoretype == SDIOD_CORE_ID)) { uint idx; sdpcmd_regs_t *sdpregs; /* get the current core index */ idx = sii->curidx; ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0)); /* switch to sdio core */ if (!(sdpregs = (sdpcmd_regs_t *)si_setcore(sih, PCMCIA_CORE_ID, 0))) sdpregs = (sdpcmd_regs_t *)si_setcore(sih, SDIOD_CORE_ID, 0); ASSERT(sdpregs); SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih->buscorerev, idx, sii->curidx, sdpregs)); /* enable backplane error and core interrupts */ W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT); W_REG(sii->osh, &sdpregs->sbintmask, (I_SB_SERR | I_SB_RESPERR | (1 << idx))); /* switch back to previous core */ si_setcoreidx(sih, idx); } /* enable interrupts */ bcmsdh_intr_enable(sii->sdh); }
/* generic kernel variant of si_attach() */ si_t * si_kattach(osl_t *osh) { static bool ksii_attached = FALSE; if (!ksii_attached) { void *regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, SI_BUS, NULL, osh != SI_OSH ? &ksii.vars : NULL, osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { if (NULL != ksii.common_info) MFREE(osh, ksii.common_info, sizeof(si_common_info_t)); SI_ERROR(("si_kattach: si_doattach failed\n")); REG_UNMAP(regs); return NULL; } REG_UNMAP(regs); /* save ticks normalized to ms for si_watchdog_ms() */ if (PMUCTL_ENAB(&ksii.pub)) { /* based on 32KHz ILP clock */ wd_msticks = 32; } else { wd_msticks = ALP_CLOCK / 1000; } ksii_attached = TRUE; SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", ksii.pub.ccrev, wd_msticks)); } return &ksii.pub; }
static uint _sb_scan(si_info_t *sii, u32 sba, void *regs, uint bus, u32 sbba, uint numcores) { uint next; uint ncc = 0; uint i; if (bus >= SB_MAXBUSES) { SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to " "scan\n", sbba, bus)); return 0; } SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores)); /* Scan all cores on the bus starting from core 0. * Core addresses must be contiguous on each bus. */ for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) { sii->coresba[next] = sbba + (i * SI_CORE_SIZE); /* change core to 'next' and read its coreid */ sii->curmap = _sb_setcoreidx(sii, next); sii->curidx = next; sii->coreid[next] = sb_coreid(&sii->pub); /* core specific processing... */ /* chipc provides # cores */ if (sii->coreid[next] == CC_CORE_ID) { chipcregs_t *cc = (chipcregs_t *) sii->curmap; u32 ccrev = sb_corerev(&sii->pub); /* determine numcores - this is the total # cores in the chip */ if (((ccrev == 4) || (ccrev >= 6))) numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; else { /* Older chips */ SI_ERROR(("sb_chip2numcores: unsupported chip " "0x%x\n", sii->pub.chip)); ASSERT(0); numcores = 1; } SI_VMSG(("_sb_scan: %u cores in the chip %s\n", numcores, sii->pub.issim ? "QT" : "")); }
static si_info_t * si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, uint *varsz) { struct si_pub *sih = &sii->pub; uint32 w, savewin; chipcregs_t *cc; char *pvars = NULL; uint origidx; ASSERT(GOODREGS(regs)); bzero((uchar*)sii, sizeof(si_info_t)); { if (NULL == (common_info_alloced = (void *)MALLOC(osh, sizeof(si_common_info_t)))) { SI_ERROR(("si_doattach: malloc failed! malloced %dbytes\n", MALLOCED(osh))); return (NULL); } bzero((uchar*)(common_info_alloced), sizeof(si_common_info_t)); } sii->common_info = (si_common_info_t *)common_info_alloced; sii->common_info->attach_count++; savewin = 0; sih->buscoreidx = BADIDX; sii->curmap = regs; sii->sdh = sdh; sii->osh = osh; /* find Chipcommon address */ if (bustype == PCI_BUS) { savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) savewin = SI_ENUM_BASE; OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); cc = (chipcregs_t *)regs; } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { cc = (chipcregs_t *)sii->curmap; } else { cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); } sih->bustype = bustype; if (bustype != BUSTYPE(bustype)) { SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype))); return NULL; } /* bus/core/clk setup for register access */ if (!si_buscore_prep(sii, bustype, devid, sdh)) { SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); return NULL; } /* ChipID recognition. * We assume we can read chipid at offset 0 from the regs arg. * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), * some way of recognizing them needs to be added here. */ w = R_REG(osh, &cc->chipid); sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; /* Might as wll fill in chip id rev & pkg */ sih->chip = w & CID_ID_MASK; sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) sih->chippkg = BCM4329_182PIN_PKG_ID; sih->issim = IS_SIM(sih->chippkg); /* scan for cores */ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { SI_MSG(("Found chip type AI (0x%08x)\n", w)); /* pass chipc address instead of original core base */ ai_scan(&sii->pub, (void *)cc, devid); } else { SI_ERROR(("Found chip of unkown type (0x%08x)\n", w)); return NULL; } /* no cores found, bail out */ if (sii->numcores == 0) { SI_ERROR(("si_doattach: could not find any cores\n")); return NULL; } /* bus/core/clk setup */ origidx = SI_CC_IDX; if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { SI_ERROR(("si_doattach: si_buscore_setup failed\n")); return NULL; } pvars = NULL; if (sii->pub.ccrev >= 20) { cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); W_REG(osh, &cc->gpiopullup, 0); W_REG(osh, &cc->gpiopulldown, 0); si_setcoreidx(sih, origidx); } /* Skip PMU initialization from the Dongle Host. * Firmware will take care of it when it comes up. */ return (sii); }
static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, uint *origidx, void *regs) { bool pci, pcie; uint i; uint pciidx, pcieidx, pcirev, pcierev; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); /* get chipcommon rev */ sii->pub.ccrev = (int)si_corerev(&sii->pub); /* get chipcommon chipstatus */ if (sii->pub.ccrev >= 11) sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); /* get chipcommon capabilites */ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); /* get pmu rev and caps */ if (sii->pub.cccaps & CC_CAP_PMU) { sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, sii->pub.pmucaps)); /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; sii->pub.buscorerev = NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; pcirev = pcierev = NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { uint cid, crev; si_setcoreidx(&sii->pub, i); cid = si_coreid(&sii->pub); crev = si_corerev(&sii->pub); /* Display cores found */ SI_MSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", i, cid, crev, sii->common_info->coresba[i], sii->common_info->regs[i])); if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { pciidx = i; pcirev = crev; pci = TRUE; } else if (cid == PCIE_CORE_ID) { pcieidx = i; pcierev = crev; pcie = TRUE; } } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && (cid == PCMCIA_CORE_ID)) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } else if (((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) && ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } /* find the core idx before entering this func. */ if ((savewin && (savewin == sii->common_info->coresba[i])) || (regs == sii->common_info->regs[i])) *origidx = i; } SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, sii->pub.buscorerev)); if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (sii->pub.chiprev <= 3)) OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was * already running. */ if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) si_core_disable(&sii->pub, 0); } /* return to the original core */ si_setcoreidx(&sii->pub, *origidx); return TRUE; }
static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, uint *origidx, void *regs) { bool pci, pcie, pcie_gen2 = FALSE; uint i; uint pciidx, pcieidx, pcirev, pcierev; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); /* get chipcommon rev */ sii->pub.ccrev = (int)si_corerev(&sii->pub); /* get chipcommon chipstatus */ if (sii->pub.ccrev >= 11) sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); /* get chipcommon capabilites */ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); /* get chipcommon extended capabilities */ if (sii->pub.ccrev >= 35) sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); /* get pmu rev and caps */ if (sii->pub.cccaps & CC_CAP_PMU) { sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, sii->pub.pmucaps)); /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; sii->pub.buscorerev = (uint)NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; pcirev = pcierev = (uint)NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { uint cid, crev; si_setcoreidx(&sii->pub, i); cid = si_coreid(&sii->pub); crev = si_corerev(&sii->pub); /* Display cores found */ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", i, cid, crev, sii->coresba[i], sii->regs[i])); if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { pciidx = i; pcirev = crev; pci = TRUE; } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) { pcieidx = i; pcierev = crev; pcie = TRUE; if (cid == PCIE2_CORE_ID) pcie_gen2 = TRUE; } } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && (cid == PCMCIA_CORE_ID)) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } else if (((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) && ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } /* find the core idx before entering this func. */ if ((savewin && (savewin == sii->coresba[i])) || (regs == sii->regs[i])) *origidx = i; } if (pci) { sii->pub.buscoretype = PCI_CORE_ID; sii->pub.buscorerev = pcirev; sii->pub.buscoreidx = pciidx; } else if (pcie) { if (pcie_gen2) sii->pub.buscoretype = PCIE2_C