34d7d3b1cf9dae892c05c717941908d7dbeac919
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 315-ath9k_hw-issue-external-reset-for-QCA955x.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 9 Jul 2016 15:26:44 +0200
3 Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
4
5 The RTC interface on the SoC needs to be reset along with the rest of
6 the WMAC.
7
8 Signed-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 @@ -1271,39 +1271,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 + if (type == ATH9K_RESET_COLD)
33 + return true;
34 +
35 + if (AR_SREV_9550(ah))
36 + return true;
37 +
38 + /* AR9330 WAR:
39 + * call external reset function to reset WMAC if:
40 + * - doing a cold reset
41 + * - we have pending frames in the TX queues.
42 + */
43 + if (AR_SREV_9330(ah)) {
44 + for (i = 0; i < AR_NUM_QCU; i++) {
45 + if (ath9k_hw_numtxpending(ah, i))
46 + return true;
47 + }
48 }
49
50 - if (ah->external_reset &&
51 - (npend || type == ATH9K_RESET_COLD)) {
52 - int reset_err = 0;
53 + return false;
54 +}
55
56 - ath_dbg(ath9k_hw_common(ah), RESET,
57 - "reset MAC via external reset\n");
58 +static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
59 +{
60 + int err;
61
62 - reset_err = ah->external_reset();
63 - if (reset_err) {
64 - ath_err(ath9k_hw_common(ah),
65 - "External reset failed, err=%d\n",
66 - reset_err);
67 - return false;
68 - }
69 + if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
70 + return true;
71
72 - REG_WRITE(ah, AR_RTC_RESET, 1);
73 + ath_dbg(ath9k_hw_common(ah), RESET,
74 + "reset MAC via external reset\n");
75 +
76 + err = ah->external_reset();
77 + if (err) {
78 + ath_err(ath9k_hw_common(ah),
79 + "External reset failed, err=%d\n", err);
80 + return false;
81 + }
82 +
83 + if (AR_SREV_9550(ah)) {
84 + REG_WRITE(ah, AR_RTC_RESET, 0);
85 + udelay(10);
86 }
87
88 + REG_WRITE(ah, AR_RTC_RESET, 1);
89 + udelay(10);
90 +
91 return true;
92 }
93
94 @@ -1356,24 +1373,24 @@ static bool ath9k_hw_set_reset(struct at
95 rst_flags |= AR_RTC_RC_MAC_COLD;
96 }
97
98 - if (AR_SREV_9330(ah)) {
99 - if (!ath9k_hw_ar9330_reset_war(ah, type))
100 - return false;
101 - }
102 -
103 if (ath9k_hw_mci_is_enabled(ah))
104 ar9003_mci_check_gpm_offset(ah);
105
106 /* DMA HALT added to resolve ar9300 and ar9580 bus error during
107 - * RTC_RC reg read
108 + * RTC_RC reg read. Also needed for AR9550 external reset
109 */
110 - if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
111 + if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
112 REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
113 ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
114 20 * AH_WAIT_TIMEOUT);
115 - REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
116 }
117
118 + if (!AR_SREV_9100(ah))
119 + ath9k_hw_external_reset(ah, type);
120 +
121 + if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
122 + REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
123 +
124 REG_WRITE(ah, AR_RTC_RC, rst_flags);
125
126 REGWRITE_BUFFER_FLUSH(ah);