uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corereg(sih, coreidx, regoff, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_corereg(sih, coreidx, regoff, mask, val); else { ASSERT(0); return 0; } }
uint si_corerev(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corerev(sih); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_corerev(sih); else { ASSERT(0); return 0; } }
bool si_iscoreup(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_iscoreup(sih); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_iscoreup(sih); else { ASSERT(0); return FALSE; } }
uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_core_sflags(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_core_sflags(sih, mask, val); else { ASSERT(0); return 0; } }
uint32 si_addrspacesize(si_t *sih, uint asidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_addrspacesize(sih, asidx); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_addrspacesize(sih, asidx); else { ASSERT(0); return 0; } }
int si_numaddrspaces(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_numaddrspaces(sih); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_numaddrspaces(sih); else { ASSERT(0); return 0; } }
void * si_setcoreidx(si_t *sih, uint coreidx) { if(sih == NULL) return NULL; if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, coreidx); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_setcoreidx(sih, coreidx); else { ASSERT(0); return NULL; } }
uint si_intflag(si_t *sih) { si_info_t *sii = SI_INFO(sih); if (CHIPTYPE(sih->socitype) == SOCI_SB) { sbconfig_t *ccsbr = (sbconfig_t *)((uintptr)((ulong) (sii->common_info->coresba[SI_CC_IDX]) + SBCONFIGOFF)); return R_REG(sii->osh, &ccsbr->sbflagst); } else if (CHIPTYPE(sih->socitype) == SOCI_AI) return R_REG(sii->osh, ((uint32 *)(uintptr) (sii->common_info->oob_router + OOB_STATUSA))); else { ASSERT(0); return 0; } }
/* * This function changes logical "focus" to the indicated core; * must be called with interrupts off. * Moreover, callers should keep interrupts off during switching out of and back to d11 core */ void * si_setcore(si_t *sih, uint coreid, uint coreunit) { uint idx; idx = si_findcoreidx(sih, coreid, coreunit); if (!GOODIDX(idx)) return (NULL); if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, idx); else if (CHIPTYPE(sih->socitype) == SOCI_AI) return ai_setcoreidx(sih, idx); else { ASSERT(0); return NULL; } }
void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val) { /* only for 4319, no requirement for SOCI_SB */ if (CHIPTYPE(sih->socitype) == SOCI_AI) { ai_write_wrap_reg(sih, offset, val); } else return; return; }
int si_bist_d11(si_t *sih, uint32 *biststatus1, uint32 *biststatus2) { si_info_t *sii; uint origidx; uint intr_val = 0; void *regs; int error = 0; bool wasup; uint32 offset = SBCONFIGOFF + SBTMSTATELOW; uint32 max_res_mask; uint32 pmu_ctrl; *biststatus1 = 0; *biststatus2 = 0; SI_ERROR(("doing the bist on D11\n")); sii = SI_INFO(sih); if (CHIPTYPE(sih->socitype) != SOCI_SB) { return 0; } /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to D11 core */ if (!(regs = si_setcore(sih, D11_CORE_ID, 0))) goto done; /* Get info for determining size */ /* coming out of reset device shoudl have clk enabled, bw set, etc */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0x4F, 0x4F); max_res_mask = si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), 0, 0); si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, 0x3fffff); if (si_corerev(&sii->pub) == 20) { uint32 phy_reset_val; uint32 bist_test_val, bist_status; /* XXX: enable the phy PLL */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl |= 0x000010000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); SPINWAIT(((si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0) & 0x01000000) == 0), 1000000); pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); /* take the phy out of reset */ phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); phy_reset_val &= ~(0x0008 << SBTML_SICF_SHIFT); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, phy_reset_val); phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); /* enable bist first */ bist_test_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); bist_test_val |= (SICF_BIST_EN << 16); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, bist_test_val); SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 1000000); bist_status = si_core_sflags(sih, 0, 0); SI_ERROR(("status are 0x%08x\n", bist_status)); if (bist_status & SISF_BIST_DONE) { if (bist_status & SISF_BIST_ERROR) { error = 1; *biststatus1 = si_corereg(sih, si_coreidx(&sii->pub), 12, 0, 0); *biststatus2 = si_corereg(sih, si_coreidx(&sii->pub), 16, 0, 0); } } /* stop the phy pll */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl &= ~0x10000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); } /* remove the resource mask */ si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, max_res_mask); /* Return to previous state and core */ if (!wasup) si_core_disable(sih, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); done: INTR_RESTORE(sii, intr_val); return error; }
void si_core_tofixup(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_tofixup(sih); }
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); }