Skip to content

Commit babb0ce

Browse files
Carl HuangKalle Valo
authored andcommitted
ath11k: pci: fix hot reset stability issues
For QCA6390, host needs to reset some registers before MHI power up to fix PCI link unstable issue if hot reset happened. Also clear all pending interrupts during power up. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 43ed15e commit babb0ce

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

drivers/net/wireless/ath/ath11k/pci.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,57 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
239239
ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
240240
}
241241

242+
static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
243+
{
244+
u32 val;
245+
int i;
246+
247+
val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
248+
249+
/* PCIE link seems very unstable after the Hot Reset*/
250+
for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
251+
if (val == 0xffffffff)
252+
mdelay(5);
253+
254+
ath11k_pci_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
255+
val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
256+
}
257+
258+
ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
259+
260+
val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
261+
val |= GCC_GCC_PCIE_HOT_RST_VAL | 0x10;
262+
ath11k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
263+
val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
264+
265+
ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
266+
267+
mdelay(5);
268+
}
269+
270+
static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
271+
{
272+
/* This is a WAR for PCIE Hotreset.
273+
* When target receive Hotreset, but will set the interrupt.
274+
* So when download SBL again, SBL will open Interrupt and
275+
* receive it, and crash immediately.
276+
*/
277+
ath11k_pci_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
278+
}
279+
242280
static void ath11k_pci_force_wake(struct ath11k_base *ab)
243281
{
244282
ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
245283
mdelay(5);
246284
}
247285

248-
static void ath11k_pci_sw_reset(struct ath11k_base *ab)
286+
static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
249287
{
250-
ath11k_pci_soc_global_reset(ab);
288+
if (power_on) {
289+
ath11k_pci_enable_ltssm(ab);
290+
ath11k_pci_clear_all_intrs(ab);
291+
}
292+
251293
ath11k_mhi_clear_vector(ab);
252294
ath11k_pci_soc_global_reset(ab);
253295
ath11k_mhi_set_mhictrl_reset(ab);
@@ -770,7 +812,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
770812

771813
ab_pci->register_window = 0;
772814
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
773-
ath11k_pci_sw_reset(ab_pci->ab);
815+
ath11k_pci_sw_reset(ab_pci->ab, true);
774816

775817
ret = ath11k_mhi_start(ab_pci);
776818
if (ret) {
@@ -785,10 +827,10 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
785827
{
786828
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
787829

830+
ath11k_pci_force_wake(ab_pci->ab);
788831
ath11k_mhi_stop(ab_pci);
789832
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
790-
ath11k_pci_force_wake(ab_pci->ab);
791-
ath11k_pci_sw_reset(ab_pci->ab);
833+
ath11k_pci_sw_reset(ab_pci->ab, false);
792834
}
793835

794836
static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)

drivers/net/wireless/ath/ath11k/pci.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@
2424
/* register used for handshake mechanism to validate UMAC is awake */
2525
#define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004
2626

27+
#define PCIE_PCIE_PARF_LTSSM 0x1e081b0
28+
#define PARM_LTSSM_VALUE 0x111
29+
30+
#define GCC_GCC_PCIE_HOT_RST 0x1e402bc
31+
#define GCC_GCC_PCIE_HOT_RST_VAL 0x10
32+
33+
#define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228
34+
#define PCIE_SMLH_REQ_RST_LINK_DOWN 0x2
35+
#define PCIE_INT_CLEAR_ALL 0xffffffff
36+
2737
struct ath11k_msi_user {
2838
char *name;
2939
int num_vectors;

0 commit comments

Comments
 (0)