diff options
Diffstat (limited to 'package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch')
-rw-r--r-- | package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch b/package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch new file mode 100644 index 0000000000..2af6fd93bc --- /dev/null +++ b/package/kernel/mac80211/patches/323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch @@ -0,0 +1,148 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Tue, 26 Jan 2016 17:57:04 +0100 +Subject: [PATCH] brcmfmac: access PMU registers using standalone PMU core if + available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On recent Broadcom chipsets PMU is present as separated core and it +can't be accessed using ChipCommon anymore as it fails with e.g.: +[ 18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f + +Add a new helper function that will return a proper core that should be +used for accessing PMU registers. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf + { + struct brcmf_chip *pub; + struct brcmf_core_priv *cc; ++ struct brcmf_core *pmu; + u32 base; + u32 val; + int ret = 0; +@@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf + capabilities_ext)); + + /* get pmu caps & rev */ ++ pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */ + if (pub->cc_caps & CC_CAP_PMU) { + val = chip->ops->read32(chip->ctx, +- CORE_CC_REG(base, pmucapabilities)); ++ CORE_CC_REG(pmu->base, pmucapabilities)); + pub->pmurev = val & PCAP_REV_MASK; + pub->pmucaps = val; + } +@@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipco + return &cc->pub; + } + ++struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub) ++{ ++ struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub); ++ struct brcmf_core *pmu; ++ ++ /* See if there is separated PMU core available */ ++ if (cc->rev >= 35 && ++ pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { ++ pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); ++ if (pmu) ++ return pmu; ++ } ++ ++ /* Fallback to ChipCommon core for older hardware */ ++ return cc; ++} ++ + bool brcmf_chip_iscoreup(struct brcmf_core *pub) + { + struct brcmf_core_priv *core; +@@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_ + { + u32 base, addr, reg, pmu_cc3_mask = ~0; + struct brcmf_chip_priv *chip; ++ struct brcmf_core *pmu = brcmf_chip_get_pmu(pub); + + brcmf_dbg(TRACE, "Enter\n"); + +@@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_ + case BRCM_CC_4335_CHIP_ID: + case BRCM_CC_4339_CHIP_ID: + /* read PMU chipcontrol register 3 */ +- addr = CORE_CC_REG(base, chipcontrol_addr); ++ addr = CORE_CC_REG(pmu->base, chipcontrol_addr); + chip->ops->write32(chip->ctx, addr, 3); +- addr = CORE_CC_REG(base, chipcontrol_data); ++ addr = CORE_CC_REG(pmu->base, chipcontrol_data); + reg = chip->ops->read32(chip->ctx, addr); + return (reg & pmu_cc3_mask) != 0; + case BRCM_CC_43430_CHIP_ID: +@@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_ + reg = chip->ops->read32(chip->ctx, addr); + return reg != 0; + default: +- addr = CORE_CC_REG(base, pmucapabilities_ext); ++ addr = CORE_CC_REG(pmu->base, pmucapabilities_ext); + reg = chip->ops->read32(chip->ctx, addr); + if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) + return false; + +- addr = CORE_CC_REG(base, retention_ctl); ++ addr = CORE_CC_REG(pmu->base, retention_ctl); + reg = chip->ops->read32(chip->ctx, addr); + return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | + PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +@@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(voi + void brcmf_chip_detach(struct brcmf_chip *chip); + struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); + struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip); ++struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub); + bool brcmf_chip_iscoreup(struct brcmf_core *core); + void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); + void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcm + const struct sdiod_drive_str *str_tab = NULL; + u32 str_mask; + u32 str_shift; +- u32 base; + u32 i; + u32 drivestrength_sel = 0; + u32 cc_data_temp; +@@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcm + } + + if (str_tab != NULL) { ++ struct brcmf_core *pmu = brcmf_chip_get_pmu(ci); ++ + for (i = 0; str_tab[i].strength != 0; i++) { + if (drivestrength >= str_tab[i].strength) { + drivestrength_sel = str_tab[i].sel; + break; + } + } +- base = brcmf_chip_get_chipcommon(ci)->base; +- addr = CORE_CC_REG(base, chipcontrol_addr); ++ addr = CORE_CC_REG(pmu->base, chipcontrol_addr); + brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); + cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); + cc_data_temp &= ~str_mask; +@@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + goto fail; + + /* set PMUControl so a backplane reset does PMU state reload */ +- reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base, +- pmucontrol); ++ reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); + reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err); + if (err) + goto fail; |