blob: 5f265b84c26e0c3aaa83a7387b763211e47a838f [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From: Felix Fietkau <nbd@nbd.name>
2Date: Sat, 9 Jul 2016 15:26:44 +0200
3Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
4
5The RTC interface on the SoC needs to be reset along with the rest of
6the WMAC.
7
8Signed-off-by: Felix Fietkau <nbd@nbd.name>
9---
10
11--- a/drivers/net/wireless/ath/ath9k/hw.c
12+++ b/drivers/net/wireless/ath/ath9k/hw.c
13@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc
14 *coef_exponent = coef_exp - 16;
15 }
16
17-/* AR9330 WAR:
18- * call external reset function to reset WMAC if:
19- * - doing a cold reset
20- * - we have pending frames in the TX queues.
21- */
22-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
23+static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
24 {
25- int i, npend = 0;
26+ int i;
27
28- for (i = 0; i < AR_NUM_QCU; i++) {
29- npend = ath9k_hw_numtxpending(ah, i);
30- if (npend)
31- break;
32- }
33-
34- if (ah->external_reset &&
35- (npend || type == ATH9K_RESET_COLD)) {
36- int reset_err = 0;
37-
38- ath_dbg(ath9k_hw_common(ah), RESET,
39- "reset MAC via external reset\n");
40-
41- reset_err = ah->external_reset();
42- if (reset_err) {
43- ath_err(ath9k_hw_common(ah),
44- "External reset failed, err=%d\n",
45- reset_err);
46- return false;
47+ if (type == ATH9K_RESET_COLD)
48+ return true;
49+
50+ if (AR_SREV_9550(ah))
51+ return true;
52+
53+ /* AR9330 WAR:
54+ * call external reset function to reset WMAC if:
55+ * - doing a cold reset
56+ * - we have pending frames in the TX queues.
57+ */
58+ if (AR_SREV_9330(ah)) {
59+ for (i = 0; i < AR_NUM_QCU; i++) {
60+ if (ath9k_hw_numtxpending(ah, i))
61+ return true;
62 }
63+ }
64+
65+ return false;
66+}
67+
68+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
69+{
70+ int err;
71+
72+ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
73+ return true;
74+
75+ ath_dbg(ath9k_hw_common(ah), RESET,
76+ "reset MAC via external reset\n");
77
78- REG_WRITE(ah, AR_RTC_RESET, 1);
79+ err = ah->external_reset();
80+ if (err) {
81+ ath_err(ath9k_hw_common(ah),
82+ "External reset failed, err=%d\n", err);
83+ return false;
84 }
85
86+ if (AR_SREV_9550(ah)) {
87+ REG_WRITE(ah, AR_RTC_RESET, 0);
88+ udelay(10);
89+ }
90+
91+ REG_WRITE(ah, AR_RTC_RESET, 1);
92+ udelay(10);
93+
94 return true;
95 }
96
97@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at
98 rst_flags |= AR_RTC_RC_MAC_COLD;
99 }
100
101- if (AR_SREV_9330(ah)) {
102- if (!ath9k_hw_ar9330_reset_war(ah, type))
103- return false;
104- }
105-
106 if (ath9k_hw_mci_is_enabled(ah))
107 ar9003_mci_check_gpm_offset(ah);
108
109 /* DMA HALT added to resolve ar9300 and ar9580 bus error during
110- * RTC_RC reg read
111+ * RTC_RC reg read. Also needed for AR9550 external reset
112 */
113- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
114+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
115 REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
116 ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
117 20 * AH_WAIT_TIMEOUT);
118- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
119 }
120
121+ if (!AR_SREV_9100(ah))
122+ ath9k_hw_external_reset(ah, type);
123+
124+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
125+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
126+
127 REG_WRITE(ah, AR_RTC_RC, rst_flags);
128
129 REGWRITE_BUFFER_FLUSH(ah);