ci = core->chip;
base = core->pub.base;
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); if (val & SSB_TMSLOW_RESET) return;
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); if ((val & SSB_TMSLOW_CLOCK) != 0) { /* * set target reject and spin until busy is clear * (preserve core-specific bits)
*/
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
val | SSB_TMSLOW_REJECT);
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); if (val & SSB_TMSHIGH_BUSY)
brcmf_err("core state still busy\n");
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); if (val & SSB_IDLOW_INITIATOR) {
val = ci->ops->read32(ci->ctx,
CORE_SB(base, sbimstate));
val |= SSB_IMSTATE_REJECT;
ci->ops->write32(ci->ctx,
CORE_SB(base, sbimstate), val);
val = ci->ops->read32(ci->ctx,
CORE_SB(base, sbimstate));
udelay(1);
SPINWAIT((ci->ops->read32(ci->ctx,
CORE_SB(base, sbimstate)) &
SSB_IMSTATE_BUSY), 100000);
}
/* set reset and reject while enabling the clocks */
val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
udelay(10);
/* clear the initiator reject bit */
val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); if (val & SSB_IDLOW_INITIATOR) {
val = ci->ops->read32(ci->ctx,
CORE_SB(base, sbimstate));
val &= ~SSB_IMSTATE_REJECT;
ci->ops->write32(ci->ctx,
CORE_SB(base, sbimstate), val);
}
}
ci = core->chip;
base = core->pub.base; /* * Must do the disable sequence first to work for * arbitrary current core state.
*/
brcmf_chip_sb_coredisable(core, 0, 0);
/* * Now do the initialization sequence. * set reset while enabling the clock and * forcing them on throughout the core
*/
ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
SSB_TMSLOW_RESET);
regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
udelay(1);
/* clear any serror */
regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); if (regdata & SSB_TMSHIGH_SERR)
ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);
/* clear reset and allow it to propagate throughout the core */
ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
udelay(1);
/* special handle two D11 cores reset */ if (core->pub.id == BCMA_CORE_80211) {
d11core2 = brcmf_chip_get_d11core(&ci->pub, 1); if (d11core2) {
brcmf_dbg(INFO, "found two d11 cores, reset both\n");
d11priv2 = container_of(d11core2, struct brcmf_core_priv, pub);
}
}
/* must disable first to work for arbitrary current core state */
brcmf_chip_ai_coredisable(core, prereset, reset); if (d11priv2)
brcmf_chip_ai_coredisable(d11priv2, prereset, reset);
switch (core->pub.id) { case BCMA_CORE_ARM_CM3:
cpu_found = true;
need_socram = true; break; case BCMA_CORE_INTERNAL_MEM:
has_socram = true; break; case BCMA_CORE_ARM_CR4:
cpu_found = true; break; case BCMA_CORE_ARM_CA7:
cpu_found = true; break; default: break;
}
}
if (!cpu_found) {
brcmf_err("CPU core not detected\n"); return -ENXIO;
} /* check RAM core presence for ARM CM3 core */ if (need_socram && !has_socram) {
brcmf_err("RAM core not provided with ARM CM3 core\n"); return -ENODEV;
} return 0;
}
if (!brcmf_chip_iscoreup(&sr->pub))
brcmf_chip_resetcore(&sr->pub, 0, 0, 0);
/* Get info for determining size */
coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));
nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {
banksize = (coreinfo & SRCI_SRBSZ_MASK);
lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; if (lss != 0)
nb--;
*ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); if (lss != 0)
*ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
} else { /* length of SRAM Banks increased for corerev greater than 23 */ if (sr->pub.rev >= 23) {
nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT))
>> SRCI_SRNB_SHIFT;
} else {
nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
} for (i = 0; i < nb; i++) {
retent = brcmf_chip_socram_banksize(sr, i, &banksize);
*ramsize += banksize; if (retent)
*srsize += banksize;
}
}
/* hardcoded save&restore memory sizes */ switch (sr->chip->pub.chip) { case BRCM_CC_4334_CHIP_ID: if (sr->chip->pub.chiprev < 2)
*srsize = (32 * 1024); break; case BRCM_CC_43430_CHIP_ID: case CY_CC_43439_CHIP_ID: /* assume sr for now as we can not check * firmware sr capability at this point.
*/
*srsize = (64 * 1024); break; default: break;
}
}
static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
{ switch (ci->pub.chip) { case BRCM_CC_4345_CHIP_ID: case BRCM_CC_43454_CHIP_ID: return 0x198000; case BRCM_CC_4335_CHIP_ID: case BRCM_CC_4339_CHIP_ID: case BRCM_CC_4350_CHIP_ID: case BRCM_CC_4354_CHIP_ID: case BRCM_CC_4356_CHIP_ID: case BRCM_CC_43567_CHIP_ID: case BRCM_CC_43569_CHIP_ID: case BRCM_CC_43570_CHIP_ID: case BRCM_CC_4358_CHIP_ID: case BRCM_CC_43602_CHIP_ID: case BRCM_CC_4371_CHIP_ID: return 0x180000; case BRCM_CC_43465_CHIP_ID: case BRCM_CC_43525_CHIP_ID: case BRCM_CC_4365_CHIP_ID: case BRCM_CC_4366_CHIP_ID: case BRCM_CC_43664_CHIP_ID: case BRCM_CC_43666_CHIP_ID: return 0x200000; case BRCM_CC_4355_CHIP_ID: case BRCM_CC_4359_CHIP_ID: return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; case BRCM_CC_4364_CHIP_ID: case CY_CC_4373_CHIP_ID: return 0x160000; case BRCM_CC_43751_CHIP_ID: case BRCM_CC_43752_CHIP_ID: case BRCM_CC_4377_CHIP_ID: return 0x170000; case BRCM_CC_4378_CHIP_ID: return 0x352000; case BRCM_CC_4387_CHIP_ID: return 0x740000; default:
brcmf_err("unknown chip: %s\n", ci->pub.name); break;
} return INVALID_RAMBASE;
}
while (desc_type != DMP_DESC_EOT) {
val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); if (!(val & DMP_DESC_VALID)) continue;
if (desc_type == DMP_DESC_EMPTY) continue;
/* need a component descriptor */ if (desc_type != DMP_DESC_COMPONENT) continue;
id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;
/* next descriptor must be component as well */
val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT)) return -EFAULT;
/* only look at cores with master port(s) */
nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
/* need core with ports */ if (nmw + nsw == 0 &&
id != BCMA_CORE_PMU &&
id != BCMA_CORE_GCI) continue;
/* try to obtain register address info */
err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap); if (err) continue;
/* finally a core to be added */
core = brcmf_chip_add_core(ci, id, base, wrap); if (IS_ERR(core)) return PTR_ERR(core);
/* Get CC core rev * Chipid is assume to be at offset 0 from SI_ENUM_BASE * For different chiptypes or old sdio hosts w/o chipcommon, * other ways of recognition should be added here.
*/
regdata = ci->ops->read32(ci->ctx,
CORE_CC_REG(ci->pub.enum_base, chipid)); if (regdata == READ_FAILED) {
brcmf_err("MMIO read failed: 0x%08x\n", regdata); return -ENODEV;
}
brcmf_chip_dmp_erom_scan(ci);
} else {
brcmf_err("chip backplane type %u is not supported\n",
socitype); return -ENODEV;
}
ret = brcmf_chip_cores_check(ci); if (ret) return ret;
/* assure chip is passive for core access */
brcmf_chip_set_passive(&ci->pub);
/* Call bus specific reset function now. Cores have been determined * but further access may require a chip specific reset at this point.
*/ if (ci->ops->reset) {
ci->ops->reset(ci->ctx, &ci->pub);
brcmf_chip_set_passive(&ci->pub);
}
core = brcmf_chip_get_core(&chip->pub, id); if (!core) return;
switch (id) { case BCMA_CORE_ARM_CM3:
brcmf_chip_coredisable(core, 0, 0); break; case BCMA_CORE_ARM_CR4: case BCMA_CORE_ARM_CA7:
cpu = container_of(core, struct brcmf_core_priv, pub);
/* clear all IOCTL bits except HALT bit */
val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);
val &= ARMCR4_BCMA_IOCTL_CPUHALT;
brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
ARMCR4_BCMA_IOCTL_CPUHALT); break; default:
brcmf_err("unknown id: %u\n", id); break;
}
}
/* See if there is separated PMU core available */ if (cc->rev >= 35 &&
pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); if (pmu) return pmu;
}
/* Fallback to ChipCommon core for older hardware */ return cc;
}
core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); if (!brcmf_chip_iscoreup(core)) {
brcmf_err("SOCRAM core is down after reset?\n"); returnfalse;
}
staticinlinevoid
brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
{ int i; struct brcmf_core *core;
brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
/* Disable the cores only and let the firmware enable them. * Releasing reset ourselves breaks BCM4387 in weird ways.
*/ for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++)
brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET |
D11_BCMA_IOCTL_PHYCLOCKEN,
D11_BCMA_IOCTL_PHYCLOCKEN);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.