diff options
author | Franky Lin <frankyl@broadcom.com> | 2011-04-25 18:45:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-25 19:40:17 -0400 |
commit | cb63e4c967541402b79a92a31c841744ca17d1aa (patch) | |
tree | 44f8ec68eea237e7dcc8ec904e97883be23930d5 | |
parent | ddd0b091dbb0cd6891f13c6157679076467aa146 (diff) |
staging: brcm80211: Add dhdsdio_chip_attach in dhd_sdio.c
dhdsdio_chip_attach and it sub functions are added for si/sb utils removal.
It will replace si_attach in following patches.
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/brcm80211/brcmfmac/dhd_sdio.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c index 40d6de3b162b..14f470358182 100644 --- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <dhdioctl.h> | 53 | #include <dhdioctl.h> |
54 | #include <sdiovar.h> | 54 | #include <sdiovar.h> |
55 | #include <siutils_priv.h> | 55 | #include <siutils_priv.h> |
56 | #include <bcmchip.h> | ||
56 | 57 | ||
57 | #ifndef DHDSDIO_MEM_DUMP_FNAME | 58 | #ifndef DHDSDIO_MEM_DUMP_FNAME |
58 | #define DHDSDIO_MEM_DUMP_FNAME "mem_dump" | 59 | #define DHDSDIO_MEM_DUMP_FNAME "mem_dump" |
@@ -166,12 +167,28 @@ typedef struct dhd_console { | |||
166 | } dhd_console_t; | 167 | } dhd_console_t; |
167 | #endif /* DHD_DEBUG */ | 168 | #endif /* DHD_DEBUG */ |
168 | 169 | ||
170 | /* misc chip info needed by some of the routines */ | ||
171 | struct chip_info { | ||
172 | u32 chip; | ||
173 | u32 chiprev; | ||
174 | u32 cccorebase; | ||
175 | u32 ccrev; | ||
176 | u32 cccaps; | ||
177 | u32 buscorebase; | ||
178 | u32 buscorerev; | ||
179 | u32 buscoretype; | ||
180 | u32 ramcorebase; | ||
181 | u32 armcorebase; | ||
182 | u32 pmurev; | ||
183 | }; | ||
184 | |||
169 | /* Private data for SDIO bus interaction */ | 185 | /* Private data for SDIO bus interaction */ |
170 | typedef struct dhd_bus { | 186 | typedef struct dhd_bus { |
171 | dhd_pub_t *dhd; | 187 | dhd_pub_t *dhd; |
172 | 188 | ||
173 | bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ | 189 | bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ |
174 | si_t *sih; /* Handle for SI calls */ | 190 | si_t *sih; /* Handle for SI calls */ |
191 | struct chip_info *ci; /* Chip info struct */ | ||
175 | char *vars; /* Variables (from CIS and/or other) */ | 192 | char *vars; /* Variables (from CIS and/or other) */ |
176 | uint varsz; /* Size of variables buffer */ | 193 | uint varsz; /* Size of variables buffer */ |
177 | u32 sbaddr; /* Current SB window pointer (-1, invalid) */ | 194 | u32 sbaddr; /* Current SB window pointer (-1, invalid) */ |
@@ -465,6 +482,7 @@ static int dhdsdio_download_nvram(struct dhd_bus *bus); | |||
465 | #ifdef BCMEMBEDIMAGE | 482 | #ifdef BCMEMBEDIMAGE |
466 | static int dhdsdio_download_code_array(struct dhd_bus *bus); | 483 | static int dhdsdio_download_code_array(struct dhd_bus *bus); |
467 | #endif | 484 | #endif |
485 | static int dhdsdio_chip_attach(struct dhd_bus *bus, void *regs); | ||
468 | 486 | ||
469 | static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) | 487 | static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) |
470 | { | 488 | { |
@@ -5289,6 +5307,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid) | |||
5289 | DHD_ERROR(("%s: si_attach failed!\n", __func__)); | 5307 | DHD_ERROR(("%s: si_attach failed!\n", __func__)); |
5290 | goto fail; | 5308 | goto fail; |
5291 | } | 5309 | } |
5310 | if (dhdsdio_chip_attach(bus, regsva)) { | ||
5311 | DHD_ERROR(("%s: dhdsdio_chip_attach failed!\n", __func__)); | ||
5312 | goto fail; | ||
5313 | } | ||
5292 | 5314 | ||
5293 | bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); | 5315 | bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); |
5294 | 5316 | ||
@@ -6071,3 +6093,234 @@ int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag) | |||
6071 | } | 6093 | } |
6072 | return bcmerror; | 6094 | return bcmerror; |
6073 | } | 6095 | } |
6096 | |||
6097 | static int | ||
6098 | dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs) | ||
6099 | { | ||
6100 | u32 regdata; | ||
6101 | |||
6102 | /* | ||
6103 | * Get CC core rev | ||
6104 | * Chipid is assume to be at offset 0 from regs arg | ||
6105 | * For different chiptypes or old sdio hosts w/o chipcommon, | ||
6106 | * other ways of recognition should be added here. | ||
6107 | */ | ||
6108 | ci->cccorebase = (u32)regs; | ||
6109 | regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4); | ||
6110 | ci->chip = regdata & CID_ID_MASK; | ||
6111 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | ||
6112 | |||
6113 | DHD_INFO(("%s: chipid=0x%x chiprev=%d\n", | ||
6114 | __func__, ci->chip, ci->chiprev)); | ||
6115 | |||
6116 | /* Address of cores for new chips should be added here */ | ||
6117 | switch (ci->chip) { | ||
6118 | case BCM4329_CHIP_ID: | ||
6119 | ci->buscorebase = BCM4329_CORE_BUS_BASE; | ||
6120 | ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE; | ||
6121 | ci->armcorebase = BCM4329_CORE_ARM_BASE; | ||
6122 | break; | ||
6123 | default: | ||
6124 | DHD_ERROR(("%s: chipid 0x%x is not supported\n", | ||
6125 | __func__, ci->chip)); | ||
6126 | return -ENODEV; | ||
6127 | } | ||
6128 | |||
6129 | regdata = bcmsdh_reg_read(sdh, | ||
6130 | CORE_SB(ci->cccorebase, sbidhigh), 4); | ||
6131 | ci->ccrev = SBCOREREV(regdata); | ||
6132 | |||
6133 | regdata = bcmsdh_reg_read(sdh, | ||
6134 | CORE_CC_REG(ci->cccorebase, pmucapabilities), 4); | ||
6135 | ci->pmurev = regdata & PCAP_REV_MASK; | ||
6136 | |||
6137 | regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4); | ||
6138 | ci->buscorerev = SBCOREREV(regdata); | ||
6139 | ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; | ||
6140 | |||
6141 | DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", | ||
6142 | __func__, ci->ccrev, ci->pmurev, | ||
6143 | ci->buscorerev, ci->buscoretype)); | ||
6144 | |||
6145 | /* get chipcommon capabilites */ | ||
6146 | ci->cccaps = bcmsdh_reg_read(sdh, | ||
6147 | CORE_CC_REG(ci->cccorebase, capabilities), 4); | ||
6148 | |||
6149 | return 0; | ||
6150 | } | ||
6151 | |||
6152 | static void | ||
6153 | dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase) | ||
6154 | { | ||
6155 | u32 regdata; | ||
6156 | |||
6157 | regdata = bcmsdh_reg_read(sdh, | ||
6158 | CORE_SB(corebase, sbtmstatelow), 4); | ||
6159 | if (regdata & SBTML_RESET) | ||
6160 | return; | ||
6161 | |||
6162 | regdata = bcmsdh_reg_read(sdh, | ||
6163 | CORE_SB(corebase, sbtmstatelow), 4); | ||
6164 | if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) { | ||
6165 | /* | ||
6166 | * set target reject and spin until busy is clear | ||
6167 | * (preserve core-specific bits) | ||
6168 | */ | ||
6169 | regdata = bcmsdh_reg_read(sdh, | ||
6170 | CORE_SB(corebase, sbtmstatelow), 4); | ||
6171 | bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4, | ||
6172 | regdata | SBTML_REJ); | ||
6173 | |||
6174 | regdata = bcmsdh_reg_read(sdh, | ||
6175 | CORE_SB(corebase, sbtmstatelow), 4); | ||
6176 | udelay(1); | ||
6177 | SPINWAIT((bcmsdh_reg_read(sdh, | ||
6178 | CORE_SB(corebase, sbtmstatehigh), 4) & | ||
6179 | SBTMH_BUSY), 100000); | ||
6180 | |||
6181 | regdata = bcmsdh_reg_read(sdh, | ||
6182 | CORE_SB(corebase, sbtmstatehigh), 4); | ||
6183 | if (regdata & SBTMH_BUSY) | ||
6184 | DHD_ERROR(("%s: ARM core still busy\n", __func__)); | ||
6185 | |||
6186 | regdata = bcmsdh_reg_read(sdh, | ||
6187 | CORE_SB(corebase, sbidlow), 4); | ||
6188 | if (regdata & SBIDL_INIT) { | ||
6189 | regdata = bcmsdh_reg_read(sdh, | ||
6190 | CORE_SB(corebase, sbimstate), 4) | | ||
6191 | SBIM_RJ; | ||
6192 | bcmsdh_reg_write(sdh, | ||
6193 | CORE_SB(corebase, sbimstate), 4, | ||
6194 | regdata); | ||
6195 | regdata = bcmsdh_reg_read(sdh, | ||
6196 | CORE_SB(corebase, sbimstate), 4); | ||
6197 | udelay(1); | ||
6198 | SPINWAIT((bcmsdh_reg_read(sdh, | ||
6199 | CORE_SB(corebase, sbimstate), 4) & | ||
6200 | SBIM_BY), 100000); | ||
6201 | } | ||
6202 | |||
6203 | /* set reset and reject while enabling the clocks */ | ||
6204 | bcmsdh_reg_write(sdh, | ||
6205 | CORE_SB(corebase, sbtmstatelow), 4, | ||
6206 | (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | | ||
6207 | SBTML_REJ | SBTML_RESET)); | ||
6208 | regdata = bcmsdh_reg_read(sdh, | ||
6209 | CORE_SB(corebase, sbtmstatelow), 4); | ||
6210 | udelay(10); | ||
6211 | |||
6212 | /* clear the initiator reject bit */ | ||
6213 | regdata = bcmsdh_reg_read(sdh, | ||
6214 | CORE_SB(corebase, sbidlow), 4); | ||
6215 | if (regdata & SBIDL_INIT) { | ||
6216 | regdata = bcmsdh_reg_read(sdh, | ||
6217 | CORE_SB(corebase, sbimstate), 4) & | ||
6218 | ~SBIM_RJ; | ||
6219 | bcmsdh_reg_write(sdh, | ||
6220 | CORE_SB(corebase, sbimstate), 4, | ||
6221 | regdata); | ||
6222 | } | ||
6223 | } | ||
6224 | |||
6225 | /* leave reset and reject asserted */ | ||
6226 | bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4, | ||
6227 | (SBTML_REJ | SBTML_RESET)); | ||
6228 | udelay(1); | ||
6229 | } | ||
6230 | |||
6231 | static int | ||
6232 | dhdsdio_chip_attach(struct dhd_bus *bus, void *regs) | ||
6233 | { | ||
6234 | struct chip_info *ci; | ||
6235 | int err; | ||
6236 | u8 clkval, clkset; | ||
6237 | |||
6238 | DHD_TRACE(("%s: Enter\n", __func__)); | ||
6239 | |||
6240 | /* alloc chip_info_t */ | ||
6241 | ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC); | ||
6242 | if (NULL == ci) { | ||
6243 | DHD_ERROR(("%s: malloc failed!\n", __func__)); | ||
6244 | return -ENOMEM; | ||
6245 | } | ||
6246 | |||
6247 | memset((unsigned char *)ci, 0, sizeof(struct chip_info)); | ||
6248 | |||
6249 | /* bus/core/clk setup for register access */ | ||
6250 | /* Try forcing SDIO core to do ALPAvail request only */ | ||
6251 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; | ||
6252 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, | ||
6253 | clkset, &err); | ||
6254 | if (err) { | ||
6255 | DHD_ERROR(("%s: error writing for HT off\n", __func__)); | ||
6256 | goto fail; | ||
6257 | } | ||
6258 | |||
6259 | /* If register supported, wait for ALPAvail and then force ALP */ | ||
6260 | /* This may take up to 15 milliseconds */ | ||
6261 | clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, | ||
6262 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); | ||
6263 | if ((clkval & ~SBSDIO_AVBITS) == clkset) { | ||
6264 | SPINWAIT(((clkval = | ||
6265 | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, | ||
6266 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
6267 | NULL)), | ||
6268 | !SBSDIO_ALPAV(clkval)), | ||
6269 | PMU_MAX_TRANSITION_DLY); | ||
6270 | if (!SBSDIO_ALPAV(clkval)) { | ||
6271 | DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n", | ||
6272 | __func__, clkval)); | ||
6273 | err = -EBUSY; | ||
6274 | goto fail; | ||
6275 | } | ||
6276 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | | ||
6277 | SBSDIO_FORCE_ALP; | ||
6278 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, | ||
6279 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
6280 | clkset, &err); | ||
6281 | udelay(65); | ||
6282 | } else { | ||
6283 | DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n", | ||
6284 | __func__, clkset, clkval)); | ||
6285 | err = -EACCES; | ||
6286 | goto fail; | ||
6287 | } | ||
6288 | |||
6289 | /* Also, disable the extra SDIO pull-ups */ | ||
6290 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, | ||
6291 | NULL); | ||
6292 | |||
6293 | err = dhdsdio_chip_recognition(bus->sdh, ci, regs); | ||
6294 | if (err) | ||
6295 | goto fail; | ||
6296 | |||
6297 | /* | ||
6298 | * Make sure any on-chip ARM is off (in case strapping is wrong), | ||
6299 | * or downloaded code was already running. | ||
6300 | */ | ||
6301 | dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase); | ||
6302 | |||
6303 | bcmsdh_reg_write(bus->sdh, | ||
6304 | CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0); | ||
6305 | bcmsdh_reg_write(bus->sdh, | ||
6306 | CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0); | ||
6307 | |||
6308 | /* Disable F2 to clear any intermediate frame state on the dongle */ | ||
6309 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, | ||
6310 | SDIO_FUNC_ENABLE_1, NULL); | ||
6311 | |||
6312 | /* WAR: cmd52 backplane read so core HW will drop ALPReq */ | ||
6313 | clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, | ||
6314 | 0, NULL); | ||
6315 | |||
6316 | /* Done with backplane-dependent accesses, can drop clock... */ | ||
6317 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, | ||
6318 | NULL); | ||
6319 | |||
6320 | bus->ci = ci; | ||
6321 | return 0; | ||
6322 | fail: | ||
6323 | bus->ci = NULL; | ||
6324 | kfree(ci); | ||
6325 | return err; | ||
6326 | } | ||