@@ -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+
242280static 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
794836static void ath11k_pci_kill_tasklets (struct ath11k_base * ab )
0 commit comments