static void brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci) { u32 base = ci->c_inf[0].base; /* get chipcommon rev */ ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); /* get chipcommon capabilites */ ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev, CORE_CC_REG(base, capabilities), NULL); /* get pmu caps & rev */ if (ci->c_inf[0].caps & CC_CAP_PMU) { ci->pmucaps = brcmf_sdio_regrl(sdiodev, CORE_CC_REG(base, pmucapabilities), NULL); ci->pmurev = ci->pmucaps & PCAP_REV_MASK; } ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id); brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", ci->c_inf[0].rev, ci->pmurev, ci->c_inf[1].rev, ci->c_inf[1].id); /* * Make sure any on-chip ARM is off (in case strapping is wrong), * or downloaded code was already running. */ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3); }
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, struct chip_info **ci_ptr, u32 regs) { int ret; struct chip_info *ci; brcmf_dbg(TRACE, "Enter\n"); /* alloc chip_info_t */ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); if (!ci) return -ENOMEM; ret = brcmf_sdio_chip_buscoreprep(sdiodev); if (ret != 0) goto err; ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs); if (ret != 0) goto err; brcmf_sdio_chip_buscoresetup(sdiodev, ci); brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 0, NULL); brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 0, NULL); *ci_ptr = ci; return 0; err: kfree(ci); return ret; }
void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, u32 drivestrength) { struct sdiod_drive_str *str_tab = NULL; u32 str_mask = 0; u32 str_shift = 0; char chn[8]; u32 base = ci->c_inf[0].base; if (!(ci->c_inf[0].caps & CC_CAP_PMU)) return; switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8; str_mask = 0x00003800; str_shift = 11; break; default: brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", brcmf_sdio_chip_name(ci->chip, chn, 8), ci->chiprev, ci->pmurev); break; } if (str_tab != NULL) { u32 drivestrength_sel = 0; u32 cc_data_temp; int i; for (i = 0; str_tab[i].strength != 0; i++) { if (drivestrength >= str_tab[i].strength) { drivestrength_sel = str_tab[i].sel; break; } } brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), 1, NULL); cc_data_temp = brcmf_sdio_regrl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), NULL); cc_data_temp &= ~str_mask; drivestrength_sel <<= str_shift; cc_data_temp |= drivestrength_sel; brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), cc_data_temp, NULL); brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", drivestrength, cc_data_temp); } }
static int brcmf_pcie_buscoreprep(void *ctx) { struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; int err; err = brcmf_pcie_get_resource(devinfo); if (err == 0) { /* Set CC watchdog to reset all the cores on the chip to bring * back dongle to a sane state. */ brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE, watchdog), 4); msleep(100); } return err; }
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, u32 regs) { u32 regdata; /* * Get CC core rev * Chipid is assume to be at offset 0 from regs arg * For different chiptypes or old sdio hosts w/o chipcommon, * other ways of recognition should be added here. */ ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; ci->c_inf[0].base = regs; regdata = brcmf_sdio_regrl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, chipid), NULL); ci->chip = regdata & CID_ID_MASK; ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); /* Address of cores for new chips should be added here */ switch (ci->chip) { case BCM4329_CHIP_ID: ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; ci->ramsize = BCM4329_RAMSIZE; break; case BCM4330_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x27004211; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x07004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x0d080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x03004211; ci->ramsize = 0x48000; break; case BCM4334_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x29004211; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x0d004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x13080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x07004211; ci->ramsize = 0x80000; break; default: brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); return -ENODEV; } switch (ci->socitype) { case SOCI_SB: ci->iscoreup = brcmf_sdio_sb_iscoreup; ci->corerev = brcmf_sdio_sb_corerev; ci->coredisable = brcmf_sdio_sb_coredisable; ci->resetcore = brcmf_sdio_sb_resetcore; break; case SOCI_AI: ci->iscoreup = brcmf_sdio_ai_iscoreup; ci->corerev = brcmf_sdio_ai_corerev; ci->coredisable = brcmf_sdio_ai_coredisable; ci->resetcore = brcmf_sdio_ai_resetcore; break; default: brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype); return -ENODEV; } return 0; }
int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) { struct brcmfmac_sdio_pd *pdata; int ret = 0; u8 data; u32 addr, gpiocontrol; pdata = &sdiodev->settings->bus.sdio; if (pdata->oob_irq_supported) { brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", pdata->oob_irq_nr); spin_lock_init(&sdiodev->irq_en_lock); sdiodev->irq_en = true; ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler, pdata->oob_irq_flags, "brcmf_oob_intr", &sdiodev->func1->dev); if (ret != 0) { brcmf_err("request_irq failed %d\n", ret); return ret; } sdiodev->oob_irq_requested = true; ret = enable_irq_wake(pdata->oob_irq_nr); if (ret != 0) { brcmf_err("enable_irq_wake failed %d\n", ret); return ret; } sdiodev->irq_wake = true; sdio_claim_host(sdiodev->func1); if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) { /* assign GPIO to SDIO core */ addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol); gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret); gpiocontrol |= 0x2; brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret); brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_SELECT, 0xf, &ret); brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret); brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret); } /* must configure SDIO_CCCR_IENx to enable irq */ data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret); data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 | SDIO_CCCR_IEN_FUNC0; brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret); /* redirect, configure and enable io for interrupt signal */ data = SDIO_CCCR_BRCM_SEPINT_MASK | SDIO_CCCR_BRCM_SEPINT_OE; if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI; brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); sdio_release_host(sdiodev->func1); } else { brcmf_dbg(SDIO, "Entering\n"); sdio_claim_host(sdiodev->func1); sdio_claim_irq(sdiodev->func1, brcmf_sdiod_ib_irqhandler); sdio_claim_irq(sdiodev->func2, brcmf_sdiod_dummy_irqhandler); sdio_release_host(sdiodev->func1); sdiodev->sd_irq_requested = true; } return 0; }
void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci, u32 drivestrength) { const struct sdiod_drive_str *str_tab = NULL; u32 str_mask; u32 str_shift; char chn[8]; u32 base = ci->c_inf[0].base; u32 i; u32 drivestrength_sel = 0; u32 cc_data_temp; u32 addr; if (!(ci->c_inf[0].caps & CC_CAP_PMU)) return; switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): str_tab = sdiod_drvstr_tab1_1v8; str_mask = 0x00003800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): str_tab = sdiod_drvstr_tab6_1v8; str_mask = 0x00001800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): /* note: 43143 does not support tristate */ i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { str_tab = sdiod_drvstr_tab2_3v3; str_mask = 0x00000007; str_shift = 0; } else brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", brcmf_sdio_chip_name(ci->chip, chn, 8), drivestrength); break; case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): str_tab = sdiod_drive_strength_tab5_1v8; str_mask = 0x00003800; str_shift = 11; break; default: brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", brcmf_sdio_chip_name(ci->chip, chn, 8), ci->chiprev, ci->pmurev); break; } if (str_tab != NULL) { for (i = 0; str_tab[i].strength != 0; i++) { if (drivestrength >= str_tab[i].strength) { drivestrength_sel = str_tab[i].sel; break; } } addr = CORE_CC_REG(base, chipcontrol_addr); brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); cc_data_temp &= ~str_mask; drivestrength_sel <<= str_shift; cc_data_temp |= drivestrength_sel; brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL); brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n", str_tab[i].strength, drivestrength, cc_data_temp); } }
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci) { u32 regdata; u32 socitype; /* 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 = brcmf_sdiod_regrl(sdiodev, CORE_CC_REG(SI_ENUM_BASE, chipid), NULL); ci->chip = regdata & CID_ID_MASK; ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && ci->chiprev >= 2) ci->chip = BCM4339_CHIP_ID; socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n", socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev); if (socitype == SOCI_SB) { if (ci->chip != BCM4329_CHIP_ID) { brcmf_err("SB chip is not supported\n"); return -ENODEV; } ci->iscoreup = brcmf_sdio_sb_iscoreup; ci->corerev = brcmf_sdio_sb_corerev; ci->coredisable = brcmf_sdio_sb_coredisable; ci->resetcore = brcmf_sdio_sb_resetcore; ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; ci->c_inf[0].base = SI_ENUM_BASE; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->ramsize = BCM4329_RAMSIZE; } else if (socitype == SOCI_AI) { ci->iscoreup = brcmf_sdio_ai_iscoreup; ci->corerev = brcmf_sdio_ai_corerev; ci->coredisable = brcmf_sdio_ai_coredisable; ci->resetcore = brcmf_sdio_ai_resetcore; ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; ci->c_inf[0].base = SI_ENUM_BASE; /* Address of cores for new chips should be added here */ switch (ci->chip) { case BCM43143_CHIP_ID: ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000; ci->c_inf[0].cib = 0x2b000000; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = BCM43143_CORE_BUS_BASE; ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000; ci->c_inf[1].cib = 0x18000000; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE; ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000; ci->c_inf[2].cib = 0x14000000; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = BCM43143_CORE_ARM_BASE; ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; ci->c_inf[3].cib = 0x07000000; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; ci->ramsize = BCM43143_RAMSIZE; break; case BCM43241_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x2a084411; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x0e004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x14080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x07004211; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; ci->ramsize = 0x90000; break; case BCM4330_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x27004211; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x07004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x0d080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x03004211; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; ci->ramsize = 0x48000; break; case BCM4334_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x29004211; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x0d004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x13080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x07004211; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; ci->ramsize = 0x80000; break; case BCM4335_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x2b084411; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18005000; ci->c_inf[1].wrapbase = 0x18105000; ci->c_inf[1].cib = 0x0f004211; ci->c_inf[2].id = BCMA_CORE_ARM_CR4; ci->c_inf[2].base = 0x18002000; ci->c_inf[2].wrapbase = 0x18102000; ci->c_inf[2].cib = 0x01084411; ci->c_inf[3].id = BCMA_CORE_80211; ci->c_inf[3].base = BCM43xx_CORE_D11_BASE; ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; ci->ramsize = 0xc0000; ci->rambase = 0x180000; break; case BCM43362_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x27004211; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18002000; ci->c_inf[1].wrapbase = 0x18102000; ci->c_inf[1].cib = 0x0a004211; ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; ci->c_inf[2].base = 0x18004000; ci->c_inf[2].wrapbase = 0x18104000; ci->c_inf[2].cib = 0x08080401; ci->c_inf[3].id = BCMA_CORE_ARM_CM3; ci->c_inf[3].base = 0x18003000; ci->c_inf[3].wrapbase = 0x18103000; ci->c_inf[3].cib = 0x03004211; ci->c_inf[4].id = BCMA_CORE_80211; ci->c_inf[4].base = BCM43xx_CORE_D11_BASE; ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000; ci->ramsize = 0x3C000; break; case BCM4339_CHIP_ID: ci->c_inf[0].wrapbase = 0x18100000; ci->c_inf[0].cib = 0x2e084411; ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; ci->c_inf[1].base = 0x18005000; ci->c_inf[1].wrapbase = 0x18105000; ci->c_inf[1].cib = 0x15004211; ci->c_inf[2].id = BCMA_CORE_ARM_CR4; ci->c_inf[2].base = 0x18002000; ci->c_inf[2].wrapbase = 0x18102000; ci->c_inf[2].cib = 0x04084411; ci->c_inf[3].id = BCMA_CORE_80211; ci->c_inf[3].base = BCM43xx_CORE_D11_BASE; ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; ci->ramsize = 0xc0000; ci->rambase = 0x180000; break; default: brcmf_err("AXI chip is not supported\n"); return -ENODEV; } } else { brcmf_err("chip backplane type %u is not supported\n", socitype); return -ENODEV; } return brcmf_sdio_chip_cichk(ci); }