OpenWrt – Rev 1

Subversion Repositories:
Rev:
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 9 Jul 2016 15:26:44 +0200
Subject: [PATCH] ath9k_hw: issue external reset for QCA955x

The RTC interface on the SoC needs to be reset along with the rest of
the WMAC.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---

--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1298,39 +1298,56 @@ void ath9k_hw_get_delta_slope_vals(struc
        *coef_exponent = coef_exp - 16;
 }
 
-/* AR9330 WAR:
- * call external reset function to reset WMAC if:
- * - doing a cold reset
- * - we have pending frames in the TX queues.
- */
-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
+static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
 {
-       int i, npend = 0;
+       int i;
 
-       for (i = 0; i < AR_NUM_QCU; i++) {
-               npend = ath9k_hw_numtxpending(ah, i);
-               if (npend)
-                       break;
-       }
-
-       if (ah->external_reset &&
-           (npend || type == ATH9K_RESET_COLD)) {
-               int reset_err = 0;
-
-               ath_dbg(ath9k_hw_common(ah), RESET,
-                       "reset MAC via external reset\n");
-
-               reset_err = ah->external_reset();
-               if (reset_err) {
-                       ath_err(ath9k_hw_common(ah),
-                               "External reset failed, err=%d\n",
-                               reset_err);
-                       return false;
+       if (type == ATH9K_RESET_COLD)
+               return true;
+
+       if (AR_SREV_9550(ah))
+               return true;
+
+       /* AR9330 WAR:
+        * call external reset function to reset WMAC if:
+        * - doing a cold reset
+        * - we have pending frames in the TX queues.
+        */
+       if (AR_SREV_9330(ah)) {
+               for (i = 0; i < AR_NUM_QCU; i++) {
+                       if (ath9k_hw_numtxpending(ah, i))
+                               return true;
                }
+       }
+
+       return false;
+}
+
+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
+{
+       int err;
+
+       if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
+               return true;
+
+       ath_dbg(ath9k_hw_common(ah), RESET,
+               "reset MAC via external reset\n");
 
-               REG_WRITE(ah, AR_RTC_RESET, 1);
+       err = ah->external_reset();
+       if (err) {
+               ath_err(ath9k_hw_common(ah),
+                       "External reset failed, err=%d\n", err);
+               return false;
        }
 
+       if (AR_SREV_9550(ah)) {
+               REG_WRITE(ah, AR_RTC_RESET, 0);
+               udelay(10);
+       }
+
+       REG_WRITE(ah, AR_RTC_RESET, 1);
+       udelay(10);
+
        return true;
 }
 
@@ -1383,24 +1400,24 @@ static bool ath9k_hw_set_reset(struct at
                        rst_flags |= AR_RTC_RC_MAC_COLD;
        }
 
-       if (AR_SREV_9330(ah)) {
-               if (!ath9k_hw_ar9330_reset_war(ah, type))
-                       return false;
-       }
-
        if (ath9k_hw_mci_is_enabled(ah))
                ar9003_mci_check_gpm_offset(ah);
 
        /* DMA HALT added to resolve ar9300 and ar9580 bus error during
-        * RTC_RC reg read
+        * RTC_RC reg read. Also needed for AR9550 external reset
         */
-       if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
+       if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
                REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
                ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
                              20 * AH_WAIT_TIMEOUT);
-               REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
        }
 
+       if (!AR_SREV_9100(ah))
+               ath9k_hw_external_reset(ah, type);
+
+       if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
+               REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
+
        REG_WRITE(ah, AR_RTC_RC, rst_flags);
 
        REGWRITE_BUFFER_FLUSH(ah);