aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2014-01-13 16:20:23 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-01-16 14:54:16 -0500
commit53036261033abdab7323a4a896a9bde84d2c2f17 (patch)
tree1463f8305582ff23f344bf3fc50fc9c16484afeb /drivers/net/wireless
parenta74d036f98280b0de312f842ad09c26de56f27c5 (diff)
brcmfmac: update core reset and disable routines.
The original core reset and disable routines do not work always on running system. These routines were updated to properly reset a core. When module is unloaded the device is put into download state where all necessary cores have been reset. This will make sure the device is in idle mode after module unload. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c8
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c149
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h6
3 files changed, 106 insertions, 57 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4f936c6b682d..19057896d92e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2263,8 +2263,6 @@ static void brcmf_sdio_bus_stop(struct device *dev)
2263 w_sdreg32(bus, local_hostintmask, 2263 w_sdreg32(bus, local_hostintmask,
2264 offsetof(struct sdpcmd_regs, intstatus)); 2264 offsetof(struct sdpcmd_regs, intstatus));
2265 2265
2266 /* Turn off the backplane clock (only) */
2267 brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
2268 sdio_release_host(bus->sdiodev->func[1]); 2266 sdio_release_host(bus->sdiodev->func[1]);
2269 2267
2270 /* Clear the data packet queues */ 2268 /* Clear the data packet queues */
@@ -4085,6 +4083,12 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
4085 if (bus->ci) { 4083 if (bus->ci) {
4086 sdio_claim_host(bus->sdiodev->func[1]); 4084 sdio_claim_host(bus->sdiodev->func[1]);
4087 brcmf_sdio_clkctl(bus, CLK_AVAIL, false); 4085 brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
4086 /* Leave the device in state where it is 'quiet'. This
4087 * is done by putting it in download_state which
4088 * essentially resets all necessary cores
4089 */
4090 msleep(20);
4091 brcmf_sdio_download_state(bus, true);
4088 brcmf_sdio_clkctl(bus, CLK_NONE, false); 4092 brcmf_sdio_clkctl(bus, CLK_NONE, false);
4089 sdio_release_host(bus->sdiodev->func[1]); 4093 sdio_release_host(bus->sdiodev->func[1]);
4090 brcmf_sdio_chip_detach(&bus->ci); 4094 brcmf_sdio_chip_detach(&bus->ci);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index a74a3d1c3e00..434297648e34 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -51,6 +51,9 @@
51#define BCM43143_CORE_ARM_BASE 0x18003000 51#define BCM43143_CORE_ARM_BASE 0x18003000
52#define BCM43143_RAMSIZE 0x70000 52#define BCM43143_RAMSIZE 0x70000
53 53
54/* All D11 cores, ID 0x812 */
55#define BCM43xx_CORE_D11_BASE 0x18001000
56
54#define SBCOREREV(sbidh) \ 57#define SBCOREREV(sbidh) \
55 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ 58 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
56 ((sbidh) & SSB_IDHIGH_RCLO)) 59 ((sbidh) & SSB_IDHIGH_RCLO))
@@ -66,6 +69,10 @@
66/* ARM CR4 core specific control flag bits */ 69/* ARM CR4 core specific control flag bits */
67#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 70#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
68 71
72/* D11 core specific control flag bits */
73#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
74#define D11_BCMA_IOCTL_PHYRESET 0x0008
75
69#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) 76#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
70/* SDIO Pad drive strength to select value mappings */ 77/* SDIO Pad drive strength to select value mappings */
71struct sdiod_drive_str { 78struct sdiod_drive_str {
@@ -193,7 +200,8 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
193 200
194static void 201static void
195brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, 202brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
196 struct chip_info *ci, u16 coreid, u32 core_bits) 203 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
204 u32 in_resetbits)
197{ 205{
198 u32 regdata, base; 206 u32 regdata, base;
199 u8 idx; 207 u8 idx;
@@ -279,52 +287,48 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
279 287
280static void 288static void
281brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, 289brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
282 struct chip_info *ci, u16 coreid, u32 core_bits) 290 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
291 u32 in_resetbits)
283{ 292{
284 u8 idx; 293 u8 idx;
285 u32 regdata; 294 u32 regdata;
295 u32 wrapbase;
286 296
287 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 297 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
288 if (idx == BRCMF_MAX_CORENUM) 298 if (idx == BRCMF_MAX_CORENUM)
289 return; 299 return;
290 300
301 wrapbase = ci->c_inf[idx].wrapbase;
302
291 /* if core is already in reset, just return */ 303 /* if core is already in reset, just return */
292 regdata = brcmf_sdiod_regrl(sdiodev, 304 regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
293 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
294 NULL);
295 if ((regdata & BCMA_RESET_CTL_RESET) != 0) 305 if ((regdata & BCMA_RESET_CTL_RESET) != 0)
296 return; 306 return;
297 307
298 /* ensure no pending backplane operation 308 /* configure reset */
299 * 300uc should be sufficient for backplane ops to be finish 309 brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
300 * extra 10ms is taken into account for firmware load stage 310 BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
301 * after 10300us carry on disabling the core anyway 311 regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
302 */
303 SPINWAIT(brcmf_sdiod_regrl(sdiodev,
304 ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
305 NULL), 10300);
306 regdata = brcmf_sdiod_regrl(sdiodev,
307 ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
308 NULL);
309 if (regdata)
310 brcmf_err("disabling core 0x%x with reset status %x\n",
311 coreid, regdata);
312 312
313 brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, 313 /* put in reset */
314 brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
314 BCMA_RESET_CTL_RESET, NULL); 315 BCMA_RESET_CTL_RESET, NULL);
315 udelay(1);
316
317 brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
318 core_bits, NULL);
319 regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
320 NULL);
321 usleep_range(10, 20); 316 usleep_range(10, 20);
322 317
318 /* wait till reset is 1 */
319 SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
320 BCMA_RESET_CTL_RESET, 300);
321
322 /* post reset configure */
323 brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
324 BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
325 regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
323} 326}
324 327
325static void 328static void
326brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, 329brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
327 struct chip_info *ci, u16 coreid, u32 core_bits) 330 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
331 u32 in_resetbits, u32 post_resetbits)
328{ 332{
329 u32 regdata; 333 u32 regdata;
330 u8 idx; 334 u8 idx;
@@ -337,7 +341,8 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
337 * Must do the disable sequence first to work for 341 * Must do the disable sequence first to work for
338 * arbitrary current core state. 342 * arbitrary current core state.
339 */ 343 */
340 brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0); 344 brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits,
345 in_resetbits);
341 346
342 /* 347 /*
343 * Now do the initialization sequence. 348 * Now do the initialization sequence.
@@ -390,35 +395,32 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
390 395
391static void 396static void
392brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, 397brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
393 struct chip_info *ci, u16 coreid, u32 core_bits) 398 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
399 u32 in_resetbits, u32 post_resetbits)
394{ 400{
395 u8 idx; 401 u8 idx;
396 u32 regdata; 402 u32 regdata;
403 u32 wrapbase;
397 404
398 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 405 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
399 if (idx == BRCMF_MAX_CORENUM) 406 if (idx == BRCMF_MAX_CORENUM)
400 return; 407 return;
401 408
409 wrapbase = ci->c_inf[idx].wrapbase;
410
402 /* must disable first to work for arbitrary current core state */ 411 /* must disable first to work for arbitrary current core state */
403 brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); 412 brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits,
413 in_resetbits);
404 414
405 /* now do initialization sequence */ 415 while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) &
406 brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 416 BCMA_RESET_CTL_RESET) {
407 core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); 417 brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL);
408 regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 418 usleep_range(40, 60);
409 NULL); 419 }
410 brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
411 0, NULL);
412 regdata = brcmf_sdiod_regrl(sdiodev,
413 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
414 NULL);
415 udelay(1);
416 420
417 brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 421 brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits |
418 core_bits | BCMA_IOCTL_CLK, NULL); 422 BCMA_IOCTL_CLK, NULL);
419 regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 423 regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
420 NULL);
421 udelay(1);
422} 424}
423 425
424#ifdef DEBUG 426#ifdef DEBUG
@@ -498,6 +500,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
498 ci->c_inf[3].base = BCM43143_CORE_ARM_BASE; 500 ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
499 ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; 501 ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
500 ci->c_inf[3].cib = 0x07000000; 502 ci->c_inf[3].cib = 0x07000000;
503 ci->c_inf[4].id = BCMA_CORE_80211;
504 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
505 ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
501 ci->ramsize = BCM43143_RAMSIZE; 506 ci->ramsize = BCM43143_RAMSIZE;
502 break; 507 break;
503 case BCM43241_CHIP_ID: 508 case BCM43241_CHIP_ID:
@@ -515,6 +520,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
515 ci->c_inf[3].base = 0x18003000; 520 ci->c_inf[3].base = 0x18003000;
516 ci->c_inf[3].wrapbase = 0x18103000; 521 ci->c_inf[3].wrapbase = 0x18103000;
517 ci->c_inf[3].cib = 0x07004211; 522 ci->c_inf[3].cib = 0x07004211;
523 ci->c_inf[4].id = BCMA_CORE_80211;
524 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
525 ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
518 ci->ramsize = 0x90000; 526 ci->ramsize = 0x90000;
519 break; 527 break;
520 case BCM4329_CHIP_ID: 528 case BCM4329_CHIP_ID:
@@ -524,6 +532,8 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
524 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; 532 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
525 ci->c_inf[3].id = BCMA_CORE_ARM_CM3; 533 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
526 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; 534 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
535 ci->c_inf[4].id = BCMA_CORE_80211;
536 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
527 ci->ramsize = BCM4329_RAMSIZE; 537 ci->ramsize = BCM4329_RAMSIZE;
528 break; 538 break;
529 case BCM4330_CHIP_ID: 539 case BCM4330_CHIP_ID:
@@ -541,6 +551,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
541 ci->c_inf[3].base = 0x18003000; 551 ci->c_inf[3].base = 0x18003000;
542 ci->c_inf[3].wrapbase = 0x18103000; 552 ci->c_inf[3].wrapbase = 0x18103000;
543 ci->c_inf[3].cib = 0x03004211; 553 ci->c_inf[3].cib = 0x03004211;
554 ci->c_inf[4].id = BCMA_CORE_80211;
555 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
556 ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
544 ci->ramsize = 0x48000; 557 ci->ramsize = 0x48000;
545 break; 558 break;
546 case BCM4334_CHIP_ID: 559 case BCM4334_CHIP_ID:
@@ -558,6 +571,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
558 ci->c_inf[3].base = 0x18003000; 571 ci->c_inf[3].base = 0x18003000;
559 ci->c_inf[3].wrapbase = 0x18103000; 572 ci->c_inf[3].wrapbase = 0x18103000;
560 ci->c_inf[3].cib = 0x07004211; 573 ci->c_inf[3].cib = 0x07004211;
574 ci->c_inf[4].id = BCMA_CORE_80211;
575 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
576 ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
561 ci->ramsize = 0x80000; 577 ci->ramsize = 0x80000;
562 break; 578 break;
563 case BCM4335_CHIP_ID: 579 case BCM4335_CHIP_ID:
@@ -571,6 +587,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
571 ci->c_inf[2].base = 0x18002000; 587 ci->c_inf[2].base = 0x18002000;
572 ci->c_inf[2].wrapbase = 0x18102000; 588 ci->c_inf[2].wrapbase = 0x18102000;
573 ci->c_inf[2].cib = 0x01084411; 589 ci->c_inf[2].cib = 0x01084411;
590 ci->c_inf[3].id = BCMA_CORE_80211;
591 ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
592 ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
574 ci->ramsize = 0xc0000; 593 ci->ramsize = 0xc0000;
575 ci->rambase = 0x180000; 594 ci->rambase = 0x180000;
576 break; 595 break;
@@ -585,6 +604,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
585 ci->c_inf[2].base = 0x18002000; 604 ci->c_inf[2].base = 0x18002000;
586 ci->c_inf[2].wrapbase = 0x18102000; 605 ci->c_inf[2].wrapbase = 0x18102000;
587 ci->c_inf[2].cib = 0x04084411; 606 ci->c_inf[2].cib = 0x04084411;
607 ci->c_inf[3].id = BCMA_CORE_80211;
608 ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
609 ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
588 ci->ramsize = 0xc0000; 610 ci->ramsize = 0xc0000;
589 ci->rambase = 0x180000; 611 ci->rambase = 0x180000;
590 break; 612 break;
@@ -603,6 +625,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
603 ci->c_inf[3].base = 0x18003000; 625 ci->c_inf[3].base = 0x18003000;
604 ci->c_inf[3].wrapbase = 0x18103000; 626 ci->c_inf[3].wrapbase = 0x18103000;
605 ci->c_inf[3].cib = 0x03004211; 627 ci->c_inf[3].cib = 0x03004211;
628 ci->c_inf[4].id = BCMA_CORE_80211;
629 ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
630 ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
606 ci->ramsize = 0x3C000; 631 ci->ramsize = 0x3C000;
607 break; 632 break;
608 default: 633 default:
@@ -713,7 +738,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
713 * Make sure any on-chip ARM is off (in case strapping is wrong), 738 * Make sure any on-chip ARM is off (in case strapping is wrong),
714 * or downloaded code was already running. 739 * or downloaded code was already running.
715 */ 740 */
716 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); 741 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
717} 742}
718 743
719int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, 744int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
@@ -846,8 +871,11 @@ static void
846brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev, 871brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
847 struct chip_info *ci) 872 struct chip_info *ci)
848{ 873{
849 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); 874 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
850 ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0); 875 ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
876 D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
877 D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
878 ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0);
851} 879}
852 880
853static bool 881static bool
@@ -867,7 +895,7 @@ brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
867 reg_addr += offsetof(struct sdpcmd_regs, intstatus); 895 reg_addr += offsetof(struct sdpcmd_regs, intstatus);
868 brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); 896 brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
869 897
870 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); 898 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0);
871 899
872 return true; 900 return true;
873} 901}
@@ -876,8 +904,22 @@ static inline void
876brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev, 904brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
877 struct chip_info *ci) 905 struct chip_info *ci)
878{ 906{
879 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 907 u8 idx;
880 ARMCR4_BCMA_IOCTL_CPUHALT); 908 u32 regdata;
909 u32 wrapbase;
910 idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
911
912 if (idx == BRCMF_MAX_CORENUM)
913 return;
914
915 wrapbase = ci->c_inf[idx].wrapbase;
916 regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
917 regdata &= ARMCR4_BCMA_IOCTL_CPUHALT;
918 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata,
919 ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT);
920 ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
921 D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
922 D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
881} 923}
882 924
883static bool 925static bool
@@ -897,7 +939,8 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
897 sizeof(ci->rst_vec)); 939 sizeof(ci->rst_vec));
898 940
899 /* restore ARM */ 941 /* restore ARM */
900 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0); 942 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
943 0, 0);
901 944
902 return true; 945 return true;
903} 946}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index c7d0dbc1ab59..91c61cb9de87 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -81,9 +81,11 @@ struct chip_info {
81 u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, 81 u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
82 u16 coreid); 82 u16 coreid);
83 void (*coredisable)(struct brcmf_sdio_dev *sdiodev, 83 void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
84 struct chip_info *ci, u16 coreid, u32 core_bits); 84 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
85 u32 in_resetbits);
85 void (*resetcore)(struct brcmf_sdio_dev *sdiodev, 86 void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
86 struct chip_info *ci, u16 coreid, u32 core_bits); 87 struct chip_info *ci, u16 coreid, u32 pre_resetbits,
88 u32 in_resetbits, u32 post_resetbits);
87}; 89};
88 90
89struct sbconfig { 91struct sbconfig {