summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath11k/mhi.c
diff options
context:
space:
mode:
authorCarl Huang <cjhuang@codeaurora.org>2020-08-17 13:31:55 +0300
committerKalle Valo <kvalo@codeaurora.org>2020-08-18 12:47:10 +0300
commitf3c603d412b3434dec15821f13fa4a1d0dd1cc84 (patch)
treed3feafefc5016f76a0288ab1af9c02215e213ed1 /drivers/net/wireless/ath/ath11k/mhi.c
parent065f5f683ea6abbc83cbf03b8789b452ab29d14f (diff)
ath11k: reset MHI during power down and power up
For QCA6390, normal power up and power down can't bring MHI to a workable state. This happens especially in warm reboot and rmmod and insmod. Host needs to write a few registers to bring MHI to normal state. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2 Signed-off-by: Carl Huang <cjhuang@codeauroro.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/1597555891-26112-10-git-send-email-kvalo@codeaurora.org
Diffstat (limited to 'drivers/net/wireless/ath/ath11k/mhi.c')
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index 62d39ef6741f..d7e60dc5b300 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -107,6 +107,51 @@ static struct mhi_controller_config ath11k_mhi_config = {
.event_cfg = ath11k_mhi_events,
};
+void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
+{
+ u32 val;
+
+ val = ath11k_pci_read32(ab, MHISTATUS);
+
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val);
+
+ /* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
+ * has SYSERR bit set and thus need to set MHICTRL_RESET
+ * to clear SYSERR.
+ */
+ ath11k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
+
+ mdelay(10);
+}
+
+static void ath11k_mhi_reset_txvecdb(struct ath11k_base *ab)
+{
+ ath11k_pci_write32(ab, PCIE_TXVECDB, 0);
+}
+
+static void ath11k_mhi_reset_txvecstatus(struct ath11k_base *ab)
+{
+ ath11k_pci_write32(ab, PCIE_TXVECSTATUS, 0);
+}
+
+static void ath11k_mhi_reset_rxvecdb(struct ath11k_base *ab)
+{
+ ath11k_pci_write32(ab, PCIE_RXVECDB, 0);
+}
+
+static void ath11k_mhi_reset_rxvecstatus(struct ath11k_base *ab)
+{
+ ath11k_pci_write32(ab, PCIE_RXVECSTATUS, 0);
+}
+
+void ath11k_mhi_clear_vector(struct ath11k_base *ab)
+{
+ ath11k_mhi_reset_txvecdb(ab);
+ ath11k_mhi_reset_txvecstatus(ab);
+ ath11k_mhi_reset_rxvecdb(ab);
+ ath11k_mhi_reset_rxvecstatus(ab);
+}
+
static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
@@ -416,7 +461,6 @@ out:
void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
{
- ath11k_mhi_set_state(ab_pci, ATH11K_MHI_RESUME);
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_OFF);
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_DEINIT);
}