diff options
author | Piotr Haber <phaber@broadcom.com> | 2013-04-11 07:28:46 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-12 14:27:53 -0400 |
commit | 4a3da9906bbf37f6b0d44ddb753d3198e73c3c6d (patch) | |
tree | ae399c6386c2db3412b30e15335f1515d894ee3e /drivers/net | |
parent | fe29f54cd574eab7b521445419f355c0ecd995cc (diff) |
brcmfmac: support save&restore firmware feature
Save & restore is an advanced power saving feature,
supported only on selected devices.
SR operation is almost completely transparent to the driver.
Support for it is hardware and firmware dependent.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Piotr Haber <phaber@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')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 262 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/include/chipcommon.h | 14 |
3 files changed, 282 insertions, 16 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 4ff2d3c52ee6..fb4ff910c8a4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -324,6 +324,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME); | |||
324 | */ | 324 | */ |
325 | #define BRCMF_IDLE_INTERVAL 1 | 325 | #define BRCMF_IDLE_INTERVAL 1 |
326 | 326 | ||
327 | #define KSO_WAIT_US 50 | ||
328 | #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) | ||
329 | |||
327 | /* | 330 | /* |
328 | * Conversion of 802.1D priority to precedence level | 331 | * Conversion of 802.1D priority to precedence level |
329 | */ | 332 | */ |
@@ -588,12 +591,14 @@ struct brcmf_sdio { | |||
588 | 591 | ||
589 | bool txoff; /* Transmit flow-controlled */ | 592 | bool txoff; /* Transmit flow-controlled */ |
590 | struct brcmf_sdio_count sdcnt; | 593 | struct brcmf_sdio_count sdcnt; |
594 | bool sr_enabled; /* SaveRestore enabled */ | ||
595 | bool sleeping; /* SDIO bus sleeping */ | ||
591 | }; | 596 | }; |
592 | 597 | ||
593 | /* clkstate */ | 598 | /* clkstate */ |
594 | #define CLK_NONE 0 | 599 | #define CLK_NONE 0 |
595 | #define CLK_SDONLY 1 | 600 | #define CLK_SDONLY 1 |
596 | #define CLK_PENDING 2 /* Not used yet */ | 601 | #define CLK_PENDING 2 |
597 | #define CLK_AVAIL 3 | 602 | #define CLK_AVAIL 3 |
598 | 603 | ||
599 | #ifdef DEBUG | 604 | #ifdef DEBUG |
@@ -665,6 +670,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) | |||
665 | return ret; | 670 | return ret; |
666 | } | 671 | } |
667 | 672 | ||
673 | static int | ||
674 | brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | ||
675 | { | ||
676 | u8 wr_val = 0, rd_val, cmp_val, bmask; | ||
677 | int err = 0; | ||
678 | int try_cnt = 0; | ||
679 | |||
680 | brcmf_dbg(TRACE, "Enter\n"); | ||
681 | |||
682 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | ||
683 | /* 1st KSO write goes to AOS wake up core if device is asleep */ | ||
684 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
685 | wr_val, &err); | ||
686 | if (err) { | ||
687 | brcmf_err("SDIO_AOS KSO write error: %d\n", err); | ||
688 | return err; | ||
689 | } | ||
690 | |||
691 | if (on) { | ||
692 | /* device WAKEUP through KSO: | ||
693 | * write bit 0 & read back until | ||
694 | * both bits 0 (kso bit) & 1 (dev on status) are set | ||
695 | */ | ||
696 | cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | | ||
697 | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK; | ||
698 | bmask = cmp_val; | ||
699 | usleep_range(2000, 3000); | ||
700 | } else { | ||
701 | /* Put device to sleep, turn off KSO */ | ||
702 | cmp_val = 0; | ||
703 | /* only check for bit0, bit1(dev on status) may not | ||
704 | * get cleared right away | ||
705 | */ | ||
706 | bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK; | ||
707 | } | ||
708 | |||
709 | do { | ||
710 | /* reliable KSO bit set/clr: | ||
711 | * the sdiod sleep write access is synced to PMU 32khz clk | ||
712 | * just one write attempt may fail, | ||
713 | * read it back until it matches written value | ||
714 | */ | ||
715 | rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
716 | &err); | ||
717 | if (((rd_val & bmask) == cmp_val) && !err) | ||
718 | break; | ||
719 | brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n", | ||
720 | try_cnt, MAX_KSO_ATTEMPTS, err); | ||
721 | udelay(KSO_WAIT_US); | ||
722 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
723 | wr_val, &err); | ||
724 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); | ||
725 | |||
726 | return err; | ||
727 | } | ||
728 | |||
668 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) | 729 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) |
669 | 730 | ||
670 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | 731 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) |
@@ -680,6 +741,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
680 | 741 | ||
681 | clkctl = 0; | 742 | clkctl = 0; |
682 | 743 | ||
744 | if (bus->sr_enabled) { | ||
745 | bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY); | ||
746 | return 0; | ||
747 | } | ||
748 | |||
683 | if (on) { | 749 | if (on) { |
684 | /* Request HT Avail */ | 750 | /* Request HT Avail */ |
685 | clkreq = | 751 | clkreq = |
@@ -856,6 +922,63 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
856 | return 0; | 922 | return 0; |
857 | } | 923 | } |
858 | 924 | ||
925 | static int | ||
926 | brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | ||
927 | { | ||
928 | int err = 0; | ||
929 | brcmf_dbg(TRACE, "Enter\n"); | ||
930 | brcmf_dbg(SDIO, "request %s currently %s\n", | ||
931 | (sleep ? "SLEEP" : "WAKE"), | ||
932 | (bus->sleeping ? "SLEEP" : "WAKE")); | ||
933 | |||
934 | /* If SR is enabled control bus state with KSO */ | ||
935 | if (bus->sr_enabled) { | ||
936 | /* Done if we're already in the requested state */ | ||
937 | if (sleep == bus->sleeping) | ||
938 | goto end; | ||
939 | |||
940 | /* Going to sleep */ | ||
941 | if (sleep) { | ||
942 | /* Don't sleep if something is pending */ | ||
943 | if (atomic_read(&bus->intstatus) || | ||
944 | atomic_read(&bus->ipend) > 0 || | ||
945 | (!atomic_read(&bus->fcstate) && | ||
946 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | ||
947 | data_ok(bus))) | ||
948 | return -EBUSY; | ||
949 | err = brcmf_sdbrcm_kso_control(bus, false); | ||
950 | /* disable watchdog */ | ||
951 | if (!err) | ||
952 | brcmf_sdbrcm_wd_timer(bus, 0); | ||
953 | } else { | ||
954 | bus->idlecount = 0; | ||
955 | err = brcmf_sdbrcm_kso_control(bus, true); | ||
956 | } | ||
957 | if (!err) { | ||
958 | /* Change state */ | ||
959 | bus->sleeping = sleep; | ||
960 | brcmf_dbg(SDIO, "new state %s\n", | ||
961 | (sleep ? "SLEEP" : "WAKE")); | ||
962 | } else { | ||
963 | brcmf_err("error while changing bus sleep state %d\n", | ||
964 | err); | ||
965 | return err; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | end: | ||
970 | /* control clocks */ | ||
971 | if (sleep) { | ||
972 | if (!bus->sr_enabled) | ||
973 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok); | ||
974 | } else { | ||
975 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok); | ||
976 | } | ||
977 | |||
978 | return err; | ||
979 | |||
980 | } | ||
981 | |||
859 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | 982 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) |
860 | { | 983 | { |
861 | u32 intstatus = 0; | 984 | u32 intstatus = 0; |
@@ -1960,7 +2083,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
1960 | sdio_claim_host(bus->sdiodev->func[1]); | 2083 | sdio_claim_host(bus->sdiodev->func[1]); |
1961 | 2084 | ||
1962 | /* Enable clock for device interrupts */ | 2085 | /* Enable clock for device interrupts */ |
1963 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2086 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
1964 | 2087 | ||
1965 | /* Disable and clear interrupts at the chip level also */ | 2088 | /* Disable and clear interrupts at the chip level also */ |
1966 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); | 2089 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); |
@@ -2096,7 +2219,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2096 | sdio_claim_host(bus->sdiodev->func[1]); | 2219 | sdio_claim_host(bus->sdiodev->func[1]); |
2097 | 2220 | ||
2098 | /* If waiting for HTAVAIL, check status */ | 2221 | /* If waiting for HTAVAIL, check status */ |
2099 | if (bus->clkstate == CLK_PENDING) { | 2222 | if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) { |
2100 | u8 clkctl, devctl = 0; | 2223 | u8 clkctl, devctl = 0; |
2101 | 2224 | ||
2102 | #ifdef DEBUG | 2225 | #ifdef DEBUG |
@@ -2142,7 +2265,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2142 | } | 2265 | } |
2143 | 2266 | ||
2144 | /* Make sure backplane clock is on */ | 2267 | /* Make sure backplane clock is on */ |
2145 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); | 2268 | brcmf_sdbrcm_bus_sleep(bus, false, true); |
2146 | 2269 | ||
2147 | /* Pending interrupt indicates new device status */ | 2270 | /* Pending interrupt indicates new device status */ |
2148 | if (atomic_read(&bus->ipend) > 0) { | 2271 | if (atomic_read(&bus->ipend) > 0) { |
@@ -2288,8 +2411,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2288 | if ((bus->clkstate != CLK_PENDING) | 2411 | if ((bus->clkstate != CLK_PENDING) |
2289 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { | 2412 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { |
2290 | bus->activity = false; | 2413 | bus->activity = false; |
2414 | brcmf_dbg(SDIO, "idle state\n"); | ||
2291 | sdio_claim_host(bus->sdiodev->func[1]); | 2415 | sdio_claim_host(bus->sdiodev->func[1]); |
2292 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 2416 | brcmf_sdbrcm_bus_sleep(bus, true, false); |
2293 | sdio_release_host(bus->sdiodev->func[1]); | 2417 | sdio_release_host(bus->sdiodev->func[1]); |
2294 | } | 2418 | } |
2295 | } | 2419 | } |
@@ -2592,7 +2716,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2592 | 2716 | ||
2593 | /* Make sure backplane clock is on */ | 2717 | /* Make sure backplane clock is on */ |
2594 | sdio_claim_host(bus->sdiodev->func[1]); | 2718 | sdio_claim_host(bus->sdiodev->func[1]); |
2595 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2719 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
2596 | sdio_release_host(bus->sdiodev->func[1]); | 2720 | sdio_release_host(bus->sdiodev->func[1]); |
2597 | 2721 | ||
2598 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ | 2722 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ |
@@ -2650,6 +2774,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2650 | 2774 | ||
2651 | bus->activity = false; | 2775 | bus->activity = false; |
2652 | sdio_claim_host(bus->sdiodev->func[1]); | 2776 | sdio_claim_host(bus->sdiodev->func[1]); |
2777 | brcmf_dbg(INFO, "idle\n"); | ||
2653 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2778 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); |
2654 | sdio_release_host(bus->sdiodev->func[1]); | 2779 | sdio_release_host(bus->sdiodev->func[1]); |
2655 | } else { | 2780 | } else { |
@@ -2686,7 +2811,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2686 | * address of sdpcm_shared structure | 2811 | * address of sdpcm_shared structure |
2687 | */ | 2812 | */ |
2688 | sdio_claim_host(bus->sdiodev->func[1]); | 2813 | sdio_claim_host(bus->sdiodev->func[1]); |
2689 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2814 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
2690 | rv = brcmf_sdbrcm_membytes(bus, false, shaddr, | 2815 | rv = brcmf_sdbrcm_membytes(bus, false, shaddr, |
2691 | (u8 *)&addr_le, 4); | 2816 | (u8 *)&addr_le, 4); |
2692 | sdio_release_host(bus->sdiodev->func[1]); | 2817 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -3325,6 +3450,103 @@ err: | |||
3325 | return bcmerror; | 3450 | return bcmerror; |
3326 | } | 3451 | } |
3327 | 3452 | ||
3453 | static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus) | ||
3454 | { | ||
3455 | u32 addr, reg; | ||
3456 | |||
3457 | brcmf_dbg(TRACE, "Enter\n"); | ||
3458 | |||
3459 | /* old chips with PMU version less than 17 don't support save restore */ | ||
3460 | if (bus->ci->pmurev < 17) | ||
3461 | return false; | ||
3462 | |||
3463 | /* read PMU chipcontrol register 3*/ | ||
3464 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); | ||
3465 | brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL); | ||
3466 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); | ||
3467 | reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL); | ||
3468 | |||
3469 | return (bool)reg; | ||
3470 | } | ||
3471 | |||
3472 | static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus) | ||
3473 | { | ||
3474 | int err = 0; | ||
3475 | u8 val; | ||
3476 | |||
3477 | brcmf_dbg(TRACE, "Enter\n"); | ||
3478 | |||
3479 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | ||
3480 | &err); | ||
3481 | if (err) { | ||
3482 | brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n"); | ||
3483 | return; | ||
3484 | } | ||
3485 | |||
3486 | val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; | ||
3487 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | ||
3488 | val, &err); | ||
3489 | if (err) { | ||
3490 | brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n"); | ||
3491 | return; | ||
3492 | } | ||
3493 | |||
3494 | /* Add CMD14 Support */ | ||
3495 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, | ||
3496 | (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | | ||
3497 | SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), | ||
3498 | &err); | ||
3499 | if (err) { | ||
3500 | brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n"); | ||
3501 | return; | ||
3502 | } | ||
3503 | |||
3504 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
3505 | SBSDIO_FORCE_HT, &err); | ||
3506 | if (err) { | ||
3507 | brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n"); | ||
3508 | return; | ||
3509 | } | ||
3510 | |||
3511 | /* set flag */ | ||
3512 | bus->sr_enabled = true; | ||
3513 | brcmf_dbg(INFO, "SR enabled\n"); | ||
3514 | } | ||
3515 | |||
3516 | /* enable KSO bit */ | ||
3517 | static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | ||
3518 | { | ||
3519 | u8 val; | ||
3520 | int err = 0; | ||
3521 | |||
3522 | brcmf_dbg(TRACE, "Enter\n"); | ||
3523 | |||
3524 | /* KSO bit added in SDIO core rev 12 */ | ||
3525 | if (bus->ci->c_inf[1].rev < 12) | ||
3526 | return 0; | ||
3527 | |||
3528 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
3529 | &err); | ||
3530 | if (err) { | ||
3531 | brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n"); | ||
3532 | return err; | ||
3533 | } | ||
3534 | |||
3535 | if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { | ||
3536 | val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << | ||
3537 | SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | ||
3538 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
3539 | val, &err); | ||
3540 | if (err) { | ||
3541 | brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n"); | ||
3542 | return err; | ||
3543 | } | ||
3544 | } | ||
3545 | |||
3546 | return 0; | ||
3547 | } | ||
3548 | |||
3549 | |||
3328 | static bool | 3550 | static bool |
3329 | brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | 3551 | brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) |
3330 | { | 3552 | { |
@@ -3423,8 +3645,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3423 | ret = -ENODEV; | 3645 | ret = -ENODEV; |
3424 | } | 3646 | } |
3425 | 3647 | ||
3426 | /* Restore previous clock setting */ | 3648 | if (brcmf_sdbrcm_sr_capable(bus)) { |
3427 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); | 3649 | brcmf_sdbrcm_sr_init(bus); |
3650 | } else { | ||
3651 | /* Restore previous clock setting */ | ||
3652 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
3653 | saveclk, &err); | ||
3654 | } | ||
3428 | 3655 | ||
3429 | if (ret == 0) { | 3656 | if (ret == 0) { |
3430 | ret = brcmf_sdio_intr_register(bus->sdiodev); | 3657 | ret = brcmf_sdio_intr_register(bus->sdiodev); |
@@ -3485,7 +3712,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3485 | brcmf_dbg(TIMER, "Enter\n"); | 3712 | brcmf_dbg(TIMER, "Enter\n"); |
3486 | 3713 | ||
3487 | /* Poll period: check device if appropriate. */ | 3714 | /* Poll period: check device if appropriate. */ |
3488 | if (bus->poll && (++bus->polltick >= bus->pollrate)) { | 3715 | if (!bus->sr_enabled && |
3716 | bus->poll && (++bus->polltick >= bus->pollrate)) { | ||
3489 | u32 intstatus = 0; | 3717 | u32 intstatus = 0; |
3490 | 3718 | ||
3491 | /* Reset poll tick */ | 3719 | /* Reset poll tick */ |
@@ -3536,7 +3764,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3536 | bus->console.count -= bus->console_interval; | 3764 | bus->console.count -= bus->console_interval; |
3537 | sdio_claim_host(bus->sdiodev->func[1]); | 3765 | sdio_claim_host(bus->sdiodev->func[1]); |
3538 | /* Make sure backplane clock is on */ | 3766 | /* Make sure backplane clock is on */ |
3539 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 3767 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
3540 | if (brcmf_sdbrcm_readconsole(bus) < 0) | 3768 | if (brcmf_sdbrcm_readconsole(bus) < 0) |
3541 | /* stop on error */ | 3769 | /* stop on error */ |
3542 | bus->console_interval = 0; | 3770 | bus->console_interval = 0; |
@@ -3553,8 +3781,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3553 | bus->activity = false; | 3781 | bus->activity = false; |
3554 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 3782 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); |
3555 | } else { | 3783 | } else { |
3784 | brcmf_dbg(SDIO, "idle\n"); | ||
3556 | sdio_claim_host(bus->sdiodev->func[1]); | 3785 | sdio_claim_host(bus->sdiodev->func[1]); |
3557 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 3786 | brcmf_sdbrcm_bus_sleep(bus, true, false); |
3558 | sdio_release_host(bus->sdiodev->func[1]); | 3787 | sdio_release_host(bus->sdiodev->func[1]); |
3559 | } | 3788 | } |
3560 | } | 3789 | } |
@@ -3686,6 +3915,11 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3686 | goto fail; | 3915 | goto fail; |
3687 | } | 3916 | } |
3688 | 3917 | ||
3918 | if (brcmf_sdbrcm_kso_init(bus)) { | ||
3919 | brcmf_err("error enabling KSO\n"); | ||
3920 | goto fail; | ||
3921 | } | ||
3922 | |||
3689 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, | 3923 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, |
3690 | SDIO_DRIVE_STRENGTH); | 3924 | SDIO_DRIVE_STRENGTH); |
3691 | 3925 | ||
@@ -3755,6 +3989,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
3755 | bus->use_rxchain = false; | 3989 | bus->use_rxchain = false; |
3756 | bus->sd_rxchain = false; | 3990 | bus->sd_rxchain = false; |
3757 | 3991 | ||
3992 | /* SR state */ | ||
3993 | bus->sleeping = false; | ||
3994 | bus->sr_enabled = false; | ||
3995 | |||
3758 | return true; | 3996 | return true; |
3759 | } | 3997 | } |
3760 | 3998 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 0d30afd8c672..4e681ae9eb81 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -48,7 +48,11 @@ | |||
48 | #define SBSDIO_NUM_FUNCTION 3 | 48 | #define SBSDIO_NUM_FUNCTION 3 |
49 | 49 | ||
50 | /* function 0 vendor specific CCCR registers */ | 50 | /* function 0 vendor specific CCCR registers */ |
51 | #define SDIO_CCCR_BRCM_SEPINT 0xf2 | 51 | #define SDIO_CCCR_BRCM_CARDCAP 0xf0 |
52 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 | ||
53 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 | ||
54 | #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 | ||
55 | #define SDIO_CCCR_BRCM_SEPINT 0xf2 | ||
52 | 56 | ||
53 | #define SDIO_SEPINT_MASK 0x01 | 57 | #define SDIO_SEPINT_MASK 0x01 |
54 | #define SDIO_SEPINT_OE 0x02 | 58 | #define SDIO_SEPINT_OE 0x02 |
@@ -97,9 +101,23 @@ | |||
97 | #define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B | 101 | #define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B |
98 | /* Read Frame Byte Count High */ | 102 | /* Read Frame Byte Count High */ |
99 | #define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C | 103 | #define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C |
104 | /* MesBusyCtl (rev 11) */ | ||
105 | #define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D | ||
106 | /* Sdio Core Rev 12 */ | ||
107 | #define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E | ||
108 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1 | ||
109 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0 | ||
110 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2 | ||
111 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1 | ||
112 | #define SBSDIO_FUNC1_SLEEPCSR 0x1001F | ||
113 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1 | ||
114 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0 | ||
115 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1 | ||
116 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2 | ||
117 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1 | ||
100 | 118 | ||
101 | #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ | 119 | #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ |
102 | #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ | 120 | #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */ |
103 | 121 | ||
104 | /* function 1 OCP space */ | 122 | /* function 1 OCP space */ |
105 | 123 | ||
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h index f96834a7c055..d242333b7559 100644 --- a/drivers/net/wireless/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/brcm80211/include/chipcommon.h | |||
@@ -205,7 +205,7 @@ struct chipcregs { | |||
205 | u32 res_req_timer_sel; | 205 | u32 res_req_timer_sel; |
206 | u32 res_req_timer; | 206 | u32 res_req_timer; |
207 | u32 res_req_mask; | 207 | u32 res_req_mask; |
208 | u32 PAD; | 208 | u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */ |
209 | u32 chipcontrol_addr; /* 0x650 */ | 209 | u32 chipcontrol_addr; /* 0x650 */ |
210 | u32 chipcontrol_data; /* 0x654 */ | 210 | u32 chipcontrol_data; /* 0x654 */ |
211 | u32 regcontrol_addr; | 211 | u32 regcontrol_addr; |
@@ -214,7 +214,11 @@ struct chipcregs { | |||
214 | u32 pllcontrol_data; | 214 | u32 pllcontrol_data; |
215 | u32 pmustrapopt; /* 0x668, corerev >= 28 */ | 215 | u32 pmustrapopt; /* 0x668, corerev >= 28 */ |
216 | u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ | 216 | u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ |
217 | u32 PAD[100]; | 217 | u32 retention_ctl; /* 0x670, pmurev >= 15 */ |
218 | u32 PAD[3]; | ||
219 | u32 retention_grpidx; /* 0x680 */ | ||
220 | u32 retention_grpctl; /* 0x684 */ | ||
221 | u32 PAD[94]; | ||
218 | u16 sromotp[768]; | 222 | u16 sromotp[768]; |
219 | }; | 223 | }; |
220 | 224 | ||
@@ -276,6 +280,12 @@ struct chipcregs { | |||
276 | #define PCAP5_VC_SHIFT 22 | 280 | #define PCAP5_VC_SHIFT 22 |
277 | #define PCAP5_CC_MASK 0xf8000000 | 281 | #define PCAP5_CC_MASK 0xf8000000 |
278 | #define PCAP5_CC_SHIFT 27 | 282 | #define PCAP5_CC_SHIFT 27 |
283 | /* pmucapabilites_ext PMU rev >= 15 */ | ||
284 | #define PCAPEXT_SR_SUPPORTED_MASK (1 << 1) | ||
285 | /* retention_ctl PMU rev >= 15 */ | ||
286 | #define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26) | ||
287 | #define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27) | ||
288 | |||
279 | 289 | ||
280 | /* | 290 | /* |
281 | * Maximum delay for the PMU state transition in us. | 291 | * Maximum delay for the PMU state transition in us. |