1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2008-2011 Atheros Communications Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission to use, copy, modify, and/or distribute this software for any
5*4882a593Smuzhiyun * purpose with or without fee is hereby granted, provided that the above
6*4882a593Smuzhiyun * copyright notice and this permission notice appear in all copies.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*4882a593Smuzhiyun * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*4882a593Smuzhiyun * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*4882a593Smuzhiyun * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*4882a593Smuzhiyun * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*4882a593Smuzhiyun * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/time.h>
21*4882a593Smuzhiyun #include <linux/bitops.h>
22*4882a593Smuzhiyun #include <linux/etherdevice.h>
23*4882a593Smuzhiyun #include <linux/gpio.h>
24*4882a593Smuzhiyun #include <asm/unaligned.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "hw.h"
27*4882a593Smuzhiyun #include "hw-ops.h"
28*4882a593Smuzhiyun #include "ar9003_mac.h"
29*4882a593Smuzhiyun #include "ar9003_mci.h"
30*4882a593Smuzhiyun #include "ar9003_phy.h"
31*4882a593Smuzhiyun #include "ath9k.h"
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun MODULE_AUTHOR("Atheros Communications");
36*4882a593Smuzhiyun MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
37*4882a593Smuzhiyun MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
38*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
39*4882a593Smuzhiyun
ath9k_hw_set_clockrate(struct ath_hw * ah)40*4882a593Smuzhiyun static void ath9k_hw_set_clockrate(struct ath_hw *ah)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
43*4882a593Smuzhiyun struct ath9k_channel *chan = ah->curchan;
44*4882a593Smuzhiyun unsigned int clockrate;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
47*4882a593Smuzhiyun if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
48*4882a593Smuzhiyun clockrate = 117;
49*4882a593Smuzhiyun else if (!chan) /* should really check for CCK instead */
50*4882a593Smuzhiyun clockrate = ATH9K_CLOCK_RATE_CCK;
51*4882a593Smuzhiyun else if (IS_CHAN_2GHZ(chan))
52*4882a593Smuzhiyun clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
53*4882a593Smuzhiyun else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
54*4882a593Smuzhiyun clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
55*4882a593Smuzhiyun else
56*4882a593Smuzhiyun clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun if (chan) {
59*4882a593Smuzhiyun if (IS_CHAN_HT40(chan))
60*4882a593Smuzhiyun clockrate *= 2;
61*4882a593Smuzhiyun if (IS_CHAN_HALF_RATE(chan))
62*4882a593Smuzhiyun clockrate /= 2;
63*4882a593Smuzhiyun if (IS_CHAN_QUARTER_RATE(chan))
64*4882a593Smuzhiyun clockrate /= 4;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun common->clockrate = clockrate;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
ath9k_hw_mac_to_clks(struct ath_hw * ah,u32 usecs)70*4882a593Smuzhiyun static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun return usecs * common->clockrate;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
ath9k_hw_wait(struct ath_hw * ah,u32 reg,u32 mask,u32 val,u32 timeout)77*4882a593Smuzhiyun bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun int i;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun BUG_ON(timeout < AH_TIME_QUANTUM);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
84*4882a593Smuzhiyun if ((REG_READ(ah, reg) & mask) == val)
85*4882a593Smuzhiyun return true;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun udelay(AH_TIME_QUANTUM);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), ANY,
91*4882a593Smuzhiyun "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
92*4882a593Smuzhiyun timeout, reg, REG_READ(ah, reg), mask, val);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return false;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_wait);
97*4882a593Smuzhiyun
ath9k_hw_synth_delay(struct ath_hw * ah,struct ath9k_channel * chan,int hw_delay)98*4882a593Smuzhiyun void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan,
99*4882a593Smuzhiyun int hw_delay)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun hw_delay /= 10;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (IS_CHAN_HALF_RATE(chan))
104*4882a593Smuzhiyun hw_delay *= 2;
105*4882a593Smuzhiyun else if (IS_CHAN_QUARTER_RATE(chan))
106*4882a593Smuzhiyun hw_delay *= 4;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun udelay(hw_delay + BASE_ACTIVATE_DELAY);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
ath9k_hw_write_array(struct ath_hw * ah,const struct ar5416IniArray * array,int column,unsigned int * writecnt)111*4882a593Smuzhiyun void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array,
112*4882a593Smuzhiyun int column, unsigned int *writecnt)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun int r;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
117*4882a593Smuzhiyun for (r = 0; r < array->ia_rows; r++) {
118*4882a593Smuzhiyun REG_WRITE(ah, INI_RA(array, r, 0),
119*4882a593Smuzhiyun INI_RA(array, r, column));
120*4882a593Smuzhiyun DO_DELAY(*writecnt);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
ath9k_hw_read_array(struct ath_hw * ah,u32 array[][2],int size)125*4882a593Smuzhiyun void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun u32 *tmp_reg_list, *tmp_data;
128*4882a593Smuzhiyun int i;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun tmp_reg_list = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
131*4882a593Smuzhiyun if (!tmp_reg_list) {
132*4882a593Smuzhiyun dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__);
133*4882a593Smuzhiyun return;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun tmp_data = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
137*4882a593Smuzhiyun if (!tmp_data) {
138*4882a593Smuzhiyun dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__);
139*4882a593Smuzhiyun goto error_tmp_data;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun for (i = 0; i < size; i++)
143*4882a593Smuzhiyun tmp_reg_list[i] = array[i][0];
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun for (i = 0; i < size; i++)
148*4882a593Smuzhiyun array[i][1] = tmp_data[i];
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun kfree(tmp_data);
151*4882a593Smuzhiyun error_tmp_data:
152*4882a593Smuzhiyun kfree(tmp_reg_list);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
ath9k_hw_reverse_bits(u32 val,u32 n)155*4882a593Smuzhiyun u32 ath9k_hw_reverse_bits(u32 val, u32 n)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun u32 retval;
158*4882a593Smuzhiyun int i;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun for (i = 0, retval = 0; i < n; i++) {
161*4882a593Smuzhiyun retval = (retval << 1) | (val & 1);
162*4882a593Smuzhiyun val >>= 1;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun return retval;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
ath9k_hw_computetxtime(struct ath_hw * ah,u8 phy,int kbps,u32 frameLen,u16 rateix,bool shortPreamble)167*4882a593Smuzhiyun u16 ath9k_hw_computetxtime(struct ath_hw *ah,
168*4882a593Smuzhiyun u8 phy, int kbps,
169*4882a593Smuzhiyun u32 frameLen, u16 rateix,
170*4882a593Smuzhiyun bool shortPreamble)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (kbps == 0)
175*4882a593Smuzhiyun return 0;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun switch (phy) {
178*4882a593Smuzhiyun case WLAN_RC_PHY_CCK:
179*4882a593Smuzhiyun phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
180*4882a593Smuzhiyun if (shortPreamble)
181*4882a593Smuzhiyun phyTime >>= 1;
182*4882a593Smuzhiyun numBits = frameLen << 3;
183*4882a593Smuzhiyun txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
184*4882a593Smuzhiyun break;
185*4882a593Smuzhiyun case WLAN_RC_PHY_OFDM:
186*4882a593Smuzhiyun if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
187*4882a593Smuzhiyun bitsPerSymbol =
188*4882a593Smuzhiyun ((kbps >> 2) * OFDM_SYMBOL_TIME_QUARTER) / 1000;
189*4882a593Smuzhiyun numBits = OFDM_PLCP_BITS + (frameLen << 3);
190*4882a593Smuzhiyun numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
191*4882a593Smuzhiyun txTime = OFDM_SIFS_TIME_QUARTER
192*4882a593Smuzhiyun + OFDM_PREAMBLE_TIME_QUARTER
193*4882a593Smuzhiyun + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
194*4882a593Smuzhiyun } else if (ah->curchan &&
195*4882a593Smuzhiyun IS_CHAN_HALF_RATE(ah->curchan)) {
196*4882a593Smuzhiyun bitsPerSymbol =
197*4882a593Smuzhiyun ((kbps >> 1) * OFDM_SYMBOL_TIME_HALF) / 1000;
198*4882a593Smuzhiyun numBits = OFDM_PLCP_BITS + (frameLen << 3);
199*4882a593Smuzhiyun numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
200*4882a593Smuzhiyun txTime = OFDM_SIFS_TIME_HALF +
201*4882a593Smuzhiyun OFDM_PREAMBLE_TIME_HALF
202*4882a593Smuzhiyun + (numSymbols * OFDM_SYMBOL_TIME_HALF);
203*4882a593Smuzhiyun } else {
204*4882a593Smuzhiyun bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
205*4882a593Smuzhiyun numBits = OFDM_PLCP_BITS + (frameLen << 3);
206*4882a593Smuzhiyun numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
207*4882a593Smuzhiyun txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
208*4882a593Smuzhiyun + (numSymbols * OFDM_SYMBOL_TIME);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun break;
211*4882a593Smuzhiyun default:
212*4882a593Smuzhiyun ath_err(ath9k_hw_common(ah),
213*4882a593Smuzhiyun "Unknown phy %u (rate ix %u)\n", phy, rateix);
214*4882a593Smuzhiyun txTime = 0;
215*4882a593Smuzhiyun break;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun return txTime;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_computetxtime);
221*4882a593Smuzhiyun
ath9k_hw_get_channel_centers(struct ath_hw * ah,struct ath9k_channel * chan,struct chan_centers * centers)222*4882a593Smuzhiyun void ath9k_hw_get_channel_centers(struct ath_hw *ah,
223*4882a593Smuzhiyun struct ath9k_channel *chan,
224*4882a593Smuzhiyun struct chan_centers *centers)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun int8_t extoff;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (!IS_CHAN_HT40(chan)) {
229*4882a593Smuzhiyun centers->ctl_center = centers->ext_center =
230*4882a593Smuzhiyun centers->synth_center = chan->channel;
231*4882a593Smuzhiyun return;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (IS_CHAN_HT40PLUS(chan)) {
235*4882a593Smuzhiyun centers->synth_center =
236*4882a593Smuzhiyun chan->channel + HT40_CHANNEL_CENTER_SHIFT;
237*4882a593Smuzhiyun extoff = 1;
238*4882a593Smuzhiyun } else {
239*4882a593Smuzhiyun centers->synth_center =
240*4882a593Smuzhiyun chan->channel - HT40_CHANNEL_CENTER_SHIFT;
241*4882a593Smuzhiyun extoff = -1;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun centers->ctl_center =
245*4882a593Smuzhiyun centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
246*4882a593Smuzhiyun /* 25 MHz spacing is supported by hw but not on upper layers */
247*4882a593Smuzhiyun centers->ext_center =
248*4882a593Smuzhiyun centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /******************/
252*4882a593Smuzhiyun /* Chip Revisions */
253*4882a593Smuzhiyun /******************/
254*4882a593Smuzhiyun
ath9k_hw_read_revisions(struct ath_hw * ah)255*4882a593Smuzhiyun static bool ath9k_hw_read_revisions(struct ath_hw *ah)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun u32 srev;
258*4882a593Smuzhiyun u32 val;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (ah->get_mac_revision)
261*4882a593Smuzhiyun ah->hw_version.macRev = ah->get_mac_revision();
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun switch (ah->hw_version.devid) {
264*4882a593Smuzhiyun case AR5416_AR9100_DEVID:
265*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9100;
266*4882a593Smuzhiyun break;
267*4882a593Smuzhiyun case AR9300_DEVID_AR9330:
268*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9330;
269*4882a593Smuzhiyun if (!ah->get_mac_revision) {
270*4882a593Smuzhiyun val = REG_READ(ah, AR_SREV);
271*4882a593Smuzhiyun ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun return true;
274*4882a593Smuzhiyun case AR9300_DEVID_AR9340:
275*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9340;
276*4882a593Smuzhiyun return true;
277*4882a593Smuzhiyun case AR9300_DEVID_QCA955X:
278*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9550;
279*4882a593Smuzhiyun return true;
280*4882a593Smuzhiyun case AR9300_DEVID_AR953X:
281*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9531;
282*4882a593Smuzhiyun return true;
283*4882a593Smuzhiyun case AR9300_DEVID_QCA956X:
284*4882a593Smuzhiyun ah->hw_version.macVersion = AR_SREV_VERSION_9561;
285*4882a593Smuzhiyun return true;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun srev = REG_READ(ah, AR_SREV);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (srev == -1) {
291*4882a593Smuzhiyun ath_err(ath9k_hw_common(ah),
292*4882a593Smuzhiyun "Failed to read SREV register");
293*4882a593Smuzhiyun return false;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun val = srev & AR_SREV_ID;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (val == 0xFF) {
299*4882a593Smuzhiyun val = srev;
300*4882a593Smuzhiyun ah->hw_version.macVersion =
301*4882a593Smuzhiyun (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
302*4882a593Smuzhiyun ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
305*4882a593Smuzhiyun ah->is_pciexpress = true;
306*4882a593Smuzhiyun else
307*4882a593Smuzhiyun ah->is_pciexpress = (val &
308*4882a593Smuzhiyun AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
309*4882a593Smuzhiyun } else {
310*4882a593Smuzhiyun if (!AR_SREV_9100(ah))
311*4882a593Smuzhiyun ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun ah->hw_version.macRev = val & AR_SREV_REVISION;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
316*4882a593Smuzhiyun ah->is_pciexpress = true;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun return true;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun /************************************/
323*4882a593Smuzhiyun /* HW Attach, Detach, Init Routines */
324*4882a593Smuzhiyun /************************************/
325*4882a593Smuzhiyun
ath9k_hw_disablepcie(struct ath_hw * ah)326*4882a593Smuzhiyun static void ath9k_hw_disablepcie(struct ath_hw *ah)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun if (!AR_SREV_5416(ah))
329*4882a593Smuzhiyun return;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
332*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
333*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
334*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
335*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
336*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
337*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
338*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
339*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* This should work for all families including legacy */
ath9k_hw_chip_test(struct ath_hw * ah)345*4882a593Smuzhiyun static bool ath9k_hw_chip_test(struct ath_hw *ah)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
348*4882a593Smuzhiyun u32 regAddr[2] = { AR_STA_ID0 };
349*4882a593Smuzhiyun u32 regHold[2];
350*4882a593Smuzhiyun static const u32 patternData[4] = {
351*4882a593Smuzhiyun 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
352*4882a593Smuzhiyun };
353*4882a593Smuzhiyun int i, j, loop_max;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah)) {
356*4882a593Smuzhiyun loop_max = 2;
357*4882a593Smuzhiyun regAddr[1] = AR_PHY_BASE + (8 << 2);
358*4882a593Smuzhiyun } else
359*4882a593Smuzhiyun loop_max = 1;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun for (i = 0; i < loop_max; i++) {
362*4882a593Smuzhiyun u32 addr = regAddr[i];
363*4882a593Smuzhiyun u32 wrData, rdData;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun regHold[i] = REG_READ(ah, addr);
366*4882a593Smuzhiyun for (j = 0; j < 0x100; j++) {
367*4882a593Smuzhiyun wrData = (j << 16) | j;
368*4882a593Smuzhiyun REG_WRITE(ah, addr, wrData);
369*4882a593Smuzhiyun rdData = REG_READ(ah, addr);
370*4882a593Smuzhiyun if (rdData != wrData) {
371*4882a593Smuzhiyun ath_err(common,
372*4882a593Smuzhiyun "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
373*4882a593Smuzhiyun addr, wrData, rdData);
374*4882a593Smuzhiyun return false;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
378*4882a593Smuzhiyun wrData = patternData[j];
379*4882a593Smuzhiyun REG_WRITE(ah, addr, wrData);
380*4882a593Smuzhiyun rdData = REG_READ(ah, addr);
381*4882a593Smuzhiyun if (wrData != rdData) {
382*4882a593Smuzhiyun ath_err(common,
383*4882a593Smuzhiyun "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
384*4882a593Smuzhiyun addr, wrData, rdData);
385*4882a593Smuzhiyun return false;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun REG_WRITE(ah, regAddr[i], regHold[i]);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun udelay(100);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun return true;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
ath9k_hw_init_config(struct ath_hw * ah)395*4882a593Smuzhiyun static void ath9k_hw_init_config(struct ath_hw *ah)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun ah->config.dma_beacon_response_time = 1;
400*4882a593Smuzhiyun ah->config.sw_beacon_response_time = 6;
401*4882a593Smuzhiyun ah->config.cwm_ignore_extcca = false;
402*4882a593Smuzhiyun ah->config.analog_shiftreg = 1;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun ah->config.rx_intr_mitigation = true;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
407*4882a593Smuzhiyun ah->config.rimt_last = 500;
408*4882a593Smuzhiyun ah->config.rimt_first = 2000;
409*4882a593Smuzhiyun } else {
410*4882a593Smuzhiyun ah->config.rimt_last = 250;
411*4882a593Smuzhiyun ah->config.rimt_first = 700;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
415*4882a593Smuzhiyun ah->config.pll_pwrsave = 7;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun * We need this for PCI devices only (Cardbus, PCI, miniPCI)
419*4882a593Smuzhiyun * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
420*4882a593Smuzhiyun * This means we use it for all AR5416 devices, and the few
421*4882a593Smuzhiyun * minor PCI AR9280 devices out there.
422*4882a593Smuzhiyun *
423*4882a593Smuzhiyun * Serialization is required because these devices do not handle
424*4882a593Smuzhiyun * well the case of two concurrent reads/writes due to the latency
425*4882a593Smuzhiyun * involved. During one read/write another read/write can be issued
426*4882a593Smuzhiyun * on another CPU while the previous read/write may still be working
427*4882a593Smuzhiyun * on our hardware, if we hit this case the hardware poops in a loop.
428*4882a593Smuzhiyun * We prevent this by serializing reads and writes.
429*4882a593Smuzhiyun *
430*4882a593Smuzhiyun * This issue is not present on PCI-Express devices or pre-AR5416
431*4882a593Smuzhiyun * devices (legacy, 802.11abg).
432*4882a593Smuzhiyun */
433*4882a593Smuzhiyun if (num_possible_cpus() > 1)
434*4882a593Smuzhiyun ah->config.serialize_regmode = SER_REG_MODE_AUTO;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
437*4882a593Smuzhiyun if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
438*4882a593Smuzhiyun ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) &&
439*4882a593Smuzhiyun !ah->is_pciexpress)) {
440*4882a593Smuzhiyun ah->config.serialize_regmode = SER_REG_MODE_ON;
441*4882a593Smuzhiyun } else {
442*4882a593Smuzhiyun ah->config.serialize_regmode = SER_REG_MODE_OFF;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun ath_dbg(common, RESET, "serialize_regmode is %d\n",
447*4882a593Smuzhiyun ah->config.serialize_regmode);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
450*4882a593Smuzhiyun ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
451*4882a593Smuzhiyun else
452*4882a593Smuzhiyun ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
ath9k_hw_init_defaults(struct ath_hw * ah)455*4882a593Smuzhiyun static void ath9k_hw_init_defaults(struct ath_hw *ah)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun regulatory->country_code = CTRY_DEFAULT;
460*4882a593Smuzhiyun regulatory->power_limit = MAX_COMBINED_POWER;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun ah->hw_version.magic = AR5416_MAGIC;
463*4882a593Smuzhiyun ah->hw_version.subvendorid = 0;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE |
466*4882a593Smuzhiyun AR_STA_ID1_MCAST_KSRCH;
467*4882a593Smuzhiyun if (AR_SREV_9100(ah))
468*4882a593Smuzhiyun ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun ah->slottime = 9;
471*4882a593Smuzhiyun ah->globaltxtimeout = (u32) -1;
472*4882a593Smuzhiyun ah->power_mode = ATH9K_PM_UNDEFINED;
473*4882a593Smuzhiyun ah->htc_reset_init = true;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun ah->tpc_enabled = false;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun ah->ani_function = ATH9K_ANI_ALL;
478*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
479*4882a593Smuzhiyun ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
482*4882a593Smuzhiyun ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
483*4882a593Smuzhiyun else
484*4882a593Smuzhiyun ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
ath9k_hw_init_macaddr(struct ath_hw * ah)487*4882a593Smuzhiyun static void ath9k_hw_init_macaddr(struct ath_hw *ah)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
490*4882a593Smuzhiyun int i;
491*4882a593Smuzhiyun u16 eeval;
492*4882a593Smuzhiyun static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /* MAC address may already be loaded via ath9k_platform_data */
495*4882a593Smuzhiyun if (is_valid_ether_addr(common->macaddr))
496*4882a593Smuzhiyun return;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
499*4882a593Smuzhiyun eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
500*4882a593Smuzhiyun common->macaddr[2 * i] = eeval >> 8;
501*4882a593Smuzhiyun common->macaddr[2 * i + 1] = eeval & 0xff;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun if (is_valid_ether_addr(common->macaddr))
505*4882a593Smuzhiyun return;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun ath_err(common, "eeprom contains invalid mac address: %pM\n",
508*4882a593Smuzhiyun common->macaddr);
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun eth_random_addr(common->macaddr);
511*4882a593Smuzhiyun ath_err(common, "random mac address will be used: %pM\n",
512*4882a593Smuzhiyun common->macaddr);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun return;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
ath9k_hw_post_init(struct ath_hw * ah)517*4882a593Smuzhiyun static int ath9k_hw_post_init(struct ath_hw *ah)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
520*4882a593Smuzhiyun int ecode;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun if (common->bus_ops->ath_bus_type != ATH_USB) {
523*4882a593Smuzhiyun if (!ath9k_hw_chip_test(ah))
524*4882a593Smuzhiyun return -ENODEV;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah)) {
528*4882a593Smuzhiyun ecode = ar9002_hw_rf_claim(ah);
529*4882a593Smuzhiyun if (ecode != 0)
530*4882a593Smuzhiyun return ecode;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun ecode = ath9k_hw_eeprom_init(ah);
534*4882a593Smuzhiyun if (ecode != 0)
535*4882a593Smuzhiyun return ecode;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), CONFIG, "Eeprom VER: %d, REV: %d\n",
538*4882a593Smuzhiyun ah->eep_ops->get_eeprom_ver(ah),
539*4882a593Smuzhiyun ah->eep_ops->get_eeprom_rev(ah));
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun ath9k_hw_ani_init(ah);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun /*
544*4882a593Smuzhiyun * EEPROM needs to be initialized before we do this.
545*4882a593Smuzhiyun * This is required for regulatory compliance.
546*4882a593Smuzhiyun */
547*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
548*4882a593Smuzhiyun u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
549*4882a593Smuzhiyun if ((regdmn & 0xF0) == CTL_FCC) {
550*4882a593Smuzhiyun ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ;
551*4882a593Smuzhiyun ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun return 0;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
ath9k_hw_attach_ops(struct ath_hw * ah)558*4882a593Smuzhiyun static int ath9k_hw_attach_ops(struct ath_hw *ah)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
561*4882a593Smuzhiyun return ar9002_hw_attach_ops(ah);
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun ar9003_hw_attach_ops(ah);
564*4882a593Smuzhiyun return 0;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* Called for all hardware families */
__ath9k_hw_init(struct ath_hw * ah)568*4882a593Smuzhiyun static int __ath9k_hw_init(struct ath_hw *ah)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
571*4882a593Smuzhiyun int r = 0;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun if (!ath9k_hw_read_revisions(ah)) {
574*4882a593Smuzhiyun ath_err(common, "Could not read hardware revisions");
575*4882a593Smuzhiyun return -EOPNOTSUPP;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun switch (ah->hw_version.macVersion) {
579*4882a593Smuzhiyun case AR_SREV_VERSION_5416_PCI:
580*4882a593Smuzhiyun case AR_SREV_VERSION_5416_PCIE:
581*4882a593Smuzhiyun case AR_SREV_VERSION_9160:
582*4882a593Smuzhiyun case AR_SREV_VERSION_9100:
583*4882a593Smuzhiyun case AR_SREV_VERSION_9280:
584*4882a593Smuzhiyun case AR_SREV_VERSION_9285:
585*4882a593Smuzhiyun case AR_SREV_VERSION_9287:
586*4882a593Smuzhiyun case AR_SREV_VERSION_9271:
587*4882a593Smuzhiyun case AR_SREV_VERSION_9300:
588*4882a593Smuzhiyun case AR_SREV_VERSION_9330:
589*4882a593Smuzhiyun case AR_SREV_VERSION_9485:
590*4882a593Smuzhiyun case AR_SREV_VERSION_9340:
591*4882a593Smuzhiyun case AR_SREV_VERSION_9462:
592*4882a593Smuzhiyun case AR_SREV_VERSION_9550:
593*4882a593Smuzhiyun case AR_SREV_VERSION_9565:
594*4882a593Smuzhiyun case AR_SREV_VERSION_9531:
595*4882a593Smuzhiyun case AR_SREV_VERSION_9561:
596*4882a593Smuzhiyun break;
597*4882a593Smuzhiyun default:
598*4882a593Smuzhiyun ath_err(common,
599*4882a593Smuzhiyun "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
600*4882a593Smuzhiyun ah->hw_version.macVersion, ah->hw_version.macRev);
601*4882a593Smuzhiyun return -EOPNOTSUPP;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun /*
605*4882a593Smuzhiyun * Read back AR_WA into a permanent copy and set bits 14 and 17.
606*4882a593Smuzhiyun * We need to do this to avoid RMW of this register. We cannot
607*4882a593Smuzhiyun * read the reg when chip is asleep.
608*4882a593Smuzhiyun */
609*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
610*4882a593Smuzhiyun ah->WARegVal = REG_READ(ah, AR_WA);
611*4882a593Smuzhiyun ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
612*4882a593Smuzhiyun AR_WA_ASPM_TIMER_BASED_DISABLE);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
616*4882a593Smuzhiyun ath_err(common, "Couldn't reset chip\n");
617*4882a593Smuzhiyun return -EIO;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (AR_SREV_9565(ah)) {
621*4882a593Smuzhiyun ah->WARegVal |= AR_WA_BIT22;
622*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal);
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun ath9k_hw_init_defaults(ah);
626*4882a593Smuzhiyun ath9k_hw_init_config(ah);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun r = ath9k_hw_attach_ops(ah);
629*4882a593Smuzhiyun if (r)
630*4882a593Smuzhiyun return r;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
633*4882a593Smuzhiyun ath_err(common, "Couldn't wakeup chip\n");
634*4882a593Smuzhiyun return -EIO;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
638*4882a593Smuzhiyun AR_SREV_9330(ah) || AR_SREV_9550(ah))
639*4882a593Smuzhiyun ah->is_pciexpress = false;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
642*4882a593Smuzhiyun ath9k_hw_init_cal_settings(ah);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (!ah->is_pciexpress)
645*4882a593Smuzhiyun ath9k_hw_disablepcie(ah);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun r = ath9k_hw_post_init(ah);
648*4882a593Smuzhiyun if (r)
649*4882a593Smuzhiyun return r;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun ath9k_hw_init_mode_gain_regs(ah);
652*4882a593Smuzhiyun r = ath9k_hw_fill_cap_info(ah);
653*4882a593Smuzhiyun if (r)
654*4882a593Smuzhiyun return r;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun ath9k_hw_init_macaddr(ah);
657*4882a593Smuzhiyun ath9k_hw_init_hang_checks(ah);
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun common->state = ATH_HW_INITIALIZED;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun return 0;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
ath9k_hw_init(struct ath_hw * ah)664*4882a593Smuzhiyun int ath9k_hw_init(struct ath_hw *ah)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun int ret;
667*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
670*4882a593Smuzhiyun switch (ah->hw_version.devid) {
671*4882a593Smuzhiyun case AR5416_DEVID_PCI:
672*4882a593Smuzhiyun case AR5416_DEVID_PCIE:
673*4882a593Smuzhiyun case AR5416_AR9100_DEVID:
674*4882a593Smuzhiyun case AR9160_DEVID_PCI:
675*4882a593Smuzhiyun case AR9280_DEVID_PCI:
676*4882a593Smuzhiyun case AR9280_DEVID_PCIE:
677*4882a593Smuzhiyun case AR9285_DEVID_PCIE:
678*4882a593Smuzhiyun case AR9287_DEVID_PCI:
679*4882a593Smuzhiyun case AR9287_DEVID_PCIE:
680*4882a593Smuzhiyun case AR2427_DEVID_PCIE:
681*4882a593Smuzhiyun case AR9300_DEVID_PCIE:
682*4882a593Smuzhiyun case AR9300_DEVID_AR9485_PCIE:
683*4882a593Smuzhiyun case AR9300_DEVID_AR9330:
684*4882a593Smuzhiyun case AR9300_DEVID_AR9340:
685*4882a593Smuzhiyun case AR9300_DEVID_QCA955X:
686*4882a593Smuzhiyun case AR9300_DEVID_AR9580:
687*4882a593Smuzhiyun case AR9300_DEVID_AR9462:
688*4882a593Smuzhiyun case AR9485_DEVID_AR1111:
689*4882a593Smuzhiyun case AR9300_DEVID_AR9565:
690*4882a593Smuzhiyun case AR9300_DEVID_AR953X:
691*4882a593Smuzhiyun case AR9300_DEVID_QCA956X:
692*4882a593Smuzhiyun break;
693*4882a593Smuzhiyun default:
694*4882a593Smuzhiyun if (common->bus_ops->ath_bus_type == ATH_USB)
695*4882a593Smuzhiyun break;
696*4882a593Smuzhiyun ath_err(common, "Hardware device ID 0x%04x not supported\n",
697*4882a593Smuzhiyun ah->hw_version.devid);
698*4882a593Smuzhiyun return -EOPNOTSUPP;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun ret = __ath9k_hw_init(ah);
702*4882a593Smuzhiyun if (ret) {
703*4882a593Smuzhiyun ath_err(common,
704*4882a593Smuzhiyun "Unable to initialize hardware; initialization status: %d\n",
705*4882a593Smuzhiyun ret);
706*4882a593Smuzhiyun return ret;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun ath_dynack_init(ah);
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun return 0;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_init);
714*4882a593Smuzhiyun
ath9k_hw_init_qos(struct ath_hw * ah)715*4882a593Smuzhiyun static void ath9k_hw_init_qos(struct ath_hw *ah)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
720*4882a593Smuzhiyun REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun REG_WRITE(ah, AR_QOS_NO_ACK,
723*4882a593Smuzhiyun SM(2, AR_QOS_NO_ACK_TWO_BIT) |
724*4882a593Smuzhiyun SM(5, AR_QOS_NO_ACK_BIT_OFF) |
725*4882a593Smuzhiyun SM(0, AR_QOS_NO_ACK_BYTE_OFF));
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
728*4882a593Smuzhiyun REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
729*4882a593Smuzhiyun REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
730*4882a593Smuzhiyun REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
731*4882a593Smuzhiyun REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
ar9003_get_pll_sqsum_dvc(struct ath_hw * ah)736*4882a593Smuzhiyun u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
739*4882a593Smuzhiyun int i = 0;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
742*4882a593Smuzhiyun udelay(100);
743*4882a593Smuzhiyun REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) {
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun udelay(100);
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun if (WARN_ON_ONCE(i >= 100)) {
750*4882a593Smuzhiyun ath_err(common, "PLL4 measurement not done\n");
751*4882a593Smuzhiyun break;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun i++;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
760*4882a593Smuzhiyun
ath9k_hw_init_pll(struct ath_hw * ah,struct ath9k_channel * chan)761*4882a593Smuzhiyun static void ath9k_hw_init_pll(struct ath_hw *ah,
762*4882a593Smuzhiyun struct ath9k_channel *chan)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun u32 pll;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun pll = ath9k_hw_compute_pll_control(ah, chan);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
769*4882a593Smuzhiyun /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
770*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
771*4882a593Smuzhiyun AR_CH0_BB_DPLL2_PLL_PWD, 0x1);
772*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
773*4882a593Smuzhiyun AR_CH0_DPLL2_KD, 0x40);
774*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
775*4882a593Smuzhiyun AR_CH0_DPLL2_KI, 0x4);
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
778*4882a593Smuzhiyun AR_CH0_BB_DPLL1_REFDIV, 0x5);
779*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
780*4882a593Smuzhiyun AR_CH0_BB_DPLL1_NINI, 0x58);
781*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
782*4882a593Smuzhiyun AR_CH0_BB_DPLL1_NFRAC, 0x0);
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
785*4882a593Smuzhiyun AR_CH0_BB_DPLL2_OUTDIV, 0x1);
786*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
787*4882a593Smuzhiyun AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1);
788*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
789*4882a593Smuzhiyun AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1);
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun /* program BB PLL phase_shift to 0x6 */
792*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
793*4882a593Smuzhiyun AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6);
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
796*4882a593Smuzhiyun AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
797*4882a593Smuzhiyun udelay(1000);
798*4882a593Smuzhiyun } else if (AR_SREV_9330(ah)) {
799*4882a593Smuzhiyun u32 ddr_dpll2, pll_control2, kd;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun if (ah->is_clk_25mhz) {
802*4882a593Smuzhiyun ddr_dpll2 = 0x18e82f01;
803*4882a593Smuzhiyun pll_control2 = 0xe04a3d;
804*4882a593Smuzhiyun kd = 0x1d;
805*4882a593Smuzhiyun } else {
806*4882a593Smuzhiyun ddr_dpll2 = 0x19e82f01;
807*4882a593Smuzhiyun pll_control2 = 0x886666;
808*4882a593Smuzhiyun kd = 0x3d;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun /* program DDR PLL ki and kd value */
812*4882a593Smuzhiyun REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun /* program DDR PLL phase_shift */
815*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
816*4882a593Smuzhiyun AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_PLL_CONTROL,
819*4882a593Smuzhiyun pll | AR_RTC_9300_PLL_BYPASS);
820*4882a593Smuzhiyun udelay(1000);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun /* program refdiv, nint, frac to RTC register */
823*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun /* program BB PLL kd and ki value */
826*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
827*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun /* program BB PLL phase_shift */
830*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
831*4882a593Smuzhiyun AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
832*4882a593Smuzhiyun } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
833*4882a593Smuzhiyun AR_SREV_9561(ah)) {
834*4882a593Smuzhiyun u32 regval, pll2_divint, pll2_divfrac, refdiv;
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_PLL_CONTROL,
837*4882a593Smuzhiyun pll | AR_RTC_9300_SOC_PLL_BYPASS);
838*4882a593Smuzhiyun udelay(1000);
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16);
841*4882a593Smuzhiyun udelay(100);
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun if (ah->is_clk_25mhz) {
844*4882a593Smuzhiyun if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
845*4882a593Smuzhiyun pll2_divint = 0x1c;
846*4882a593Smuzhiyun pll2_divfrac = 0xa3d2;
847*4882a593Smuzhiyun refdiv = 1;
848*4882a593Smuzhiyun } else {
849*4882a593Smuzhiyun pll2_divint = 0x54;
850*4882a593Smuzhiyun pll2_divfrac = 0x1eb85;
851*4882a593Smuzhiyun refdiv = 3;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun } else {
854*4882a593Smuzhiyun if (AR_SREV_9340(ah)) {
855*4882a593Smuzhiyun pll2_divint = 88;
856*4882a593Smuzhiyun pll2_divfrac = 0;
857*4882a593Smuzhiyun refdiv = 5;
858*4882a593Smuzhiyun } else {
859*4882a593Smuzhiyun pll2_divint = 0x11;
860*4882a593Smuzhiyun pll2_divfrac = (AR_SREV_9531(ah) ||
861*4882a593Smuzhiyun AR_SREV_9561(ah)) ?
862*4882a593Smuzhiyun 0x26665 : 0x26666;
863*4882a593Smuzhiyun refdiv = 1;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun regval = REG_READ(ah, AR_PHY_PLL_MODE);
868*4882a593Smuzhiyun if (AR_SREV_9531(ah) || AR_SREV_9561(ah))
869*4882a593Smuzhiyun regval |= (0x1 << 22);
870*4882a593Smuzhiyun else
871*4882a593Smuzhiyun regval |= (0x1 << 16);
872*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
873*4882a593Smuzhiyun udelay(100);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) |
876*4882a593Smuzhiyun (pll2_divint << 18) | pll2_divfrac);
877*4882a593Smuzhiyun udelay(100);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun regval = REG_READ(ah, AR_PHY_PLL_MODE);
880*4882a593Smuzhiyun if (AR_SREV_9340(ah))
881*4882a593Smuzhiyun regval = (regval & 0x80071fff) |
882*4882a593Smuzhiyun (0x1 << 30) |
883*4882a593Smuzhiyun (0x1 << 13) |
884*4882a593Smuzhiyun (0x4 << 26) |
885*4882a593Smuzhiyun (0x18 << 19);
886*4882a593Smuzhiyun else if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
887*4882a593Smuzhiyun regval = (regval & 0x01c00fff) |
888*4882a593Smuzhiyun (0x1 << 31) |
889*4882a593Smuzhiyun (0x2 << 29) |
890*4882a593Smuzhiyun (0xa << 25) |
891*4882a593Smuzhiyun (0x1 << 19);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun if (AR_SREV_9531(ah))
894*4882a593Smuzhiyun regval |= (0x6 << 12);
895*4882a593Smuzhiyun } else
896*4882a593Smuzhiyun regval = (regval & 0x80071fff) |
897*4882a593Smuzhiyun (0x3 << 30) |
898*4882a593Smuzhiyun (0x1 << 13) |
899*4882a593Smuzhiyun (0x4 << 26) |
900*4882a593Smuzhiyun (0x60 << 19);
901*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (AR_SREV_9531(ah) || AR_SREV_9561(ah))
904*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_PLL_MODE,
905*4882a593Smuzhiyun REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff);
906*4882a593Smuzhiyun else
907*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_PLL_MODE,
908*4882a593Smuzhiyun REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun udelay(1000);
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (AR_SREV_9565(ah))
914*4882a593Smuzhiyun pll |= 0x40000;
915*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
918*4882a593Smuzhiyun AR_SREV_9550(ah))
919*4882a593Smuzhiyun udelay(1000);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* Switch the core clock for ar9271 to 117Mhz */
922*4882a593Smuzhiyun if (AR_SREV_9271(ah)) {
923*4882a593Smuzhiyun udelay(500);
924*4882a593Smuzhiyun REG_WRITE(ah, 0x50040, 0x304);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun udelay(RTC_PLL_SETTLE_DELAY);
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
ath9k_hw_init_interrupt_masks(struct ath_hw * ah,enum nl80211_iftype opmode)932*4882a593Smuzhiyun static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
933*4882a593Smuzhiyun enum nl80211_iftype opmode)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun u32 sync_default = AR_INTR_SYNC_DEFAULT;
936*4882a593Smuzhiyun u32 imr_reg = AR_IMR_TXERR |
937*4882a593Smuzhiyun AR_IMR_TXURN |
938*4882a593Smuzhiyun AR_IMR_RXERR |
939*4882a593Smuzhiyun AR_IMR_RXORN |
940*4882a593Smuzhiyun AR_IMR_BCNMISC;
941*4882a593Smuzhiyun u32 msi_cfg = 0;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
944*4882a593Smuzhiyun AR_SREV_9561(ah))
945*4882a593Smuzhiyun sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
948*4882a593Smuzhiyun imr_reg |= AR_IMR_RXOK_HP;
949*4882a593Smuzhiyun if (ah->config.rx_intr_mitigation) {
950*4882a593Smuzhiyun imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
951*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR;
952*4882a593Smuzhiyun } else {
953*4882a593Smuzhiyun imr_reg |= AR_IMR_RXOK_LP;
954*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_RXOK;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun } else {
957*4882a593Smuzhiyun if (ah->config.rx_intr_mitigation) {
958*4882a593Smuzhiyun imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
959*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR;
960*4882a593Smuzhiyun } else {
961*4882a593Smuzhiyun imr_reg |= AR_IMR_RXOK;
962*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_RXOK;
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun if (ah->config.tx_intr_mitigation) {
967*4882a593Smuzhiyun imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
968*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_TXINTM | AR_INTCFG_MSI_TXMINTR;
969*4882a593Smuzhiyun } else {
970*4882a593Smuzhiyun imr_reg |= AR_IMR_TXOK;
971*4882a593Smuzhiyun msi_cfg |= AR_INTCFG_MSI_TXOK;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun REG_WRITE(ah, AR_IMR, imr_reg);
977*4882a593Smuzhiyun ah->imrs2_reg |= AR_IMR_S2_GTT;
978*4882a593Smuzhiyun REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun if (ah->msi_enabled) {
981*4882a593Smuzhiyun ah->msi_reg = REG_READ(ah, AR_PCIE_MSI);
982*4882a593Smuzhiyun ah->msi_reg |= AR_PCIE_MSI_HW_DBI_WR_EN;
983*4882a593Smuzhiyun ah->msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
984*4882a593Smuzhiyun REG_WRITE(ah, AR_INTCFG, msi_cfg);
985*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), ANY,
986*4882a593Smuzhiyun "value of AR_INTCFG=0x%X, msi_cfg=0x%X\n",
987*4882a593Smuzhiyun REG_READ(ah, AR_INTCFG), msi_cfg);
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun if (!AR_SREV_9100(ah)) {
991*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
992*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
993*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
999*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
1000*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0);
1001*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0);
1002*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0);
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun
ath9k_hw_set_sifs_time(struct ath_hw * ah,u32 us)1006*4882a593Smuzhiyun static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
1009*4882a593Smuzhiyun val = min(val, (u32) 0xFFFF);
1010*4882a593Smuzhiyun REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
ath9k_hw_setslottime(struct ath_hw * ah,u32 us)1013*4882a593Smuzhiyun void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun u32 val = ath9k_hw_mac_to_clks(ah, us);
1016*4882a593Smuzhiyun val = min(val, (u32) 0xFFFF);
1017*4882a593Smuzhiyun REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun
ath9k_hw_set_ack_timeout(struct ath_hw * ah,u32 us)1020*4882a593Smuzhiyun void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
1021*4882a593Smuzhiyun {
1022*4882a593Smuzhiyun u32 val = ath9k_hw_mac_to_clks(ah, us);
1023*4882a593Smuzhiyun val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
1024*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
ath9k_hw_set_cts_timeout(struct ath_hw * ah,u32 us)1027*4882a593Smuzhiyun void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun u32 val = ath9k_hw_mac_to_clks(ah, us);
1030*4882a593Smuzhiyun val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
1031*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun
ath9k_hw_set_global_txtimeout(struct ath_hw * ah,u32 tu)1034*4882a593Smuzhiyun static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
1035*4882a593Smuzhiyun {
1036*4882a593Smuzhiyun if (tu > 0xFFFF) {
1037*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), XMIT, "bad global tx timeout %u\n",
1038*4882a593Smuzhiyun tu);
1039*4882a593Smuzhiyun ah->globaltxtimeout = (u32) -1;
1040*4882a593Smuzhiyun return false;
1041*4882a593Smuzhiyun } else {
1042*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
1043*4882a593Smuzhiyun ah->globaltxtimeout = tu;
1044*4882a593Smuzhiyun return true;
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
ath9k_hw_init_global_settings(struct ath_hw * ah)1048*4882a593Smuzhiyun void ath9k_hw_init_global_settings(struct ath_hw *ah)
1049*4882a593Smuzhiyun {
1050*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1051*4882a593Smuzhiyun const struct ath9k_channel *chan = ah->curchan;
1052*4882a593Smuzhiyun int acktimeout, ctstimeout, ack_offset = 0;
1053*4882a593Smuzhiyun int slottime;
1054*4882a593Smuzhiyun int sifstime;
1055*4882a593Smuzhiyun int rx_lat = 0, tx_lat = 0, eifs = 0, ack_shift = 0;
1056*4882a593Smuzhiyun u32 reg;
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n",
1059*4882a593Smuzhiyun ah->misc_mode);
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun if (!chan)
1062*4882a593Smuzhiyun return;
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun if (ah->misc_mode != 0)
1065*4882a593Smuzhiyun REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun if (IS_CHAN_A_FAST_CLOCK(ah, chan))
1068*4882a593Smuzhiyun rx_lat = 41;
1069*4882a593Smuzhiyun else
1070*4882a593Smuzhiyun rx_lat = 37;
1071*4882a593Smuzhiyun tx_lat = 54;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun if (IS_CHAN_5GHZ(chan))
1074*4882a593Smuzhiyun sifstime = 16;
1075*4882a593Smuzhiyun else
1076*4882a593Smuzhiyun sifstime = 10;
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun if (IS_CHAN_HALF_RATE(chan)) {
1079*4882a593Smuzhiyun eifs = 175;
1080*4882a593Smuzhiyun rx_lat *= 2;
1081*4882a593Smuzhiyun tx_lat *= 2;
1082*4882a593Smuzhiyun if (IS_CHAN_A_FAST_CLOCK(ah, chan))
1083*4882a593Smuzhiyun tx_lat += 11;
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun sifstime = 32;
1086*4882a593Smuzhiyun ack_offset = 16;
1087*4882a593Smuzhiyun ack_shift = 3;
1088*4882a593Smuzhiyun slottime = 13;
1089*4882a593Smuzhiyun } else if (IS_CHAN_QUARTER_RATE(chan)) {
1090*4882a593Smuzhiyun eifs = 340;
1091*4882a593Smuzhiyun rx_lat = (rx_lat * 4) - 1;
1092*4882a593Smuzhiyun tx_lat *= 4;
1093*4882a593Smuzhiyun if (IS_CHAN_A_FAST_CLOCK(ah, chan))
1094*4882a593Smuzhiyun tx_lat += 22;
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun sifstime = 64;
1097*4882a593Smuzhiyun ack_offset = 32;
1098*4882a593Smuzhiyun ack_shift = 1;
1099*4882a593Smuzhiyun slottime = 21;
1100*4882a593Smuzhiyun } else {
1101*4882a593Smuzhiyun if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
1102*4882a593Smuzhiyun eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
1103*4882a593Smuzhiyun reg = AR_USEC_ASYNC_FIFO;
1104*4882a593Smuzhiyun } else {
1105*4882a593Smuzhiyun eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
1106*4882a593Smuzhiyun common->clockrate;
1107*4882a593Smuzhiyun reg = REG_READ(ah, AR_USEC);
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun rx_lat = MS(reg, AR_USEC_RX_LAT);
1110*4882a593Smuzhiyun tx_lat = MS(reg, AR_USEC_TX_LAT);
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun slottime = ah->slottime;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun /* As defined by IEEE 802.11-2007 17.3.8.6 */
1116*4882a593Smuzhiyun slottime += 3 * ah->coverage_class;
1117*4882a593Smuzhiyun acktimeout = slottime + sifstime + ack_offset;
1118*4882a593Smuzhiyun ctstimeout = acktimeout;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun /*
1121*4882a593Smuzhiyun * Workaround for early ACK timeouts, add an offset to match the
1122*4882a593Smuzhiyun * initval's 64us ack timeout value. Use 48us for the CTS timeout.
1123*4882a593Smuzhiyun * This was initially only meant to work around an issue with delayed
1124*4882a593Smuzhiyun * BA frames in some implementations, but it has been found to fix ACK
1125*4882a593Smuzhiyun * timeout issues in other cases as well.
1126*4882a593Smuzhiyun */
1127*4882a593Smuzhiyun if (IS_CHAN_2GHZ(chan) &&
1128*4882a593Smuzhiyun !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
1129*4882a593Smuzhiyun acktimeout += 64 - sifstime - ah->slottime;
1130*4882a593Smuzhiyun ctstimeout += 48 - sifstime - ah->slottime;
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun if (ah->dynack.enabled) {
1134*4882a593Smuzhiyun acktimeout = ah->dynack.ackto;
1135*4882a593Smuzhiyun ctstimeout = acktimeout;
1136*4882a593Smuzhiyun slottime = (acktimeout - 3) / 2;
1137*4882a593Smuzhiyun } else {
1138*4882a593Smuzhiyun ah->dynack.ackto = acktimeout;
1139*4882a593Smuzhiyun }
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun ath9k_hw_set_sifs_time(ah, sifstime);
1142*4882a593Smuzhiyun ath9k_hw_setslottime(ah, slottime);
1143*4882a593Smuzhiyun ath9k_hw_set_ack_timeout(ah, acktimeout);
1144*4882a593Smuzhiyun ath9k_hw_set_cts_timeout(ah, ctstimeout);
1145*4882a593Smuzhiyun if (ah->globaltxtimeout != (u32) -1)
1146*4882a593Smuzhiyun ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
1149*4882a593Smuzhiyun REG_RMW(ah, AR_USEC,
1150*4882a593Smuzhiyun (common->clockrate - 1) |
1151*4882a593Smuzhiyun SM(rx_lat, AR_USEC_RX_LAT) |
1152*4882a593Smuzhiyun SM(tx_lat, AR_USEC_TX_LAT),
1153*4882a593Smuzhiyun AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
1156*4882a593Smuzhiyun REG_RMW(ah, AR_TXSIFS,
1157*4882a593Smuzhiyun sifstime | SM(ack_shift, AR_TXSIFS_ACK_SHIFT),
1158*4882a593Smuzhiyun (AR_TXSIFS_TIME | AR_TXSIFS_ACK_SHIFT));
1159*4882a593Smuzhiyun }
1160*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_init_global_settings);
1161*4882a593Smuzhiyun
ath9k_hw_deinit(struct ath_hw * ah)1162*4882a593Smuzhiyun void ath9k_hw_deinit(struct ath_hw *ah)
1163*4882a593Smuzhiyun {
1164*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun if (common->state < ATH_HW_INITIALIZED)
1167*4882a593Smuzhiyun return;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
1170*4882a593Smuzhiyun }
1171*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_deinit);
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun /*******/
1174*4882a593Smuzhiyun /* INI */
1175*4882a593Smuzhiyun /*******/
1176*4882a593Smuzhiyun
ath9k_regd_get_ctl(struct ath_regulatory * reg,struct ath9k_channel * chan)1177*4882a593Smuzhiyun u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
1178*4882a593Smuzhiyun {
1179*4882a593Smuzhiyun u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun if (IS_CHAN_2GHZ(chan))
1182*4882a593Smuzhiyun ctl |= CTL_11G;
1183*4882a593Smuzhiyun else
1184*4882a593Smuzhiyun ctl |= CTL_11A;
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun return ctl;
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun /****************************************/
1190*4882a593Smuzhiyun /* Reset and Channel Switching Routines */
1191*4882a593Smuzhiyun /****************************************/
1192*4882a593Smuzhiyun
ath9k_hw_set_dma(struct ath_hw * ah)1193*4882a593Smuzhiyun static inline void ath9k_hw_set_dma(struct ath_hw *ah)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1196*4882a593Smuzhiyun int txbuf_size;
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun /*
1201*4882a593Smuzhiyun * set AHB_MODE not to do cacheline prefetches
1202*4882a593Smuzhiyun */
1203*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
1204*4882a593Smuzhiyun REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun /*
1207*4882a593Smuzhiyun * let mac dma reads be in 128 byte chunks
1208*4882a593Smuzhiyun */
1209*4882a593Smuzhiyun REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun /*
1214*4882a593Smuzhiyun * Restore TX Trigger Level to its pre-reset value.
1215*4882a593Smuzhiyun * The initial value depends on whether aggregation is enabled, and is
1216*4882a593Smuzhiyun * adjusted whenever underruns are detected.
1217*4882a593Smuzhiyun */
1218*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
1219*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun /*
1224*4882a593Smuzhiyun * let mac dma writes be in 128 byte chunks
1225*4882a593Smuzhiyun */
1226*4882a593Smuzhiyun REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK);
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun /*
1229*4882a593Smuzhiyun * Setup receive FIFO threshold to hold off TX activities
1230*4882a593Smuzhiyun */
1231*4882a593Smuzhiyun REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
1234*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
1235*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
1238*4882a593Smuzhiyun ah->caps.rx_status_len);
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun /*
1242*4882a593Smuzhiyun * reduce the number of usable entries in PCU TXBUF to avoid
1243*4882a593Smuzhiyun * wrap around issues.
1244*4882a593Smuzhiyun */
1245*4882a593Smuzhiyun if (AR_SREV_9285(ah)) {
1246*4882a593Smuzhiyun /* For AR9285 the number of Fifos are reduced to half.
1247*4882a593Smuzhiyun * So set the usable tx buf size also to half to
1248*4882a593Smuzhiyun * avoid data/delimiter underruns
1249*4882a593Smuzhiyun */
1250*4882a593Smuzhiyun txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE;
1251*4882a593Smuzhiyun } else if (AR_SREV_9340_13_OR_LATER(ah)) {
1252*4882a593Smuzhiyun /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */
1253*4882a593Smuzhiyun txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE;
1254*4882a593Smuzhiyun } else {
1255*4882a593Smuzhiyun txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE;
1256*4882a593Smuzhiyun }
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun if (!AR_SREV_9271(ah))
1259*4882a593Smuzhiyun REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size);
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
1264*4882a593Smuzhiyun ath9k_hw_reset_txstatus_ring(ah);
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun
ath9k_hw_set_operating_mode(struct ath_hw * ah,int opmode)1267*4882a593Smuzhiyun static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC;
1270*4882a593Smuzhiyun u32 set = AR_STA_ID1_KSRCH_MODE;
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun ENABLE_REG_RMW_BUFFER(ah);
1273*4882a593Smuzhiyun switch (opmode) {
1274*4882a593Smuzhiyun case NL80211_IFTYPE_ADHOC:
1275*4882a593Smuzhiyun if (!AR_SREV_9340_13(ah)) {
1276*4882a593Smuzhiyun set |= AR_STA_ID1_ADHOC;
1277*4882a593Smuzhiyun REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1278*4882a593Smuzhiyun break;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun fallthrough;
1281*4882a593Smuzhiyun case NL80211_IFTYPE_OCB:
1282*4882a593Smuzhiyun case NL80211_IFTYPE_MESH_POINT:
1283*4882a593Smuzhiyun case NL80211_IFTYPE_AP:
1284*4882a593Smuzhiyun set |= AR_STA_ID1_STA_AP;
1285*4882a593Smuzhiyun fallthrough;
1286*4882a593Smuzhiyun case NL80211_IFTYPE_STATION:
1287*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1288*4882a593Smuzhiyun break;
1289*4882a593Smuzhiyun default:
1290*4882a593Smuzhiyun if (!ah->is_monitoring)
1291*4882a593Smuzhiyun set = 0;
1292*4882a593Smuzhiyun break;
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun REG_RMW(ah, AR_STA_ID1, set, mask);
1295*4882a593Smuzhiyun REG_RMW_BUFFER_FLUSH(ah);
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun
ath9k_hw_get_delta_slope_vals(struct ath_hw * ah,u32 coef_scaled,u32 * coef_mantissa,u32 * coef_exponent)1298*4882a593Smuzhiyun void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
1299*4882a593Smuzhiyun u32 *coef_mantissa, u32 *coef_exponent)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun u32 coef_exp, coef_man;
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun for (coef_exp = 31; coef_exp > 0; coef_exp--)
1304*4882a593Smuzhiyun if ((coef_scaled >> coef_exp) & 0x1)
1305*4882a593Smuzhiyun break;
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun coef_exp = 14 - (coef_exp - COEF_SCALE_S);
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
1312*4882a593Smuzhiyun *coef_exponent = coef_exp - 16;
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyun /* AR9330 WAR:
1316*4882a593Smuzhiyun * call external reset function to reset WMAC if:
1317*4882a593Smuzhiyun * - doing a cold reset
1318*4882a593Smuzhiyun * - we have pending frames in the TX queues.
1319*4882a593Smuzhiyun */
ath9k_hw_ar9330_reset_war(struct ath_hw * ah,int type)1320*4882a593Smuzhiyun static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
1321*4882a593Smuzhiyun {
1322*4882a593Smuzhiyun int i, npend = 0;
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun for (i = 0; i < AR_NUM_QCU; i++) {
1325*4882a593Smuzhiyun npend = ath9k_hw_numtxpending(ah, i);
1326*4882a593Smuzhiyun if (npend)
1327*4882a593Smuzhiyun break;
1328*4882a593Smuzhiyun }
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun if (ah->external_reset &&
1331*4882a593Smuzhiyun (npend || type == ATH9K_RESET_COLD)) {
1332*4882a593Smuzhiyun int reset_err = 0;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), RESET,
1335*4882a593Smuzhiyun "reset MAC via external reset\n");
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun reset_err = ah->external_reset();
1338*4882a593Smuzhiyun if (reset_err) {
1339*4882a593Smuzhiyun ath_err(ath9k_hw_common(ah),
1340*4882a593Smuzhiyun "External reset failed, err=%d\n",
1341*4882a593Smuzhiyun reset_err);
1342*4882a593Smuzhiyun return false;
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun
1345*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_RESET, 1);
1346*4882a593Smuzhiyun }
1347*4882a593Smuzhiyun
1348*4882a593Smuzhiyun return true;
1349*4882a593Smuzhiyun }
1350*4882a593Smuzhiyun
ath9k_hw_set_reset(struct ath_hw * ah,int type)1351*4882a593Smuzhiyun static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
1352*4882a593Smuzhiyun {
1353*4882a593Smuzhiyun u32 rst_flags;
1354*4882a593Smuzhiyun u32 tmpReg;
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun if (AR_SREV_9100(ah)) {
1357*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK,
1358*4882a593Smuzhiyun AR_RTC_DERIVED_CLK_PERIOD, 1);
1359*4882a593Smuzhiyun (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
1365*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal);
1366*4882a593Smuzhiyun udelay(10);
1367*4882a593Smuzhiyun }
1368*4882a593Smuzhiyun
1369*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1370*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_ON_INT);
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun if (AR_SREV_9100(ah)) {
1373*4882a593Smuzhiyun rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
1374*4882a593Smuzhiyun AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
1375*4882a593Smuzhiyun } else {
1376*4882a593Smuzhiyun tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
1377*4882a593Smuzhiyun if (AR_SREV_9340(ah))
1378*4882a593Smuzhiyun tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT;
1379*4882a593Smuzhiyun else
1380*4882a593Smuzhiyun tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT |
1381*4882a593Smuzhiyun AR_INTR_SYNC_RADM_CPL_TIMEOUT;
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun if (tmpReg) {
1384*4882a593Smuzhiyun u32 val;
1385*4882a593Smuzhiyun REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun val = AR_RC_HOSTIF;
1388*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
1389*4882a593Smuzhiyun val |= AR_RC_AHB;
1390*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, val);
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun } else if (!AR_SREV_9300_20_OR_LATER(ah))
1393*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, AR_RC_AHB);
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun rst_flags = AR_RTC_RC_MAC_WARM;
1396*4882a593Smuzhiyun if (type == ATH9K_RESET_COLD)
1397*4882a593Smuzhiyun rst_flags |= AR_RTC_RC_MAC_COLD;
1398*4882a593Smuzhiyun }
1399*4882a593Smuzhiyun
1400*4882a593Smuzhiyun if (AR_SREV_9330(ah)) {
1401*4882a593Smuzhiyun if (!ath9k_hw_ar9330_reset_war(ah, type))
1402*4882a593Smuzhiyun return false;
1403*4882a593Smuzhiyun }
1404*4882a593Smuzhiyun
1405*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
1406*4882a593Smuzhiyun ar9003_mci_check_gpm_offset(ah);
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun /* DMA HALT added to resolve ar9300 and ar9580 bus error during
1409*4882a593Smuzhiyun * RTC_RC reg read
1410*4882a593Smuzhiyun */
1411*4882a593Smuzhiyun if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
1412*4882a593Smuzhiyun REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
1413*4882a593Smuzhiyun ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
1414*4882a593Smuzhiyun 20 * AH_WAIT_TIMEOUT);
1415*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
1416*4882a593Smuzhiyun }
1417*4882a593Smuzhiyun
1418*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_RC, rst_flags);
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1421*4882a593Smuzhiyun
1422*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
1423*4882a593Smuzhiyun udelay(50);
1424*4882a593Smuzhiyun else if (AR_SREV_9100(ah))
1425*4882a593Smuzhiyun mdelay(10);
1426*4882a593Smuzhiyun else
1427*4882a593Smuzhiyun udelay(100);
1428*4882a593Smuzhiyun
1429*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_RC, 0);
1430*4882a593Smuzhiyun if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
1431*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), RESET, "RTC stuck in MAC reset\n");
1432*4882a593Smuzhiyun return false;
1433*4882a593Smuzhiyun }
1434*4882a593Smuzhiyun
1435*4882a593Smuzhiyun if (!AR_SREV_9100(ah))
1436*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, 0);
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun if (AR_SREV_9100(ah))
1439*4882a593Smuzhiyun udelay(50);
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun return true;
1442*4882a593Smuzhiyun }
1443*4882a593Smuzhiyun
ath9k_hw_set_reset_power_on(struct ath_hw * ah)1444*4882a593Smuzhiyun static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1445*4882a593Smuzhiyun {
1446*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
1449*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal);
1450*4882a593Smuzhiyun udelay(10);
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1454*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_ON_INT);
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
1457*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, AR_RC_AHB);
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_RESET, 0);
1460*4882a593Smuzhiyun
1461*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1462*4882a593Smuzhiyun
1463*4882a593Smuzhiyun udelay(2);
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
1466*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, 0);
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_RESET, 1);
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun if (!ath9k_hw_wait(ah,
1471*4882a593Smuzhiyun AR_RTC_STATUS,
1472*4882a593Smuzhiyun AR_RTC_STATUS_M,
1473*4882a593Smuzhiyun AR_RTC_STATUS_ON,
1474*4882a593Smuzhiyun AH_WAIT_TIMEOUT)) {
1475*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), RESET, "RTC not waking up\n");
1476*4882a593Smuzhiyun return false;
1477*4882a593Smuzhiyun }
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
1480*4882a593Smuzhiyun }
1481*4882a593Smuzhiyun
ath9k_hw_set_reset_reg(struct ath_hw * ah,u32 type)1482*4882a593Smuzhiyun static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
1483*4882a593Smuzhiyun {
1484*4882a593Smuzhiyun bool ret = false;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
1487*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal);
1488*4882a593Smuzhiyun udelay(10);
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1492*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun if (!ah->reset_power_on)
1495*4882a593Smuzhiyun type = ATH9K_RESET_POWER_ON;
1496*4882a593Smuzhiyun
1497*4882a593Smuzhiyun switch (type) {
1498*4882a593Smuzhiyun case ATH9K_RESET_POWER_ON:
1499*4882a593Smuzhiyun ret = ath9k_hw_set_reset_power_on(ah);
1500*4882a593Smuzhiyun if (ret)
1501*4882a593Smuzhiyun ah->reset_power_on = true;
1502*4882a593Smuzhiyun break;
1503*4882a593Smuzhiyun case ATH9K_RESET_WARM:
1504*4882a593Smuzhiyun case ATH9K_RESET_COLD:
1505*4882a593Smuzhiyun ret = ath9k_hw_set_reset(ah, type);
1506*4882a593Smuzhiyun break;
1507*4882a593Smuzhiyun default:
1508*4882a593Smuzhiyun break;
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun
1511*4882a593Smuzhiyun return ret;
1512*4882a593Smuzhiyun }
1513*4882a593Smuzhiyun
ath9k_hw_chip_reset(struct ath_hw * ah,struct ath9k_channel * chan)1514*4882a593Smuzhiyun static bool ath9k_hw_chip_reset(struct ath_hw *ah,
1515*4882a593Smuzhiyun struct ath9k_channel *chan)
1516*4882a593Smuzhiyun {
1517*4882a593Smuzhiyun int reset_type = ATH9K_RESET_WARM;
1518*4882a593Smuzhiyun
1519*4882a593Smuzhiyun if (AR_SREV_9280(ah)) {
1520*4882a593Smuzhiyun if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
1521*4882a593Smuzhiyun reset_type = ATH9K_RESET_POWER_ON;
1522*4882a593Smuzhiyun else
1523*4882a593Smuzhiyun reset_type = ATH9K_RESET_COLD;
1524*4882a593Smuzhiyun } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
1525*4882a593Smuzhiyun (REG_READ(ah, AR_CR) & AR_CR_RXE))
1526*4882a593Smuzhiyun reset_type = ATH9K_RESET_COLD;
1527*4882a593Smuzhiyun
1528*4882a593Smuzhiyun if (!ath9k_hw_set_reset_reg(ah, reset_type))
1529*4882a593Smuzhiyun return false;
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
1532*4882a593Smuzhiyun return false;
1533*4882a593Smuzhiyun
1534*4882a593Smuzhiyun ah->chip_fullsleep = false;
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun if (AR_SREV_9330(ah))
1537*4882a593Smuzhiyun ar9003_hw_internal_regulator_apply(ah);
1538*4882a593Smuzhiyun ath9k_hw_init_pll(ah, chan);
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun return true;
1541*4882a593Smuzhiyun }
1542*4882a593Smuzhiyun
ath9k_hw_channel_change(struct ath_hw * ah,struct ath9k_channel * chan)1543*4882a593Smuzhiyun static bool ath9k_hw_channel_change(struct ath_hw *ah,
1544*4882a593Smuzhiyun struct ath9k_channel *chan)
1545*4882a593Smuzhiyun {
1546*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1547*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
1548*4882a593Smuzhiyun bool band_switch = false, mode_diff = false;
1549*4882a593Smuzhiyun u8 ini_reloaded = 0;
1550*4882a593Smuzhiyun u32 qnum;
1551*4882a593Smuzhiyun int r;
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
1554*4882a593Smuzhiyun u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags;
1555*4882a593Smuzhiyun band_switch = !!(flags_diff & CHANNEL_5GHZ);
1556*4882a593Smuzhiyun mode_diff = !!(flags_diff & ~CHANNEL_HT);
1557*4882a593Smuzhiyun }
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
1560*4882a593Smuzhiyun if (ath9k_hw_numtxpending(ah, qnum)) {
1561*4882a593Smuzhiyun ath_dbg(common, QUEUE,
1562*4882a593Smuzhiyun "Transmit frames pending on queue %d\n", qnum);
1563*4882a593Smuzhiyun return false;
1564*4882a593Smuzhiyun }
1565*4882a593Smuzhiyun }
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun if (!ath9k_hw_rfbus_req(ah)) {
1568*4882a593Smuzhiyun ath_err(common, "Could not kill baseband RX\n");
1569*4882a593Smuzhiyun return false;
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun if (band_switch || mode_diff) {
1573*4882a593Smuzhiyun ath9k_hw_mark_phy_inactive(ah);
1574*4882a593Smuzhiyun udelay(5);
1575*4882a593Smuzhiyun
1576*4882a593Smuzhiyun if (band_switch)
1577*4882a593Smuzhiyun ath9k_hw_init_pll(ah, chan);
1578*4882a593Smuzhiyun
1579*4882a593Smuzhiyun if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
1580*4882a593Smuzhiyun ath_err(common, "Failed to do fast channel change\n");
1581*4882a593Smuzhiyun return false;
1582*4882a593Smuzhiyun }
1583*4882a593Smuzhiyun }
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun ath9k_hw_set_channel_regs(ah, chan);
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun r = ath9k_hw_rf_set_freq(ah, chan);
1588*4882a593Smuzhiyun if (r) {
1589*4882a593Smuzhiyun ath_err(common, "Failed to set channel\n");
1590*4882a593Smuzhiyun return false;
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun ath9k_hw_set_clockrate(ah);
1593*4882a593Smuzhiyun ath9k_hw_apply_txpower(ah, chan, false);
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun ath9k_hw_set_delta_slope(ah, chan);
1596*4882a593Smuzhiyun ath9k_hw_spur_mitigate_freq(ah, chan);
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun if (band_switch || ini_reloaded)
1599*4882a593Smuzhiyun ah->eep_ops->set_board_values(ah, chan);
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun ath9k_hw_init_bb(ah, chan);
1602*4882a593Smuzhiyun ath9k_hw_rfbus_done(ah);
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun if (band_switch || ini_reloaded) {
1605*4882a593Smuzhiyun ah->ah_flags |= AH_FASTCC;
1606*4882a593Smuzhiyun ath9k_hw_init_cal(ah, chan);
1607*4882a593Smuzhiyun ah->ah_flags &= ~AH_FASTCC;
1608*4882a593Smuzhiyun }
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun return true;
1611*4882a593Smuzhiyun }
1612*4882a593Smuzhiyun
ath9k_hw_apply_gpio_override(struct ath_hw * ah)1613*4882a593Smuzhiyun static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
1614*4882a593Smuzhiyun {
1615*4882a593Smuzhiyun u32 gpio_mask = ah->gpio_mask;
1616*4882a593Smuzhiyun int i;
1617*4882a593Smuzhiyun
1618*4882a593Smuzhiyun for (i = 0; gpio_mask; i++, gpio_mask >>= 1) {
1619*4882a593Smuzhiyun if (!(gpio_mask & 1))
1620*4882a593Smuzhiyun continue;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun ath9k_hw_gpio_request_out(ah, i, NULL,
1623*4882a593Smuzhiyun AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1624*4882a593Smuzhiyun ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
1625*4882a593Smuzhiyun }
1626*4882a593Smuzhiyun }
1627*4882a593Smuzhiyun
ath9k_hw_check_nav(struct ath_hw * ah)1628*4882a593Smuzhiyun void ath9k_hw_check_nav(struct ath_hw *ah)
1629*4882a593Smuzhiyun {
1630*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1631*4882a593Smuzhiyun u32 val;
1632*4882a593Smuzhiyun
1633*4882a593Smuzhiyun val = REG_READ(ah, AR_NAV);
1634*4882a593Smuzhiyun if (val != 0xdeadbeef && val > 0x7fff) {
1635*4882a593Smuzhiyun ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val);
1636*4882a593Smuzhiyun REG_WRITE(ah, AR_NAV, 0);
1637*4882a593Smuzhiyun }
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_check_nav);
1640*4882a593Smuzhiyun
ath9k_hw_check_alive(struct ath_hw * ah)1641*4882a593Smuzhiyun bool ath9k_hw_check_alive(struct ath_hw *ah)
1642*4882a593Smuzhiyun {
1643*4882a593Smuzhiyun int count = 50;
1644*4882a593Smuzhiyun u32 reg, last_val;
1645*4882a593Smuzhiyun
1646*4882a593Smuzhiyun /* Check if chip failed to wake up */
1647*4882a593Smuzhiyun if (REG_READ(ah, AR_CFG) == 0xdeadbeef)
1648*4882a593Smuzhiyun return false;
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun if (AR_SREV_9300(ah))
1651*4882a593Smuzhiyun return !ath9k_hw_detect_mac_hang(ah);
1652*4882a593Smuzhiyun
1653*4882a593Smuzhiyun if (AR_SREV_9285_12_OR_LATER(ah))
1654*4882a593Smuzhiyun return true;
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun last_val = REG_READ(ah, AR_OBS_BUS_1);
1657*4882a593Smuzhiyun do {
1658*4882a593Smuzhiyun reg = REG_READ(ah, AR_OBS_BUS_1);
1659*4882a593Smuzhiyun if (reg != last_val)
1660*4882a593Smuzhiyun return true;
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun udelay(1);
1663*4882a593Smuzhiyun last_val = reg;
1664*4882a593Smuzhiyun if ((reg & 0x7E7FFFEF) == 0x00702400)
1665*4882a593Smuzhiyun continue;
1666*4882a593Smuzhiyun
1667*4882a593Smuzhiyun switch (reg & 0x7E000B00) {
1668*4882a593Smuzhiyun case 0x1E000000:
1669*4882a593Smuzhiyun case 0x52000B00:
1670*4882a593Smuzhiyun case 0x18000B00:
1671*4882a593Smuzhiyun continue;
1672*4882a593Smuzhiyun default:
1673*4882a593Smuzhiyun return true;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun } while (count-- > 0);
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun return false;
1678*4882a593Smuzhiyun }
1679*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_check_alive);
1680*4882a593Smuzhiyun
ath9k_hw_init_mfp(struct ath_hw * ah)1681*4882a593Smuzhiyun static void ath9k_hw_init_mfp(struct ath_hw *ah)
1682*4882a593Smuzhiyun {
1683*4882a593Smuzhiyun /* Setup MFP options for CCMP */
1684*4882a593Smuzhiyun if (AR_SREV_9280_20_OR_LATER(ah)) {
1685*4882a593Smuzhiyun /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
1686*4882a593Smuzhiyun * frames when constructing CCMP AAD. */
1687*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
1688*4882a593Smuzhiyun 0xc7ff);
1689*4882a593Smuzhiyun if (AR_SREV_9271(ah) || AR_DEVID_7010(ah))
1690*4882a593Smuzhiyun ah->sw_mgmt_crypto_tx = true;
1691*4882a593Smuzhiyun else
1692*4882a593Smuzhiyun ah->sw_mgmt_crypto_tx = false;
1693*4882a593Smuzhiyun ah->sw_mgmt_crypto_rx = false;
1694*4882a593Smuzhiyun } else if (AR_SREV_9160_10_OR_LATER(ah)) {
1695*4882a593Smuzhiyun /* Disable hardware crypto for management frames */
1696*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
1697*4882a593Smuzhiyun AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
1698*4882a593Smuzhiyun REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
1699*4882a593Smuzhiyun AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
1700*4882a593Smuzhiyun ah->sw_mgmt_crypto_tx = true;
1701*4882a593Smuzhiyun ah->sw_mgmt_crypto_rx = true;
1702*4882a593Smuzhiyun } else {
1703*4882a593Smuzhiyun ah->sw_mgmt_crypto_tx = true;
1704*4882a593Smuzhiyun ah->sw_mgmt_crypto_rx = true;
1705*4882a593Smuzhiyun }
1706*4882a593Smuzhiyun }
1707*4882a593Smuzhiyun
ath9k_hw_reset_opmode(struct ath_hw * ah,u32 macStaId1,u32 saveDefAntenna)1708*4882a593Smuzhiyun static void ath9k_hw_reset_opmode(struct ath_hw *ah,
1709*4882a593Smuzhiyun u32 macStaId1, u32 saveDefAntenna)
1710*4882a593Smuzhiyun {
1711*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1712*4882a593Smuzhiyun
1713*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1714*4882a593Smuzhiyun
1715*4882a593Smuzhiyun REG_RMW(ah, AR_STA_ID1, macStaId1
1716*4882a593Smuzhiyun | AR_STA_ID1_RTS_USE_DEF
1717*4882a593Smuzhiyun | ah->sta_id1_defaults,
1718*4882a593Smuzhiyun ~AR_STA_ID1_SADH_MASK);
1719*4882a593Smuzhiyun ath_hw_setbssidmask(common);
1720*4882a593Smuzhiyun REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
1721*4882a593Smuzhiyun ath9k_hw_write_associd(ah);
1722*4882a593Smuzhiyun REG_WRITE(ah, AR_ISR, ~0);
1723*4882a593Smuzhiyun REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun ath9k_hw_set_operating_mode(ah, ah->opmode);
1728*4882a593Smuzhiyun }
1729*4882a593Smuzhiyun
ath9k_hw_init_queues(struct ath_hw * ah)1730*4882a593Smuzhiyun static void ath9k_hw_init_queues(struct ath_hw *ah)
1731*4882a593Smuzhiyun {
1732*4882a593Smuzhiyun int i;
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun for (i = 0; i < AR_NUM_DCU; i++)
1737*4882a593Smuzhiyun REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
1738*4882a593Smuzhiyun
1739*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
1740*4882a593Smuzhiyun
1741*4882a593Smuzhiyun ah->intr_txqs = 0;
1742*4882a593Smuzhiyun for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
1743*4882a593Smuzhiyun ath9k_hw_resettxqueue(ah, i);
1744*4882a593Smuzhiyun }
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun /*
1747*4882a593Smuzhiyun * For big endian systems turn on swapping for descriptors
1748*4882a593Smuzhiyun */
ath9k_hw_init_desc(struct ath_hw * ah)1749*4882a593Smuzhiyun static void ath9k_hw_init_desc(struct ath_hw *ah)
1750*4882a593Smuzhiyun {
1751*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1752*4882a593Smuzhiyun
1753*4882a593Smuzhiyun if (AR_SREV_9100(ah)) {
1754*4882a593Smuzhiyun u32 mask;
1755*4882a593Smuzhiyun mask = REG_READ(ah, AR_CFG);
1756*4882a593Smuzhiyun if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
1757*4882a593Smuzhiyun ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
1758*4882a593Smuzhiyun mask);
1759*4882a593Smuzhiyun } else {
1760*4882a593Smuzhiyun mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
1761*4882a593Smuzhiyun REG_WRITE(ah, AR_CFG, mask);
1762*4882a593Smuzhiyun ath_dbg(common, RESET, "Setting CFG 0x%x\n",
1763*4882a593Smuzhiyun REG_READ(ah, AR_CFG));
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun } else {
1766*4882a593Smuzhiyun if (common->bus_ops->ath_bus_type == ATH_USB) {
1767*4882a593Smuzhiyun /* Configure AR9271 target WLAN */
1768*4882a593Smuzhiyun if (AR_SREV_9271(ah))
1769*4882a593Smuzhiyun REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
1770*4882a593Smuzhiyun else
1771*4882a593Smuzhiyun REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
1772*4882a593Smuzhiyun }
1773*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
1774*4882a593Smuzhiyun else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
1775*4882a593Smuzhiyun AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
1776*4882a593Smuzhiyun AR_SREV_9561(ah))
1777*4882a593Smuzhiyun REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
1778*4882a593Smuzhiyun else
1779*4882a593Smuzhiyun REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
1780*4882a593Smuzhiyun #endif
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun }
1783*4882a593Smuzhiyun
1784*4882a593Smuzhiyun /*
1785*4882a593Smuzhiyun * Fast channel change:
1786*4882a593Smuzhiyun * (Change synthesizer based on channel freq without resetting chip)
1787*4882a593Smuzhiyun */
ath9k_hw_do_fastcc(struct ath_hw * ah,struct ath9k_channel * chan)1788*4882a593Smuzhiyun static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
1789*4882a593Smuzhiyun {
1790*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1791*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
1792*4882a593Smuzhiyun int ret;
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
1795*4882a593Smuzhiyun goto fail;
1796*4882a593Smuzhiyun
1797*4882a593Smuzhiyun if (ah->chip_fullsleep)
1798*4882a593Smuzhiyun goto fail;
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun if (!ah->curchan)
1801*4882a593Smuzhiyun goto fail;
1802*4882a593Smuzhiyun
1803*4882a593Smuzhiyun if (chan->channel == ah->curchan->channel)
1804*4882a593Smuzhiyun goto fail;
1805*4882a593Smuzhiyun
1806*4882a593Smuzhiyun if ((ah->curchan->channelFlags | chan->channelFlags) &
1807*4882a593Smuzhiyun (CHANNEL_HALF | CHANNEL_QUARTER))
1808*4882a593Smuzhiyun goto fail;
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun /*
1811*4882a593Smuzhiyun * If cross-band fcc is not supoprted, bail out if channelFlags differ.
1812*4882a593Smuzhiyun */
1813*4882a593Smuzhiyun if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) &&
1814*4882a593Smuzhiyun ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT))
1815*4882a593Smuzhiyun goto fail;
1816*4882a593Smuzhiyun
1817*4882a593Smuzhiyun if (!ath9k_hw_check_alive(ah))
1818*4882a593Smuzhiyun goto fail;
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyun /*
1821*4882a593Smuzhiyun * For AR9462, make sure that calibration data for
1822*4882a593Smuzhiyun * re-using are present.
1823*4882a593Smuzhiyun */
1824*4882a593Smuzhiyun if (AR_SREV_9462(ah) && (ah->caldata &&
1825*4882a593Smuzhiyun (!test_bit(TXIQCAL_DONE, &ah->caldata->cal_flags) ||
1826*4882a593Smuzhiyun !test_bit(TXCLCAL_DONE, &ah->caldata->cal_flags) ||
1827*4882a593Smuzhiyun !test_bit(RTT_DONE, &ah->caldata->cal_flags))))
1828*4882a593Smuzhiyun goto fail;
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
1831*4882a593Smuzhiyun ah->curchan->channel, chan->channel);
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun ret = ath9k_hw_channel_change(ah, chan);
1834*4882a593Smuzhiyun if (!ret)
1835*4882a593Smuzhiyun goto fail;
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
1838*4882a593Smuzhiyun ar9003_mci_2g5g_switch(ah, false);
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun ath9k_hw_loadnf(ah, ah->curchan);
1841*4882a593Smuzhiyun ath9k_hw_start_nfcal(ah, true);
1842*4882a593Smuzhiyun
1843*4882a593Smuzhiyun if (AR_SREV_9271(ah))
1844*4882a593Smuzhiyun ar9002_hw_load_ani_reg(ah, chan);
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun return 0;
1847*4882a593Smuzhiyun fail:
1848*4882a593Smuzhiyun return -EINVAL;
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun
ath9k_hw_get_tsf_offset(struct timespec64 * last,struct timespec64 * cur)1851*4882a593Smuzhiyun u32 ath9k_hw_get_tsf_offset(struct timespec64 *last, struct timespec64 *cur)
1852*4882a593Smuzhiyun {
1853*4882a593Smuzhiyun struct timespec64 ts;
1854*4882a593Smuzhiyun s64 usec;
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun if (!cur) {
1857*4882a593Smuzhiyun ktime_get_raw_ts64(&ts);
1858*4882a593Smuzhiyun cur = &ts;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun
1861*4882a593Smuzhiyun usec = cur->tv_sec * 1000000ULL + cur->tv_nsec / 1000;
1862*4882a593Smuzhiyun usec -= last->tv_sec * 1000000ULL + last->tv_nsec / 1000;
1863*4882a593Smuzhiyun
1864*4882a593Smuzhiyun return (u32) usec;
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
1867*4882a593Smuzhiyun
ath9k_hw_reset(struct ath_hw * ah,struct ath9k_channel * chan,struct ath9k_hw_cal_data * caldata,bool fastcc)1868*4882a593Smuzhiyun int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1869*4882a593Smuzhiyun struct ath9k_hw_cal_data *caldata, bool fastcc)
1870*4882a593Smuzhiyun {
1871*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
1872*4882a593Smuzhiyun u32 saveLedState;
1873*4882a593Smuzhiyun u32 saveDefAntenna;
1874*4882a593Smuzhiyun u32 macStaId1;
1875*4882a593Smuzhiyun struct timespec64 tsf_ts;
1876*4882a593Smuzhiyun u32 tsf_offset;
1877*4882a593Smuzhiyun u64 tsf = 0;
1878*4882a593Smuzhiyun int r;
1879*4882a593Smuzhiyun bool start_mci_reset = false;
1880*4882a593Smuzhiyun bool save_fullsleep = ah->chip_fullsleep;
1881*4882a593Smuzhiyun
1882*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah)) {
1883*4882a593Smuzhiyun start_mci_reset = ar9003_mci_start_reset(ah, chan);
1884*4882a593Smuzhiyun if (start_mci_reset)
1885*4882a593Smuzhiyun return 0;
1886*4882a593Smuzhiyun }
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
1889*4882a593Smuzhiyun return -EIO;
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun if (ah->curchan && !ah->chip_fullsleep)
1892*4882a593Smuzhiyun ath9k_hw_getnf(ah, ah->curchan);
1893*4882a593Smuzhiyun
1894*4882a593Smuzhiyun ah->caldata = caldata;
1895*4882a593Smuzhiyun if (caldata && (chan->channel != caldata->channel ||
1896*4882a593Smuzhiyun chan->channelFlags != caldata->channelFlags)) {
1897*4882a593Smuzhiyun /* Operating channel changed, reset channel calibration data */
1898*4882a593Smuzhiyun memset(caldata, 0, sizeof(*caldata));
1899*4882a593Smuzhiyun ath9k_init_nfcal_hist_buffer(ah, chan);
1900*4882a593Smuzhiyun } else if (caldata) {
1901*4882a593Smuzhiyun clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags);
1902*4882a593Smuzhiyun }
1903*4882a593Smuzhiyun ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor);
1904*4882a593Smuzhiyun
1905*4882a593Smuzhiyun if (fastcc) {
1906*4882a593Smuzhiyun r = ath9k_hw_do_fastcc(ah, chan);
1907*4882a593Smuzhiyun if (!r)
1908*4882a593Smuzhiyun return r;
1909*4882a593Smuzhiyun }
1910*4882a593Smuzhiyun
1911*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
1912*4882a593Smuzhiyun ar9003_mci_stop_bt(ah, save_fullsleep);
1913*4882a593Smuzhiyun
1914*4882a593Smuzhiyun saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
1915*4882a593Smuzhiyun if (saveDefAntenna == 0)
1916*4882a593Smuzhiyun saveDefAntenna = 1;
1917*4882a593Smuzhiyun
1918*4882a593Smuzhiyun macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun /* Save TSF before chip reset, a cold reset clears it */
1921*4882a593Smuzhiyun ktime_get_raw_ts64(&tsf_ts);
1922*4882a593Smuzhiyun tsf = ath9k_hw_gettsf64(ah);
1923*4882a593Smuzhiyun
1924*4882a593Smuzhiyun saveLedState = REG_READ(ah, AR_CFG_LED) &
1925*4882a593Smuzhiyun (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
1926*4882a593Smuzhiyun AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun ath9k_hw_mark_phy_inactive(ah);
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun ah->paprd_table_write_done = false;
1931*4882a593Smuzhiyun
1932*4882a593Smuzhiyun /* Only required on the first reset */
1933*4882a593Smuzhiyun if (AR_SREV_9271(ah) && ah->htc_reset_init) {
1934*4882a593Smuzhiyun REG_WRITE(ah,
1935*4882a593Smuzhiyun AR9271_RESET_POWER_DOWN_CONTROL,
1936*4882a593Smuzhiyun AR9271_RADIO_RF_RST);
1937*4882a593Smuzhiyun udelay(50);
1938*4882a593Smuzhiyun }
1939*4882a593Smuzhiyun
1940*4882a593Smuzhiyun if (!ath9k_hw_chip_reset(ah, chan)) {
1941*4882a593Smuzhiyun ath_err(common, "Chip reset failed\n");
1942*4882a593Smuzhiyun return -EINVAL;
1943*4882a593Smuzhiyun }
1944*4882a593Smuzhiyun
1945*4882a593Smuzhiyun /* Only required on the first reset */
1946*4882a593Smuzhiyun if (AR_SREV_9271(ah) && ah->htc_reset_init) {
1947*4882a593Smuzhiyun ah->htc_reset_init = false;
1948*4882a593Smuzhiyun REG_WRITE(ah,
1949*4882a593Smuzhiyun AR9271_RESET_POWER_DOWN_CONTROL,
1950*4882a593Smuzhiyun AR9271_GATE_MAC_CTL);
1951*4882a593Smuzhiyun udelay(50);
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun
1954*4882a593Smuzhiyun /* Restore TSF */
1955*4882a593Smuzhiyun tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
1956*4882a593Smuzhiyun ath9k_hw_settsf64(ah, tsf + tsf_offset);
1957*4882a593Smuzhiyun
1958*4882a593Smuzhiyun if (AR_SREV_9280_20_OR_LATER(ah))
1959*4882a593Smuzhiyun REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
1960*4882a593Smuzhiyun
1961*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
1962*4882a593Smuzhiyun ar9002_hw_enable_async_fifo(ah);
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun r = ath9k_hw_process_ini(ah, chan);
1965*4882a593Smuzhiyun if (r)
1966*4882a593Smuzhiyun return r;
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun ath9k_hw_set_rfmode(ah, chan);
1969*4882a593Smuzhiyun
1970*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
1971*4882a593Smuzhiyun ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep);
1972*4882a593Smuzhiyun
1973*4882a593Smuzhiyun /*
1974*4882a593Smuzhiyun * Some AR91xx SoC devices frequently fail to accept TSF writes
1975*4882a593Smuzhiyun * right after the chip reset. When that happens, write a new
1976*4882a593Smuzhiyun * value after the initvals have been applied.
1977*4882a593Smuzhiyun */
1978*4882a593Smuzhiyun if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
1979*4882a593Smuzhiyun tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
1980*4882a593Smuzhiyun ath9k_hw_settsf64(ah, tsf + tsf_offset);
1981*4882a593Smuzhiyun }
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun ath9k_hw_init_mfp(ah);
1984*4882a593Smuzhiyun
1985*4882a593Smuzhiyun ath9k_hw_set_delta_slope(ah, chan);
1986*4882a593Smuzhiyun ath9k_hw_spur_mitigate_freq(ah, chan);
1987*4882a593Smuzhiyun ah->eep_ops->set_board_values(ah, chan);
1988*4882a593Smuzhiyun
1989*4882a593Smuzhiyun ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna);
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun r = ath9k_hw_rf_set_freq(ah, chan);
1992*4882a593Smuzhiyun if (r)
1993*4882a593Smuzhiyun return r;
1994*4882a593Smuzhiyun
1995*4882a593Smuzhiyun ath9k_hw_set_clockrate(ah);
1996*4882a593Smuzhiyun
1997*4882a593Smuzhiyun ath9k_hw_init_queues(ah);
1998*4882a593Smuzhiyun ath9k_hw_init_interrupt_masks(ah, ah->opmode);
1999*4882a593Smuzhiyun ath9k_hw_ani_cache_ini_regs(ah);
2000*4882a593Smuzhiyun ath9k_hw_init_qos(ah);
2001*4882a593Smuzhiyun
2002*4882a593Smuzhiyun if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2003*4882a593Smuzhiyun ath9k_hw_gpio_request_in(ah, ah->rfkill_gpio, "ath9k-rfkill");
2004*4882a593Smuzhiyun
2005*4882a593Smuzhiyun ath9k_hw_init_global_settings(ah);
2006*4882a593Smuzhiyun
2007*4882a593Smuzhiyun if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
2008*4882a593Smuzhiyun REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
2009*4882a593Smuzhiyun AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
2010*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
2011*4882a593Smuzhiyun AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
2012*4882a593Smuzhiyun REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
2013*4882a593Smuzhiyun AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
2014*4882a593Smuzhiyun }
2015*4882a593Smuzhiyun
2016*4882a593Smuzhiyun REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun ath9k_hw_set_dma(ah);
2019*4882a593Smuzhiyun
2020*4882a593Smuzhiyun if (!ath9k_hw_mci_is_enabled(ah))
2021*4882a593Smuzhiyun REG_WRITE(ah, AR_OBS, 8);
2022*4882a593Smuzhiyun
2023*4882a593Smuzhiyun ENABLE_REG_RMW_BUFFER(ah);
2024*4882a593Smuzhiyun if (ah->config.rx_intr_mitigation) {
2025*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last);
2026*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first);
2027*4882a593Smuzhiyun }
2028*4882a593Smuzhiyun
2029*4882a593Smuzhiyun if (ah->config.tx_intr_mitigation) {
2030*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
2031*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
2032*4882a593Smuzhiyun }
2033*4882a593Smuzhiyun REG_RMW_BUFFER_FLUSH(ah);
2034*4882a593Smuzhiyun
2035*4882a593Smuzhiyun ath9k_hw_init_bb(ah, chan);
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun if (caldata) {
2038*4882a593Smuzhiyun clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
2039*4882a593Smuzhiyun clear_bit(TXCLCAL_DONE, &caldata->cal_flags);
2040*4882a593Smuzhiyun }
2041*4882a593Smuzhiyun if (!ath9k_hw_init_cal(ah, chan))
2042*4882a593Smuzhiyun return -EIO;
2043*4882a593Smuzhiyun
2044*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata))
2045*4882a593Smuzhiyun return -EIO;
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun ath9k_hw_restore_chainmask(ah);
2050*4882a593Smuzhiyun REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
2053*4882a593Smuzhiyun
2054*4882a593Smuzhiyun ath9k_hw_gen_timer_start_tsf2(ah);
2055*4882a593Smuzhiyun
2056*4882a593Smuzhiyun ath9k_hw_init_desc(ah);
2057*4882a593Smuzhiyun
2058*4882a593Smuzhiyun if (ath9k_hw_btcoex_is_enabled(ah))
2059*4882a593Smuzhiyun ath9k_hw_btcoex_enable(ah);
2060*4882a593Smuzhiyun
2061*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2062*4882a593Smuzhiyun ar9003_mci_check_bt(ah);
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
2065*4882a593Smuzhiyun ath9k_hw_loadnf(ah, chan);
2066*4882a593Smuzhiyun ath9k_hw_start_nfcal(ah, true);
2067*4882a593Smuzhiyun }
2068*4882a593Smuzhiyun
2069*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
2070*4882a593Smuzhiyun ar9003_hw_bb_watchdog_config(ah);
2071*4882a593Smuzhiyun
2072*4882a593Smuzhiyun if (ah->config.hw_hang_checks & HW_PHYRESTART_CLC_WAR)
2073*4882a593Smuzhiyun ar9003_hw_disable_phy_restart(ah);
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun ath9k_hw_apply_gpio_override(ah);
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun if (AR_SREV_9565(ah) && common->bt_ant_diversity)
2078*4882a593Smuzhiyun REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
2079*4882a593Smuzhiyun
2080*4882a593Smuzhiyun if (ah->hw->conf.radar_enabled) {
2081*4882a593Smuzhiyun /* set HW specific DFS configuration */
2082*4882a593Smuzhiyun ah->radar_conf.ext_channel = IS_CHAN_HT40(chan);
2083*4882a593Smuzhiyun ath9k_hw_set_radar_params(ah);
2084*4882a593Smuzhiyun }
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyun return 0;
2087*4882a593Smuzhiyun }
2088*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_reset);
2089*4882a593Smuzhiyun
2090*4882a593Smuzhiyun /******************************/
2091*4882a593Smuzhiyun /* Power Management (Chipset) */
2092*4882a593Smuzhiyun /******************************/
2093*4882a593Smuzhiyun
2094*4882a593Smuzhiyun /*
2095*4882a593Smuzhiyun * Notify Power Mgt is disabled in self-generated frames.
2096*4882a593Smuzhiyun * If requested, force chip to sleep.
2097*4882a593Smuzhiyun */
ath9k_set_power_sleep(struct ath_hw * ah)2098*4882a593Smuzhiyun static void ath9k_set_power_sleep(struct ath_hw *ah)
2099*4882a593Smuzhiyun {
2100*4882a593Smuzhiyun REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
2103*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff);
2104*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff);
2105*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff);
2106*4882a593Smuzhiyun /* xxx Required for WLAN only case ? */
2107*4882a593Smuzhiyun REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
2108*4882a593Smuzhiyun udelay(100);
2109*4882a593Smuzhiyun }
2110*4882a593Smuzhiyun
2111*4882a593Smuzhiyun /*
2112*4882a593Smuzhiyun * Clear the RTC force wake bit to allow the
2113*4882a593Smuzhiyun * mac to go to sleep.
2114*4882a593Smuzhiyun */
2115*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
2116*4882a593Smuzhiyun
2117*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2118*4882a593Smuzhiyun udelay(100);
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
2121*4882a593Smuzhiyun REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
2122*4882a593Smuzhiyun
2123*4882a593Smuzhiyun /* Shutdown chip. Active low */
2124*4882a593Smuzhiyun if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) {
2125*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
2126*4882a593Smuzhiyun udelay(2);
2127*4882a593Smuzhiyun }
2128*4882a593Smuzhiyun
2129*4882a593Smuzhiyun /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
2130*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
2131*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
2132*4882a593Smuzhiyun }
2133*4882a593Smuzhiyun
2134*4882a593Smuzhiyun /*
2135*4882a593Smuzhiyun * Notify Power Management is enabled in self-generating
2136*4882a593Smuzhiyun * frames. If request, set power mode of chip to
2137*4882a593Smuzhiyun * auto/normal. Duration in units of 128us (1/8 TU).
2138*4882a593Smuzhiyun */
ath9k_set_power_network_sleep(struct ath_hw * ah)2139*4882a593Smuzhiyun static void ath9k_set_power_network_sleep(struct ath_hw *ah)
2140*4882a593Smuzhiyun {
2141*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
2142*4882a593Smuzhiyun
2143*4882a593Smuzhiyun REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
2146*4882a593Smuzhiyun /* Set WakeOnInterrupt bit; clear ForceWake bit */
2147*4882a593Smuzhiyun REG_WRITE(ah, AR_RTC_FORCE_WAKE,
2148*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_ON_INT);
2149*4882a593Smuzhiyun } else {
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun /* When chip goes into network sleep, it could be waken
2152*4882a593Smuzhiyun * up by MCI_INT interrupt caused by BT's HW messages
2153*4882a593Smuzhiyun * (LNA_xxx, CONT_xxx) which chould be in a very fast
2154*4882a593Smuzhiyun * rate (~100us). This will cause chip to leave and
2155*4882a593Smuzhiyun * re-enter network sleep mode frequently, which in
2156*4882a593Smuzhiyun * consequence will have WLAN MCI HW to generate lots of
2157*4882a593Smuzhiyun * SYS_WAKING and SYS_SLEEPING messages which will make
2158*4882a593Smuzhiyun * BT CPU to busy to process.
2159*4882a593Smuzhiyun */
2160*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2161*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
2162*4882a593Smuzhiyun AR_MCI_INTERRUPT_RX_HW_MSG_MASK);
2163*4882a593Smuzhiyun /*
2164*4882a593Smuzhiyun * Clear the RTC force wake bit to allow the
2165*4882a593Smuzhiyun * mac to go to sleep.
2166*4882a593Smuzhiyun */
2167*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
2168*4882a593Smuzhiyun
2169*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2170*4882a593Smuzhiyun udelay(30);
2171*4882a593Smuzhiyun }
2172*4882a593Smuzhiyun
2173*4882a593Smuzhiyun /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
2174*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
2175*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
2176*4882a593Smuzhiyun }
2177*4882a593Smuzhiyun
ath9k_hw_set_power_awake(struct ath_hw * ah)2178*4882a593Smuzhiyun static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
2179*4882a593Smuzhiyun {
2180*4882a593Smuzhiyun u32 val;
2181*4882a593Smuzhiyun int i;
2182*4882a593Smuzhiyun
2183*4882a593Smuzhiyun /* Set Bits 14 and 17 of AR_WA before powering on the chip. */
2184*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
2185*4882a593Smuzhiyun REG_WRITE(ah, AR_WA, ah->WARegVal);
2186*4882a593Smuzhiyun udelay(10);
2187*4882a593Smuzhiyun }
2188*4882a593Smuzhiyun
2189*4882a593Smuzhiyun if ((REG_READ(ah, AR_RTC_STATUS) &
2190*4882a593Smuzhiyun AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
2191*4882a593Smuzhiyun if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
2192*4882a593Smuzhiyun return false;
2193*4882a593Smuzhiyun }
2194*4882a593Smuzhiyun if (!AR_SREV_9300_20_OR_LATER(ah))
2195*4882a593Smuzhiyun ath9k_hw_init_pll(ah, NULL);
2196*4882a593Smuzhiyun }
2197*4882a593Smuzhiyun if (AR_SREV_9100(ah))
2198*4882a593Smuzhiyun REG_SET_BIT(ah, AR_RTC_RESET,
2199*4882a593Smuzhiyun AR_RTC_RESET_EN);
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
2202*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_EN);
2203*4882a593Smuzhiyun if (AR_SREV_9100(ah))
2204*4882a593Smuzhiyun mdelay(10);
2205*4882a593Smuzhiyun else
2206*4882a593Smuzhiyun udelay(50);
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun for (i = POWER_UP_TIME / 50; i > 0; i--) {
2209*4882a593Smuzhiyun val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
2210*4882a593Smuzhiyun if (val == AR_RTC_STATUS_ON)
2211*4882a593Smuzhiyun break;
2212*4882a593Smuzhiyun udelay(50);
2213*4882a593Smuzhiyun REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
2214*4882a593Smuzhiyun AR_RTC_FORCE_WAKE_EN);
2215*4882a593Smuzhiyun }
2216*4882a593Smuzhiyun if (i == 0) {
2217*4882a593Smuzhiyun ath_err(ath9k_hw_common(ah),
2218*4882a593Smuzhiyun "Failed to wakeup in %uus\n",
2219*4882a593Smuzhiyun POWER_UP_TIME / 20);
2220*4882a593Smuzhiyun return false;
2221*4882a593Smuzhiyun }
2222*4882a593Smuzhiyun
2223*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2224*4882a593Smuzhiyun ar9003_mci_set_power_awake(ah);
2225*4882a593Smuzhiyun
2226*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2227*4882a593Smuzhiyun
2228*4882a593Smuzhiyun return true;
2229*4882a593Smuzhiyun }
2230*4882a593Smuzhiyun
ath9k_hw_setpower(struct ath_hw * ah,enum ath9k_power_mode mode)2231*4882a593Smuzhiyun bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
2232*4882a593Smuzhiyun {
2233*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
2234*4882a593Smuzhiyun int status = true;
2235*4882a593Smuzhiyun static const char *modes[] = {
2236*4882a593Smuzhiyun "AWAKE",
2237*4882a593Smuzhiyun "FULL-SLEEP",
2238*4882a593Smuzhiyun "NETWORK SLEEP",
2239*4882a593Smuzhiyun "UNDEFINED"
2240*4882a593Smuzhiyun };
2241*4882a593Smuzhiyun
2242*4882a593Smuzhiyun if (ah->power_mode == mode)
2243*4882a593Smuzhiyun return status;
2244*4882a593Smuzhiyun
2245*4882a593Smuzhiyun ath_dbg(common, RESET, "%s -> %s\n",
2246*4882a593Smuzhiyun modes[ah->power_mode], modes[mode]);
2247*4882a593Smuzhiyun
2248*4882a593Smuzhiyun switch (mode) {
2249*4882a593Smuzhiyun case ATH9K_PM_AWAKE:
2250*4882a593Smuzhiyun status = ath9k_hw_set_power_awake(ah);
2251*4882a593Smuzhiyun break;
2252*4882a593Smuzhiyun case ATH9K_PM_FULL_SLEEP:
2253*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2254*4882a593Smuzhiyun ar9003_mci_set_full_sleep(ah);
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun ath9k_set_power_sleep(ah);
2257*4882a593Smuzhiyun ah->chip_fullsleep = true;
2258*4882a593Smuzhiyun break;
2259*4882a593Smuzhiyun case ATH9K_PM_NETWORK_SLEEP:
2260*4882a593Smuzhiyun ath9k_set_power_network_sleep(ah);
2261*4882a593Smuzhiyun break;
2262*4882a593Smuzhiyun default:
2263*4882a593Smuzhiyun ath_err(common, "Unknown power mode %u\n", mode);
2264*4882a593Smuzhiyun return false;
2265*4882a593Smuzhiyun }
2266*4882a593Smuzhiyun ah->power_mode = mode;
2267*4882a593Smuzhiyun
2268*4882a593Smuzhiyun /*
2269*4882a593Smuzhiyun * XXX: If this warning never comes up after a while then
2270*4882a593Smuzhiyun * simply keep the ATH_DBG_WARN_ON_ONCE() but make
2271*4882a593Smuzhiyun * ath9k_hw_setpower() return type void.
2272*4882a593Smuzhiyun */
2273*4882a593Smuzhiyun
2274*4882a593Smuzhiyun if (!(ah->ah_flags & AH_UNPLUGGED))
2275*4882a593Smuzhiyun ATH_DBG_WARN_ON_ONCE(!status);
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun return status;
2278*4882a593Smuzhiyun }
2279*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_setpower);
2280*4882a593Smuzhiyun
2281*4882a593Smuzhiyun /*******************/
2282*4882a593Smuzhiyun /* Beacon Handling */
2283*4882a593Smuzhiyun /*******************/
2284*4882a593Smuzhiyun
ath9k_hw_beaconinit(struct ath_hw * ah,u32 next_beacon,u32 beacon_period)2285*4882a593Smuzhiyun void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
2286*4882a593Smuzhiyun {
2287*4882a593Smuzhiyun int flags = 0;
2288*4882a593Smuzhiyun
2289*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
2290*4882a593Smuzhiyun
2291*4882a593Smuzhiyun switch (ah->opmode) {
2292*4882a593Smuzhiyun case NL80211_IFTYPE_ADHOC:
2293*4882a593Smuzhiyun REG_SET_BIT(ah, AR_TXCFG,
2294*4882a593Smuzhiyun AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
2295*4882a593Smuzhiyun fallthrough;
2296*4882a593Smuzhiyun case NL80211_IFTYPE_MESH_POINT:
2297*4882a593Smuzhiyun case NL80211_IFTYPE_AP:
2298*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
2299*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon -
2300*4882a593Smuzhiyun TU_TO_USEC(ah->config.dma_beacon_response_time));
2301*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_SWBA, next_beacon -
2302*4882a593Smuzhiyun TU_TO_USEC(ah->config.sw_beacon_response_time));
2303*4882a593Smuzhiyun flags |=
2304*4882a593Smuzhiyun AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
2305*4882a593Smuzhiyun break;
2306*4882a593Smuzhiyun default:
2307*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), BEACON,
2308*4882a593Smuzhiyun "%s: unsupported opmode: %d\n", __func__, ah->opmode);
2309*4882a593Smuzhiyun return;
2310*4882a593Smuzhiyun break;
2311*4882a593Smuzhiyun }
2312*4882a593Smuzhiyun
2313*4882a593Smuzhiyun REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
2314*4882a593Smuzhiyun REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
2315*4882a593Smuzhiyun REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
2316*4882a593Smuzhiyun
2317*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
2318*4882a593Smuzhiyun
2319*4882a593Smuzhiyun REG_SET_BIT(ah, AR_TIMER_MODE, flags);
2320*4882a593Smuzhiyun }
2321*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_beaconinit);
2322*4882a593Smuzhiyun
ath9k_hw_set_sta_beacon_timers(struct ath_hw * ah,const struct ath9k_beacon_state * bs)2323*4882a593Smuzhiyun void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
2324*4882a593Smuzhiyun const struct ath9k_beacon_state *bs)
2325*4882a593Smuzhiyun {
2326*4882a593Smuzhiyun u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
2327*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
2328*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
2329*4882a593Smuzhiyun
2330*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
2331*4882a593Smuzhiyun
2332*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt);
2333*4882a593Smuzhiyun REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval);
2334*4882a593Smuzhiyun REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval);
2335*4882a593Smuzhiyun
2336*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
2337*4882a593Smuzhiyun
2338*4882a593Smuzhiyun REG_RMW_FIELD(ah, AR_RSSI_THR,
2339*4882a593Smuzhiyun AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
2340*4882a593Smuzhiyun
2341*4882a593Smuzhiyun beaconintval = bs->bs_intval;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun if (bs->bs_sleepduration > beaconintval)
2344*4882a593Smuzhiyun beaconintval = bs->bs_sleepduration;
2345*4882a593Smuzhiyun
2346*4882a593Smuzhiyun dtimperiod = bs->bs_dtimperiod;
2347*4882a593Smuzhiyun if (bs->bs_sleepduration > dtimperiod)
2348*4882a593Smuzhiyun dtimperiod = bs->bs_sleepduration;
2349*4882a593Smuzhiyun
2350*4882a593Smuzhiyun if (beaconintval == dtimperiod)
2351*4882a593Smuzhiyun nextTbtt = bs->bs_nextdtim;
2352*4882a593Smuzhiyun else
2353*4882a593Smuzhiyun nextTbtt = bs->bs_nexttbtt;
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun ath_dbg(common, BEACON, "next DTIM %u\n", bs->bs_nextdtim);
2356*4882a593Smuzhiyun ath_dbg(common, BEACON, "next beacon %u\n", nextTbtt);
2357*4882a593Smuzhiyun ath_dbg(common, BEACON, "beacon period %u\n", beaconintval);
2358*4882a593Smuzhiyun ath_dbg(common, BEACON, "DTIM period %u\n", dtimperiod);
2359*4882a593Smuzhiyun
2360*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
2361*4882a593Smuzhiyun
2362*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP);
2363*4882a593Smuzhiyun REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP);
2364*4882a593Smuzhiyun
2365*4882a593Smuzhiyun REG_WRITE(ah, AR_SLEEP1,
2366*4882a593Smuzhiyun SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
2367*4882a593Smuzhiyun | AR_SLEEP1_ASSUME_DTIM);
2368*4882a593Smuzhiyun
2369*4882a593Smuzhiyun if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
2370*4882a593Smuzhiyun beacontimeout = (BEACON_TIMEOUT_VAL << 3);
2371*4882a593Smuzhiyun else
2372*4882a593Smuzhiyun beacontimeout = MIN_BEACON_TIMEOUT_VAL;
2373*4882a593Smuzhiyun
2374*4882a593Smuzhiyun REG_WRITE(ah, AR_SLEEP2,
2375*4882a593Smuzhiyun SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
2376*4882a593Smuzhiyun
2377*4882a593Smuzhiyun REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
2378*4882a593Smuzhiyun REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
2381*4882a593Smuzhiyun
2382*4882a593Smuzhiyun REG_SET_BIT(ah, AR_TIMER_MODE,
2383*4882a593Smuzhiyun AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
2384*4882a593Smuzhiyun AR_DTIM_TIMER_EN);
2385*4882a593Smuzhiyun
2386*4882a593Smuzhiyun /* TSF Out of Range Threshold */
2387*4882a593Smuzhiyun REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
2388*4882a593Smuzhiyun }
2389*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
2390*4882a593Smuzhiyun
2391*4882a593Smuzhiyun /*******************/
2392*4882a593Smuzhiyun /* HW Capabilities */
2393*4882a593Smuzhiyun /*******************/
2394*4882a593Smuzhiyun
fixup_chainmask(u8 chip_chainmask,u8 eeprom_chainmask)2395*4882a593Smuzhiyun static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
2396*4882a593Smuzhiyun {
2397*4882a593Smuzhiyun eeprom_chainmask &= chip_chainmask;
2398*4882a593Smuzhiyun if (eeprom_chainmask)
2399*4882a593Smuzhiyun return eeprom_chainmask;
2400*4882a593Smuzhiyun else
2401*4882a593Smuzhiyun return chip_chainmask;
2402*4882a593Smuzhiyun }
2403*4882a593Smuzhiyun
2404*4882a593Smuzhiyun /**
2405*4882a593Smuzhiyun * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset
2406*4882a593Smuzhiyun * @ah: the atheros hardware data structure
2407*4882a593Smuzhiyun *
2408*4882a593Smuzhiyun * We enable DFS support upstream on chipsets which have passed a series
2409*4882a593Smuzhiyun * of tests. The testing requirements are going to be documented. Desired
2410*4882a593Smuzhiyun * test requirements are documented at:
2411*4882a593Smuzhiyun *
2412*4882a593Smuzhiyun * https://wireless.wiki.kernel.org/en/users/Drivers/ath9k/dfs
2413*4882a593Smuzhiyun *
2414*4882a593Smuzhiyun * Once a new chipset gets properly tested an individual commit can be used
2415*4882a593Smuzhiyun * to document the testing for DFS for that chipset.
2416*4882a593Smuzhiyun */
ath9k_hw_dfs_tested(struct ath_hw * ah)2417*4882a593Smuzhiyun static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
2418*4882a593Smuzhiyun {
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun switch (ah->hw_version.macVersion) {
2421*4882a593Smuzhiyun /* for temporary testing DFS with 9280 */
2422*4882a593Smuzhiyun case AR_SREV_VERSION_9280:
2423*4882a593Smuzhiyun /* AR9580 will likely be our first target to get testing on */
2424*4882a593Smuzhiyun case AR_SREV_VERSION_9580:
2425*4882a593Smuzhiyun return true;
2426*4882a593Smuzhiyun default:
2427*4882a593Smuzhiyun return false;
2428*4882a593Smuzhiyun }
2429*4882a593Smuzhiyun }
2430*4882a593Smuzhiyun
ath9k_gpio_cap_init(struct ath_hw * ah)2431*4882a593Smuzhiyun static void ath9k_gpio_cap_init(struct ath_hw *ah)
2432*4882a593Smuzhiyun {
2433*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
2434*4882a593Smuzhiyun
2435*4882a593Smuzhiyun if (AR_SREV_9271(ah)) {
2436*4882a593Smuzhiyun pCap->num_gpio_pins = AR9271_NUM_GPIO;
2437*4882a593Smuzhiyun pCap->gpio_mask = AR9271_GPIO_MASK;
2438*4882a593Smuzhiyun } else if (AR_DEVID_7010(ah)) {
2439*4882a593Smuzhiyun pCap->num_gpio_pins = AR7010_NUM_GPIO;
2440*4882a593Smuzhiyun pCap->gpio_mask = AR7010_GPIO_MASK;
2441*4882a593Smuzhiyun } else if (AR_SREV_9287(ah)) {
2442*4882a593Smuzhiyun pCap->num_gpio_pins = AR9287_NUM_GPIO;
2443*4882a593Smuzhiyun pCap->gpio_mask = AR9287_GPIO_MASK;
2444*4882a593Smuzhiyun } else if (AR_SREV_9285(ah)) {
2445*4882a593Smuzhiyun pCap->num_gpio_pins = AR9285_NUM_GPIO;
2446*4882a593Smuzhiyun pCap->gpio_mask = AR9285_GPIO_MASK;
2447*4882a593Smuzhiyun } else if (AR_SREV_9280(ah)) {
2448*4882a593Smuzhiyun pCap->num_gpio_pins = AR9280_NUM_GPIO;
2449*4882a593Smuzhiyun pCap->gpio_mask = AR9280_GPIO_MASK;
2450*4882a593Smuzhiyun } else if (AR_SREV_9300(ah)) {
2451*4882a593Smuzhiyun pCap->num_gpio_pins = AR9300_NUM_GPIO;
2452*4882a593Smuzhiyun pCap->gpio_mask = AR9300_GPIO_MASK;
2453*4882a593Smuzhiyun } else if (AR_SREV_9330(ah)) {
2454*4882a593Smuzhiyun pCap->num_gpio_pins = AR9330_NUM_GPIO;
2455*4882a593Smuzhiyun pCap->gpio_mask = AR9330_GPIO_MASK;
2456*4882a593Smuzhiyun } else if (AR_SREV_9340(ah)) {
2457*4882a593Smuzhiyun pCap->num_gpio_pins = AR9340_NUM_GPIO;
2458*4882a593Smuzhiyun pCap->gpio_mask = AR9340_GPIO_MASK;
2459*4882a593Smuzhiyun } else if (AR_SREV_9462(ah)) {
2460*4882a593Smuzhiyun pCap->num_gpio_pins = AR9462_NUM_GPIO;
2461*4882a593Smuzhiyun pCap->gpio_mask = AR9462_GPIO_MASK;
2462*4882a593Smuzhiyun } else if (AR_SREV_9485(ah)) {
2463*4882a593Smuzhiyun pCap->num_gpio_pins = AR9485_NUM_GPIO;
2464*4882a593Smuzhiyun pCap->gpio_mask = AR9485_GPIO_MASK;
2465*4882a593Smuzhiyun } else if (AR_SREV_9531(ah)) {
2466*4882a593Smuzhiyun pCap->num_gpio_pins = AR9531_NUM_GPIO;
2467*4882a593Smuzhiyun pCap->gpio_mask = AR9531_GPIO_MASK;
2468*4882a593Smuzhiyun } else if (AR_SREV_9550(ah)) {
2469*4882a593Smuzhiyun pCap->num_gpio_pins = AR9550_NUM_GPIO;
2470*4882a593Smuzhiyun pCap->gpio_mask = AR9550_GPIO_MASK;
2471*4882a593Smuzhiyun } else if (AR_SREV_9561(ah)) {
2472*4882a593Smuzhiyun pCap->num_gpio_pins = AR9561_NUM_GPIO;
2473*4882a593Smuzhiyun pCap->gpio_mask = AR9561_GPIO_MASK;
2474*4882a593Smuzhiyun } else if (AR_SREV_9565(ah)) {
2475*4882a593Smuzhiyun pCap->num_gpio_pins = AR9565_NUM_GPIO;
2476*4882a593Smuzhiyun pCap->gpio_mask = AR9565_GPIO_MASK;
2477*4882a593Smuzhiyun } else if (AR_SREV_9580(ah)) {
2478*4882a593Smuzhiyun pCap->num_gpio_pins = AR9580_NUM_GPIO;
2479*4882a593Smuzhiyun pCap->gpio_mask = AR9580_GPIO_MASK;
2480*4882a593Smuzhiyun } else {
2481*4882a593Smuzhiyun pCap->num_gpio_pins = AR_NUM_GPIO;
2482*4882a593Smuzhiyun pCap->gpio_mask = AR_GPIO_MASK;
2483*4882a593Smuzhiyun }
2484*4882a593Smuzhiyun }
2485*4882a593Smuzhiyun
ath9k_hw_fill_cap_info(struct ath_hw * ah)2486*4882a593Smuzhiyun int ath9k_hw_fill_cap_info(struct ath_hw *ah)
2487*4882a593Smuzhiyun {
2488*4882a593Smuzhiyun struct ath9k_hw_capabilities *pCap = &ah->caps;
2489*4882a593Smuzhiyun struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
2490*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
2491*4882a593Smuzhiyun
2492*4882a593Smuzhiyun u16 eeval;
2493*4882a593Smuzhiyun u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
2494*4882a593Smuzhiyun
2495*4882a593Smuzhiyun eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
2496*4882a593Smuzhiyun regulatory->current_rd = eeval;
2497*4882a593Smuzhiyun
2498*4882a593Smuzhiyun if (ah->opmode != NL80211_IFTYPE_AP &&
2499*4882a593Smuzhiyun ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
2500*4882a593Smuzhiyun if (regulatory->current_rd == 0x64 ||
2501*4882a593Smuzhiyun regulatory->current_rd == 0x65)
2502*4882a593Smuzhiyun regulatory->current_rd += 5;
2503*4882a593Smuzhiyun else if (regulatory->current_rd == 0x41)
2504*4882a593Smuzhiyun regulatory->current_rd = 0x43;
2505*4882a593Smuzhiyun ath_dbg(common, REGULATORY, "regdomain mapped to 0x%x\n",
2506*4882a593Smuzhiyun regulatory->current_rd);
2507*4882a593Smuzhiyun }
2508*4882a593Smuzhiyun
2509*4882a593Smuzhiyun eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
2510*4882a593Smuzhiyun
2511*4882a593Smuzhiyun if (eeval & AR5416_OPFLAGS_11A) {
2512*4882a593Smuzhiyun if (ah->disable_5ghz)
2513*4882a593Smuzhiyun ath_warn(common, "disabling 5GHz band\n");
2514*4882a593Smuzhiyun else
2515*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
2516*4882a593Smuzhiyun }
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun if (eeval & AR5416_OPFLAGS_11G) {
2519*4882a593Smuzhiyun if (ah->disable_2ghz)
2520*4882a593Smuzhiyun ath_warn(common, "disabling 2GHz band\n");
2521*4882a593Smuzhiyun else
2522*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
2523*4882a593Smuzhiyun }
2524*4882a593Smuzhiyun
2525*4882a593Smuzhiyun if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
2526*4882a593Smuzhiyun ath_err(common, "both bands are disabled\n");
2527*4882a593Smuzhiyun return -EINVAL;
2528*4882a593Smuzhiyun }
2529*4882a593Smuzhiyun
2530*4882a593Smuzhiyun ath9k_gpio_cap_init(ah);
2531*4882a593Smuzhiyun
2532*4882a593Smuzhiyun if (AR_SREV_9485(ah) ||
2533*4882a593Smuzhiyun AR_SREV_9285(ah) ||
2534*4882a593Smuzhiyun AR_SREV_9330(ah) ||
2535*4882a593Smuzhiyun AR_SREV_9565(ah))
2536*4882a593Smuzhiyun pCap->chip_chainmask = 1;
2537*4882a593Smuzhiyun else if (!AR_SREV_9280_20_OR_LATER(ah))
2538*4882a593Smuzhiyun pCap->chip_chainmask = 7;
2539*4882a593Smuzhiyun else if (!AR_SREV_9300_20_OR_LATER(ah) ||
2540*4882a593Smuzhiyun AR_SREV_9340(ah) ||
2541*4882a593Smuzhiyun AR_SREV_9462(ah) ||
2542*4882a593Smuzhiyun AR_SREV_9531(ah))
2543*4882a593Smuzhiyun pCap->chip_chainmask = 3;
2544*4882a593Smuzhiyun else
2545*4882a593Smuzhiyun pCap->chip_chainmask = 7;
2546*4882a593Smuzhiyun
2547*4882a593Smuzhiyun pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
2548*4882a593Smuzhiyun /*
2549*4882a593Smuzhiyun * For AR9271 we will temporarilly uses the rx chainmax as read from
2550*4882a593Smuzhiyun * the EEPROM.
2551*4882a593Smuzhiyun */
2552*4882a593Smuzhiyun if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
2553*4882a593Smuzhiyun !(eeval & AR5416_OPFLAGS_11A) &&
2554*4882a593Smuzhiyun !(AR_SREV_9271(ah)))
2555*4882a593Smuzhiyun /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */
2556*4882a593Smuzhiyun pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
2557*4882a593Smuzhiyun else if (AR_SREV_9100(ah))
2558*4882a593Smuzhiyun pCap->rx_chainmask = 0x7;
2559*4882a593Smuzhiyun else
2560*4882a593Smuzhiyun /* Use rx_chainmask from EEPROM. */
2561*4882a593Smuzhiyun pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
2562*4882a593Smuzhiyun
2563*4882a593Smuzhiyun pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask);
2564*4882a593Smuzhiyun pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask);
2565*4882a593Smuzhiyun ah->txchainmask = pCap->tx_chainmask;
2566*4882a593Smuzhiyun ah->rxchainmask = pCap->rx_chainmask;
2567*4882a593Smuzhiyun
2568*4882a593Smuzhiyun ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
2569*4882a593Smuzhiyun
2570*4882a593Smuzhiyun /* enable key search for every frame in an aggregate */
2571*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
2572*4882a593Smuzhiyun ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
2573*4882a593Smuzhiyun
2574*4882a593Smuzhiyun common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
2575*4882a593Smuzhiyun
2576*4882a593Smuzhiyun if (ah->hw_version.devid != AR2427_DEVID_PCIE)
2577*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_HT;
2578*4882a593Smuzhiyun else
2579*4882a593Smuzhiyun pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
2580*4882a593Smuzhiyun
2581*4882a593Smuzhiyun if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
2582*4882a593Smuzhiyun pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
2583*4882a593Smuzhiyun else
2584*4882a593Smuzhiyun pCap->rts_aggr_limit = (8 * 1024);
2585*4882a593Smuzhiyun
2586*4882a593Smuzhiyun #ifdef CONFIG_ATH9K_RFKILL
2587*4882a593Smuzhiyun ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
2588*4882a593Smuzhiyun if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
2589*4882a593Smuzhiyun ah->rfkill_gpio =
2590*4882a593Smuzhiyun MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
2591*4882a593Smuzhiyun ah->rfkill_polarity =
2592*4882a593Smuzhiyun MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
2593*4882a593Smuzhiyun
2594*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
2595*4882a593Smuzhiyun }
2596*4882a593Smuzhiyun #endif
2597*4882a593Smuzhiyun if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah))
2598*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
2599*4882a593Smuzhiyun else
2600*4882a593Smuzhiyun pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
2601*4882a593Smuzhiyun
2602*4882a593Smuzhiyun if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
2603*4882a593Smuzhiyun pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
2604*4882a593Smuzhiyun else
2605*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
2608*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
2609*4882a593Smuzhiyun if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) &&
2610*4882a593Smuzhiyun !AR_SREV_9561(ah) && !AR_SREV_9565(ah))
2611*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
2614*4882a593Smuzhiyun pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
2615*4882a593Smuzhiyun pCap->rx_status_len = sizeof(struct ar9003_rxs);
2616*4882a593Smuzhiyun pCap->tx_desc_len = sizeof(struct ar9003_txc);
2617*4882a593Smuzhiyun pCap->txs_len = sizeof(struct ar9003_txs);
2618*4882a593Smuzhiyun } else {
2619*4882a593Smuzhiyun pCap->tx_desc_len = sizeof(struct ath_desc);
2620*4882a593Smuzhiyun if (AR_SREV_9280_20(ah))
2621*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
2622*4882a593Smuzhiyun }
2623*4882a593Smuzhiyun
2624*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah))
2625*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun if (AR_SREV_9561(ah))
2628*4882a593Smuzhiyun ah->ent_mode = 0x3BDA000;
2629*4882a593Smuzhiyun else if (AR_SREV_9300_20_OR_LATER(ah))
2630*4882a593Smuzhiyun ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
2631*4882a593Smuzhiyun
2632*4882a593Smuzhiyun if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
2633*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
2634*4882a593Smuzhiyun
2635*4882a593Smuzhiyun if (AR_SREV_9285(ah)) {
2636*4882a593Smuzhiyun if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
2637*4882a593Smuzhiyun ant_div_ctl1 =
2638*4882a593Smuzhiyun ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
2639*4882a593Smuzhiyun if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) {
2640*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
2641*4882a593Smuzhiyun ath_info(common, "Enable LNA combining\n");
2642*4882a593Smuzhiyun }
2643*4882a593Smuzhiyun }
2644*4882a593Smuzhiyun }
2645*4882a593Smuzhiyun
2646*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah)) {
2647*4882a593Smuzhiyun if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
2648*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_APM;
2649*4882a593Smuzhiyun }
2650*4882a593Smuzhiyun
2651*4882a593Smuzhiyun if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
2652*4882a593Smuzhiyun ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
2653*4882a593Smuzhiyun if ((ant_div_ctl1 >> 0x6) == 0x3) {
2654*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
2655*4882a593Smuzhiyun ath_info(common, "Enable LNA combining\n");
2656*4882a593Smuzhiyun }
2657*4882a593Smuzhiyun }
2658*4882a593Smuzhiyun
2659*4882a593Smuzhiyun if (ath9k_hw_dfs_tested(ah))
2660*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_DFS;
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun tx_chainmask = pCap->tx_chainmask;
2663*4882a593Smuzhiyun rx_chainmask = pCap->rx_chainmask;
2664*4882a593Smuzhiyun while (tx_chainmask || rx_chainmask) {
2665*4882a593Smuzhiyun if (tx_chainmask & BIT(0))
2666*4882a593Smuzhiyun pCap->max_txchains++;
2667*4882a593Smuzhiyun if (rx_chainmask & BIT(0))
2668*4882a593Smuzhiyun pCap->max_rxchains++;
2669*4882a593Smuzhiyun
2670*4882a593Smuzhiyun tx_chainmask >>= 1;
2671*4882a593Smuzhiyun rx_chainmask >>= 1;
2672*4882a593Smuzhiyun }
2673*4882a593Smuzhiyun
2674*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
2675*4882a593Smuzhiyun if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
2676*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_MCI;
2677*4882a593Smuzhiyun
2678*4882a593Smuzhiyun if (AR_SREV_9462_20_OR_LATER(ah))
2679*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_RTT;
2680*4882a593Smuzhiyun }
2681*4882a593Smuzhiyun
2682*4882a593Smuzhiyun if (AR_SREV_9300_20_OR_LATER(ah) &&
2683*4882a593Smuzhiyun ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
2684*4882a593Smuzhiyun pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
2685*4882a593Smuzhiyun
2686*4882a593Smuzhiyun #ifdef CONFIG_ATH9K_WOW
2687*4882a593Smuzhiyun if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah))
2688*4882a593Smuzhiyun ah->wow.max_patterns = MAX_NUM_PATTERN;
2689*4882a593Smuzhiyun else
2690*4882a593Smuzhiyun ah->wow.max_patterns = MAX_NUM_PATTERN_LEGACY;
2691*4882a593Smuzhiyun #endif
2692*4882a593Smuzhiyun
2693*4882a593Smuzhiyun return 0;
2694*4882a593Smuzhiyun }
2695*4882a593Smuzhiyun
2696*4882a593Smuzhiyun /****************************/
2697*4882a593Smuzhiyun /* GPIO / RFKILL / Antennae */
2698*4882a593Smuzhiyun /****************************/
2699*4882a593Smuzhiyun
ath9k_hw_gpio_cfg_output_mux(struct ath_hw * ah,u32 gpio,u32 type)2700*4882a593Smuzhiyun static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type)
2701*4882a593Smuzhiyun {
2702*4882a593Smuzhiyun int addr;
2703*4882a593Smuzhiyun u32 gpio_shift, tmp;
2704*4882a593Smuzhiyun
2705*4882a593Smuzhiyun if (gpio > 11)
2706*4882a593Smuzhiyun addr = AR_GPIO_OUTPUT_MUX3;
2707*4882a593Smuzhiyun else if (gpio > 5)
2708*4882a593Smuzhiyun addr = AR_GPIO_OUTPUT_MUX2;
2709*4882a593Smuzhiyun else
2710*4882a593Smuzhiyun addr = AR_GPIO_OUTPUT_MUX1;
2711*4882a593Smuzhiyun
2712*4882a593Smuzhiyun gpio_shift = (gpio % 6) * 5;
2713*4882a593Smuzhiyun
2714*4882a593Smuzhiyun if (AR_SREV_9280_20_OR_LATER(ah) ||
2715*4882a593Smuzhiyun (addr != AR_GPIO_OUTPUT_MUX1)) {
2716*4882a593Smuzhiyun REG_RMW(ah, addr, (type << gpio_shift),
2717*4882a593Smuzhiyun (0x1f << gpio_shift));
2718*4882a593Smuzhiyun } else {
2719*4882a593Smuzhiyun tmp = REG_READ(ah, addr);
2720*4882a593Smuzhiyun tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
2721*4882a593Smuzhiyun tmp &= ~(0x1f << gpio_shift);
2722*4882a593Smuzhiyun tmp |= (type << gpio_shift);
2723*4882a593Smuzhiyun REG_WRITE(ah, addr, tmp);
2724*4882a593Smuzhiyun }
2725*4882a593Smuzhiyun }
2726*4882a593Smuzhiyun
2727*4882a593Smuzhiyun /* BSP should set the corresponding MUX register correctly.
2728*4882a593Smuzhiyun */
ath9k_hw_gpio_cfg_soc(struct ath_hw * ah,u32 gpio,bool out,const char * label)2729*4882a593Smuzhiyun static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
2730*4882a593Smuzhiyun const char *label)
2731*4882a593Smuzhiyun {
2732*4882a593Smuzhiyun int err;
2733*4882a593Smuzhiyun
2734*4882a593Smuzhiyun if (ah->caps.gpio_requested & BIT(gpio))
2735*4882a593Smuzhiyun return;
2736*4882a593Smuzhiyun
2737*4882a593Smuzhiyun err = gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label);
2738*4882a593Smuzhiyun if (err) {
2739*4882a593Smuzhiyun ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n",
2740*4882a593Smuzhiyun gpio, err);
2741*4882a593Smuzhiyun return;
2742*4882a593Smuzhiyun }
2743*4882a593Smuzhiyun
2744*4882a593Smuzhiyun ah->caps.gpio_requested |= BIT(gpio);
2745*4882a593Smuzhiyun }
2746*4882a593Smuzhiyun
ath9k_hw_gpio_cfg_wmac(struct ath_hw * ah,u32 gpio,bool out,u32 ah_signal_type)2747*4882a593Smuzhiyun static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
2748*4882a593Smuzhiyun u32 ah_signal_type)
2749*4882a593Smuzhiyun {
2750*4882a593Smuzhiyun u32 gpio_set, gpio_shift = gpio;
2751*4882a593Smuzhiyun
2752*4882a593Smuzhiyun if (AR_DEVID_7010(ah)) {
2753*4882a593Smuzhiyun gpio_set = out ?
2754*4882a593Smuzhiyun AR7010_GPIO_OE_AS_OUTPUT : AR7010_GPIO_OE_AS_INPUT;
2755*4882a593Smuzhiyun REG_RMW(ah, AR7010_GPIO_OE, gpio_set << gpio_shift,
2756*4882a593Smuzhiyun AR7010_GPIO_OE_MASK << gpio_shift);
2757*4882a593Smuzhiyun } else if (AR_SREV_SOC(ah)) {
2758*4882a593Smuzhiyun gpio_set = out ? 1 : 0;
2759*4882a593Smuzhiyun REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
2760*4882a593Smuzhiyun gpio_set << gpio_shift);
2761*4882a593Smuzhiyun } else {
2762*4882a593Smuzhiyun gpio_shift = gpio << 1;
2763*4882a593Smuzhiyun gpio_set = out ?
2764*4882a593Smuzhiyun AR_GPIO_OE_OUT_DRV_ALL : AR_GPIO_OE_OUT_DRV_NO;
2765*4882a593Smuzhiyun REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
2766*4882a593Smuzhiyun AR_GPIO_OE_OUT_DRV << gpio_shift);
2767*4882a593Smuzhiyun
2768*4882a593Smuzhiyun if (out)
2769*4882a593Smuzhiyun ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
2770*4882a593Smuzhiyun }
2771*4882a593Smuzhiyun }
2772*4882a593Smuzhiyun
ath9k_hw_gpio_request(struct ath_hw * ah,u32 gpio,bool out,const char * label,u32 ah_signal_type)2773*4882a593Smuzhiyun static void ath9k_hw_gpio_request(struct ath_hw *ah, u32 gpio, bool out,
2774*4882a593Smuzhiyun const char *label, u32 ah_signal_type)
2775*4882a593Smuzhiyun {
2776*4882a593Smuzhiyun WARN_ON(gpio >= ah->caps.num_gpio_pins);
2777*4882a593Smuzhiyun
2778*4882a593Smuzhiyun if (BIT(gpio) & ah->caps.gpio_mask)
2779*4882a593Smuzhiyun ath9k_hw_gpio_cfg_wmac(ah, gpio, out, ah_signal_type);
2780*4882a593Smuzhiyun else if (AR_SREV_SOC(ah))
2781*4882a593Smuzhiyun ath9k_hw_gpio_cfg_soc(ah, gpio, out, label);
2782*4882a593Smuzhiyun else
2783*4882a593Smuzhiyun WARN_ON(1);
2784*4882a593Smuzhiyun }
2785*4882a593Smuzhiyun
ath9k_hw_gpio_request_in(struct ath_hw * ah,u32 gpio,const char * label)2786*4882a593Smuzhiyun void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label)
2787*4882a593Smuzhiyun {
2788*4882a593Smuzhiyun ath9k_hw_gpio_request(ah, gpio, false, label, 0);
2789*4882a593Smuzhiyun }
2790*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gpio_request_in);
2791*4882a593Smuzhiyun
ath9k_hw_gpio_request_out(struct ath_hw * ah,u32 gpio,const char * label,u32 ah_signal_type)2792*4882a593Smuzhiyun void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label,
2793*4882a593Smuzhiyun u32 ah_signal_type)
2794*4882a593Smuzhiyun {
2795*4882a593Smuzhiyun ath9k_hw_gpio_request(ah, gpio, true, label, ah_signal_type);
2796*4882a593Smuzhiyun }
2797*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gpio_request_out);
2798*4882a593Smuzhiyun
ath9k_hw_gpio_free(struct ath_hw * ah,u32 gpio)2799*4882a593Smuzhiyun void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio)
2800*4882a593Smuzhiyun {
2801*4882a593Smuzhiyun if (!AR_SREV_SOC(ah))
2802*4882a593Smuzhiyun return;
2803*4882a593Smuzhiyun
2804*4882a593Smuzhiyun WARN_ON(gpio >= ah->caps.num_gpio_pins);
2805*4882a593Smuzhiyun
2806*4882a593Smuzhiyun if (ah->caps.gpio_requested & BIT(gpio)) {
2807*4882a593Smuzhiyun gpio_free(gpio);
2808*4882a593Smuzhiyun ah->caps.gpio_requested &= ~BIT(gpio);
2809*4882a593Smuzhiyun }
2810*4882a593Smuzhiyun }
2811*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gpio_free);
2812*4882a593Smuzhiyun
ath9k_hw_gpio_get(struct ath_hw * ah,u32 gpio)2813*4882a593Smuzhiyun u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
2814*4882a593Smuzhiyun {
2815*4882a593Smuzhiyun u32 val = 0xffffffff;
2816*4882a593Smuzhiyun
2817*4882a593Smuzhiyun #define MS_REG_READ(x, y) \
2818*4882a593Smuzhiyun (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & BIT(y))
2819*4882a593Smuzhiyun
2820*4882a593Smuzhiyun WARN_ON(gpio >= ah->caps.num_gpio_pins);
2821*4882a593Smuzhiyun
2822*4882a593Smuzhiyun if (BIT(gpio) & ah->caps.gpio_mask) {
2823*4882a593Smuzhiyun if (AR_SREV_9271(ah))
2824*4882a593Smuzhiyun val = MS_REG_READ(AR9271, gpio);
2825*4882a593Smuzhiyun else if (AR_SREV_9287(ah))
2826*4882a593Smuzhiyun val = MS_REG_READ(AR9287, gpio);
2827*4882a593Smuzhiyun else if (AR_SREV_9285(ah))
2828*4882a593Smuzhiyun val = MS_REG_READ(AR9285, gpio);
2829*4882a593Smuzhiyun else if (AR_SREV_9280(ah))
2830*4882a593Smuzhiyun val = MS_REG_READ(AR928X, gpio);
2831*4882a593Smuzhiyun else if (AR_DEVID_7010(ah))
2832*4882a593Smuzhiyun val = REG_READ(ah, AR7010_GPIO_IN) & BIT(gpio);
2833*4882a593Smuzhiyun else if (AR_SREV_9300_20_OR_LATER(ah))
2834*4882a593Smuzhiyun val = REG_READ(ah, AR_GPIO_IN) & BIT(gpio);
2835*4882a593Smuzhiyun else
2836*4882a593Smuzhiyun val = MS_REG_READ(AR, gpio);
2837*4882a593Smuzhiyun } else if (BIT(gpio) & ah->caps.gpio_requested) {
2838*4882a593Smuzhiyun val = gpio_get_value(gpio) & BIT(gpio);
2839*4882a593Smuzhiyun } else {
2840*4882a593Smuzhiyun WARN_ON(1);
2841*4882a593Smuzhiyun }
2842*4882a593Smuzhiyun
2843*4882a593Smuzhiyun return !!val;
2844*4882a593Smuzhiyun }
2845*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gpio_get);
2846*4882a593Smuzhiyun
ath9k_hw_set_gpio(struct ath_hw * ah,u32 gpio,u32 val)2847*4882a593Smuzhiyun void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
2848*4882a593Smuzhiyun {
2849*4882a593Smuzhiyun WARN_ON(gpio >= ah->caps.num_gpio_pins);
2850*4882a593Smuzhiyun
2851*4882a593Smuzhiyun if (AR_DEVID_7010(ah) || AR_SREV_9271(ah))
2852*4882a593Smuzhiyun val = !val;
2853*4882a593Smuzhiyun else
2854*4882a593Smuzhiyun val = !!val;
2855*4882a593Smuzhiyun
2856*4882a593Smuzhiyun if (BIT(gpio) & ah->caps.gpio_mask) {
2857*4882a593Smuzhiyun u32 out_addr = AR_DEVID_7010(ah) ?
2858*4882a593Smuzhiyun AR7010_GPIO_OUT : AR_GPIO_IN_OUT;
2859*4882a593Smuzhiyun
2860*4882a593Smuzhiyun REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
2861*4882a593Smuzhiyun } else if (BIT(gpio) & ah->caps.gpio_requested) {
2862*4882a593Smuzhiyun gpio_set_value(gpio, val);
2863*4882a593Smuzhiyun } else {
2864*4882a593Smuzhiyun WARN_ON(1);
2865*4882a593Smuzhiyun }
2866*4882a593Smuzhiyun }
2867*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_set_gpio);
2868*4882a593Smuzhiyun
ath9k_hw_setantenna(struct ath_hw * ah,u32 antenna)2869*4882a593Smuzhiyun void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
2870*4882a593Smuzhiyun {
2871*4882a593Smuzhiyun REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
2872*4882a593Smuzhiyun }
2873*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_setantenna);
2874*4882a593Smuzhiyun
2875*4882a593Smuzhiyun /*********************/
2876*4882a593Smuzhiyun /* General Operation */
2877*4882a593Smuzhiyun /*********************/
2878*4882a593Smuzhiyun
ath9k_hw_getrxfilter(struct ath_hw * ah)2879*4882a593Smuzhiyun u32 ath9k_hw_getrxfilter(struct ath_hw *ah)
2880*4882a593Smuzhiyun {
2881*4882a593Smuzhiyun u32 bits = REG_READ(ah, AR_RX_FILTER);
2882*4882a593Smuzhiyun u32 phybits = REG_READ(ah, AR_PHY_ERR);
2883*4882a593Smuzhiyun
2884*4882a593Smuzhiyun if (phybits & AR_PHY_ERR_RADAR)
2885*4882a593Smuzhiyun bits |= ATH9K_RX_FILTER_PHYRADAR;
2886*4882a593Smuzhiyun if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
2887*4882a593Smuzhiyun bits |= ATH9K_RX_FILTER_PHYERR;
2888*4882a593Smuzhiyun
2889*4882a593Smuzhiyun return bits;
2890*4882a593Smuzhiyun }
2891*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_getrxfilter);
2892*4882a593Smuzhiyun
ath9k_hw_setrxfilter(struct ath_hw * ah,u32 bits)2893*4882a593Smuzhiyun void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
2894*4882a593Smuzhiyun {
2895*4882a593Smuzhiyun u32 phybits;
2896*4882a593Smuzhiyun
2897*4882a593Smuzhiyun ENABLE_REGWRITE_BUFFER(ah);
2898*4882a593Smuzhiyun
2899*4882a593Smuzhiyun REG_WRITE(ah, AR_RX_FILTER, bits);
2900*4882a593Smuzhiyun
2901*4882a593Smuzhiyun phybits = 0;
2902*4882a593Smuzhiyun if (bits & ATH9K_RX_FILTER_PHYRADAR)
2903*4882a593Smuzhiyun phybits |= AR_PHY_ERR_RADAR;
2904*4882a593Smuzhiyun if (bits & ATH9K_RX_FILTER_PHYERR)
2905*4882a593Smuzhiyun phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
2906*4882a593Smuzhiyun REG_WRITE(ah, AR_PHY_ERR, phybits);
2907*4882a593Smuzhiyun
2908*4882a593Smuzhiyun if (phybits)
2909*4882a593Smuzhiyun REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
2910*4882a593Smuzhiyun else
2911*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
2912*4882a593Smuzhiyun
2913*4882a593Smuzhiyun REGWRITE_BUFFER_FLUSH(ah);
2914*4882a593Smuzhiyun }
2915*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_setrxfilter);
2916*4882a593Smuzhiyun
ath9k_hw_phy_disable(struct ath_hw * ah)2917*4882a593Smuzhiyun bool ath9k_hw_phy_disable(struct ath_hw *ah)
2918*4882a593Smuzhiyun {
2919*4882a593Smuzhiyun if (ath9k_hw_mci_is_enabled(ah))
2920*4882a593Smuzhiyun ar9003_mci_bt_gain_ctrl(ah);
2921*4882a593Smuzhiyun
2922*4882a593Smuzhiyun if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
2923*4882a593Smuzhiyun return false;
2924*4882a593Smuzhiyun
2925*4882a593Smuzhiyun ath9k_hw_init_pll(ah, NULL);
2926*4882a593Smuzhiyun ah->htc_reset_init = true;
2927*4882a593Smuzhiyun return true;
2928*4882a593Smuzhiyun }
2929*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_phy_disable);
2930*4882a593Smuzhiyun
ath9k_hw_disable(struct ath_hw * ah)2931*4882a593Smuzhiyun bool ath9k_hw_disable(struct ath_hw *ah)
2932*4882a593Smuzhiyun {
2933*4882a593Smuzhiyun if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
2934*4882a593Smuzhiyun return false;
2935*4882a593Smuzhiyun
2936*4882a593Smuzhiyun if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD))
2937*4882a593Smuzhiyun return false;
2938*4882a593Smuzhiyun
2939*4882a593Smuzhiyun ath9k_hw_init_pll(ah, NULL);
2940*4882a593Smuzhiyun return true;
2941*4882a593Smuzhiyun }
2942*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_disable);
2943*4882a593Smuzhiyun
get_antenna_gain(struct ath_hw * ah,struct ath9k_channel * chan)2944*4882a593Smuzhiyun static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
2945*4882a593Smuzhiyun {
2946*4882a593Smuzhiyun enum eeprom_param gain_param;
2947*4882a593Smuzhiyun
2948*4882a593Smuzhiyun if (IS_CHAN_2GHZ(chan))
2949*4882a593Smuzhiyun gain_param = EEP_ANTENNA_GAIN_2G;
2950*4882a593Smuzhiyun else
2951*4882a593Smuzhiyun gain_param = EEP_ANTENNA_GAIN_5G;
2952*4882a593Smuzhiyun
2953*4882a593Smuzhiyun return ah->eep_ops->get_eeprom(ah, gain_param);
2954*4882a593Smuzhiyun }
2955*4882a593Smuzhiyun
ath9k_hw_apply_txpower(struct ath_hw * ah,struct ath9k_channel * chan,bool test)2956*4882a593Smuzhiyun void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
2957*4882a593Smuzhiyun bool test)
2958*4882a593Smuzhiyun {
2959*4882a593Smuzhiyun struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
2960*4882a593Smuzhiyun struct ieee80211_channel *channel;
2961*4882a593Smuzhiyun int chan_pwr, new_pwr;
2962*4882a593Smuzhiyun u16 ctl = NO_CTL;
2963*4882a593Smuzhiyun
2964*4882a593Smuzhiyun if (!chan)
2965*4882a593Smuzhiyun return;
2966*4882a593Smuzhiyun
2967*4882a593Smuzhiyun if (!test)
2968*4882a593Smuzhiyun ctl = ath9k_regd_get_ctl(reg, chan);
2969*4882a593Smuzhiyun
2970*4882a593Smuzhiyun channel = chan->chan;
2971*4882a593Smuzhiyun chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER);
2972*4882a593Smuzhiyun new_pwr = min_t(int, chan_pwr, reg->power_limit);
2973*4882a593Smuzhiyun
2974*4882a593Smuzhiyun ah->eep_ops->set_txpower(ah, chan, ctl,
2975*4882a593Smuzhiyun get_antenna_gain(ah, chan), new_pwr, test);
2976*4882a593Smuzhiyun }
2977*4882a593Smuzhiyun
ath9k_hw_set_txpowerlimit(struct ath_hw * ah,u32 limit,bool test)2978*4882a593Smuzhiyun void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
2979*4882a593Smuzhiyun {
2980*4882a593Smuzhiyun struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
2981*4882a593Smuzhiyun struct ath9k_channel *chan = ah->curchan;
2982*4882a593Smuzhiyun struct ieee80211_channel *channel = chan->chan;
2983*4882a593Smuzhiyun
2984*4882a593Smuzhiyun reg->power_limit = min_t(u32, limit, MAX_COMBINED_POWER);
2985*4882a593Smuzhiyun if (test)
2986*4882a593Smuzhiyun channel->max_power = MAX_COMBINED_POWER / 2;
2987*4882a593Smuzhiyun
2988*4882a593Smuzhiyun ath9k_hw_apply_txpower(ah, chan, test);
2989*4882a593Smuzhiyun
2990*4882a593Smuzhiyun if (test)
2991*4882a593Smuzhiyun channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
2992*4882a593Smuzhiyun }
2993*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
2994*4882a593Smuzhiyun
ath9k_hw_setopmode(struct ath_hw * ah)2995*4882a593Smuzhiyun void ath9k_hw_setopmode(struct ath_hw *ah)
2996*4882a593Smuzhiyun {
2997*4882a593Smuzhiyun ath9k_hw_set_operating_mode(ah, ah->opmode);
2998*4882a593Smuzhiyun }
2999*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_setopmode);
3000*4882a593Smuzhiyun
ath9k_hw_setmcastfilter(struct ath_hw * ah,u32 filter0,u32 filter1)3001*4882a593Smuzhiyun void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
3002*4882a593Smuzhiyun {
3003*4882a593Smuzhiyun REG_WRITE(ah, AR_MCAST_FIL0, filter0);
3004*4882a593Smuzhiyun REG_WRITE(ah, AR_MCAST_FIL1, filter1);
3005*4882a593Smuzhiyun }
3006*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_setmcastfilter);
3007*4882a593Smuzhiyun
ath9k_hw_write_associd(struct ath_hw * ah)3008*4882a593Smuzhiyun void ath9k_hw_write_associd(struct ath_hw *ah)
3009*4882a593Smuzhiyun {
3010*4882a593Smuzhiyun struct ath_common *common = ath9k_hw_common(ah);
3011*4882a593Smuzhiyun
3012*4882a593Smuzhiyun REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid));
3013*4882a593Smuzhiyun REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) |
3014*4882a593Smuzhiyun ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
3015*4882a593Smuzhiyun }
3016*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_write_associd);
3017*4882a593Smuzhiyun
3018*4882a593Smuzhiyun #define ATH9K_MAX_TSF_READ 10
3019*4882a593Smuzhiyun
ath9k_hw_gettsf64(struct ath_hw * ah)3020*4882a593Smuzhiyun u64 ath9k_hw_gettsf64(struct ath_hw *ah)
3021*4882a593Smuzhiyun {
3022*4882a593Smuzhiyun u32 tsf_lower, tsf_upper1, tsf_upper2;
3023*4882a593Smuzhiyun int i;
3024*4882a593Smuzhiyun
3025*4882a593Smuzhiyun tsf_upper1 = REG_READ(ah, AR_TSF_U32);
3026*4882a593Smuzhiyun for (i = 0; i < ATH9K_MAX_TSF_READ; i++) {
3027*4882a593Smuzhiyun tsf_lower = REG_READ(ah, AR_TSF_L32);
3028*4882a593Smuzhiyun tsf_upper2 = REG_READ(ah, AR_TSF_U32);
3029*4882a593Smuzhiyun if (tsf_upper2 == tsf_upper1)
3030*4882a593Smuzhiyun break;
3031*4882a593Smuzhiyun tsf_upper1 = tsf_upper2;
3032*4882a593Smuzhiyun }
3033*4882a593Smuzhiyun
3034*4882a593Smuzhiyun WARN_ON( i == ATH9K_MAX_TSF_READ );
3035*4882a593Smuzhiyun
3036*4882a593Smuzhiyun return (((u64)tsf_upper1 << 32) | tsf_lower);
3037*4882a593Smuzhiyun }
3038*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gettsf64);
3039*4882a593Smuzhiyun
ath9k_hw_settsf64(struct ath_hw * ah,u64 tsf64)3040*4882a593Smuzhiyun void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
3041*4882a593Smuzhiyun {
3042*4882a593Smuzhiyun REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
3043*4882a593Smuzhiyun REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
3044*4882a593Smuzhiyun }
3045*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_settsf64);
3046*4882a593Smuzhiyun
ath9k_hw_reset_tsf(struct ath_hw * ah)3047*4882a593Smuzhiyun void ath9k_hw_reset_tsf(struct ath_hw *ah)
3048*4882a593Smuzhiyun {
3049*4882a593Smuzhiyun if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0,
3050*4882a593Smuzhiyun AH_TSF_WRITE_TIMEOUT))
3051*4882a593Smuzhiyun ath_dbg(ath9k_hw_common(ah), RESET,
3052*4882a593Smuzhiyun "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
3053*4882a593Smuzhiyun
3054*4882a593Smuzhiyun REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
3055*4882a593Smuzhiyun }
3056*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_reset_tsf);
3057*4882a593Smuzhiyun
ath9k_hw_set_tsfadjust(struct ath_hw * ah,bool set)3058*4882a593Smuzhiyun void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set)
3059*4882a593Smuzhiyun {
3060*4882a593Smuzhiyun if (set)
3061*4882a593Smuzhiyun ah->misc_mode |= AR_PCU_TX_ADD_TSF;
3062*4882a593Smuzhiyun else
3063*4882a593Smuzhiyun ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
3064*4882a593Smuzhiyun }
3065*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_set_tsfadjust);
3066*4882a593Smuzhiyun
ath9k_hw_set11nmac2040(struct ath_hw * ah,struct ath9k_channel * chan)3067*4882a593Smuzhiyun void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan)
3068*4882a593Smuzhiyun {
3069*4882a593Smuzhiyun u32 macmode;
3070*4882a593Smuzhiyun
3071*4882a593Smuzhiyun if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca)
3072*4882a593Smuzhiyun macmode = AR_2040_JOINED_RX_CLEAR;
3073*4882a593Smuzhiyun else
3074*4882a593Smuzhiyun macmode = 0;
3075*4882a593Smuzhiyun
3076*4882a593Smuzhiyun REG_WRITE(ah, AR_2040_MODE, macmode);
3077*4882a593Smuzhiyun }
3078*4882a593Smuzhiyun
3079*4882a593Smuzhiyun /* HW Generic timers configuration */
3080*4882a593Smuzhiyun
3081*4882a593Smuzhiyun static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
3082*4882a593Smuzhiyun {
3083*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3084*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3085*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3086*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3087*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3088*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3089*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3090*4882a593Smuzhiyun {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
3091*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER, AR_NDP2_PERIOD, AR_NDP2_TIMER_MODE, 0x0001},
3092*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 1*4, AR_NDP2_PERIOD + 1*4,
3093*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0002},
3094*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 2*4, AR_NDP2_PERIOD + 2*4,
3095*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0004},
3096*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 3*4, AR_NDP2_PERIOD + 3*4,
3097*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0008},
3098*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 4*4, AR_NDP2_PERIOD + 4*4,
3099*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0010},
3100*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 5*4, AR_NDP2_PERIOD + 5*4,
3101*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0020},
3102*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 6*4, AR_NDP2_PERIOD + 6*4,
3103*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0040},
3104*4882a593Smuzhiyun {AR_NEXT_NDP2_TIMER + 7*4, AR_NDP2_PERIOD + 7*4,
3105*4882a593Smuzhiyun AR_NDP2_TIMER_MODE, 0x0080}
3106*4882a593Smuzhiyun };
3107*4882a593Smuzhiyun
3108*4882a593Smuzhiyun /* HW generic timer primitives */
3109*4882a593Smuzhiyun
ath9k_hw_gettsf32(struct ath_hw * ah)3110*4882a593Smuzhiyun u32 ath9k_hw_gettsf32(struct ath_hw *ah)
3111*4882a593Smuzhiyun {
3112*4882a593Smuzhiyun return REG_READ(ah, AR_TSF_L32);
3113*4882a593Smuzhiyun }
3114*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gettsf32);
3115*4882a593Smuzhiyun
ath9k_hw_gen_timer_start_tsf2(struct ath_hw * ah)3116*4882a593Smuzhiyun void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah)
3117*4882a593Smuzhiyun {
3118*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3119*4882a593Smuzhiyun
3120*4882a593Smuzhiyun if (timer_table->tsf2_enabled) {
3121*4882a593Smuzhiyun REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
3122*4882a593Smuzhiyun REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
3123*4882a593Smuzhiyun }
3124*4882a593Smuzhiyun }
3125*4882a593Smuzhiyun
ath_gen_timer_alloc(struct ath_hw * ah,void (* trigger)(void *),void (* overflow)(void *),void * arg,u8 timer_index)3126*4882a593Smuzhiyun struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
3127*4882a593Smuzhiyun void (*trigger)(void *),
3128*4882a593Smuzhiyun void (*overflow)(void *),
3129*4882a593Smuzhiyun void *arg,
3130*4882a593Smuzhiyun u8 timer_index)
3131*4882a593Smuzhiyun {
3132*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3133*4882a593Smuzhiyun struct ath_gen_timer *timer;
3134*4882a593Smuzhiyun
3135*4882a593Smuzhiyun if ((timer_index < AR_FIRST_NDP_TIMER) ||
3136*4882a593Smuzhiyun (timer_index >= ATH_MAX_GEN_TIMER))
3137*4882a593Smuzhiyun return NULL;
3138*4882a593Smuzhiyun
3139*4882a593Smuzhiyun if ((timer_index > AR_FIRST_NDP_TIMER) &&
3140*4882a593Smuzhiyun !AR_SREV_9300_20_OR_LATER(ah))
3141*4882a593Smuzhiyun return NULL;
3142*4882a593Smuzhiyun
3143*4882a593Smuzhiyun timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
3144*4882a593Smuzhiyun if (timer == NULL)
3145*4882a593Smuzhiyun return NULL;
3146*4882a593Smuzhiyun
3147*4882a593Smuzhiyun /* allocate a hardware generic timer slot */
3148*4882a593Smuzhiyun timer_table->timers[timer_index] = timer;
3149*4882a593Smuzhiyun timer->index = timer_index;
3150*4882a593Smuzhiyun timer->trigger = trigger;
3151*4882a593Smuzhiyun timer->overflow = overflow;
3152*4882a593Smuzhiyun timer->arg = arg;
3153*4882a593Smuzhiyun
3154*4882a593Smuzhiyun if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) {
3155*4882a593Smuzhiyun timer_table->tsf2_enabled = true;
3156*4882a593Smuzhiyun ath9k_hw_gen_timer_start_tsf2(ah);
3157*4882a593Smuzhiyun }
3158*4882a593Smuzhiyun
3159*4882a593Smuzhiyun return timer;
3160*4882a593Smuzhiyun }
3161*4882a593Smuzhiyun EXPORT_SYMBOL(ath_gen_timer_alloc);
3162*4882a593Smuzhiyun
ath9k_hw_gen_timer_start(struct ath_hw * ah,struct ath_gen_timer * timer,u32 timer_next,u32 timer_period)3163*4882a593Smuzhiyun void ath9k_hw_gen_timer_start(struct ath_hw *ah,
3164*4882a593Smuzhiyun struct ath_gen_timer *timer,
3165*4882a593Smuzhiyun u32 timer_next,
3166*4882a593Smuzhiyun u32 timer_period)
3167*4882a593Smuzhiyun {
3168*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3169*4882a593Smuzhiyun u32 mask = 0;
3170*4882a593Smuzhiyun
3171*4882a593Smuzhiyun timer_table->timer_mask |= BIT(timer->index);
3172*4882a593Smuzhiyun
3173*4882a593Smuzhiyun /*
3174*4882a593Smuzhiyun * Program generic timer registers
3175*4882a593Smuzhiyun */
3176*4882a593Smuzhiyun REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr,
3177*4882a593Smuzhiyun timer_next);
3178*4882a593Smuzhiyun REG_WRITE(ah, gen_tmr_configuration[timer->index].period_addr,
3179*4882a593Smuzhiyun timer_period);
3180*4882a593Smuzhiyun REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
3181*4882a593Smuzhiyun gen_tmr_configuration[timer->index].mode_mask);
3182*4882a593Smuzhiyun
3183*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
3184*4882a593Smuzhiyun /*
3185*4882a593Smuzhiyun * Starting from AR9462, each generic timer can select which tsf
3186*4882a593Smuzhiyun * to use. But we still follow the old rule, 0 - 7 use tsf and
3187*4882a593Smuzhiyun * 8 - 15 use tsf2.
3188*4882a593Smuzhiyun */
3189*4882a593Smuzhiyun if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
3190*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
3191*4882a593Smuzhiyun (1 << timer->index));
3192*4882a593Smuzhiyun else
3193*4882a593Smuzhiyun REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
3194*4882a593Smuzhiyun (1 << timer->index));
3195*4882a593Smuzhiyun }
3196*4882a593Smuzhiyun
3197*4882a593Smuzhiyun if (timer->trigger)
3198*4882a593Smuzhiyun mask |= SM(AR_GENTMR_BIT(timer->index),
3199*4882a593Smuzhiyun AR_IMR_S5_GENTIMER_TRIG);
3200*4882a593Smuzhiyun if (timer->overflow)
3201*4882a593Smuzhiyun mask |= SM(AR_GENTMR_BIT(timer->index),
3202*4882a593Smuzhiyun AR_IMR_S5_GENTIMER_THRESH);
3203*4882a593Smuzhiyun
3204*4882a593Smuzhiyun REG_SET_BIT(ah, AR_IMR_S5, mask);
3205*4882a593Smuzhiyun
3206*4882a593Smuzhiyun if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
3207*4882a593Smuzhiyun ah->imask |= ATH9K_INT_GENTIMER;
3208*4882a593Smuzhiyun ath9k_hw_set_interrupts(ah);
3209*4882a593Smuzhiyun }
3210*4882a593Smuzhiyun }
3211*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
3212*4882a593Smuzhiyun
ath9k_hw_gen_timer_stop(struct ath_hw * ah,struct ath_gen_timer * timer)3213*4882a593Smuzhiyun void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
3214*4882a593Smuzhiyun {
3215*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3216*4882a593Smuzhiyun
3217*4882a593Smuzhiyun /* Clear generic timer enable bits. */
3218*4882a593Smuzhiyun REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
3219*4882a593Smuzhiyun gen_tmr_configuration[timer->index].mode_mask);
3220*4882a593Smuzhiyun
3221*4882a593Smuzhiyun if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
3222*4882a593Smuzhiyun /*
3223*4882a593Smuzhiyun * Need to switch back to TSF if it was using TSF2.
3224*4882a593Smuzhiyun */
3225*4882a593Smuzhiyun if ((timer->index >= AR_GEN_TIMER_BANK_1_LEN)) {
3226*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
3227*4882a593Smuzhiyun (1 << timer->index));
3228*4882a593Smuzhiyun }
3229*4882a593Smuzhiyun }
3230*4882a593Smuzhiyun
3231*4882a593Smuzhiyun /* Disable both trigger and thresh interrupt masks */
3232*4882a593Smuzhiyun REG_CLR_BIT(ah, AR_IMR_S5,
3233*4882a593Smuzhiyun (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
3234*4882a593Smuzhiyun SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
3235*4882a593Smuzhiyun
3236*4882a593Smuzhiyun timer_table->timer_mask &= ~BIT(timer->index);
3237*4882a593Smuzhiyun
3238*4882a593Smuzhiyun if (timer_table->timer_mask == 0) {
3239*4882a593Smuzhiyun ah->imask &= ~ATH9K_INT_GENTIMER;
3240*4882a593Smuzhiyun ath9k_hw_set_interrupts(ah);
3241*4882a593Smuzhiyun }
3242*4882a593Smuzhiyun }
3243*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
3244*4882a593Smuzhiyun
ath_gen_timer_free(struct ath_hw * ah,struct ath_gen_timer * timer)3245*4882a593Smuzhiyun void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer)
3246*4882a593Smuzhiyun {
3247*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3248*4882a593Smuzhiyun
3249*4882a593Smuzhiyun /* free the hardware generic timer slot */
3250*4882a593Smuzhiyun timer_table->timers[timer->index] = NULL;
3251*4882a593Smuzhiyun kfree(timer);
3252*4882a593Smuzhiyun }
3253*4882a593Smuzhiyun EXPORT_SYMBOL(ath_gen_timer_free);
3254*4882a593Smuzhiyun
3255*4882a593Smuzhiyun /*
3256*4882a593Smuzhiyun * Generic Timer Interrupts handling
3257*4882a593Smuzhiyun */
ath_gen_timer_isr(struct ath_hw * ah)3258*4882a593Smuzhiyun void ath_gen_timer_isr(struct ath_hw *ah)
3259*4882a593Smuzhiyun {
3260*4882a593Smuzhiyun struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
3261*4882a593Smuzhiyun struct ath_gen_timer *timer;
3262*4882a593Smuzhiyun unsigned long trigger_mask, thresh_mask;
3263*4882a593Smuzhiyun unsigned int index;
3264*4882a593Smuzhiyun
3265*4882a593Smuzhiyun /* get hardware generic timer interrupt status */
3266*4882a593Smuzhiyun trigger_mask = ah->intr_gen_timer_trigger;
3267*4882a593Smuzhiyun thresh_mask = ah->intr_gen_timer_thresh;
3268*4882a593Smuzhiyun trigger_mask &= timer_table->timer_mask;
3269*4882a593Smuzhiyun thresh_mask &= timer_table->timer_mask;
3270*4882a593Smuzhiyun
3271*4882a593Smuzhiyun for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) {
3272*4882a593Smuzhiyun timer = timer_table->timers[index];
3273*4882a593Smuzhiyun if (!timer)
3274*4882a593Smuzhiyun continue;
3275*4882a593Smuzhiyun if (!timer->overflow)
3276*4882a593Smuzhiyun continue;
3277*4882a593Smuzhiyun
3278*4882a593Smuzhiyun trigger_mask &= ~BIT(index);
3279*4882a593Smuzhiyun timer->overflow(timer->arg);
3280*4882a593Smuzhiyun }
3281*4882a593Smuzhiyun
3282*4882a593Smuzhiyun for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) {
3283*4882a593Smuzhiyun timer = timer_table->timers[index];
3284*4882a593Smuzhiyun if (!timer)
3285*4882a593Smuzhiyun continue;
3286*4882a593Smuzhiyun if (!timer->trigger)
3287*4882a593Smuzhiyun continue;
3288*4882a593Smuzhiyun timer->trigger(timer->arg);
3289*4882a593Smuzhiyun }
3290*4882a593Smuzhiyun }
3291*4882a593Smuzhiyun EXPORT_SYMBOL(ath_gen_timer_isr);
3292*4882a593Smuzhiyun
3293*4882a593Smuzhiyun /********/
3294*4882a593Smuzhiyun /* HTC */
3295*4882a593Smuzhiyun /********/
3296*4882a593Smuzhiyun
3297*4882a593Smuzhiyun static struct {
3298*4882a593Smuzhiyun u32 version;
3299*4882a593Smuzhiyun const char * name;
3300*4882a593Smuzhiyun } ath_mac_bb_names[] = {
3301*4882a593Smuzhiyun /* Devices with external radios */
3302*4882a593Smuzhiyun { AR_SREV_VERSION_5416_PCI, "5416" },
3303*4882a593Smuzhiyun { AR_SREV_VERSION_5416_PCIE, "5418" },
3304*4882a593Smuzhiyun { AR_SREV_VERSION_9100, "9100" },
3305*4882a593Smuzhiyun { AR_SREV_VERSION_9160, "9160" },
3306*4882a593Smuzhiyun /* Single-chip solutions */
3307*4882a593Smuzhiyun { AR_SREV_VERSION_9280, "9280" },
3308*4882a593Smuzhiyun { AR_SREV_VERSION_9285, "9285" },
3309*4882a593Smuzhiyun { AR_SREV_VERSION_9287, "9287" },
3310*4882a593Smuzhiyun { AR_SREV_VERSION_9271, "9271" },
3311*4882a593Smuzhiyun { AR_SREV_VERSION_9300, "9300" },
3312*4882a593Smuzhiyun { AR_SREV_VERSION_9330, "9330" },
3313*4882a593Smuzhiyun { AR_SREV_VERSION_9340, "9340" },
3314*4882a593Smuzhiyun { AR_SREV_VERSION_9485, "9485" },
3315*4882a593Smuzhiyun { AR_SREV_VERSION_9462, "9462" },
3316*4882a593Smuzhiyun { AR_SREV_VERSION_9550, "9550" },
3317*4882a593Smuzhiyun { AR_SREV_VERSION_9565, "9565" },
3318*4882a593Smuzhiyun { AR_SREV_VERSION_9531, "9531" },
3319*4882a593Smuzhiyun { AR_SREV_VERSION_9561, "9561" },
3320*4882a593Smuzhiyun };
3321*4882a593Smuzhiyun
3322*4882a593Smuzhiyun /* For devices with external radios */
3323*4882a593Smuzhiyun static struct {
3324*4882a593Smuzhiyun u16 version;
3325*4882a593Smuzhiyun const char * name;
3326*4882a593Smuzhiyun } ath_rf_names[] = {
3327*4882a593Smuzhiyun { 0, "5133" },
3328*4882a593Smuzhiyun { AR_RAD5133_SREV_MAJOR, "5133" },
3329*4882a593Smuzhiyun { AR_RAD5122_SREV_MAJOR, "5122" },
3330*4882a593Smuzhiyun { AR_RAD2133_SREV_MAJOR, "2133" },
3331*4882a593Smuzhiyun { AR_RAD2122_SREV_MAJOR, "2122" }
3332*4882a593Smuzhiyun };
3333*4882a593Smuzhiyun
3334*4882a593Smuzhiyun /*
3335*4882a593Smuzhiyun * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
3336*4882a593Smuzhiyun */
ath9k_hw_mac_bb_name(u32 mac_bb_version)3337*4882a593Smuzhiyun static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
3338*4882a593Smuzhiyun {
3339*4882a593Smuzhiyun int i;
3340*4882a593Smuzhiyun
3341*4882a593Smuzhiyun for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
3342*4882a593Smuzhiyun if (ath_mac_bb_names[i].version == mac_bb_version) {
3343*4882a593Smuzhiyun return ath_mac_bb_names[i].name;
3344*4882a593Smuzhiyun }
3345*4882a593Smuzhiyun }
3346*4882a593Smuzhiyun
3347*4882a593Smuzhiyun return "????";
3348*4882a593Smuzhiyun }
3349*4882a593Smuzhiyun
3350*4882a593Smuzhiyun /*
3351*4882a593Smuzhiyun * Return the RF name. "????" is returned if the RF is unknown.
3352*4882a593Smuzhiyun * Used for devices with external radios.
3353*4882a593Smuzhiyun */
ath9k_hw_rf_name(u16 rf_version)3354*4882a593Smuzhiyun static const char *ath9k_hw_rf_name(u16 rf_version)
3355*4882a593Smuzhiyun {
3356*4882a593Smuzhiyun int i;
3357*4882a593Smuzhiyun
3358*4882a593Smuzhiyun for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
3359*4882a593Smuzhiyun if (ath_rf_names[i].version == rf_version) {
3360*4882a593Smuzhiyun return ath_rf_names[i].name;
3361*4882a593Smuzhiyun }
3362*4882a593Smuzhiyun }
3363*4882a593Smuzhiyun
3364*4882a593Smuzhiyun return "????";
3365*4882a593Smuzhiyun }
3366*4882a593Smuzhiyun
ath9k_hw_name(struct ath_hw * ah,char * hw_name,size_t len)3367*4882a593Smuzhiyun void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
3368*4882a593Smuzhiyun {
3369*4882a593Smuzhiyun int used;
3370*4882a593Smuzhiyun
3371*4882a593Smuzhiyun /* chipsets >= AR9280 are single-chip */
3372*4882a593Smuzhiyun if (AR_SREV_9280_20_OR_LATER(ah)) {
3373*4882a593Smuzhiyun used = scnprintf(hw_name, len,
3374*4882a593Smuzhiyun "Atheros AR%s Rev:%x",
3375*4882a593Smuzhiyun ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
3376*4882a593Smuzhiyun ah->hw_version.macRev);
3377*4882a593Smuzhiyun }
3378*4882a593Smuzhiyun else {
3379*4882a593Smuzhiyun used = scnprintf(hw_name, len,
3380*4882a593Smuzhiyun "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
3381*4882a593Smuzhiyun ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
3382*4882a593Smuzhiyun ah->hw_version.macRev,
3383*4882a593Smuzhiyun ath9k_hw_rf_name((ah->hw_version.analog5GhzRev
3384*4882a593Smuzhiyun & AR_RADIO_SREV_MAJOR)),
3385*4882a593Smuzhiyun ah->hw_version.phyRev);
3386*4882a593Smuzhiyun }
3387*4882a593Smuzhiyun
3388*4882a593Smuzhiyun hw_name[used] = '\0';
3389*4882a593Smuzhiyun }
3390*4882a593Smuzhiyun EXPORT_SYMBOL(ath9k_hw_name);
3391