6095
5987
DHD_TRACE(("%s: WLAN ON DONE\n",
6098
bcmerror = BCME_SDIO_ERROR;
6100
bcmerror = BCME_SDIO_ERROR;
6102
bcmerror = BCME_NOTDOWN;
5994
bcmerror = -EISCONN;
6103
5995
DHD_ERROR(("%s: Set DEVRESET=false invoked when device "
6104
5996
"is on\n", __func__));
6105
bcmerror = BCME_SDIO_ERROR;
6108
6000
return bcmerror;
6004
dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
6010
* Chipid is assume to be at offset 0 from regs arg
6011
* For different chiptypes or old sdio hosts w/o chipcommon,
6012
* other ways of recognition should be added here.
6014
ci->cccorebase = (u32)regs;
6015
regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4);
6016
ci->chip = regdata & CID_ID_MASK;
6017
ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
6019
DHD_INFO(("%s: chipid=0x%x chiprev=%d\n",
6020
__func__, ci->chip, ci->chiprev));
6022
/* Address of cores for new chips should be added here */
6024
case BCM4329_CHIP_ID:
6025
ci->buscorebase = BCM4329_CORE_BUS_BASE;
6026
ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
6027
ci->armcorebase = BCM4329_CORE_ARM_BASE;
6028
ci->ramsize = BCM4329_RAMSIZE;
6031
DHD_ERROR(("%s: chipid 0x%x is not supported\n",
6032
__func__, ci->chip));
6036
regdata = bcmsdh_reg_read(sdh,
6037
CORE_SB(ci->cccorebase, sbidhigh), 4);
6038
ci->ccrev = SBCOREREV(regdata);
6040
regdata = bcmsdh_reg_read(sdh,
6041
CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
6042
ci->pmurev = regdata & PCAP_REV_MASK;
6044
regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4);
6045
ci->buscorerev = SBCOREREV(regdata);
6046
ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
6048
DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
6049
__func__, ci->ccrev, ci->pmurev,
6050
ci->buscorerev, ci->buscoretype));
6052
/* get chipcommon capabilites */
6053
ci->cccaps = bcmsdh_reg_read(sdh,
6054
CORE_CC_REG(ci->cccorebase, capabilities), 4);
6060
dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase)
6064
regdata = bcmsdh_reg_read(sdh,
6065
CORE_SB(corebase, sbtmstatelow), 4);
6066
if (regdata & SBTML_RESET)
6069
regdata = bcmsdh_reg_read(sdh,
6070
CORE_SB(corebase, sbtmstatelow), 4);
6071
if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
6073
* set target reject and spin until busy is clear
6074
* (preserve core-specific bits)
6076
regdata = bcmsdh_reg_read(sdh,
6077
CORE_SB(corebase, sbtmstatelow), 4);
6078
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6079
regdata | SBTML_REJ);
6081
regdata = bcmsdh_reg_read(sdh,
6082
CORE_SB(corebase, sbtmstatelow), 4);
6084
SPINWAIT((bcmsdh_reg_read(sdh,
6085
CORE_SB(corebase, sbtmstatehigh), 4) &
6086
SBTMH_BUSY), 100000);
6088
regdata = bcmsdh_reg_read(sdh,
6089
CORE_SB(corebase, sbtmstatehigh), 4);
6090
if (regdata & SBTMH_BUSY)
6091
DHD_ERROR(("%s: ARM core still busy\n", __func__));
6093
regdata = bcmsdh_reg_read(sdh,
6094
CORE_SB(corebase, sbidlow), 4);
6095
if (regdata & SBIDL_INIT) {
6096
regdata = bcmsdh_reg_read(sdh,
6097
CORE_SB(corebase, sbimstate), 4) |
6099
bcmsdh_reg_write(sdh,
6100
CORE_SB(corebase, sbimstate), 4,
6102
regdata = bcmsdh_reg_read(sdh,
6103
CORE_SB(corebase, sbimstate), 4);
6105
SPINWAIT((bcmsdh_reg_read(sdh,
6106
CORE_SB(corebase, sbimstate), 4) &
6110
/* set reset and reject while enabling the clocks */
6111
bcmsdh_reg_write(sdh,
6112
CORE_SB(corebase, sbtmstatelow), 4,
6113
(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6114
SBTML_REJ | SBTML_RESET));
6115
regdata = bcmsdh_reg_read(sdh,
6116
CORE_SB(corebase, sbtmstatelow), 4);
6119
/* clear the initiator reject bit */
6120
regdata = bcmsdh_reg_read(sdh,
6121
CORE_SB(corebase, sbidlow), 4);
6122
if (regdata & SBIDL_INIT) {
6123
regdata = bcmsdh_reg_read(sdh,
6124
CORE_SB(corebase, sbimstate), 4) &
6126
bcmsdh_reg_write(sdh,
6127
CORE_SB(corebase, sbimstate), 4,
6132
/* leave reset and reject asserted */
6133
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6134
(SBTML_REJ | SBTML_RESET));
6139
dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
6141
struct chip_info *ci;
6145
DHD_TRACE(("%s: Enter\n", __func__));
6147
/* alloc chip_info_t */
6148
ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
6150
DHD_ERROR(("%s: malloc failed!\n", __func__));
6154
memset((unsigned char *)ci, 0, sizeof(struct chip_info));
6156
/* bus/core/clk setup for register access */
6157
/* Try forcing SDIO core to do ALPAvail request only */
6158
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
6159
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
6162
DHD_ERROR(("%s: error writing for HT off\n", __func__));
6166
/* If register supported, wait for ALPAvail and then force ALP */
6167
/* This may take up to 15 milliseconds */
6168
clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6169
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
6170
if ((clkval & ~SBSDIO_AVBITS) == clkset) {
6172
bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6173
SBSDIO_FUNC1_CHIPCLKCSR,
6175
!SBSDIO_ALPAV(clkval)),
6176
PMU_MAX_TRANSITION_DLY);
6177
if (!SBSDIO_ALPAV(clkval)) {
6178
DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n",
6183
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
6185
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
6186
SBSDIO_FUNC1_CHIPCLKCSR,
6190
DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
6191
__func__, clkset, clkval));
6196
/* Also, disable the extra SDIO pull-ups */
6197
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
6200
err = dhdsdio_chip_recognition(bus->sdh, ci, regs);
6205
* Make sure any on-chip ARM is off (in case strapping is wrong),
6206
* or downloaded code was already running.
6208
dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase);
6210
bcmsdh_reg_write(bus->sdh,
6211
CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
6212
bcmsdh_reg_write(bus->sdh,
6213
CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
6215
/* Disable F2 to clear any intermediate frame state on the dongle */
6216
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
6217
SDIO_FUNC_ENABLE_1, NULL);
6219
/* WAR: cmd52 backplane read so core HW will drop ALPReq */
6220
clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6223
/* Done with backplane-dependent accesses, can drop clock... */
6224
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
6236
dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
6241
* Must do the disable sequence first to work for
6242
* arbitrary current core state.
6244
dhdsdio_chip_disablecore(sdh, corebase);
6247
* Now do the initialization sequence.
6248
* set reset while enabling the clock and
6249
* forcing them on throughout the core
6251
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6252
((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6256
regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbtmstatehigh), 4);
6257
if (regdata & SBTMH_SERR)
6258
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatehigh), 4, 0);
6260
regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbimstate), 4);
6261
if (regdata & (SBIM_IBE | SBIM_TO))
6262
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbimstate), 4,
6263
regdata & ~(SBIM_IBE | SBIM_TO));
6265
/* clear reset and allow it to propagate throughout the core */
6266
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6267
(SICF_FGC << SBTML_SICF_SHIFT) |
6268
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6271
/* leave clock enabled */
6272
bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6273
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6277
/* SDIO Pad drive strength to select value mappings */
6278
struct sdiod_drive_str {
6279
u8 strength; /* Pad Drive Strength in mA */
6280
u8 sel; /* Chip-specific select value */
6283
/* SDIO Drive Strength to sel value table for PMU Rev 1 */
6284
static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
6292
/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
6293
static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
6304
/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
6305
static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
6317
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
6320
dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
6321
struct sdiod_drive_str *str_tab = NULL;
6326
if (!(bus->ci->cccaps & CC_CAP_PMU))
6329
switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
6330
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
6331
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
6332
str_mask = 0x30000000;
6335
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
6336
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
6337
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
6338
str_mask = 0x00003800;
6341
case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
6342
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
6343
str_mask = 0x00003800;
6347
DHD_ERROR(("No SDIO Drive strength init"
6348
"done for chip %s rev %d pmurev %d\n",
6349
bcm_chipname(bus->ci->chip, chn, 8),
6350
bus->ci->chiprev, bus->ci->pmurev));
6354
if (str_tab != NULL) {
6355
u32 drivestrength_sel = 0;
6359
for (i = 0; str_tab[i].strength != 0; i++) {
6360
if (drivestrength >= str_tab[i].strength) {
6361
drivestrength_sel = str_tab[i].sel;
6366
bcmsdh_reg_write(bus->sdh,
6367
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6369
cc_data_temp = bcmsdh_reg_read(bus->sdh,
6370
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
6371
cc_data_temp &= ~str_mask;
6372
drivestrength_sel <<= str_shift;
6373
cc_data_temp |= drivestrength_sel;
6374
bcmsdh_reg_write(bus->sdh,
6375
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6378
DHD_INFO(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
6379
drivestrength, cc_data_temp));
6384
dhdsdio_chip_detach(struct dhd_bus *bus)
6386
DHD_TRACE(("%s: Enter\n", __func__));