diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath5k/Makefile | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/ath5k.h | 390 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/attach.c | 315 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/caps.c | 193 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/debug.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/desc.c | 667 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/desc.h (renamed from drivers/net/wireless/ath5k/hw.h) | 400 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/dma.c | 566 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/eeprom.c | 466 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/eeprom.h | 215 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/gpio.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/hw.c | 4492 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/initvals.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/pcu.c | 1002 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/phy.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/qcu.c | 488 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/reg.h | 102 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/reset.c | 925 |
19 files changed, 5435 insertions, 5042 deletions
diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index 564ecd0c5d4b..719cfaef7085 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile | |||
@@ -1,6 +1,14 @@ | |||
1 | ath5k-y += base.o | 1 | ath5k-y += caps.o |
2 | ath5k-y += hw.o | ||
3 | ath5k-y += initvals.o | 2 | ath5k-y += initvals.o |
3 | ath5k-y += eeprom.o | ||
4 | ath5k-y += gpio.o | ||
5 | ath5k-y += desc.o | ||
6 | ath5k-y += dma.o | ||
7 | ath5k-y += qcu.o | ||
8 | ath5k-y += pcu.o | ||
4 | ath5k-y += phy.o | 9 | ath5k-y += phy.o |
10 | ath5k-y += reset.o | ||
11 | ath5k-y += attach.o | ||
12 | ath5k-y += base.o | ||
5 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 13 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
6 | obj-$(CONFIG_ATH5K) += ath5k.o | 14 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index c1b497873668..4c0211798a7a 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -18,18 +18,23 @@ | |||
18 | #ifndef _ATH5K_H | 18 | #ifndef _ATH5K_H |
19 | #define _ATH5K_H | 19 | #define _ATH5K_H |
20 | 20 | ||
21 | /* Set this to 1 to disable regulatory domain restrictions for channel tests. | 21 | /* TODO: Clean up channel debuging -doesn't work anyway- and start |
22 | * WARNING: This is for debuging only and has side effects (eg. scan takes too | 22 | * working on reg. control code using all available eeprom information |
23 | * long and results timeouts). It's also illegal to tune to some of the | 23 | * -rev. engineering needed- */ |
24 | * supported frequencies in some countries, so use this at your own risk, | ||
25 | * you've been warned. */ | ||
26 | #define CHAN_DEBUG 0 | 24 | #define CHAN_DEBUG 0 |
27 | 25 | ||
28 | #include <linux/io.h> | 26 | #include <linux/io.h> |
29 | #include <linux/types.h> | 27 | #include <linux/types.h> |
30 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
31 | 29 | ||
32 | #include "hw.h" | 30 | /* RX/TX descriptor hw structs |
31 | * TODO: Driver part should only see sw structs */ | ||
32 | #include "desc.h" | ||
33 | |||
34 | /* EEPROM structs/offsets | ||
35 | * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) | ||
36 | * and clean up common bits, then introduce set/get functions in eeprom.c */ | ||
37 | #include "eeprom.h" | ||
33 | 38 | ||
34 | /* PCI IDs */ | 39 | /* PCI IDs */ |
35 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ | 40 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ |
@@ -87,7 +92,92 @@ | |||
87 | ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) | 92 | ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) |
88 | 93 | ||
89 | /* | 94 | /* |
95 | * AR5K REGISTER ACCESS | ||
96 | */ | ||
97 | |||
98 | /* Some macros to read/write fields */ | ||
99 | |||
100 | /* First shift, then mask */ | ||
101 | #define AR5K_REG_SM(_val, _flags) \ | ||
102 | (((_val) << _flags##_S) & (_flags)) | ||
103 | |||
104 | /* First mask, then shift */ | ||
105 | #define AR5K_REG_MS(_val, _flags) \ | ||
106 | (((_val) & (_flags)) >> _flags##_S) | ||
107 | |||
108 | /* Some registers can hold multiple values of interest. For this | ||
109 | * reason when we want to write to these registers we must first | ||
110 | * retrieve the values which we do not want to clear (lets call this | ||
111 | * old_data) and then set the register with this and our new_value: | ||
112 | * ( old_data | new_value) */ | ||
113 | #define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ | ||
114 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ | ||
115 | (((_val) << _flags##_S) & (_flags)), _reg) | ||
116 | |||
117 | #define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ | ||
118 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ | ||
119 | (_mask)) | (_flags), _reg) | ||
120 | |||
121 | #define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ | ||
122 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) | ||
123 | |||
124 | #define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ | ||
125 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) | ||
126 | |||
127 | /* Access to PHY registers */ | ||
128 | #define AR5K_PHY_READ(ah, _reg) \ | ||
129 | ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) | ||
130 | |||
131 | #define AR5K_PHY_WRITE(ah, _reg, _val) \ | ||
132 | ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) | ||
133 | |||
134 | /* Access QCU registers per queue */ | ||
135 | #define AR5K_REG_READ_Q(ah, _reg, _queue) \ | ||
136 | (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ | ||
137 | |||
138 | #define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ | ||
139 | ath5k_hw_reg_write(ah, (1 << _queue), _reg) | ||
140 | |||
141 | #define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ | ||
142 | _reg |= 1 << _queue; \ | ||
143 | } while (0) | ||
144 | |||
145 | #define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ | ||
146 | _reg &= ~(1 << _queue); \ | ||
147 | } while (0) | ||
148 | |||
149 | /* Used while writing initvals */ | ||
150 | #define AR5K_REG_WAIT(_i) do { \ | ||
151 | if (_i % 64) \ | ||
152 | udelay(1); \ | ||
153 | } while (0) | ||
154 | |||
155 | /* Register dumps are done per operation mode */ | ||
156 | #define AR5K_INI_RFGAIN_5GHZ 0 | ||
157 | #define AR5K_INI_RFGAIN_2GHZ 1 | ||
158 | |||
159 | /* TODO: Clean this up */ | ||
160 | #define AR5K_INI_VAL_11A 0 | ||
161 | #define AR5K_INI_VAL_11A_TURBO 1 | ||
162 | #define AR5K_INI_VAL_11B 2 | ||
163 | #define AR5K_INI_VAL_11G 3 | ||
164 | #define AR5K_INI_VAL_11G_TURBO 4 | ||
165 | #define AR5K_INI_VAL_XR 0 | ||
166 | #define AR5K_INI_VAL_MAX 5 | ||
167 | |||
168 | #define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
169 | #define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
170 | |||
171 | /* Used for BSSID etc manipulation */ | ||
172 | #define AR5K_LOW_ID(_a)( \ | ||
173 | (_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ | ||
174 | ) | ||
175 | |||
176 | #define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) | ||
177 | |||
178 | /* | ||
90 | * Some tuneable values (these should be changeable by the user) | 179 | * Some tuneable values (these should be changeable by the user) |
180 | * TODO: Make use of them and add more options OR use debug/configfs | ||
91 | */ | 181 | */ |
92 | #define AR5K_TUNE_DMA_BEACON_RESP 2 | 182 | #define AR5K_TUNE_DMA_BEACON_RESP 2 |
93 | #define AR5K_TUNE_SW_BEACON_RESP 10 | 183 | #define AR5K_TUNE_SW_BEACON_RESP 10 |
@@ -98,13 +188,13 @@ | |||
98 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 | 188 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 |
99 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to | 189 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to |
100 | * be the max value. */ | 190 | * be the max value. */ |
101 | #define AR5K_TUNE_RSSI_THRES 129 | 191 | #define AR5K_TUNE_RSSI_THRES 129 |
102 | /* This must be set when setting the RSSI threshold otherwise it can | 192 | /* This must be set when setting the RSSI threshold otherwise it can |
103 | * prevent a reset. If AR5K_RSSI_THR is read after writing to it | 193 | * prevent a reset. If AR5K_RSSI_THR is read after writing to it |
104 | * the BMISS_THRES will be seen as 0, seems harware doesn't keep | 194 | * the BMISS_THRES will be seen as 0, seems harware doesn't keep |
105 | * track of it. Max value depends on harware. For AR5210 this is just 7. | 195 | * track of it. Max value depends on harware. For AR5210 this is just 7. |
106 | * For AR5211+ this seems to be up to 255. */ | 196 | * For AR5211+ this seems to be up to 255. */ |
107 | #define AR5K_TUNE_BMISS_THRES 7 | 197 | #define AR5K_TUNE_BMISS_THRES 7 |
108 | #define AR5K_TUNE_REGISTER_DWELL_TIME 20000 | 198 | #define AR5K_TUNE_REGISTER_DWELL_TIME 20000 |
109 | #define AR5K_TUNE_BEACON_INTERVAL 100 | 199 | #define AR5K_TUNE_BEACON_INTERVAL 100 |
110 | #define AR5K_TUNE_AIFS 2 | 200 | #define AR5K_TUNE_AIFS 2 |
@@ -123,6 +213,55 @@ | |||
123 | #define AR5K_TUNE_ANT_DIVERSITY true | 213 | #define AR5K_TUNE_ANT_DIVERSITY true |
124 | #define AR5K_TUNE_HWTXTRIES 4 | 214 | #define AR5K_TUNE_HWTXTRIES 4 |
125 | 215 | ||
216 | #define AR5K_INIT_CARR_SENSE_EN 1 | ||
217 | |||
218 | /*Swap RX/TX Descriptor for big endian archs*/ | ||
219 | #if defined(__BIG_ENDIAN) | ||
220 | #define AR5K_INIT_CFG ( \ | ||
221 | AR5K_CFG_SWTD | AR5K_CFG_SWRD \ | ||
222 | ) | ||
223 | #else | ||
224 | #define AR5K_INIT_CFG 0x00000000 | ||
225 | #endif | ||
226 | |||
227 | /* Initial values */ | ||
228 | #define AR5K_INIT_TX_LATENCY 502 | ||
229 | #define AR5K_INIT_USEC 39 | ||
230 | #define AR5K_INIT_USEC_TURBO 79 | ||
231 | #define AR5K_INIT_USEC_32 31 | ||
232 | #define AR5K_INIT_SLOT_TIME 396 | ||
233 | #define AR5K_INIT_SLOT_TIME_TURBO 480 | ||
234 | #define AR5K_INIT_ACK_CTS_TIMEOUT 1024 | ||
235 | #define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 | ||
236 | #define AR5K_INIT_PROG_IFS 920 | ||
237 | #define AR5K_INIT_PROG_IFS_TURBO 960 | ||
238 | #define AR5K_INIT_EIFS 3440 | ||
239 | #define AR5K_INIT_EIFS_TURBO 6880 | ||
240 | #define AR5K_INIT_SIFS 560 | ||
241 | #define AR5K_INIT_SIFS_TURBO 480 | ||
242 | #define AR5K_INIT_SH_RETRY 10 | ||
243 | #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY | ||
244 | #define AR5K_INIT_SSH_RETRY 32 | ||
245 | #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY | ||
246 | #define AR5K_INIT_TX_RETRY 10 | ||
247 | |||
248 | #define AR5K_INIT_TRANSMIT_LATENCY ( \ | ||
249 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
250 | (AR5K_INIT_USEC) \ | ||
251 | ) | ||
252 | #define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ | ||
253 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
254 | (AR5K_INIT_USEC_TURBO) \ | ||
255 | ) | ||
256 | #define AR5K_INIT_PROTO_TIME_CNTRL ( \ | ||
257 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ | ||
258 | (AR5K_INIT_PROG_IFS) \ | ||
259 | ) | ||
260 | #define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ | ||
261 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ | ||
262 | (AR5K_INIT_PROG_IFS_TURBO) \ | ||
263 | ) | ||
264 | |||
126 | /* token to use for aifs, cwmin, cwmax in MadWiFi */ | 265 | /* token to use for aifs, cwmin, cwmax in MadWiFi */ |
127 | #define AR5K_TXQ_USEDEFAULT ((u32) -1) | 266 | #define AR5K_TXQ_USEDEFAULT ((u32) -1) |
128 | 267 | ||
@@ -196,7 +335,6 @@ struct ath5k_srev_name { | |||
196 | #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ | 335 | #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ |
197 | 336 | ||
198 | /* IEEE defs */ | 337 | /* IEEE defs */ |
199 | |||
200 | #define IEEE80211_MAX_LEN 2500 | 338 | #define IEEE80211_MAX_LEN 2500 |
201 | 339 | ||
202 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | 340 | /* TODO add support to mac80211 for vendor-specific rates and modes */ |
@@ -268,16 +406,13 @@ enum ath5k_driver_mode { | |||
268 | AR5K_MODE_MAX = 5 | 406 | AR5K_MODE_MAX = 5 |
269 | }; | 407 | }; |
270 | 408 | ||
271 | /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */ | ||
272 | #define AR5K_SET_SHORT_PREAMBLE 0x04 | ||
273 | |||
274 | 409 | ||
275 | /****************\ | 410 | /****************\ |
276 | TX DEFINITIONS | 411 | TX DEFINITIONS |
277 | \****************/ | 412 | \****************/ |
278 | 413 | ||
279 | /* | 414 | /* |
280 | * TX Status | 415 | * TX Status descriptor |
281 | */ | 416 | */ |
282 | struct ath5k_tx_status { | 417 | struct ath5k_tx_status { |
283 | u16 ts_seqnum; | 418 | u16 ts_seqnum; |
@@ -349,7 +484,6 @@ enum ath5k_tx_queue_id { | |||
349 | AR5K_TX_QUEUE_ID_XR_DATA = 9, | 484 | AR5K_TX_QUEUE_ID_XR_DATA = 9, |
350 | }; | 485 | }; |
351 | 486 | ||
352 | |||
353 | /* | 487 | /* |
354 | * Flags to set hw queue's parameters... | 488 | * Flags to set hw queue's parameters... |
355 | */ | 489 | */ |
@@ -382,7 +516,8 @@ struct ath5k_txq_info { | |||
382 | 516 | ||
383 | /* | 517 | /* |
384 | * Transmit packet types. | 518 | * Transmit packet types. |
385 | * These are not fully used inside OpenHAL yet | 519 | * used on tx control descriptor |
520 | * TODO: Use them inside base.c corectly | ||
386 | */ | 521 | */ |
387 | enum ath5k_pkt_type { | 522 | enum ath5k_pkt_type { |
388 | AR5K_PKT_TYPE_NORMAL = 0, | 523 | AR5K_PKT_TYPE_NORMAL = 0, |
@@ -425,7 +560,7 @@ enum ath5k_dmasize { | |||
425 | \****************/ | 560 | \****************/ |
426 | 561 | ||
427 | /* | 562 | /* |
428 | * RX Status | 563 | * RX Status descriptor |
429 | */ | 564 | */ |
430 | struct ath5k_rx_status { | 565 | struct ath5k_rx_status { |
431 | u16 rs_datalen; | 566 | u16 rs_datalen; |
@@ -489,34 +624,59 @@ struct ath5k_beacon_state { | |||
489 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) | 624 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) |
490 | 625 | ||
491 | 626 | ||
627 | /*******************************\ | ||
628 | GAIN OPTIMIZATION DEFINITIONS | ||
629 | \*******************************/ | ||
630 | |||
631 | enum ath5k_rfgain { | ||
632 | AR5K_RFGAIN_INACTIVE = 0, | ||
633 | AR5K_RFGAIN_READ_REQUESTED, | ||
634 | AR5K_RFGAIN_NEED_CHANGE, | ||
635 | }; | ||
636 | |||
637 | #define AR5K_GAIN_CRN_FIX_BITS_5111 4 | ||
638 | #define AR5K_GAIN_CRN_FIX_BITS_5112 7 | ||
639 | #define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 | ||
640 | #define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 | ||
641 | #define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 | ||
642 | #define AR5K_GAIN_CCK_PROBE_CORR 5 | ||
643 | #define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 | ||
644 | #define AR5K_GAIN_STEP_COUNT 10 | ||
645 | #define AR5K_GAIN_PARAM_TX_CLIP 0 | ||
646 | #define AR5K_GAIN_PARAM_PD_90 1 | ||
647 | #define AR5K_GAIN_PARAM_PD_84 2 | ||
648 | #define AR5K_GAIN_PARAM_GAIN_SEL 3 | ||
649 | #define AR5K_GAIN_PARAM_MIX_ORN 0 | ||
650 | #define AR5K_GAIN_PARAM_PD_138 1 | ||
651 | #define AR5K_GAIN_PARAM_PD_137 2 | ||
652 | #define AR5K_GAIN_PARAM_PD_136 3 | ||
653 | #define AR5K_GAIN_PARAM_PD_132 4 | ||
654 | #define AR5K_GAIN_PARAM_PD_131 5 | ||
655 | #define AR5K_GAIN_PARAM_PD_130 6 | ||
656 | #define AR5K_GAIN_CHECK_ADJUST(_g) \ | ||
657 | ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) | ||
658 | |||
659 | struct ath5k_gain_opt_step { | ||
660 | s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; | ||
661 | s32 gos_gain; | ||
662 | }; | ||
663 | |||
664 | struct ath5k_gain { | ||
665 | u32 g_step_idx; | ||
666 | u32 g_current; | ||
667 | u32 g_target; | ||
668 | u32 g_low; | ||
669 | u32 g_high; | ||
670 | u32 g_f_corr; | ||
671 | u32 g_active; | ||
672 | const struct ath5k_gain_opt_step *g_step; | ||
673 | }; | ||
674 | |||
675 | |||
492 | /********************\ | 676 | /********************\ |
493 | COMMON DEFINITIONS | 677 | COMMON DEFINITIONS |
494 | \********************/ | 678 | \********************/ |
495 | 679 | ||
496 | /* | ||
497 | * Atheros hardware descriptor | ||
498 | * This is read and written to by the hardware | ||
499 | */ | ||
500 | struct ath5k_desc { | ||
501 | u32 ds_link; /* physical address of the next descriptor */ | ||
502 | u32 ds_data; /* physical address of data buffer (skb) */ | ||
503 | |||
504 | union { | ||
505 | struct ath5k_hw_5210_tx_desc ds_tx5210; | ||
506 | struct ath5k_hw_5212_tx_desc ds_tx5212; | ||
507 | struct ath5k_hw_all_rx_desc ds_rx; | ||
508 | } ud; | ||
509 | } __packed; | ||
510 | |||
511 | #define AR5K_RXDESC_INTREQ 0x0020 | ||
512 | |||
513 | #define AR5K_TXDESC_CLRDMASK 0x0001 | ||
514 | #define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ | ||
515 | #define AR5K_TXDESC_RTSENA 0x0004 | ||
516 | #define AR5K_TXDESC_CTSENA 0x0008 | ||
517 | #define AR5K_TXDESC_INTREQ 0x0010 | ||
518 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ | ||
519 | |||
520 | #define AR5K_SLOT_TIME_9 396 | 680 | #define AR5K_SLOT_TIME_9 396 |
521 | #define AR5K_SLOT_TIME_20 880 | 681 | #define AR5K_SLOT_TIME_20 880 |
522 | #define AR5K_SLOT_TIME_MAX 0xffff | 682 | #define AR5K_SLOT_TIME_MAX 0xffff |
@@ -548,15 +708,16 @@ struct ath5k_desc { | |||
548 | #define CHANNEL_MODES CHANNEL_ALL | 708 | #define CHANNEL_MODES CHANNEL_ALL |
549 | 709 | ||
550 | /* | 710 | /* |
551 | * Used internaly in OpenHAL (ar5211.c/ar5212.c | 711 | * Used internaly for reset_tx_queue). |
552 | * for reset_tx_queue). Also see struct struct ieee80211_channel. | 712 | * Also see struct struct ieee80211_channel. |
553 | */ | 713 | */ |
554 | #define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) | 714 | #define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) |
555 | #define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) | 715 | #define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) |
556 | 716 | ||
557 | /* | 717 | /* |
558 | * The following structure will be used to map 2GHz channels to | 718 | * The following structure is used to map 2GHz channels to |
559 | * 5GHz Atheros channels. | 719 | * 5GHz Atheros channels. |
720 | * TODO: Clean up | ||
560 | */ | 721 | */ |
561 | struct ath5k_athchan_2ghz { | 722 | struct ath5k_athchan_2ghz { |
562 | u32 a2_flags; | 723 | u32 a2_flags; |
@@ -564,9 +725,9 @@ struct ath5k_athchan_2ghz { | |||
564 | }; | 725 | }; |
565 | 726 | ||
566 | 727 | ||
567 | /* | 728 | /******************\ |
568 | * Rate definitions | 729 | RATE DEFINITIONS |
569 | */ | 730 | \******************/ |
570 | 731 | ||
571 | /** | 732 | /** |
572 | * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. | 733 | * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. |
@@ -618,6 +779,8 @@ struct ath5k_athchan_2ghz { | |||
618 | #define ATH5K_RATE_CODE_XR_2M 0x06 | 779 | #define ATH5K_RATE_CODE_XR_2M 0x06 |
619 | #define ATH5K_RATE_CODE_XR_3M 0x01 | 780 | #define ATH5K_RATE_CODE_XR_3M 0x01 |
620 | 781 | ||
782 | /* adding this flag to rate_code enables short preamble */ | ||
783 | #define AR5K_SET_SHORT_PREAMBLE 0x04 | ||
621 | 784 | ||
622 | /* | 785 | /* |
623 | * Crypto definitions | 786 | * Crypto definitions |
@@ -639,7 +802,6 @@ struct ath5k_athchan_2ghz { | |||
639 | return (false); \ | 802 | return (false); \ |
640 | } while (0) | 803 | } while (0) |
641 | 804 | ||
642 | |||
643 | enum ath5k_ant_setting { | 805 | enum ath5k_ant_setting { |
644 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ | 806 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ |
645 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ | 807 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ |
@@ -750,7 +912,8 @@ enum ath5k_power_mode { | |||
750 | 912 | ||
751 | /* | 913 | /* |
752 | * These match net80211 definitions (not used in | 914 | * These match net80211 definitions (not used in |
753 | * d80211). | 915 | * mac80211). |
916 | * TODO: Clean this up | ||
754 | */ | 917 | */ |
755 | #define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ | 918 | #define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ |
756 | #define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ | 919 | #define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ |
@@ -766,7 +929,8 @@ enum ath5k_power_mode { | |||
766 | /* | 929 | /* |
767 | * Chipset capabilities -see ath5k_hw_get_capability- | 930 | * Chipset capabilities -see ath5k_hw_get_capability- |
768 | * get_capability function is not yet fully implemented | 931 | * get_capability function is not yet fully implemented |
769 | * in OpenHAL so most of these don't work yet... | 932 | * in ath5k so most of these don't work yet... |
933 | * TODO: Implement these & merge with _TUNE_ stuff above | ||
770 | */ | 934 | */ |
771 | enum ath5k_capability_type { | 935 | enum ath5k_capability_type { |
772 | AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ | 936 | AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ |
@@ -835,6 +999,7 @@ struct ath5k_capabilities { | |||
835 | #define AR5K_MAX_GPIO 10 | 999 | #define AR5K_MAX_GPIO 10 |
836 | #define AR5K_MAX_RF_BANKS 8 | 1000 | #define AR5K_MAX_RF_BANKS 8 |
837 | 1001 | ||
1002 | /* TODO: Clean up and merge with ath5k_softc */ | ||
838 | struct ath5k_hw { | 1003 | struct ath5k_hw { |
839 | u32 ah_magic; | 1004 | u32 ah_magic; |
840 | 1005 | ||
@@ -927,11 +1092,13 @@ struct ath5k_hw { | |||
927 | /* | 1092 | /* |
928 | * Function pointers | 1093 | * Function pointers |
929 | */ | 1094 | */ |
1095 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1096 | u32 size, unsigned int flags); | ||
930 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1097 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
931 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | 1098 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, |
932 | unsigned int, unsigned int, unsigned int, unsigned int, | 1099 | unsigned int, unsigned int, unsigned int, unsigned int, |
933 | unsigned int, unsigned int, unsigned int); | 1100 | unsigned int, unsigned int, unsigned int); |
934 | int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1101 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
935 | unsigned int, unsigned int, unsigned int, unsigned int, | 1102 | unsigned int, unsigned int, unsigned int, unsigned int, |
936 | unsigned int, unsigned int); | 1103 | unsigned int, unsigned int); |
937 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1104 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
@@ -944,33 +1111,38 @@ struct ath5k_hw { | |||
944 | * Prototypes | 1111 | * Prototypes |
945 | */ | 1112 | */ |
946 | 1113 | ||
947 | /* General Functions */ | ||
948 | extern int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set); | ||
949 | /* Attach/Detach Functions */ | 1114 | /* Attach/Detach Functions */ |
950 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); | 1115 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); |
951 | extern const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, unsigned int mode); | ||
952 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1116 | extern void ath5k_hw_detach(struct ath5k_hw *ah); |
1117 | |||
953 | /* Reset Functions */ | 1118 | /* Reset Functions */ |
1119 | extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | ||
954 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel); | 1120 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel); |
955 | /* Power management functions */ | 1121 | /* Power management functions */ |
956 | extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); | 1122 | extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); |
1123 | |||
957 | /* DMA Related Functions */ | 1124 | /* DMA Related Functions */ |
958 | extern void ath5k_hw_start_rx(struct ath5k_hw *ah); | 1125 | extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); |
959 | extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | 1126 | extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); |
960 | extern u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah); | 1127 | extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); |
961 | extern void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr); | 1128 | extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); |
962 | extern int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue); | 1129 | extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
963 | extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1130 | extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
964 | extern u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue); | 1131 | extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); |
965 | extern int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr); | 1132 | extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, |
1133 | u32 phys_addr); | ||
966 | extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | 1134 | extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); |
967 | /* Interrupt handling */ | 1135 | /* Interrupt handling */ |
968 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | 1136 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); |
969 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1137 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
970 | extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); | 1138 | extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum |
1139 | ath5k_int new_mask); | ||
971 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); | 1140 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); |
1141 | |||
972 | /* EEPROM access functions */ | 1142 | /* EEPROM access functions */ |
973 | extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); | 1143 | extern int ath5k_eeprom_init(struct ath5k_hw *ah); |
1144 | extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | ||
1145 | |||
974 | /* Protocol Control Unit Functions */ | 1146 | /* Protocol Control Unit Functions */ |
975 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1147 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); |
976 | /* BSSID Functions */ | 1148 | /* BSSID Functions */ |
@@ -980,14 +1152,14 @@ extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc | |||
980 | extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1152 | extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
981 | /* Receive start/stop functions */ | 1153 | /* Receive start/stop functions */ |
982 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1154 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
983 | extern void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah); | 1155 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
984 | /* RX Filter functions */ | 1156 | /* RX Filter functions */ |
985 | extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | 1157 | extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); |
986 | extern int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index); | 1158 | extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); |
987 | extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | 1159 | extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); |
988 | extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | 1160 | extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); |
989 | extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | 1161 | extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); |
990 | /* Beacon related functions */ | 1162 | /* Beacon control functions */ |
991 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); | 1163 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); |
992 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1164 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
993 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1165 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
@@ -1009,61 +1181,129 @@ extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | |||
1009 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1181 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); |
1010 | extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); | 1182 | extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); |
1011 | extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | 1183 | extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); |
1184 | |||
1012 | /* Queue Control Unit, DFS Control Unit Functions */ | 1185 | /* Queue Control Unit, DFS Control Unit Functions */ |
1013 | extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info); | ||
1014 | extern int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info); | ||
1015 | extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); | 1186 | extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); |
1187 | extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
1188 | const struct ath5k_txq_info *queue_info); | ||
1189 | extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, | ||
1190 | enum ath5k_tx_queue queue_type, | ||
1191 | struct ath5k_txq_info *queue_info); | ||
1192 | extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | ||
1016 | extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1193 | extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1017 | extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1194 | extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1018 | extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | ||
1019 | extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | ||
1020 | extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); | 1195 | extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); |
1196 | extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | ||
1197 | |||
1021 | /* Hardware Descriptor Functions */ | 1198 | /* Hardware Descriptor Functions */ |
1022 | extern int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags); | 1199 | extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
1200 | |||
1023 | /* GPIO Functions */ | 1201 | /* GPIO Functions */ |
1024 | extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1202 | extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
1025 | extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); | ||
1026 | extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | 1203 | extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); |
1204 | extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); | ||
1027 | extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); | 1205 | extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); |
1028 | extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | 1206 | extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); |
1029 | extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); | 1207 | extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); |
1208 | |||
1030 | /* Misc functions */ | 1209 | /* Misc functions */ |
1210 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); | ||
1031 | extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); | 1211 | extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); |
1032 | 1212 | extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | |
1213 | extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | ||
1033 | 1214 | ||
1034 | /* Initial register settings functions */ | 1215 | /* Initial register settings functions */ |
1035 | extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | 1216 | extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); |
1217 | |||
1036 | /* Initialize RF */ | 1218 | /* Initialize RF */ |
1037 | extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode); | 1219 | extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode); |
1038 | extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq); | 1220 | extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq); |
1039 | extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah); | 1221 | extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah); |
1040 | extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah); | 1222 | extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah); |
1041 | |||
1042 | |||
1043 | /* PHY/RF channel functions */ | 1223 | /* PHY/RF channel functions */ |
1044 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1224 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1045 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1225 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1046 | /* PHY calibration */ | 1226 | /* PHY calibration */ |
1047 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1227 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1048 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1228 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); |
1049 | /* Misc PHY functions */ | 1229 | /* Misc PHY functions */ |
1050 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | 1230 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1051 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); | 1231 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); |
1052 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | 1232 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); |
1053 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1233 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1054 | /* TX power setup */ | 1234 | /* TX power setup */ |
1055 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower); | 1235 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower); |
1056 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power); | 1236 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power); |
1057 | 1237 | ||
1238 | /* | ||
1239 | * Functions used internaly | ||
1240 | */ | ||
1241 | |||
1242 | /* | ||
1243 | * Translate usec to hw clock units | ||
1244 | */ | ||
1245 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
1246 | { | ||
1247 | return turbo ? (usec * 80) : (usec * 40); | ||
1248 | } | ||
1058 | 1249 | ||
1250 | /* | ||
1251 | * Translate hw clock units to usec | ||
1252 | */ | ||
1253 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
1254 | { | ||
1255 | return turbo ? (clock / 80) : (clock / 40); | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | * Read from a register | ||
1260 | */ | ||
1059 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | 1261 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) |
1060 | { | 1262 | { |
1061 | return ioread32(ah->ah_iobase + reg); | 1263 | return ioread32(ah->ah_iobase + reg); |
1062 | } | 1264 | } |
1063 | 1265 | ||
1266 | /* | ||
1267 | * Write to a register | ||
1268 | */ | ||
1064 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | 1269 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) |
1065 | { | 1270 | { |
1066 | iowrite32(val, ah->ah_iobase + reg); | 1271 | iowrite32(val, ah->ah_iobase + reg); |
1067 | } | 1272 | } |
1068 | 1273 | ||
1274 | #if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) | ||
1275 | /* | ||
1276 | * Check if a register write has been completed | ||
1277 | */ | ||
1278 | static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, | ||
1279 | u32 val, bool is_set) | ||
1280 | { | ||
1281 | int i; | ||
1282 | u32 data; | ||
1283 | |||
1284 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
1285 | data = ath5k_hw_reg_read(ah, reg); | ||
1286 | if (is_set && (data & flag)) | ||
1287 | break; | ||
1288 | else if ((data & flag) == val) | ||
1289 | break; | ||
1290 | udelay(15); | ||
1291 | } | ||
1292 | |||
1293 | return (i <= 0) ? -EAGAIN : 0; | ||
1294 | } | ||
1295 | #endif | ||
1296 | |||
1297 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | ||
1298 | { | ||
1299 | u32 retval = 0, bit, i; | ||
1300 | |||
1301 | for (i = 0; i < bits; i++) { | ||
1302 | bit = (val >> i) & 1; | ||
1303 | retval = (retval << 1) | bit; | ||
1304 | } | ||
1305 | |||
1306 | return retval; | ||
1307 | } | ||
1308 | |||
1069 | #endif | 1309 | #endif |
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c new file mode 100644 index 000000000000..0eb2511fe147 --- /dev/null +++ b/drivers/net/wireless/ath5k/attach.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /*************************************\ | ||
20 | * Attach/Detach Functions and helpers * | ||
21 | \*************************************/ | ||
22 | |||
23 | #include <linux/pci.h> | ||
24 | #include "ath5k.h" | ||
25 | #include "reg.h" | ||
26 | #include "debug.h" | ||
27 | #include "base.h" | ||
28 | |||
29 | /** | ||
30 | * ath5k_hw_post - Power On Self Test helper function | ||
31 | * | ||
32 | * @ah: The &struct ath5k_hw | ||
33 | */ | ||
34 | static int ath5k_hw_post(struct ath5k_hw *ah) | ||
35 | { | ||
36 | |||
37 | int i, c; | ||
38 | u16 cur_reg; | ||
39 | u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; | ||
40 | u32 var_pattern; | ||
41 | u32 static_pattern[4] = { | ||
42 | 0x55555555, 0xaaaaaaaa, | ||
43 | 0x66666666, 0x99999999 | ||
44 | }; | ||
45 | u32 init_val; | ||
46 | u32 cur_val; | ||
47 | |||
48 | for (c = 0; c < 2; c++) { | ||
49 | |||
50 | cur_reg = regs[c]; | ||
51 | |||
52 | /* Save previous value */ | ||
53 | init_val = ath5k_hw_reg_read(ah, cur_reg); | ||
54 | |||
55 | for (i = 0; i < 256; i++) { | ||
56 | var_pattern = i << 16 | i; | ||
57 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
58 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
59 | |||
60 | if (cur_val != var_pattern) { | ||
61 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
62 | return -EAGAIN; | ||
63 | } | ||
64 | |||
65 | /* Found on ndiswrapper dumps */ | ||
66 | var_pattern = 0x0039080f; | ||
67 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
68 | } | ||
69 | |||
70 | for (i = 0; i < 4; i++) { | ||
71 | var_pattern = static_pattern[i]; | ||
72 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
73 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
74 | |||
75 | if (cur_val != var_pattern) { | ||
76 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
77 | return -EAGAIN; | ||
78 | } | ||
79 | |||
80 | /* Found on ndiswrapper dumps */ | ||
81 | var_pattern = 0x003b080f; | ||
82 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
83 | } | ||
84 | |||
85 | /* Restore previous value */ | ||
86 | ath5k_hw_reg_write(ah, init_val, cur_reg); | ||
87 | |||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | |||
92 | } | ||
93 | |||
94 | /** | ||
95 | * ath5k_hw_attach - Check if hw is supported and init the needed structs | ||
96 | * | ||
97 | * @sc: The &struct ath5k_softc we got from the driver's attach function | ||
98 | * @mac_version: The mac version id (check out ath5k.h) based on pci id | ||
99 | * | ||
100 | * Check if the device is supported, perform a POST and initialize the needed | ||
101 | * structs. Returns -ENOMEM if we don't have memory for the needed structs, | ||
102 | * -ENODEV if the device is not supported or prints an error msg if something | ||
103 | * else went wrong. | ||
104 | */ | ||
105 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | ||
106 | { | ||
107 | struct ath5k_hw *ah; | ||
108 | struct pci_dev *pdev = sc->pdev; | ||
109 | u8 mac[ETH_ALEN]; | ||
110 | int ret; | ||
111 | u32 srev; | ||
112 | |||
113 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
114 | ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
115 | if (ah == NULL) { | ||
116 | ret = -ENOMEM; | ||
117 | ATH5K_ERR(sc, "out of memory\n"); | ||
118 | goto err; | ||
119 | } | ||
120 | |||
121 | ah->ah_sc = sc; | ||
122 | ah->ah_iobase = sc->iobase; | ||
123 | |||
124 | /* | ||
125 | * HW information | ||
126 | */ | ||
127 | ah->ah_op_mode = IEEE80211_IF_TYPE_STA; | ||
128 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | ||
129 | ah->ah_turbo = false; | ||
130 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
131 | ah->ah_imr = 0; | ||
132 | ah->ah_atim_window = 0; | ||
133 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
134 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
135 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | ||
136 | ah->ah_software_retry = false; | ||
137 | ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; | ||
138 | |||
139 | /* | ||
140 | * Set the mac revision based on the pci id | ||
141 | */ | ||
142 | ah->ah_version = mac_version; | ||
143 | |||
144 | /*Fill the ath5k_hw struct with the needed functions*/ | ||
145 | ret = ath5k_hw_init_desc_functions(ah); | ||
146 | if (ret) | ||
147 | goto err_free; | ||
148 | |||
149 | /* Bring device out of sleep and reset it's units */ | ||
150 | ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true); | ||
151 | if (ret) | ||
152 | goto err_free; | ||
153 | |||
154 | /* Get MAC, PHY and RADIO revisions */ | ||
155 | srev = ath5k_hw_reg_read(ah, AR5K_SREV); | ||
156 | ah->ah_mac_srev = srev; | ||
157 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | ||
158 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
159 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | ||
160 | 0xffffffff; | ||
161 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | ||
162 | CHANNEL_5GHZ); | ||
163 | |||
164 | if (ah->ah_version == AR5K_AR5210) | ||
165 | ah->ah_radio_2ghz_revision = 0; | ||
166 | else | ||
167 | ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, | ||
168 | CHANNEL_2GHZ); | ||
169 | |||
170 | /* Return on unsuported chips (unsupported eeprom etc) */ | ||
171 | if ((srev >= AR5K_SREV_VER_AR5416) && | ||
172 | (srev < AR5K_SREV_VER_AR2425)) { | ||
173 | ATH5K_ERR(sc, "Device not yet supported.\n"); | ||
174 | ret = -ENODEV; | ||
175 | goto err_free; | ||
176 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
177 | ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); | ||
178 | } | ||
179 | |||
180 | /* Identify single chip solutions */ | ||
181 | if (((srev <= AR5K_SREV_VER_AR5414) && | ||
182 | (srev >= AR5K_SREV_VER_AR2413)) || | ||
183 | (srev == AR5K_SREV_VER_AR2425)) { | ||
184 | ah->ah_single_chip = true; | ||
185 | } else { | ||
186 | ah->ah_single_chip = false; | ||
187 | } | ||
188 | |||
189 | /* Single chip radio */ | ||
190 | if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision) | ||
191 | ah->ah_radio_2ghz_revision = 0; | ||
192 | |||
193 | /* Identify the radio chip*/ | ||
194 | if (ah->ah_version == AR5K_AR5210) { | ||
195 | ah->ah_radio = AR5K_RF5110; | ||
196 | /* | ||
197 | * Register returns 0x0/0x04 for radio revision | ||
198 | * so ath5k_hw_radio_revision doesn't parse the value | ||
199 | * correctly. For now we are based on mac's srev to | ||
200 | * identify RF2425 radio. | ||
201 | */ | ||
202 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
203 | ah->ah_radio = AR5K_RF2425; | ||
204 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; | ||
205 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { | ||
206 | ah->ah_radio = AR5K_RF5111; | ||
207 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; | ||
208 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { | ||
209 | ah->ah_radio = AR5K_RF5112; | ||
210 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
211 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | ||
212 | ah->ah_radio = AR5K_RF2413; | ||
213 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; | ||
214 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { | ||
215 | ah->ah_radio = AR5K_RF5413; | ||
216 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; | ||
217 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { | ||
218 | /* AR5424 */ | ||
219 | if (srev >= AR5K_SREV_VER_AR5424) { | ||
220 | ah->ah_radio = AR5K_RF5413; | ||
221 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; | ||
222 | /* AR2424 */ | ||
223 | } else { | ||
224 | ah->ah_radio = AR5K_RF2413; /* For testing */ | ||
225 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; | ||
226 | } | ||
227 | } | ||
228 | ah->ah_phy = AR5K_PHY(0); | ||
229 | |||
230 | /* | ||
231 | * Write PCI-E power save settings | ||
232 | */ | ||
233 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | ||
234 | ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); | ||
235 | ath5k_hw_reg_write(ah, 0x24924924, 0x4080); | ||
236 | ath5k_hw_reg_write(ah, 0x28000039, 0x4080); | ||
237 | ath5k_hw_reg_write(ah, 0x53160824, 0x4080); | ||
238 | ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); | ||
239 | ath5k_hw_reg_write(ah, 0x001defff, 0x4080); | ||
240 | ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); | ||
241 | ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); | ||
242 | ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); | ||
243 | ath5k_hw_reg_write(ah, 0x00000000, 0x4084); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * POST | ||
248 | */ | ||
249 | ret = ath5k_hw_post(ah); | ||
250 | if (ret) | ||
251 | goto err_free; | ||
252 | |||
253 | /* Write AR5K_PCICFG_UNK on 2112B and later chips */ | ||
254 | if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || | ||
255 | srev > AR5K_SREV_VER_AR2413) { | ||
256 | ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Get card capabilities, values, ... | ||
261 | */ | ||
262 | ret = ath5k_eeprom_init(ah); | ||
263 | if (ret) { | ||
264 | ATH5K_ERR(sc, "unable to init EEPROM\n"); | ||
265 | goto err_free; | ||
266 | } | ||
267 | |||
268 | /* Get misc capabilities */ | ||
269 | ret = ath5k_hw_set_capabilities(ah); | ||
270 | if (ret) { | ||
271 | ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", | ||
272 | sc->pdev->device); | ||
273 | goto err_free; | ||
274 | } | ||
275 | |||
276 | /* Get MAC address */ | ||
277 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
278 | if (ret) { | ||
279 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
280 | sc->pdev->device); | ||
281 | goto err_free; | ||
282 | } | ||
283 | |||
284 | ath5k_hw_set_lladdr(ah, mac); | ||
285 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | ||
286 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | ||
287 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
288 | ath5k_hw_set_opmode(ah); | ||
289 | |||
290 | ath5k_hw_set_rfgain_opt(ah); | ||
291 | |||
292 | return ah; | ||
293 | err_free: | ||
294 | kfree(ah); | ||
295 | err: | ||
296 | return ERR_PTR(ret); | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * ath5k_hw_detach - Free the ath5k_hw struct | ||
301 | * | ||
302 | * @ah: The &struct ath5k_hw | ||
303 | */ | ||
304 | void ath5k_hw_detach(struct ath5k_hw *ah) | ||
305 | { | ||
306 | ATH5K_TRACE(ah->ah_sc); | ||
307 | |||
308 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); | ||
309 | |||
310 | if (ah->ah_rf_banks != NULL) | ||
311 | kfree(ah->ah_rf_banks); | ||
312 | |||
313 | /* assume interrupts are down */ | ||
314 | kfree(ah); | ||
315 | } | ||
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index bcec74e839e9..7989ab5c2bba 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -707,7 +707,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
707 | * return false w/o doing anything. MAC's that do | 707 | * return false w/o doing anything. MAC's that do |
708 | * support it will return true w/o doing anything. | 708 | * support it will return true w/o doing anything. |
709 | */ | 709 | */ |
710 | ret = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | 710 | ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); |
711 | if (ret < 0) | 711 | if (ret < 0) |
712 | goto err; | 712 | goto err; |
713 | if (ret > 0) | 713 | if (ret > 0) |
@@ -1137,7 +1137,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1137 | ds = bf->desc; | 1137 | ds = bf->desc; |
1138 | ds->ds_link = bf->daddr; /* link to self */ | 1138 | ds->ds_link = bf->daddr; /* link to self */ |
1139 | ds->ds_data = bf->skbaddr; | 1139 | ds->ds_data = bf->skbaddr; |
1140 | ath5k_hw_setup_rx_desc(ah, ds, | 1140 | ah->ah_setup_rx_desc(ah, ds, |
1141 | skb_tailroom(skb), /* buffer size */ | 1141 | skb_tailroom(skb), /* buffer size */ |
1142 | 0); | 1142 | 0); |
1143 | 1143 | ||
@@ -1188,12 +1188,12 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1188 | list_add_tail(&bf->list, &txq->q); | 1188 | list_add_tail(&bf->list, &txq->q); |
1189 | sc->tx_stats[txq->qnum].len++; | 1189 | sc->tx_stats[txq->qnum].len++; |
1190 | if (txq->link == NULL) /* is this first packet? */ | 1190 | if (txq->link == NULL) /* is this first packet? */ |
1191 | ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr); | 1191 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); |
1192 | else /* no, so only link it */ | 1192 | else /* no, so only link it */ |
1193 | *txq->link = bf->daddr; | 1193 | *txq->link = bf->daddr; |
1194 | 1194 | ||
1195 | txq->link = &ds->ds_link; | 1195 | txq->link = &ds->ds_link; |
1196 | ath5k_hw_tx_start(ah, txq->qnum); | 1196 | ath5k_hw_start_tx_dma(ah, txq->qnum); |
1197 | mmiowb(); | 1197 | mmiowb(); |
1198 | spin_unlock_bh(&txq->lock); | 1198 | spin_unlock_bh(&txq->lock); |
1199 | 1199 | ||
@@ -1393,7 +1393,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1393 | "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", | 1393 | "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", |
1394 | qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); | 1394 | qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); |
1395 | 1395 | ||
1396 | ret = ath5k_hw_setup_tx_queueprops(ah, sc->bhalq, &qi); | 1396 | ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi); |
1397 | if (ret) { | 1397 | if (ret) { |
1398 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " | 1398 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " |
1399 | "hardware queue!\n", __func__); | 1399 | "hardware queue!\n", __func__); |
@@ -1442,14 +1442,14 @@ ath5k_txq_cleanup(struct ath5k_softc *sc) | |||
1442 | /* don't touch the hardware if marked invalid */ | 1442 | /* don't touch the hardware if marked invalid */ |
1443 | ath5k_hw_stop_tx_dma(ah, sc->bhalq); | 1443 | ath5k_hw_stop_tx_dma(ah, sc->bhalq); |
1444 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", | 1444 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", |
1445 | ath5k_hw_get_tx_buf(ah, sc->bhalq)); | 1445 | ath5k_hw_get_txdp(ah, sc->bhalq)); |
1446 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | 1446 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) |
1447 | if (sc->txqs[i].setup) { | 1447 | if (sc->txqs[i].setup) { |
1448 | ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); | 1448 | ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); |
1449 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " | 1449 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " |
1450 | "link %p\n", | 1450 | "link %p\n", |
1451 | sc->txqs[i].qnum, | 1451 | sc->txqs[i].qnum, |
1452 | ath5k_hw_get_tx_buf(ah, | 1452 | ath5k_hw_get_txdp(ah, |
1453 | sc->txqs[i].qnum), | 1453 | sc->txqs[i].qnum), |
1454 | sc->txqs[i].link); | 1454 | sc->txqs[i].link); |
1455 | } | 1455 | } |
@@ -1509,8 +1509,8 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1509 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | 1509 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); |
1510 | spin_unlock_bh(&sc->rxbuflock); | 1510 | spin_unlock_bh(&sc->rxbuflock); |
1511 | 1511 | ||
1512 | ath5k_hw_put_rx_buf(ah, bf->daddr); | 1512 | ath5k_hw_set_rxdp(ah, bf->daddr); |
1513 | ath5k_hw_start_rx(ah); /* enable recv descriptors */ | 1513 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ |
1514 | ath5k_mode_setup(sc); /* set filters, etc. */ | 1514 | ath5k_mode_setup(sc); /* set filters, etc. */ |
1515 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | 1515 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ |
1516 | 1516 | ||
@@ -1527,7 +1527,7 @@ ath5k_rx_stop(struct ath5k_softc *sc) | |||
1527 | { | 1527 | { |
1528 | struct ath5k_hw *ah = sc->ah; | 1528 | struct ath5k_hw *ah = sc->ah; |
1529 | 1529 | ||
1530 | ath5k_hw_stop_pcu_recv(ah); /* disable PCU */ | 1530 | ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ |
1531 | ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ | 1531 | ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ |
1532 | ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ | 1532 | ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ |
1533 | 1533 | ||
@@ -1976,8 +1976,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
1976 | /* NB: hw still stops DMA, so proceed */ | 1976 | /* NB: hw still stops DMA, so proceed */ |
1977 | } | 1977 | } |
1978 | 1978 | ||
1979 | ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); | 1979 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); |
1980 | ath5k_hw_tx_start(ah, sc->bhalq); | 1980 | ath5k_hw_start_tx_dma(ah, sc->bhalq); |
1981 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", | 1981 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", |
1982 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); | 1982 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); |
1983 | 1983 | ||
@@ -2106,7 +2106,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2106 | { | 2106 | { |
2107 | struct ath5k_hw *ah = sc->ah; | 2107 | struct ath5k_hw *ah = sc->ah; |
2108 | 2108 | ||
2109 | ath5k_hw_set_intr(ah, 0); | 2109 | ath5k_hw_set_imr(ah, 0); |
2110 | sc->bmisscount = 0; | 2110 | sc->bmisscount = 0; |
2111 | sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); | 2111 | sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); |
2112 | 2112 | ||
@@ -2132,7 +2132,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2132 | } | 2132 | } |
2133 | /* TODO else AP */ | 2133 | /* TODO else AP */ |
2134 | 2134 | ||
2135 | ath5k_hw_set_intr(ah, sc->imask); | 2135 | ath5k_hw_set_imr(ah, sc->imask); |
2136 | } | 2136 | } |
2137 | 2137 | ||
2138 | 2138 | ||
@@ -2211,7 +2211,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) | |||
2211 | 2211 | ||
2212 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | 2212 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { |
2213 | ath5k_led_off(sc); | 2213 | ath5k_led_off(sc); |
2214 | ath5k_hw_set_intr(ah, 0); | 2214 | ath5k_hw_set_imr(ah, 0); |
2215 | synchronize_irq(sc->pdev->irq); | 2215 | synchronize_irq(sc->pdev->irq); |
2216 | } | 2216 | } |
2217 | ath5k_txq_cleanup(sc); | 2217 | ath5k_txq_cleanup(sc); |
@@ -2604,7 +2604,7 @@ ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel) | |||
2604 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); | 2604 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); |
2605 | 2605 | ||
2606 | if (stop) { | 2606 | if (stop) { |
2607 | ath5k_hw_set_intr(ah, 0); | 2607 | ath5k_hw_set_imr(ah, 0); |
2608 | ath5k_txq_cleanup(sc); | 2608 | ath5k_txq_cleanup(sc); |
2609 | ath5k_rx_stop(sc); | 2609 | ath5k_rx_stop(sc); |
2610 | } | 2610 | } |
diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath5k/caps.c new file mode 100644 index 000000000000..150f5ed204a0 --- /dev/null +++ b/drivers/net/wireless/ath5k/caps.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | /**************\ | ||
21 | * Capabilities * | ||
22 | \**************/ | ||
23 | |||
24 | #include "ath5k.h" | ||
25 | #include "reg.h" | ||
26 | #include "debug.h" | ||
27 | #include "base.h" | ||
28 | |||
29 | /* | ||
30 | * Fill the capabilities struct | ||
31 | * TODO: Merge this with EEPROM code when we are done with it | ||
32 | */ | ||
33 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | ||
34 | { | ||
35 | u16 ee_header; | ||
36 | |||
37 | ATH5K_TRACE(ah->ah_sc); | ||
38 | /* Capabilities stored in the EEPROM */ | ||
39 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | ||
40 | |||
41 | if (ah->ah_version == AR5K_AR5210) { | ||
42 | /* | ||
43 | * Set radio capabilities | ||
44 | * (The AR5110 only supports the middle 5GHz band) | ||
45 | */ | ||
46 | ah->ah_capabilities.cap_range.range_5ghz_min = 5120; | ||
47 | ah->ah_capabilities.cap_range.range_5ghz_max = 5430; | ||
48 | ah->ah_capabilities.cap_range.range_2ghz_min = 0; | ||
49 | ah->ah_capabilities.cap_range.range_2ghz_max = 0; | ||
50 | |||
51 | /* Set supported modes */ | ||
52 | __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); | ||
53 | __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); | ||
54 | } else { | ||
55 | /* | ||
56 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz | ||
57 | * XXX and from 2312 to 2732GHz. There are problems with the | ||
58 | * XXX current ieee80211 implementation because the IEEE | ||
59 | * XXX channel mapping does not support negative channel | ||
60 | * XXX numbers (2312MHz is channel -19). Of course, this | ||
61 | * XXX doesn't matter because these channels are out of range | ||
62 | * XXX but some regulation domains like MKK (Japan) will | ||
63 | * XXX support frequencies somewhere around 4.8GHz. | ||
64 | */ | ||
65 | |||
66 | /* | ||
67 | * Set radio capabilities | ||
68 | */ | ||
69 | |||
70 | if (AR5K_EEPROM_HDR_11A(ee_header)) { | ||
71 | /* 4920 */ | ||
72 | ah->ah_capabilities.cap_range.range_5ghz_min = 5005; | ||
73 | ah->ah_capabilities.cap_range.range_5ghz_max = 6100; | ||
74 | |||
75 | /* Set supported modes */ | ||
76 | __set_bit(AR5K_MODE_11A, | ||
77 | ah->ah_capabilities.cap_mode); | ||
78 | __set_bit(AR5K_MODE_11A_TURBO, | ||
79 | ah->ah_capabilities.cap_mode); | ||
80 | if (ah->ah_version == AR5K_AR5212) | ||
81 | __set_bit(AR5K_MODE_11G_TURBO, | ||
82 | ah->ah_capabilities.cap_mode); | ||
83 | } | ||
84 | |||
85 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | ||
86 | * connected */ | ||
87 | if (AR5K_EEPROM_HDR_11B(ee_header) || | ||
88 | AR5K_EEPROM_HDR_11G(ee_header)) { | ||
89 | /* 2312 */ | ||
90 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; | ||
91 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | ||
92 | |||
93 | if (AR5K_EEPROM_HDR_11B(ee_header)) | ||
94 | __set_bit(AR5K_MODE_11B, | ||
95 | ah->ah_capabilities.cap_mode); | ||
96 | |||
97 | if (AR5K_EEPROM_HDR_11G(ee_header)) | ||
98 | __set_bit(AR5K_MODE_11G, | ||
99 | ah->ah_capabilities.cap_mode); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* GPIO */ | ||
104 | ah->ah_gpio_npins = AR5K_NUM_GPIO; | ||
105 | |||
106 | /* Set number of supported TX queues */ | ||
107 | if (ah->ah_version == AR5K_AR5210) | ||
108 | ah->ah_capabilities.cap_queues.q_tx_num = | ||
109 | AR5K_NUM_TX_QUEUES_NOQCU; | ||
110 | else | ||
111 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | /* Main function used by the driver part to check caps */ | ||
117 | int ath5k_hw_get_capability(struct ath5k_hw *ah, | ||
118 | enum ath5k_capability_type cap_type, | ||
119 | u32 capability, u32 *result) | ||
120 | { | ||
121 | ATH5K_TRACE(ah->ah_sc); | ||
122 | |||
123 | switch (cap_type) { | ||
124 | case AR5K_CAP_NUM_TXQUEUES: | ||
125 | if (result) { | ||
126 | if (ah->ah_version == AR5K_AR5210) | ||
127 | *result = AR5K_NUM_TX_QUEUES_NOQCU; | ||
128 | else | ||
129 | *result = AR5K_NUM_TX_QUEUES; | ||
130 | goto yes; | ||
131 | } | ||
132 | case AR5K_CAP_VEOL: | ||
133 | goto yes; | ||
134 | case AR5K_CAP_COMPRESSION: | ||
135 | if (ah->ah_version == AR5K_AR5212) | ||
136 | goto yes; | ||
137 | else | ||
138 | goto no; | ||
139 | case AR5K_CAP_BURST: | ||
140 | goto yes; | ||
141 | case AR5K_CAP_TPC: | ||
142 | goto yes; | ||
143 | case AR5K_CAP_BSSIDMASK: | ||
144 | if (ah->ah_version == AR5K_AR5212) | ||
145 | goto yes; | ||
146 | else | ||
147 | goto no; | ||
148 | case AR5K_CAP_XR: | ||
149 | if (ah->ah_version == AR5K_AR5212) | ||
150 | goto yes; | ||
151 | else | ||
152 | goto no; | ||
153 | default: | ||
154 | goto no; | ||
155 | } | ||
156 | |||
157 | no: | ||
158 | return -EINVAL; | ||
159 | yes: | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * TODO: Following functions should be part of a new function | ||
165 | * set_capability | ||
166 | */ | ||
167 | |||
168 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, | ||
169 | u16 assoc_id) | ||
170 | { | ||
171 | ATH5K_TRACE(ah->ah_sc); | ||
172 | |||
173 | if (ah->ah_version == AR5K_AR5210) { | ||
174 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
175 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | return -EIO; | ||
180 | } | ||
181 | |||
182 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) | ||
183 | { | ||
184 | ATH5K_TRACE(ah->ah_sc); | ||
185 | |||
186 | if (ah->ah_version == AR5K_AR5210) { | ||
187 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
188 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | return -EIO; | ||
193 | } | ||
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 6fa6c8e04ff0..8f92d670f614 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -58,8 +58,8 @@ | |||
58 | * THE POSSIBILITY OF SUCH DAMAGES. | 58 | * THE POSSIBILITY OF SUCH DAMAGES. |
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include "debug.h" | ||
62 | #include "base.h" | 61 | #include "base.h" |
62 | #include "debug.h" | ||
63 | 63 | ||
64 | static unsigned int ath5k_debug; | 64 | static unsigned int ath5k_debug; |
65 | module_param_named(debug, ath5k_debug, uint, 0); | 65 | module_param_named(debug, ath5k_debug, uint, 0); |
@@ -525,7 +525,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
525 | return; | 525 | return; |
526 | 526 | ||
527 | printk(KERN_DEBUG "rx queue %x, link %p\n", | 527 | printk(KERN_DEBUG "rx queue %x, link %p\n", |
528 | ath5k_hw_get_rx_buf(ah), sc->rxlink); | 528 | ath5k_hw_get_rxdp(ah), sc->rxlink); |
529 | 529 | ||
530 | spin_lock_bh(&sc->rxbuflock); | 530 | spin_lock_bh(&sc->rxbuflock); |
531 | list_for_each_entry(bf, &sc->rxbuf, list) { | 531 | list_for_each_entry(bf, &sc->rxbuf, list) { |
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c new file mode 100644 index 000000000000..d45b90a6e06c --- /dev/null +++ b/drivers/net/wireless/ath5k/desc.c | |||
@@ -0,0 +1,667 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | /******************************\ | ||
21 | Hardware Descriptor Functions | ||
22 | \******************************/ | ||
23 | |||
24 | #include "ath5k.h" | ||
25 | #include "reg.h" | ||
26 | #include "debug.h" | ||
27 | #include "base.h" | ||
28 | |||
29 | /* | ||
30 | * TX Descriptors | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * Initialize the 2-word tx control descriptor on 5210/5211 | ||
35 | */ | ||
36 | static int | ||
37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
38 | unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, | ||
39 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | ||
40 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | ||
41 | unsigned int rtscts_rate, unsigned int rtscts_duration) | ||
42 | { | ||
43 | u32 frame_type; | ||
44 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
45 | unsigned int frame_len; | ||
46 | |||
47 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
48 | |||
49 | /* | ||
50 | * Validate input | ||
51 | * - Zero retries don't make sense. | ||
52 | * - A zero rate will put the HW into a mode where it continously sends | ||
53 | * noise on the channel, so it is important to avoid this. | ||
54 | */ | ||
55 | if (unlikely(tx_tries0 == 0)) { | ||
56 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
57 | WARN_ON(1); | ||
58 | return -EINVAL; | ||
59 | } | ||
60 | if (unlikely(tx_rate0 == 0)) { | ||
61 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
62 | WARN_ON(1); | ||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | /* Clear descriptor */ | ||
67 | memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); | ||
68 | |||
69 | /* Setup control descriptor */ | ||
70 | |||
71 | /* Verify and set frame length */ | ||
72 | |||
73 | /* remove padding we might have added before */ | ||
74 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | ||
75 | |||
76 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | ||
77 | return -EINVAL; | ||
78 | |||
79 | tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; | ||
80 | |||
81 | /* Verify and set buffer length */ | ||
82 | |||
83 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
84 | if (type == AR5K_PKT_TYPE_BEACON) | ||
85 | pkt_len = roundup(pkt_len, 4); | ||
86 | |||
87 | if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) | ||
88 | return -EINVAL; | ||
89 | |||
90 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | ||
91 | |||
92 | /* | ||
93 | * Verify and set header length | ||
94 | * XXX: I only found that on 5210 code, does it work on 5211 ? | ||
95 | */ | ||
96 | if (ah->ah_version == AR5K_AR5210) { | ||
97 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | ||
98 | return -EINVAL; | ||
99 | tx_ctl->tx_control_0 |= | ||
100 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | ||
101 | } | ||
102 | |||
103 | /*Diferences between 5210-5211*/ | ||
104 | if (ah->ah_version == AR5K_AR5210) { | ||
105 | switch (type) { | ||
106 | case AR5K_PKT_TYPE_BEACON: | ||
107 | case AR5K_PKT_TYPE_PROBE_RESP: | ||
108 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; | ||
109 | case AR5K_PKT_TYPE_PIFS: | ||
110 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | ||
111 | default: | ||
112 | frame_type = type /*<< 2 ?*/; | ||
113 | } | ||
114 | |||
115 | tx_ctl->tx_control_0 |= | ||
116 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | ||
117 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
118 | |||
119 | } else { | ||
120 | tx_ctl->tx_control_0 |= | ||
121 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | | ||
122 | AR5K_REG_SM(antenna_mode, | ||
123 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
124 | tx_ctl->tx_control_1 |= | ||
125 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | ||
126 | } | ||
127 | #define _TX_FLAGS(_c, _flag) \ | ||
128 | if (flags & AR5K_TXDESC_##_flag) { \ | ||
129 | tx_ctl->tx_control_##_c |= \ | ||
130 | AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ | ||
131 | } | ||
132 | |||
133 | _TX_FLAGS(0, CLRDMASK); | ||
134 | _TX_FLAGS(0, VEOL); | ||
135 | _TX_FLAGS(0, INTREQ); | ||
136 | _TX_FLAGS(0, RTSENA); | ||
137 | _TX_FLAGS(1, NOACK); | ||
138 | |||
139 | #undef _TX_FLAGS | ||
140 | |||
141 | /* | ||
142 | * WEP crap | ||
143 | */ | ||
144 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
145 | tx_ctl->tx_control_0 |= | ||
146 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
147 | tx_ctl->tx_control_1 |= | ||
148 | AR5K_REG_SM(key_index, | ||
149 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * RTS/CTS Duration [5210 ?] | ||
154 | */ | ||
155 | if ((ah->ah_version == AR5K_AR5210) && | ||
156 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | ||
157 | tx_ctl->tx_control_1 |= rtscts_duration & | ||
158 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Initialize the 4-word tx control descriptor on 5212 | ||
165 | */ | ||
166 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | ||
167 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | ||
168 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | ||
169 | unsigned int tx_tries0, unsigned int key_index, | ||
170 | unsigned int antenna_mode, unsigned int flags, | ||
171 | unsigned int rtscts_rate, | ||
172 | unsigned int rtscts_duration) | ||
173 | { | ||
174 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
175 | unsigned int frame_len; | ||
176 | |||
177 | ATH5K_TRACE(ah->ah_sc); | ||
178 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
179 | |||
180 | /* | ||
181 | * Validate input | ||
182 | * - Zero retries don't make sense. | ||
183 | * - A zero rate will put the HW into a mode where it continously sends | ||
184 | * noise on the channel, so it is important to avoid this. | ||
185 | */ | ||
186 | if (unlikely(tx_tries0 == 0)) { | ||
187 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
188 | WARN_ON(1); | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | if (unlikely(tx_rate0 == 0)) { | ||
192 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
193 | WARN_ON(1); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | /* Clear descriptor */ | ||
198 | memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); | ||
199 | |||
200 | /* Setup control descriptor */ | ||
201 | |||
202 | /* Verify and set frame length */ | ||
203 | |||
204 | /* remove padding we might have added before */ | ||
205 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | ||
206 | |||
207 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | ||
208 | return -EINVAL; | ||
209 | |||
210 | tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | ||
211 | |||
212 | /* Verify and set buffer length */ | ||
213 | |||
214 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
215 | if (type == AR5K_PKT_TYPE_BEACON) | ||
216 | pkt_len = roundup(pkt_len, 4); | ||
217 | |||
218 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | ||
219 | return -EINVAL; | ||
220 | |||
221 | tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | ||
222 | |||
223 | tx_ctl->tx_control_0 |= | ||
224 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | ||
225 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
226 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | ||
227 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | ||
228 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | ||
229 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | ||
230 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
231 | |||
232 | #define _TX_FLAGS(_c, _flag) \ | ||
233 | if (flags & AR5K_TXDESC_##_flag) { \ | ||
234 | tx_ctl->tx_control_##_c |= \ | ||
235 | AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ | ||
236 | } | ||
237 | |||
238 | _TX_FLAGS(0, CLRDMASK); | ||
239 | _TX_FLAGS(0, VEOL); | ||
240 | _TX_FLAGS(0, INTREQ); | ||
241 | _TX_FLAGS(0, RTSENA); | ||
242 | _TX_FLAGS(0, CTSENA); | ||
243 | _TX_FLAGS(1, NOACK); | ||
244 | |||
245 | #undef _TX_FLAGS | ||
246 | |||
247 | /* | ||
248 | * WEP crap | ||
249 | */ | ||
250 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
251 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
252 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | ||
253 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * RTS/CTS | ||
258 | */ | ||
259 | if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { | ||
260 | if ((flags & AR5K_TXDESC_RTSENA) && | ||
261 | (flags & AR5K_TXDESC_CTSENA)) | ||
262 | return -EINVAL; | ||
263 | tx_ctl->tx_control_2 |= rtscts_duration & | ||
264 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | ||
265 | tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | ||
266 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 | ||
274 | */ | ||
275 | static int | ||
276 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
277 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
278 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | ||
279 | { | ||
280 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
281 | |||
282 | /* | ||
283 | * Rates can be 0 as long as the retry count is 0 too. | ||
284 | * A zero rate and nonzero retry count will put the HW into a mode where | ||
285 | * it continously sends noise on the channel, so it is important to | ||
286 | * avoid this. | ||
287 | */ | ||
288 | if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || | ||
289 | (tx_rate2 == 0 && tx_tries2 != 0) || | ||
290 | (tx_rate3 == 0 && tx_tries3 != 0))) { | ||
291 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
292 | WARN_ON(1); | ||
293 | return -EINVAL; | ||
294 | } | ||
295 | |||
296 | if (ah->ah_version == AR5K_AR5212) { | ||
297 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
298 | |||
299 | #define _XTX_TRIES(_n) \ | ||
300 | if (tx_tries##_n) { \ | ||
301 | tx_ctl->tx_control_2 |= \ | ||
302 | AR5K_REG_SM(tx_tries##_n, \ | ||
303 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ | ||
304 | tx_ctl->tx_control_3 |= \ | ||
305 | AR5K_REG_SM(tx_rate##_n, \ | ||
306 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ | ||
307 | } | ||
308 | |||
309 | _XTX_TRIES(1); | ||
310 | _XTX_TRIES(2); | ||
311 | _XTX_TRIES(3); | ||
312 | |||
313 | #undef _XTX_TRIES | ||
314 | |||
315 | return 1; | ||
316 | } | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * Proccess the tx status descriptor on 5210/5211 | ||
323 | */ | ||
324 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | ||
325 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | ||
326 | { | ||
327 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
328 | struct ath5k_hw_tx_status *tx_status; | ||
329 | |||
330 | ATH5K_TRACE(ah->ah_sc); | ||
331 | |||
332 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
333 | tx_status = &desc->ud.ds_tx5210.tx_stat; | ||
334 | |||
335 | /* No frame has been send or error */ | ||
336 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | ||
337 | return -EINPROGRESS; | ||
338 | |||
339 | /* | ||
340 | * Get descriptor status | ||
341 | */ | ||
342 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
343 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
344 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
345 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
346 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
347 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
348 | /*TODO: ts->ts_virtcol + test*/ | ||
349 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
350 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
351 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
352 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
353 | ts->ts_antenna = 1; | ||
354 | ts->ts_status = 0; | ||
355 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, | ||
356 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
357 | |||
358 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | ||
359 | if (tx_status->tx_status_0 & | ||
360 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
361 | ts->ts_status |= AR5K_TXERR_XRETRY; | ||
362 | |||
363 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
364 | ts->ts_status |= AR5K_TXERR_FIFO; | ||
365 | |||
366 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
367 | ts->ts_status |= AR5K_TXERR_FILT; | ||
368 | } | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * Proccess a tx status descriptor on 5212 | ||
375 | */ | ||
376 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | ||
377 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | ||
378 | { | ||
379 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
380 | struct ath5k_hw_tx_status *tx_status; | ||
381 | |||
382 | ATH5K_TRACE(ah->ah_sc); | ||
383 | |||
384 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
385 | tx_status = &desc->ud.ds_tx5212.tx_stat; | ||
386 | |||
387 | /* No frame has been send or error */ | ||
388 | if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) | ||
389 | return -EINPROGRESS; | ||
390 | |||
391 | /* | ||
392 | * Get descriptor status | ||
393 | */ | ||
394 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
395 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
396 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
397 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
398 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
399 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
400 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
401 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
402 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
403 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
404 | ts->ts_antenna = (tx_status->tx_status_1 & | ||
405 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | ||
406 | ts->ts_status = 0; | ||
407 | |||
408 | switch (AR5K_REG_MS(tx_status->tx_status_1, | ||
409 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { | ||
410 | case 0: | ||
411 | ts->ts_rate = tx_ctl->tx_control_3 & | ||
412 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
413 | break; | ||
414 | case 1: | ||
415 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
416 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | ||
417 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
418 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
419 | break; | ||
420 | case 2: | ||
421 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
422 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
423 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
424 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
425 | break; | ||
426 | case 3: | ||
427 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
428 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
429 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
430 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | /* TX error */ | ||
435 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | ||
436 | if (tx_status->tx_status_0 & | ||
437 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
438 | ts->ts_status |= AR5K_TXERR_XRETRY; | ||
439 | |||
440 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
441 | ts->ts_status |= AR5K_TXERR_FIFO; | ||
442 | |||
443 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
444 | ts->ts_status |= AR5K_TXERR_FILT; | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * RX Descriptors | ||
452 | */ | ||
453 | |||
454 | /* | ||
455 | * Initialize an rx control descriptor | ||
456 | */ | ||
457 | static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
458 | u32 size, unsigned int flags) | ||
459 | { | ||
460 | struct ath5k_hw_rx_ctl *rx_ctl; | ||
461 | |||
462 | ATH5K_TRACE(ah->ah_sc); | ||
463 | rx_ctl = &desc->ud.ds_rx.rx_ctl; | ||
464 | |||
465 | /* | ||
466 | * Clear the descriptor | ||
467 | * If we don't clean the status descriptor, | ||
468 | * while scanning we get too many results, | ||
469 | * most of them virtual, after some secs | ||
470 | * of scanning system hangs. M.F. | ||
471 | */ | ||
472 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); | ||
473 | |||
474 | /* Setup descriptor */ | ||
475 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | ||
476 | if (unlikely(rx_ctl->rx_control_1 != size)) | ||
477 | return -EINVAL; | ||
478 | |||
479 | if (flags & AR5K_RXDESC_INTREQ) | ||
480 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Proccess the rx status descriptor on 5210/5211 | ||
487 | */ | ||
488 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | ||
489 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | ||
490 | { | ||
491 | struct ath5k_hw_rx_status *rx_status; | ||
492 | |||
493 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
494 | |||
495 | /* No frame received / not ready */ | ||
496 | if (unlikely(!(rx_status->rx_status_1 & | ||
497 | AR5K_5210_RX_DESC_STATUS1_DONE))) | ||
498 | return -EINPROGRESS; | ||
499 | |||
500 | /* | ||
501 | * Frame receive status | ||
502 | */ | ||
503 | rs->rs_datalen = rx_status->rx_status_0 & | ||
504 | AR5K_5210_RX_DESC_STATUS0_DATA_LEN; | ||
505 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
506 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
507 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
508 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); | ||
509 | rs->rs_antenna = rx_status->rx_status_0 & | ||
510 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
511 | rs->rs_more = rx_status->rx_status_0 & | ||
512 | AR5K_5210_RX_DESC_STATUS0_MORE; | ||
513 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ | ||
514 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
515 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
516 | rs->rs_status = 0; | ||
517 | rs->rs_phyerr = 0; | ||
518 | |||
519 | /* | ||
520 | * Key table status | ||
521 | */ | ||
522 | if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
523 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
524 | AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); | ||
525 | else | ||
526 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | ||
527 | |||
528 | /* | ||
529 | * Receive/descriptor errors | ||
530 | */ | ||
531 | if (!(rx_status->rx_status_1 & | ||
532 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | ||
533 | if (rx_status->rx_status_1 & | ||
534 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) | ||
535 | rs->rs_status |= AR5K_RXERR_CRC; | ||
536 | |||
537 | if (rx_status->rx_status_1 & | ||
538 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) | ||
539 | rs->rs_status |= AR5K_RXERR_FIFO; | ||
540 | |||
541 | if (rx_status->rx_status_1 & | ||
542 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { | ||
543 | rs->rs_status |= AR5K_RXERR_PHY; | ||
544 | rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, | ||
545 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); | ||
546 | } | ||
547 | |||
548 | if (rx_status->rx_status_1 & | ||
549 | AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
550 | rs->rs_status |= AR5K_RXERR_DECRYPT; | ||
551 | } | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Proccess the rx status descriptor on 5212 | ||
558 | */ | ||
559 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | ||
560 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | ||
561 | { | ||
562 | struct ath5k_hw_rx_status *rx_status; | ||
563 | struct ath5k_hw_rx_error *rx_err; | ||
564 | |||
565 | ATH5K_TRACE(ah->ah_sc); | ||
566 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
567 | |||
568 | /* Overlay on error */ | ||
569 | rx_err = &desc->ud.ds_rx.u.rx_err; | ||
570 | |||
571 | /* No frame received / not ready */ | ||
572 | if (unlikely(!(rx_status->rx_status_1 & | ||
573 | AR5K_5212_RX_DESC_STATUS1_DONE))) | ||
574 | return -EINPROGRESS; | ||
575 | |||
576 | /* | ||
577 | * Frame receive status | ||
578 | */ | ||
579 | rs->rs_datalen = rx_status->rx_status_0 & | ||
580 | AR5K_5212_RX_DESC_STATUS0_DATA_LEN; | ||
581 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
582 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
583 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
584 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); | ||
585 | rs->rs_antenna = rx_status->rx_status_0 & | ||
586 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
587 | rs->rs_more = rx_status->rx_status_0 & | ||
588 | AR5K_5212_RX_DESC_STATUS0_MORE; | ||
589 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
590 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
591 | rs->rs_status = 0; | ||
592 | rs->rs_phyerr = 0; | ||
593 | |||
594 | /* | ||
595 | * Key table status | ||
596 | */ | ||
597 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
598 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
599 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | ||
600 | else | ||
601 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | ||
602 | |||
603 | /* | ||
604 | * Receive/descriptor errors | ||
605 | */ | ||
606 | if (!(rx_status->rx_status_1 & | ||
607 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | ||
608 | if (rx_status->rx_status_1 & | ||
609 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | ||
610 | rs->rs_status |= AR5K_RXERR_CRC; | ||
611 | |||
612 | if (rx_status->rx_status_1 & | ||
613 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | ||
614 | rs->rs_status |= AR5K_RXERR_PHY; | ||
615 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | ||
616 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | ||
617 | } | ||
618 | |||
619 | if (rx_status->rx_status_1 & | ||
620 | AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
621 | rs->rs_status |= AR5K_RXERR_DECRYPT; | ||
622 | |||
623 | if (rx_status->rx_status_1 & | ||
624 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | ||
625 | rs->rs_status |= AR5K_RXERR_MIC; | ||
626 | } | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | * Init function pointers inside ath5k_hw struct | ||
633 | */ | ||
634 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | ||
635 | { | ||
636 | |||
637 | if (ah->ah_version != AR5K_AR5210 && | ||
638 | ah->ah_version != AR5K_AR5211 && | ||
639 | ah->ah_version != AR5K_AR5212) | ||
640 | return -ENOTSUPP; | ||
641 | |||
642 | /* XXX: What is this magic value and where is it used ? */ | ||
643 | if (ah->ah_version == AR5K_AR5212) | ||
644 | ah->ah_magic = AR5K_EEPROM_MAGIC_5212; | ||
645 | else if (ah->ah_version == AR5K_AR5211) | ||
646 | ah->ah_magic = AR5K_EEPROM_MAGIC_5211; | ||
647 | |||
648 | if (ah->ah_version == AR5K_AR5212) { | ||
649 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | ||
650 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | ||
651 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; | ||
652 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; | ||
653 | } else { | ||
654 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | ||
655 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | ||
656 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; | ||
657 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | ||
658 | } | ||
659 | |||
660 | if (ah->ah_version == AR5K_AR5212) | ||
661 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; | ||
662 | else if (ah->ah_version <= AR5K_AR5211) | ||
663 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/desc.h index 64fca8dcb386..56158c804e3e 100644 --- a/drivers/net/wireless/ath5k/hw.h +++ b/drivers/net/wireless/ath5k/desc.h | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | 2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> |
3 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> | 3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> |
4 | * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org> | ||
5 | * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
6 | * | 4 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | 5 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,159 +13,9 @@ | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | * | ||
18 | */ | 17 | */ |
19 | 18 | ||
20 | #include <linux/delay.h> | ||
21 | |||
22 | /* | ||
23 | * Gain settings | ||
24 | */ | ||
25 | |||
26 | enum ath5k_rfgain { | ||
27 | AR5K_RFGAIN_INACTIVE = 0, | ||
28 | AR5K_RFGAIN_READ_REQUESTED, | ||
29 | AR5K_RFGAIN_NEED_CHANGE, | ||
30 | }; | ||
31 | |||
32 | #define AR5K_GAIN_CRN_FIX_BITS_5111 4 | ||
33 | #define AR5K_GAIN_CRN_FIX_BITS_5112 7 | ||
34 | #define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 | ||
35 | #define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 | ||
36 | #define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 | ||
37 | #define AR5K_GAIN_CCK_PROBE_CORR 5 | ||
38 | #define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 | ||
39 | #define AR5K_GAIN_STEP_COUNT 10 | ||
40 | #define AR5K_GAIN_PARAM_TX_CLIP 0 | ||
41 | #define AR5K_GAIN_PARAM_PD_90 1 | ||
42 | #define AR5K_GAIN_PARAM_PD_84 2 | ||
43 | #define AR5K_GAIN_PARAM_GAIN_SEL 3 | ||
44 | #define AR5K_GAIN_PARAM_MIX_ORN 0 | ||
45 | #define AR5K_GAIN_PARAM_PD_138 1 | ||
46 | #define AR5K_GAIN_PARAM_PD_137 2 | ||
47 | #define AR5K_GAIN_PARAM_PD_136 3 | ||
48 | #define AR5K_GAIN_PARAM_PD_132 4 | ||
49 | #define AR5K_GAIN_PARAM_PD_131 5 | ||
50 | #define AR5K_GAIN_PARAM_PD_130 6 | ||
51 | #define AR5K_GAIN_CHECK_ADJUST(_g) \ | ||
52 | ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) | ||
53 | |||
54 | struct ath5k_gain_opt_step { | ||
55 | s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; | ||
56 | s32 gos_gain; | ||
57 | }; | ||
58 | |||
59 | struct ath5k_gain { | ||
60 | u32 g_step_idx; | ||
61 | u32 g_current; | ||
62 | u32 g_target; | ||
63 | u32 g_low; | ||
64 | u32 g_high; | ||
65 | u32 g_f_corr; | ||
66 | u32 g_active; | ||
67 | const struct ath5k_gain_opt_step *g_step; | ||
68 | }; | ||
69 | |||
70 | |||
71 | /* | ||
72 | * HW SPECIFIC STRUCTS | ||
73 | */ | ||
74 | |||
75 | /* Some EEPROM defines */ | ||
76 | #define AR5K_EEPROM_EEP_SCALE 100 | ||
77 | #define AR5K_EEPROM_EEP_DELTA 10 | ||
78 | #define AR5K_EEPROM_N_MODES 3 | ||
79 | #define AR5K_EEPROM_N_5GHZ_CHAN 10 | ||
80 | #define AR5K_EEPROM_N_2GHZ_CHAN 3 | ||
81 | #define AR5K_EEPROM_MAX_CHAN 10 | ||
82 | #define AR5K_EEPROM_N_PCDAC 11 | ||
83 | #define AR5K_EEPROM_N_TEST_FREQ 8 | ||
84 | #define AR5K_EEPROM_N_EDGES 8 | ||
85 | #define AR5K_EEPROM_N_INTERCEPTS 11 | ||
86 | #define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) | ||
87 | #define AR5K_EEPROM_PCDAC_M 0x3f | ||
88 | #define AR5K_EEPROM_PCDAC_START 1 | ||
89 | #define AR5K_EEPROM_PCDAC_STOP 63 | ||
90 | #define AR5K_EEPROM_PCDAC_STEP 1 | ||
91 | #define AR5K_EEPROM_NON_EDGE_M 0x40 | ||
92 | #define AR5K_EEPROM_CHANNEL_POWER 8 | ||
93 | #define AR5K_EEPROM_N_OBDB 4 | ||
94 | #define AR5K_EEPROM_OBDB_DIS 0xffff | ||
95 | #define AR5K_EEPROM_CHANNEL_DIS 0xff | ||
96 | #define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) | ||
97 | #define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) | ||
98 | #define AR5K_EEPROM_MAX_CTLS 32 | ||
99 | #define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 | ||
100 | #define AR5K_EEPROM_N_XPD0_POINTS 4 | ||
101 | #define AR5K_EEPROM_N_XPD3_POINTS 3 | ||
102 | #define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 | ||
103 | #define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 | ||
104 | #define AR5K_EEPROM_POWER_M 0x3f | ||
105 | #define AR5K_EEPROM_POWER_MIN 0 | ||
106 | #define AR5K_EEPROM_POWER_MAX 3150 | ||
107 | #define AR5K_EEPROM_POWER_STEP 50 | ||
108 | #define AR5K_EEPROM_POWER_TABLE_SIZE 64 | ||
109 | #define AR5K_EEPROM_N_POWER_LOC_11B 4 | ||
110 | #define AR5K_EEPROM_N_POWER_LOC_11G 6 | ||
111 | #define AR5K_EEPROM_I_GAIN 10 | ||
112 | #define AR5K_EEPROM_CCK_OFDM_DELTA 15 | ||
113 | #define AR5K_EEPROM_N_IQ_CAL 2 | ||
114 | |||
115 | /* Struct to hold EEPROM calibration data */ | ||
116 | struct ath5k_eeprom_info { | ||
117 | u16 ee_magic; | ||
118 | u16 ee_protect; | ||
119 | u16 ee_regdomain; | ||
120 | u16 ee_version; | ||
121 | u16 ee_header; | ||
122 | u16 ee_ant_gain; | ||
123 | u16 ee_misc0; | ||
124 | u16 ee_misc1; | ||
125 | u16 ee_cck_ofdm_gain_delta; | ||
126 | u16 ee_cck_ofdm_power_delta; | ||
127 | u16 ee_scaled_cck_delta; | ||
128 | |||
129 | /* Used for tx thermal adjustment (eeprom_init, rfregs) */ | ||
130 | u16 ee_tx_clip; | ||
131 | u16 ee_pwd_84; | ||
132 | u16 ee_pwd_90; | ||
133 | u16 ee_gain_select; | ||
134 | |||
135 | /* RF Calibration settings (reset, rfregs) */ | ||
136 | u16 ee_i_cal[AR5K_EEPROM_N_MODES]; | ||
137 | u16 ee_q_cal[AR5K_EEPROM_N_MODES]; | ||
138 | u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; | ||
139 | u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; | ||
140 | u16 ee_xr_power[AR5K_EEPROM_N_MODES]; | ||
141 | u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; | ||
142 | u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES]; | ||
143 | u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; | ||
144 | u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
145 | u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
146 | u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; | ||
147 | u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; | ||
148 | u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; | ||
149 | u16 ee_thr_62[AR5K_EEPROM_N_MODES]; | ||
150 | u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; | ||
151 | u16 ee_xpd[AR5K_EEPROM_N_MODES]; | ||
152 | u16 ee_x_gain[AR5K_EEPROM_N_MODES]; | ||
153 | u16 ee_i_gain[AR5K_EEPROM_N_MODES]; | ||
154 | u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; | ||
155 | |||
156 | /* Unused */ | ||
157 | u16 ee_false_detect[AR5K_EEPROM_N_MODES]; | ||
158 | u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN]; | ||
159 | u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/ | ||
160 | |||
161 | /* Conformance test limits (Unused) */ | ||
162 | u16 ee_ctls; | ||
163 | u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; | ||
164 | |||
165 | /* Noise Floor Calibration settings */ | ||
166 | s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; | ||
167 | s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; | ||
168 | s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; | ||
169 | }; | ||
170 | |||
171 | /* | 19 | /* |
172 | * Internal RX/TX descriptor structures | 20 | * Internal RX/TX descriptor structures |
173 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) | 21 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) |
@@ -178,14 +26,15 @@ struct ath5k_eeprom_info { | |||
178 | */ | 26 | */ |
179 | struct ath5k_hw_rx_ctl { | 27 | struct ath5k_hw_rx_ctl { |
180 | u32 rx_control_0; /* RX control word 0 */ | 28 | u32 rx_control_0; /* RX control word 0 */ |
29 | u32 rx_control_1; /* RX control word 1 */ | ||
30 | } __packed; | ||
181 | 31 | ||
32 | /* RX control word 0 field/sflags */ | ||
182 | #define AR5K_DESC_RX_CTL0 0x00000000 | 33 | #define AR5K_DESC_RX_CTL0 0x00000000 |
183 | 34 | ||
184 | u32 rx_control_1; /* RX control word 1 */ | 35 | /* RX control word 1 fields/flags */ |
185 | |||
186 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff | 36 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff |
187 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 | 37 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 |
188 | } __packed; | ||
189 | 38 | ||
190 | /* | 39 | /* |
191 | * common hardware RX status descriptor | 40 | * common hardware RX status descriptor |
@@ -197,6 +46,7 @@ struct ath5k_hw_rx_status { | |||
197 | } __packed; | 46 | } __packed; |
198 | 47 | ||
199 | /* 5210/5211 */ | 48 | /* 5210/5211 */ |
49 | /* RX status word 0 fields/flags */ | ||
200 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 50 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff |
201 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 | 51 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 |
202 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | 52 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 |
@@ -205,6 +55,8 @@ struct ath5k_hw_rx_status { | |||
205 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | 55 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 |
206 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | 56 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 |
207 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | 57 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 |
58 | |||
59 | /* RX status word 1 fields/flags */ | ||
208 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 | 60 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 |
209 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 61 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 |
210 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 62 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 |
@@ -220,6 +72,7 @@ struct ath5k_hw_rx_status { | |||
220 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | 72 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 |
221 | 73 | ||
222 | /* 5212 */ | 74 | /* 5212 */ |
75 | /* RX status word 0 fields/flags */ | ||
223 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 76 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff |
224 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 | 77 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 |
225 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | 78 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 |
@@ -229,6 +82,8 @@ struct ath5k_hw_rx_status { | |||
229 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | 82 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 |
230 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | 83 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 |
231 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | 84 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 |
85 | |||
86 | /* RX status word 1 fields/flags */ | ||
232 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 | 87 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 |
233 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 88 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 |
234 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 89 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 |
@@ -246,16 +101,18 @@ struct ath5k_hw_rx_status { | |||
246 | * common hardware RX error descriptor | 101 | * common hardware RX error descriptor |
247 | */ | 102 | */ |
248 | struct ath5k_hw_rx_error { | 103 | struct ath5k_hw_rx_error { |
249 | u32 rx_error_0; /* RX error word 0 */ | 104 | u32 rx_error_0; /* RX status word 0 */ |
105 | u32 rx_error_1; /* RX status word 1 */ | ||
106 | } __packed; | ||
250 | 107 | ||
108 | /* RX error word 0 fields/flags */ | ||
251 | #define AR5K_RX_DESC_ERROR0 0x00000000 | 109 | #define AR5K_RX_DESC_ERROR0 0x00000000 |
252 | 110 | ||
253 | u32 rx_error_1; /* RX error word 1 */ | 111 | /* RX error word 1 fields/flags */ |
254 | |||
255 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | 112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 |
256 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | 113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 |
257 | } __packed; | ||
258 | 114 | ||
115 | /* PHY Error codes */ | ||
259 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 | 116 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 |
260 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 | 117 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 |
261 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 | 118 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 |
@@ -270,7 +127,10 @@ struct ath5k_hw_rx_error { | |||
270 | */ | 127 | */ |
271 | struct ath5k_hw_2w_tx_ctl { | 128 | struct ath5k_hw_2w_tx_ctl { |
272 | u32 tx_control_0; /* TX control word 0 */ | 129 | u32 tx_control_0; /* TX control word 0 */ |
130 | u32 tx_control_1; /* TX control word 1 */ | ||
131 | } __packed; | ||
273 | 132 | ||
133 | /* TX control word 0 fields/flags */ | ||
274 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 134 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff |
275 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ | 135 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ |
276 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 | 136 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 |
@@ -284,29 +144,34 @@ struct ath5k_hw_2w_tx_ctl { | |||
284 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 | 144 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 |
285 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 | 145 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 |
286 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 | 146 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 |
287 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT (ah->ah_version == AR5K_AR5210 ? \ | 147 | |
288 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ | 148 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ |
289 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) | 149 | (ah->ah_version == AR5K_AR5210 ? \ |
150 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ | ||
151 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) | ||
152 | |||
290 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | 153 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 |
291 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 | 154 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 |
292 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | 155 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 |
293 | 156 | ||
294 | u32 tx_control_1; /* TX control word 1 */ | 157 | /* TX control word 1 fields/flags */ |
295 | |||
296 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff | 158 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff |
297 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 | 159 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 |
298 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 | 160 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 |
299 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 | 161 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 |
300 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX (ah->ah_version == AR5K_AR5210 ? \ | 162 | |
301 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ | 163 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ |
302 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) | 164 | (ah->ah_version == AR5K_AR5210 ? \ |
165 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ | ||
166 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) | ||
167 | |||
303 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | 168 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 |
304 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ | 169 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ |
305 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 | 170 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 |
306 | #define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ | 171 | #define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ |
307 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ | 172 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ |
308 | } __packed; | ||
309 | 173 | ||
174 | /* Frame types */ | ||
310 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 | 175 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 |
311 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 | 176 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 |
312 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 | 177 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 |
@@ -378,7 +243,10 @@ struct ath5k_hw_4w_tx_ctl { | |||
378 | */ | 243 | */ |
379 | struct ath5k_hw_tx_status { | 244 | struct ath5k_hw_tx_status { |
380 | u32 tx_status_0; /* TX status word 0 */ | 245 | u32 tx_status_0; /* TX status word 0 */ |
246 | u32 tx_status_1; /* TX status word 1 */ | ||
247 | } __packed; | ||
381 | 248 | ||
249 | /* TX status word 0 fields/flags */ | ||
382 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 | 250 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 |
383 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 | 251 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 |
384 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 | 252 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 |
@@ -400,8 +268,7 @@ struct ath5k_hw_tx_status { | |||
400 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 | 268 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 |
401 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 | 269 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 |
402 | 270 | ||
403 | u32 tx_status_1; /* TX status word 1 */ | 271 | /* TX status word 1 fields/flags */ |
404 | |||
405 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 | 272 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 |
406 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe | 273 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe |
407 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 | 274 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 |
@@ -411,8 +278,6 @@ struct ath5k_hw_tx_status { | |||
411 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 | 278 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 |
412 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 | 279 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 |
413 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 | 280 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 |
414 | } __packed; | ||
415 | |||
416 | 281 | ||
417 | /* | 282 | /* |
418 | * 5210/5211 hardware TX descriptor | 283 | * 5210/5211 hardware TX descriptor |
@@ -441,176 +306,27 @@ struct ath5k_hw_all_rx_desc { | |||
441 | } u; | 306 | } u; |
442 | } __packed; | 307 | } __packed; |
443 | 308 | ||
444 | |||
445 | /* | 309 | /* |
446 | * AR5K REGISTER ACCESS | 310 | * Atheros hardware descriptor |
311 | * This is read and written to by the hardware | ||
447 | */ | 312 | */ |
313 | struct ath5k_desc { | ||
314 | u32 ds_link; /* physical address of the next descriptor */ | ||
315 | u32 ds_data; /* physical address of data buffer (skb) */ | ||
448 | 316 | ||
449 | /*Swap RX/TX Descriptor for big endian archs*/ | 317 | union { |
450 | #if defined(__BIG_ENDIAN) | 318 | struct ath5k_hw_5210_tx_desc ds_tx5210; |
451 | #define AR5K_INIT_CFG ( \ | 319 | struct ath5k_hw_5212_tx_desc ds_tx5212; |
452 | AR5K_CFG_SWTD | AR5K_CFG_SWRD \ | 320 | struct ath5k_hw_all_rx_desc ds_rx; |
453 | ) | 321 | } ud; |
454 | #else | 322 | } __packed; |
455 | #define AR5K_INIT_CFG 0x00000000 | ||
456 | #endif | ||
457 | |||
458 | /*#define AR5K_REG_READ(_reg) ath5k_hw_reg_read(ah, _reg) | ||
459 | |||
460 | #define AR5K_REG_WRITE(_reg, _val) ath5k_hw_reg_write(ah, _val, _reg)*/ | ||
461 | |||
462 | #define AR5K_REG_SM(_val, _flags) \ | ||
463 | (((_val) << _flags##_S) & (_flags)) | ||
464 | |||
465 | #define AR5K_REG_MS(_val, _flags) \ | ||
466 | (((_val) & (_flags)) >> _flags##_S) | ||
467 | |||
468 | /* Some registers can hold multiple values of interest. For this | ||
469 | * reason when we want to write to these registers we must first | ||
470 | * retrieve the values which we do not want to clear (lets call this | ||
471 | * old_data) and then set the register with this and our new_value: | ||
472 | * ( old_data | new_value) */ | ||
473 | #define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ | ||
474 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ | ||
475 | (((_val) << _flags##_S) & (_flags)), _reg) | ||
476 | |||
477 | #define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ | ||
478 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ | ||
479 | (_mask)) | (_flags), _reg) | ||
480 | |||
481 | #define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ | ||
482 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) | ||
483 | |||
484 | #define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ | ||
485 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) | ||
486 | |||
487 | #define AR5K_PHY_WRITE(ah, _reg, _val) \ | ||
488 | ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) | ||
489 | |||
490 | #define AR5K_PHY_READ(ah, _reg) \ | ||
491 | ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) | ||
492 | |||
493 | #define AR5K_REG_WAIT(_i) do { \ | ||
494 | if (_i % 64) \ | ||
495 | udelay(1); \ | ||
496 | } while (0) | ||
497 | |||
498 | #define AR5K_EEPROM_READ(_o, _v) do { \ | ||
499 | if ((ret = ath5k_hw_eeprom_read(ah, (_o), &(_v))) != 0) \ | ||
500 | return (ret); \ | ||
501 | } while (0) | ||
502 | |||
503 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | ||
504 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ | ||
505 | |||
506 | /* Read status of selected queue */ | ||
507 | #define AR5K_REG_READ_Q(ah, _reg, _queue) \ | ||
508 | (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ | ||
509 | |||
510 | #define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ | ||
511 | ath5k_hw_reg_write(ah, (1 << _queue), _reg) | ||
512 | |||
513 | #define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ | ||
514 | _reg |= 1 << _queue; \ | ||
515 | } while (0) | ||
516 | |||
517 | #define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ | ||
518 | _reg &= ~(1 << _queue); \ | ||
519 | } while (0) | ||
520 | |||
521 | #define AR5K_LOW_ID(_a)( \ | ||
522 | (_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ | ||
523 | ) | ||
524 | |||
525 | #define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) | ||
526 | |||
527 | /* | ||
528 | * Initial register values | ||
529 | */ | ||
530 | |||
531 | /* | ||
532 | * Common initial register values | ||
533 | */ | ||
534 | #define AR5K_INIT_MODE CHANNEL_B | ||
535 | |||
536 | #define AR5K_INIT_TX_LATENCY 502 | ||
537 | #define AR5K_INIT_USEC 39 | ||
538 | #define AR5K_INIT_USEC_TURBO 79 | ||
539 | #define AR5K_INIT_USEC_32 31 | ||
540 | #define AR5K_INIT_CARR_SENSE_EN 1 | ||
541 | #define AR5K_INIT_PROG_IFS 920 | ||
542 | #define AR5K_INIT_PROG_IFS_TURBO 960 | ||
543 | #define AR5K_INIT_EIFS 3440 | ||
544 | #define AR5K_INIT_EIFS_TURBO 6880 | ||
545 | #define AR5K_INIT_SLOT_TIME 396 | ||
546 | #define AR5K_INIT_SLOT_TIME_TURBO 480 | ||
547 | #define AR5K_INIT_ACK_CTS_TIMEOUT 1024 | ||
548 | #define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 | ||
549 | #define AR5K_INIT_SIFS 560 | ||
550 | #define AR5K_INIT_SIFS_TURBO 480 | ||
551 | #define AR5K_INIT_SH_RETRY 10 | ||
552 | #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY | ||
553 | #define AR5K_INIT_SSH_RETRY 32 | ||
554 | #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY | ||
555 | #define AR5K_INIT_TX_RETRY 10 | ||
556 | #define AR5K_INIT_TOPS 8 | ||
557 | #define AR5K_INIT_RXNOFRM 8 | ||
558 | #define AR5K_INIT_RPGTO 0 | ||
559 | #define AR5K_INIT_TXNOFRM 0 | ||
560 | #define AR5K_INIT_BEACON_PERIOD 65535 | ||
561 | #define AR5K_INIT_TIM_OFFSET 0 | ||
562 | #define AR5K_INIT_BEACON_EN 0 | ||
563 | #define AR5K_INIT_RESET_TSF 0 | ||
564 | |||
565 | #define AR5K_INIT_TRANSMIT_LATENCY ( \ | ||
566 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
567 | (AR5K_INIT_USEC) \ | ||
568 | ) | ||
569 | #define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ | ||
570 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
571 | (AR5K_INIT_USEC_TURBO) \ | ||
572 | ) | ||
573 | #define AR5K_INIT_PROTO_TIME_CNTRL ( \ | ||
574 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ | ||
575 | (AR5K_INIT_PROG_IFS) \ | ||
576 | ) | ||
577 | #define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ | ||
578 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ | ||
579 | (AR5K_INIT_PROG_IFS_TURBO) \ | ||
580 | ) | ||
581 | #define AR5K_INIT_BEACON_CONTROL ( \ | ||
582 | (AR5K_INIT_RESET_TSF << 24) | (AR5K_INIT_BEACON_EN << 23) | \ | ||
583 | (AR5K_INIT_TIM_OFFSET << 16) | (AR5K_INIT_BEACON_PERIOD) \ | ||
584 | ) | ||
585 | |||
586 | /* | ||
587 | * Non-common initial register values which have to be loaded into the | ||
588 | * card at boot time and after each reset. | ||
589 | */ | ||
590 | |||
591 | /* Register dumps are done per operation mode */ | ||
592 | #define AR5K_INI_RFGAIN_5GHZ 0 | ||
593 | #define AR5K_INI_RFGAIN_2GHZ 1 | ||
594 | |||
595 | #define AR5K_INI_VAL_11A 0 | ||
596 | #define AR5K_INI_VAL_11A_TURBO 1 | ||
597 | #define AR5K_INI_VAL_11B 2 | ||
598 | #define AR5K_INI_VAL_11G 3 | ||
599 | #define AR5K_INI_VAL_11G_TURBO 4 | ||
600 | #define AR5K_INI_VAL_XR 0 | ||
601 | #define AR5K_INI_VAL_MAX 5 | ||
602 | |||
603 | #define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
604 | #define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
605 | 323 | ||
606 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | 324 | #define AR5K_RXDESC_INTREQ 0x0020 |
607 | { | ||
608 | u32 retval = 0, bit, i; | ||
609 | 325 | ||
610 | for (i = 0; i < bits; i++) { | 326 | #define AR5K_TXDESC_CLRDMASK 0x0001 |
611 | bit = (val >> i) & 1; | 327 | #define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ |
612 | retval = (retval << 1) | bit; | 328 | #define AR5K_TXDESC_RTSENA 0x0004 |
613 | } | 329 | #define AR5K_TXDESC_CTSENA 0x0008 |
330 | #define AR5K_TXDESC_INTREQ 0x0010 | ||
331 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ | ||
614 | 332 | ||
615 | return retval; | ||
616 | } | ||
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c new file mode 100644 index 000000000000..a28090be9603 --- /dev/null +++ b/drivers/net/wireless/ath5k/dma.c | |||
@@ -0,0 +1,566 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /*************************************\ | ||
20 | * DMA and interrupt masking functions * | ||
21 | \*************************************/ | ||
22 | |||
23 | /* | ||
24 | * dma.c - DMA and interrupt masking functions | ||
25 | * | ||
26 | * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and | ||
27 | * handle queue setup for 5210 chipset (rest are handled on qcu.c). | ||
28 | * Also we setup interrupt mask register (IMR) and read the various iterrupt | ||
29 | * status registers (ISR). | ||
30 | * | ||
31 | * TODO: Handle SISR on 5211+ and introduce a function to return the queue | ||
32 | * number that resulted the interrupt. | ||
33 | */ | ||
34 | |||
35 | #include "ath5k.h" | ||
36 | #include "reg.h" | ||
37 | #include "debug.h" | ||
38 | #include "base.h" | ||
39 | |||
40 | /*********\ | ||
41 | * Receive * | ||
42 | \*********/ | ||
43 | |||
44 | /** | ||
45 | * ath5k_hw_start_rx_dma - Start DMA receive | ||
46 | * | ||
47 | * @ah: The &struct ath5k_hw | ||
48 | */ | ||
49 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) | ||
50 | { | ||
51 | ATH5K_TRACE(ah->ah_sc); | ||
52 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); | ||
53 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * ath5k_hw_stop_rx_dma - Stop DMA receive | ||
58 | * | ||
59 | * @ah: The &struct ath5k_hw | ||
60 | */ | ||
61 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | ||
62 | { | ||
63 | unsigned int i; | ||
64 | |||
65 | ATH5K_TRACE(ah->ah_sc); | ||
66 | ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); | ||
67 | |||
68 | /* | ||
69 | * It may take some time to disable the DMA receive unit | ||
70 | */ | ||
71 | for (i = 2000; i > 0 && | ||
72 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; | ||
73 | i--) | ||
74 | udelay(10); | ||
75 | |||
76 | return i ? 0 : -EBUSY; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * ath5k_hw_get_rxdp - Get RX Descriptor's address | ||
81 | * | ||
82 | * @ah: The &struct ath5k_hw | ||
83 | * | ||
84 | * XXX: Is RXDP read and clear ? | ||
85 | */ | ||
86 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) | ||
87 | { | ||
88 | return ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * ath5k_hw_set_rxdp - Set RX Descriptor's address | ||
93 | * | ||
94 | * @ah: The &struct ath5k_hw | ||
95 | * @phys_addr: RX descriptor address | ||
96 | * | ||
97 | * XXX: Should we check if rx is enabled before setting rxdp ? | ||
98 | */ | ||
99 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | ||
100 | { | ||
101 | ATH5K_TRACE(ah->ah_sc); | ||
102 | |||
103 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); | ||
104 | } | ||
105 | |||
106 | |||
107 | /**********\ | ||
108 | * Transmit * | ||
109 | \**********/ | ||
110 | |||
111 | /** | ||
112 | * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue | ||
113 | * | ||
114 | * @ah: The &struct ath5k_hw | ||
115 | * @queue: The hw queue number | ||
116 | * | ||
117 | * Start DMA transmit for a specific queue and since 5210 doesn't have | ||
118 | * QCU/DCU, set up queue parameters for 5210 here based on queue type (one | ||
119 | * queue for normal data and one queue for beacons). For queue setup | ||
120 | * on newer chips check out qcu.c. Returns -EINVAL if queue number is out | ||
121 | * of range or if queue is already disabled. | ||
122 | * | ||
123 | * NOTE: Must be called after setting up tx control descriptor for that | ||
124 | * queue (see below). | ||
125 | */ | ||
126 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
127 | { | ||
128 | u32 tx_queue; | ||
129 | |||
130 | ATH5K_TRACE(ah->ah_sc); | ||
131 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
132 | |||
133 | /* Return if queue is declared inactive */ | ||
134 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
135 | return -EIO; | ||
136 | |||
137 | if (ah->ah_version == AR5K_AR5210) { | ||
138 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
139 | |||
140 | /* | ||
141 | * Set the queue by type on 5210 | ||
142 | */ | ||
143 | switch (ah->ah_txq[queue].tqi_type) { | ||
144 | case AR5K_TX_QUEUE_DATA: | ||
145 | tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; | ||
146 | break; | ||
147 | case AR5K_TX_QUEUE_BEACON: | ||
148 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
149 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
150 | AR5K_BSR); | ||
151 | break; | ||
152 | case AR5K_TX_QUEUE_CAB: | ||
153 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
154 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | | ||
155 | AR5K_BCR_BDMAE, AR5K_BSR); | ||
156 | break; | ||
157 | default: | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | /* Start queue */ | ||
161 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
162 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
163 | } else { | ||
164 | /* Return if queue is disabled */ | ||
165 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) | ||
166 | return -EIO; | ||
167 | |||
168 | /* Start queue */ | ||
169 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue | ||
177 | * | ||
178 | * @ah: The &struct ath5k_hw | ||
179 | * @queue: The hw queue number | ||
180 | * | ||
181 | * Stop DMA transmit on a specific hw queue and drain queue so we don't | ||
182 | * have any pending frames. Returns -EBUSY if we still have pending frames, | ||
183 | * -EINVAL if queue number is out of range. | ||
184 | * | ||
185 | * TODO: Test queue drain code | ||
186 | */ | ||
187 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
188 | { | ||
189 | unsigned int i = 100; | ||
190 | u32 tx_queue, pending; | ||
191 | |||
192 | ATH5K_TRACE(ah->ah_sc); | ||
193 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
194 | |||
195 | /* Return if queue is declared inactive */ | ||
196 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
197 | return -EIO; | ||
198 | |||
199 | if (ah->ah_version == AR5K_AR5210) { | ||
200 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
201 | |||
202 | /* | ||
203 | * Set by queue type | ||
204 | */ | ||
205 | switch (ah->ah_txq[queue].tqi_type) { | ||
206 | case AR5K_TX_QUEUE_DATA: | ||
207 | tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; | ||
208 | break; | ||
209 | case AR5K_TX_QUEUE_BEACON: | ||
210 | case AR5K_TX_QUEUE_CAB: | ||
211 | /* XXX Fix me... */ | ||
212 | tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; | ||
213 | ath5k_hw_reg_write(ah, 0, AR5K_BSR); | ||
214 | break; | ||
215 | default: | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | /* Stop queue */ | ||
220 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
221 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
222 | } else { | ||
223 | /* | ||
224 | * Schedule TX disable and wait until queue is empty | ||
225 | */ | ||
226 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); | ||
227 | |||
228 | /*Check for pending frames*/ | ||
229 | do { | ||
230 | pending = ath5k_hw_reg_read(ah, | ||
231 | AR5K_QUEUE_STATUS(queue)) & | ||
232 | AR5K_QCU_STS_FRMPENDCNT; | ||
233 | udelay(100); | ||
234 | } while (--i && pending); | ||
235 | |||
236 | /* Clear register */ | ||
237 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); | ||
238 | if (pending) | ||
239 | return -EBUSY; | ||
240 | } | ||
241 | |||
242 | /* TODO: Check for success else return error */ | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue | ||
248 | * | ||
249 | * @ah: The &struct ath5k_hw | ||
250 | * @queue: The hw queue number | ||
251 | * | ||
252 | * Get TX descriptor's address for a specific queue. For 5210 we ignore | ||
253 | * the queue number and use tx queue type since we only have 2 queues. | ||
254 | * We use TXDP0 for normal data queue and TXDP1 for beacon queue. | ||
255 | * For newer chips with QCU/DCU we just read the corresponding TXDP register. | ||
256 | * | ||
257 | * XXX: Is TXDP read and clear ? | ||
258 | */ | ||
259 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | ||
260 | { | ||
261 | u16 tx_reg; | ||
262 | |||
263 | ATH5K_TRACE(ah->ah_sc); | ||
264 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
265 | |||
266 | /* | ||
267 | * Get the transmit queue descriptor pointer from the selected queue | ||
268 | */ | ||
269 | /*5210 doesn't have QCU*/ | ||
270 | if (ah->ah_version == AR5K_AR5210) { | ||
271 | switch (ah->ah_txq[queue].tqi_type) { | ||
272 | case AR5K_TX_QUEUE_DATA: | ||
273 | tx_reg = AR5K_NOQCU_TXDP0; | ||
274 | break; | ||
275 | case AR5K_TX_QUEUE_BEACON: | ||
276 | case AR5K_TX_QUEUE_CAB: | ||
277 | tx_reg = AR5K_NOQCU_TXDP1; | ||
278 | break; | ||
279 | default: | ||
280 | return 0xffffffff; | ||
281 | } | ||
282 | } else { | ||
283 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
284 | } | ||
285 | |||
286 | return ath5k_hw_reg_read(ah, tx_reg); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue | ||
291 | * | ||
292 | * @ah: The &struct ath5k_hw | ||
293 | * @queue: The hw queue number | ||
294 | * | ||
295 | * Set TX descriptor's address for a specific queue. For 5210 we ignore | ||
296 | * the queue number and we use tx queue type since we only have 2 queues | ||
297 | * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. | ||
298 | * For newer chips with QCU/DCU we just set the corresponding TXDP register. | ||
299 | * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still | ||
300 | * active. | ||
301 | */ | ||
302 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | ||
303 | { | ||
304 | u16 tx_reg; | ||
305 | |||
306 | ATH5K_TRACE(ah->ah_sc); | ||
307 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
308 | |||
309 | /* | ||
310 | * Set the transmit queue descriptor pointer register by type | ||
311 | * on 5210 | ||
312 | */ | ||
313 | if (ah->ah_version == AR5K_AR5210) { | ||
314 | switch (ah->ah_txq[queue].tqi_type) { | ||
315 | case AR5K_TX_QUEUE_DATA: | ||
316 | tx_reg = AR5K_NOQCU_TXDP0; | ||
317 | break; | ||
318 | case AR5K_TX_QUEUE_BEACON: | ||
319 | case AR5K_TX_QUEUE_CAB: | ||
320 | tx_reg = AR5K_NOQCU_TXDP1; | ||
321 | break; | ||
322 | default: | ||
323 | return -EINVAL; | ||
324 | } | ||
325 | } else { | ||
326 | /* | ||
327 | * Set the transmit queue descriptor pointer for | ||
328 | * the selected queue on QCU for 5211+ | ||
329 | * (this won't work if the queue is still active) | ||
330 | */ | ||
331 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
332 | return -EIO; | ||
333 | |||
334 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
335 | } | ||
336 | |||
337 | /* Set descriptor pointer */ | ||
338 | ath5k_hw_reg_write(ah, phys_addr, tx_reg); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * ath5k_hw_update_tx_triglevel - Update tx trigger level | ||
345 | * | ||
346 | * @ah: The &struct ath5k_hw | ||
347 | * @increase: Flag to force increase of trigger level | ||
348 | * | ||
349 | * This function increases/decreases the tx trigger level for the tx fifo | ||
350 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes | ||
351 | * the buffer and transmits it's data. Lowering this results sending small | ||
352 | * frames more quickly but can lead to tx underruns, raising it a lot can | ||
353 | * result other problems (i think bmiss is related). Right now we start with | ||
354 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using | ||
355 | * the increase flag. Returns -EIO if we have have reached maximum/minimum. | ||
356 | * | ||
357 | * XXX: Link this with tx DMA size ? | ||
358 | * XXX: Use it to save interrupts ? | ||
359 | * TODO: Needs testing, i think it's related to bmiss... | ||
360 | */ | ||
361 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | ||
362 | { | ||
363 | u32 trigger_level, imr; | ||
364 | int ret = -EIO; | ||
365 | |||
366 | ATH5K_TRACE(ah->ah_sc); | ||
367 | |||
368 | /* | ||
369 | * Disable interrupts by setting the mask | ||
370 | */ | ||
371 | imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); | ||
372 | |||
373 | trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), | ||
374 | AR5K_TXCFG_TXFULL); | ||
375 | |||
376 | if (!increase) { | ||
377 | if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) | ||
378 | goto done; | ||
379 | } else | ||
380 | trigger_level += | ||
381 | ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); | ||
382 | |||
383 | /* | ||
384 | * Update trigger level on success | ||
385 | */ | ||
386 | if (ah->ah_version == AR5K_AR5210) | ||
387 | ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); | ||
388 | else | ||
389 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
390 | AR5K_TXCFG_TXFULL, trigger_level); | ||
391 | |||
392 | ret = 0; | ||
393 | |||
394 | done: | ||
395 | /* | ||
396 | * Restore interrupt mask | ||
397 | */ | ||
398 | ath5k_hw_set_imr(ah, imr); | ||
399 | |||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | /*******************\ | ||
404 | * Interrupt masking * | ||
405 | \*******************/ | ||
406 | |||
407 | /** | ||
408 | * ath5k_hw_is_intr_pending - Check if we have pending interrupts | ||
409 | * | ||
410 | * @ah: The &struct ath5k_hw | ||
411 | * | ||
412 | * Check if we have pending interrupts to process. Returns 1 if we | ||
413 | * have pending interrupts and 0 if we haven't. | ||
414 | */ | ||
415 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | ||
416 | { | ||
417 | ATH5K_TRACE(ah->ah_sc); | ||
418 | return ath5k_hw_reg_read(ah, AR5K_INTPEND); | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * ath5k_hw_get_isr - Get interrupt status | ||
423 | * | ||
424 | * @ah: The @struct ath5k_hw | ||
425 | * @interrupt_mask: Driver's interrupt mask used to filter out | ||
426 | * interrupts in sw. | ||
427 | * | ||
428 | * This function is used inside our interrupt handler to determine the reason | ||
429 | * for the interrupt by reading Primary Interrupt Status Register. Returns an | ||
430 | * abstract interrupt status mask which is mostly ISR with some uncommon bits | ||
431 | * being mapped on some standard non hw-specific positions | ||
432 | * (check out &ath5k_int). | ||
433 | * | ||
434 | * NOTE: We use read-and-clear register, so after this function is called ISR | ||
435 | * is zeroed. | ||
436 | * | ||
437 | * XXX: Why filter interrupts in sw with interrupt_mask ? No benefit at all | ||
438 | * plus it can be misleading (one might thing that we save interrupts this way) | ||
439 | */ | ||
440 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | ||
441 | { | ||
442 | u32 data; | ||
443 | |||
444 | ATH5K_TRACE(ah->ah_sc); | ||
445 | |||
446 | /* | ||
447 | * Read interrupt status from the Interrupt Status register | ||
448 | * on 5210 | ||
449 | */ | ||
450 | if (ah->ah_version == AR5K_AR5210) { | ||
451 | data = ath5k_hw_reg_read(ah, AR5K_ISR); | ||
452 | if (unlikely(data == AR5K_INT_NOCARD)) { | ||
453 | *interrupt_mask = data; | ||
454 | return -ENODEV; | ||
455 | } | ||
456 | } else { | ||
457 | /* | ||
458 | * Read interrupt status from the Read-And-Clear | ||
459 | * shadow register. | ||
460 | * Note: PISR/SISR Not available on 5210 | ||
461 | */ | ||
462 | data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * Get abstract interrupt mask (driver-compatible) | ||
467 | */ | ||
468 | *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; | ||
469 | |||
470 | if (unlikely(data == AR5K_INT_NOCARD)) | ||
471 | return -ENODEV; | ||
472 | |||
473 | if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR)) | ||
474 | *interrupt_mask |= AR5K_INT_RX; | ||
475 | |||
476 | if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR | ||
477 | | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL)) | ||
478 | *interrupt_mask |= AR5K_INT_TX; | ||
479 | |||
480 | if (ah->ah_version != AR5K_AR5210) { | ||
481 | /*HIU = Host Interface Unit (PCI etc)*/ | ||
482 | if (unlikely(data & (AR5K_ISR_HIUERR))) | ||
483 | *interrupt_mask |= AR5K_INT_FATAL; | ||
484 | |||
485 | /*Beacon Not Ready*/ | ||
486 | if (unlikely(data & (AR5K_ISR_BNR))) | ||
487 | *interrupt_mask |= AR5K_INT_BNR; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * XXX: BMISS interrupts may occur after association. | ||
492 | * I found this on 5210 code but it needs testing. If this is | ||
493 | * true we should disable them before assoc and re-enable them | ||
494 | * after a successfull assoc + some jiffies. | ||
495 | */ | ||
496 | #if 0 | ||
497 | interrupt_mask &= ~AR5K_INT_BMISS; | ||
498 | #endif | ||
499 | |||
500 | /* | ||
501 | * In case we didn't handle anything, | ||
502 | * print the register value. | ||
503 | */ | ||
504 | if (unlikely(*interrupt_mask == 0 && net_ratelimit())) | ||
505 | ATH5K_PRINTF("0x%08x\n", data); | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * ath5k_hw_set_imr - Set interrupt mask | ||
512 | * | ||
513 | * @ah: The &struct ath5k_hw | ||
514 | * @new_mask: The new interrupt mask to be set | ||
515 | * | ||
516 | * Set the interrupt mask in hw to save interrupts. We do that by mapping | ||
517 | * ath5k_int bits to hw-specific bits to remove abstraction and writing | ||
518 | * Interrupt Mask Register. | ||
519 | */ | ||
520 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | ||
521 | { | ||
522 | enum ath5k_int old_mask, int_mask; | ||
523 | |||
524 | /* | ||
525 | * Disable card interrupts to prevent any race conditions | ||
526 | * (they will be re-enabled afterwards). | ||
527 | */ | ||
528 | ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); | ||
529 | ath5k_hw_reg_read(ah, AR5K_IER); | ||
530 | |||
531 | old_mask = ah->ah_imr; | ||
532 | |||
533 | /* | ||
534 | * Add additional, chipset-dependent interrupt mask flags | ||
535 | * and write them to the IMR (interrupt mask register). | ||
536 | */ | ||
537 | int_mask = new_mask & AR5K_INT_COMMON; | ||
538 | |||
539 | if (new_mask & AR5K_INT_RX) | ||
540 | int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN | | ||
541 | AR5K_IMR_RXDESC; | ||
542 | |||
543 | if (new_mask & AR5K_INT_TX) | ||
544 | int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC | | ||
545 | AR5K_IMR_TXURN; | ||
546 | |||
547 | if (ah->ah_version != AR5K_AR5210) { | ||
548 | if (new_mask & AR5K_INT_FATAL) { | ||
549 | int_mask |= AR5K_IMR_HIUERR; | ||
550 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT | | ||
551 | AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); | ||
556 | |||
557 | /* Store new interrupt mask */ | ||
558 | ah->ah_imr = new_mask; | ||
559 | |||
560 | /* ..re-enable interrupts */ | ||
561 | ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); | ||
562 | ath5k_hw_reg_read(ah, AR5K_IER); | ||
563 | |||
564 | return old_mask; | ||
565 | } | ||
566 | |||
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c new file mode 100644 index 000000000000..a883839b6a9f --- /dev/null +++ b/drivers/net/wireless/ath5k/eeprom.c | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /*************************************\ | ||
20 | * EEPROM access functions and helpers * | ||
21 | \*************************************/ | ||
22 | |||
23 | #include "ath5k.h" | ||
24 | #include "reg.h" | ||
25 | #include "debug.h" | ||
26 | #include "base.h" | ||
27 | |||
28 | /* | ||
29 | * Read from eeprom | ||
30 | */ | ||
31 | static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | ||
32 | { | ||
33 | u32 status, timeout; | ||
34 | |||
35 | ATH5K_TRACE(ah->ah_sc); | ||
36 | /* | ||
37 | * Initialize EEPROM access | ||
38 | */ | ||
39 | if (ah->ah_version == AR5K_AR5210) { | ||
40 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
41 | (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); | ||
42 | } else { | ||
43 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
44 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
45 | AR5K_EEPROM_CMD_READ); | ||
46 | } | ||
47 | |||
48 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
49 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
50 | if (status & AR5K_EEPROM_STAT_RDDONE) { | ||
51 | if (status & AR5K_EEPROM_STAT_RDERR) | ||
52 | return -EIO; | ||
53 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | ||
54 | 0xffff); | ||
55 | return 0; | ||
56 | } | ||
57 | udelay(15); | ||
58 | } | ||
59 | |||
60 | return -ETIMEDOUT; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Translate binary channel representation in EEPROM to frequency | ||
65 | */ | ||
66 | static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, | ||
67 | unsigned int mode) | ||
68 | { | ||
69 | u16 val; | ||
70 | |||
71 | if (bin == AR5K_EEPROM_CHANNEL_DIS) | ||
72 | return bin; | ||
73 | |||
74 | if (mode == AR5K_EEPROM_MODE_11A) { | ||
75 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
76 | val = (5 * bin) + 4800; | ||
77 | else | ||
78 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | ||
79 | (bin * 10) + 5100; | ||
80 | } else { | ||
81 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
82 | val = bin + 2300; | ||
83 | else | ||
84 | val = bin + 2400; | ||
85 | } | ||
86 | |||
87 | return val; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Read antenna infos from eeprom | ||
92 | */ | ||
93 | static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | ||
94 | unsigned int mode) | ||
95 | { | ||
96 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
97 | u32 o = *offset; | ||
98 | u16 val; | ||
99 | int ret, i = 0; | ||
100 | |||
101 | AR5K_EEPROM_READ(o++, val); | ||
102 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | ||
103 | ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f; | ||
104 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
105 | |||
106 | AR5K_EEPROM_READ(o++, val); | ||
107 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
108 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
109 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
110 | |||
111 | AR5K_EEPROM_READ(o++, val); | ||
112 | ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; | ||
113 | ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; | ||
114 | ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; | ||
115 | |||
116 | AR5K_EEPROM_READ(o++, val); | ||
117 | ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; | ||
118 | ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; | ||
119 | ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; | ||
120 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
121 | |||
122 | AR5K_EEPROM_READ(o++, val); | ||
123 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
124 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
125 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
126 | |||
127 | /* Get antenna modes */ | ||
128 | ah->ah_antenna[mode][0] = | ||
129 | (ee->ee_ant_control[mode][0] << 4) | 0x1; | ||
130 | ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = | ||
131 | ee->ee_ant_control[mode][1] | | ||
132 | (ee->ee_ant_control[mode][2] << 6) | | ||
133 | (ee->ee_ant_control[mode][3] << 12) | | ||
134 | (ee->ee_ant_control[mode][4] << 18) | | ||
135 | (ee->ee_ant_control[mode][5] << 24); | ||
136 | ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = | ||
137 | ee->ee_ant_control[mode][6] | | ||
138 | (ee->ee_ant_control[mode][7] << 6) | | ||
139 | (ee->ee_ant_control[mode][8] << 12) | | ||
140 | (ee->ee_ant_control[mode][9] << 18) | | ||
141 | (ee->ee_ant_control[mode][10] << 24); | ||
142 | |||
143 | /* return new offset */ | ||
144 | *offset = o; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Read supported modes from eeprom | ||
151 | */ | ||
152 | static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | ||
153 | unsigned int mode) | ||
154 | { | ||
155 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
156 | u32 o = *offset; | ||
157 | u16 val; | ||
158 | int ret; | ||
159 | |||
160 | AR5K_EEPROM_READ(o++, val); | ||
161 | ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; | ||
162 | ee->ee_thr_62[mode] = val & 0xff; | ||
163 | |||
164 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
165 | ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; | ||
166 | |||
167 | AR5K_EEPROM_READ(o++, val); | ||
168 | ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; | ||
169 | ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; | ||
170 | |||
171 | AR5K_EEPROM_READ(o++, val); | ||
172 | ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; | ||
173 | |||
174 | if ((val & 0xff) & 0x80) | ||
175 | ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); | ||
176 | else | ||
177 | ee->ee_noise_floor_thr[mode] = val & 0xff; | ||
178 | |||
179 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
180 | ee->ee_noise_floor_thr[mode] = | ||
181 | mode == AR5K_EEPROM_MODE_11A ? -54 : -1; | ||
182 | |||
183 | AR5K_EEPROM_READ(o++, val); | ||
184 | ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; | ||
185 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; | ||
186 | ee->ee_xpd[mode] = val & 0x1; | ||
187 | |||
188 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) | ||
189 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; | ||
190 | |||
191 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { | ||
192 | AR5K_EEPROM_READ(o++, val); | ||
193 | ee->ee_false_detect[mode] = (val >> 6) & 0x7f; | ||
194 | |||
195 | if (mode == AR5K_EEPROM_MODE_11A) | ||
196 | ee->ee_xr_power[mode] = val & 0x3f; | ||
197 | else { | ||
198 | ee->ee_ob[mode][0] = val & 0x7; | ||
199 | ee->ee_db[mode][0] = (val >> 3) & 0x7; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { | ||
204 | ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; | ||
205 | ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; | ||
206 | } else { | ||
207 | ee->ee_i_gain[mode] = (val >> 13) & 0x7; | ||
208 | |||
209 | AR5K_EEPROM_READ(o++, val); | ||
210 | ee->ee_i_gain[mode] |= (val << 3) & 0x38; | ||
211 | |||
212 | if (mode == AR5K_EEPROM_MODE_11G) | ||
213 | ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; | ||
214 | } | ||
215 | |||
216 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && | ||
217 | mode == AR5K_EEPROM_MODE_11A) { | ||
218 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
219 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
220 | } | ||
221 | |||
222 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 && | ||
223 | mode == AR5K_EEPROM_MODE_11G) | ||
224 | ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; | ||
225 | |||
226 | /* return new offset */ | ||
227 | *offset = o; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Initialize eeprom & capabilities structs | ||
234 | */ | ||
235 | int ath5k_eeprom_init(struct ath5k_hw *ah) | ||
236 | { | ||
237 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
238 | unsigned int mode, i; | ||
239 | int ret; | ||
240 | u32 offset; | ||
241 | u16 val; | ||
242 | |||
243 | /* Initial TX thermal adjustment values */ | ||
244 | ee->ee_tx_clip = 4; | ||
245 | ee->ee_pwd_84 = ee->ee_pwd_90 = 1; | ||
246 | ee->ee_gain_select = 1; | ||
247 | |||
248 | /* | ||
249 | * Read values from EEPROM and store them in the capability structure | ||
250 | */ | ||
251 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); | ||
252 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); | ||
253 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); | ||
254 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); | ||
255 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); | ||
256 | |||
257 | /* Return if we have an old EEPROM */ | ||
258 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | ||
259 | return 0; | ||
260 | |||
261 | #ifdef notyet | ||
262 | /* | ||
263 | * Validate the checksum of the EEPROM date. There are some | ||
264 | * devices with invalid EEPROMs. | ||
265 | */ | ||
266 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | ||
267 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | ||
268 | cksum ^= val; | ||
269 | } | ||
270 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | ||
271 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | ||
272 | return -EIO; | ||
273 | } | ||
274 | #endif | ||
275 | |||
276 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | ||
277 | ee_ant_gain); | ||
278 | |||
279 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
280 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | ||
281 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | ||
282 | } | ||
283 | |||
284 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | ||
285 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); | ||
286 | ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; | ||
287 | ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; | ||
288 | |||
289 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); | ||
290 | ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; | ||
291 | ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Get conformance test limit values | ||
296 | */ | ||
297 | offset = AR5K_EEPROM_CTL(ah->ah_ee_version); | ||
298 | ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version); | ||
299 | |||
300 | for (i = 0; i < ee->ee_ctls; i++) { | ||
301 | AR5K_EEPROM_READ(offset++, val); | ||
302 | ee->ee_ctl[i] = (val >> 8) & 0xff; | ||
303 | ee->ee_ctl[i + 1] = val & 0xff; | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * Get values for 802.11a (5GHz) | ||
308 | */ | ||
309 | mode = AR5K_EEPROM_MODE_11A; | ||
310 | |||
311 | ee->ee_turbo_max_power[mode] = | ||
312 | AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); | ||
313 | |||
314 | offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); | ||
315 | |||
316 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
317 | if (ret) | ||
318 | return ret; | ||
319 | |||
320 | AR5K_EEPROM_READ(offset++, val); | ||
321 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
322 | ee->ee_ob[mode][3] = (val >> 5) & 0x7; | ||
323 | ee->ee_db[mode][3] = (val >> 2) & 0x7; | ||
324 | ee->ee_ob[mode][2] = (val << 1) & 0x7; | ||
325 | |||
326 | AR5K_EEPROM_READ(offset++, val); | ||
327 | ee->ee_ob[mode][2] |= (val >> 15) & 0x1; | ||
328 | ee->ee_db[mode][2] = (val >> 12) & 0x7; | ||
329 | ee->ee_ob[mode][1] = (val >> 9) & 0x7; | ||
330 | ee->ee_db[mode][1] = (val >> 6) & 0x7; | ||
331 | ee->ee_ob[mode][0] = (val >> 3) & 0x7; | ||
332 | ee->ee_db[mode][0] = val & 0x7; | ||
333 | |||
334 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
335 | if (ret) | ||
336 | return ret; | ||
337 | |||
338 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) { | ||
339 | AR5K_EEPROM_READ(offset++, val); | ||
340 | ee->ee_margin_tx_rx[mode] = val & 0x3f; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Get values for 802.11b (2.4GHz) | ||
345 | */ | ||
346 | mode = AR5K_EEPROM_MODE_11B; | ||
347 | offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); | ||
348 | |||
349 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
350 | if (ret) | ||
351 | return ret; | ||
352 | |||
353 | AR5K_EEPROM_READ(offset++, val); | ||
354 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
355 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
356 | ee->ee_db[mode][1] = val & 0x7; | ||
357 | |||
358 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
359 | if (ret) | ||
360 | return ret; | ||
361 | |||
362 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
363 | AR5K_EEPROM_READ(offset++, val); | ||
364 | ee->ee_cal_pier[mode][0] = | ||
365 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
366 | ee->ee_cal_pier[mode][1] = | ||
367 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
368 | |||
369 | AR5K_EEPROM_READ(offset++, val); | ||
370 | ee->ee_cal_pier[mode][2] = | ||
371 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
372 | } | ||
373 | |||
374 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
375 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
376 | |||
377 | /* | ||
378 | * Get values for 802.11g (2.4GHz) | ||
379 | */ | ||
380 | mode = AR5K_EEPROM_MODE_11G; | ||
381 | offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); | ||
382 | |||
383 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
384 | if (ret) | ||
385 | return ret; | ||
386 | |||
387 | AR5K_EEPROM_READ(offset++, val); | ||
388 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
389 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
390 | ee->ee_db[mode][1] = val & 0x7; | ||
391 | |||
392 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
393 | if (ret) | ||
394 | return ret; | ||
395 | |||
396 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
397 | AR5K_EEPROM_READ(offset++, val); | ||
398 | ee->ee_cal_pier[mode][0] = | ||
399 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
400 | ee->ee_cal_pier[mode][1] = | ||
401 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
402 | |||
403 | AR5K_EEPROM_READ(offset++, val); | ||
404 | ee->ee_turbo_max_power[mode] = val & 0x7f; | ||
405 | ee->ee_xr_power[mode] = (val >> 7) & 0x3f; | ||
406 | |||
407 | AR5K_EEPROM_READ(offset++, val); | ||
408 | ee->ee_cal_pier[mode][2] = | ||
409 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
410 | |||
411 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
412 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
413 | |||
414 | AR5K_EEPROM_READ(offset++, val); | ||
415 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
416 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
417 | |||
418 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | ||
419 | AR5K_EEPROM_READ(offset++, val); | ||
420 | ee->ee_cck_ofdm_gain_delta = val & 0xff; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Read 5GHz EEPROM channels | ||
426 | */ | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Read the MAC address from eeprom | ||
433 | */ | ||
434 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
435 | { | ||
436 | u8 mac_d[ETH_ALEN]; | ||
437 | u32 total, offset; | ||
438 | u16 data; | ||
439 | int octet, ret; | ||
440 | |||
441 | memset(mac, 0, ETH_ALEN); | ||
442 | memset(mac_d, 0, ETH_ALEN); | ||
443 | |||
444 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
445 | if (ret) | ||
446 | return ret; | ||
447 | |||
448 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
449 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | ||
450 | if (ret) | ||
451 | return ret; | ||
452 | |||
453 | total += data; | ||
454 | mac_d[octet + 1] = data & 0xff; | ||
455 | mac_d[octet] = data >> 8; | ||
456 | octet += 2; | ||
457 | } | ||
458 | |||
459 | memcpy(mac, mac_d, ETH_ALEN); | ||
460 | |||
461 | if (!total || total == 3 * 0xffff) | ||
462 | return -EINVAL; | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h new file mode 100644 index 000000000000..a468ecfbb18a --- /dev/null +++ b/drivers/net/wireless/ath5k/eeprom.h | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) | ||
21 | */ | ||
22 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ | ||
23 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ | ||
24 | #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ | ||
25 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | ||
26 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | ||
27 | |||
28 | #define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ | ||
29 | #define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ | ||
30 | #define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ | ||
31 | #define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ | ||
32 | #define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 | ||
33 | #define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ | ||
34 | #define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 | ||
35 | #define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ | ||
36 | #define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 | ||
37 | #define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ | ||
38 | #define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 | ||
39 | #define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ | ||
40 | #define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 | ||
41 | #define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ | ||
42 | #define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 | ||
43 | #define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ | ||
44 | #define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 | ||
45 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | ||
46 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | ||
47 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | ||
48 | #define AR5K_EEPROM_INFO_CKSUM 0xffff | ||
49 | #define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) | ||
50 | |||
51 | #define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ | ||
52 | #define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ | ||
53 | #define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ | ||
54 | #define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ | ||
55 | #define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ | ||
56 | #define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */ | ||
57 | #define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ | ||
58 | #define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ | ||
59 | #define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ | ||
60 | #define AR5K_EEPROM_VERSION_4_3 0x4003 | ||
61 | #define AR5K_EEPROM_VERSION_4_4 0x4004 | ||
62 | #define AR5K_EEPROM_VERSION_4_5 0x4005 | ||
63 | #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ | ||
64 | #define AR5K_EEPROM_VERSION_4_7 0x4007 | ||
65 | |||
66 | #define AR5K_EEPROM_MODE_11A 0 | ||
67 | #define AR5K_EEPROM_MODE_11B 1 | ||
68 | #define AR5K_EEPROM_MODE_11G 2 | ||
69 | |||
70 | #define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ | ||
71 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) | ||
72 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) | ||
73 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) | ||
74 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | ||
75 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | ||
76 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | ||
77 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */ | ||
78 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | ||
79 | |||
80 | #define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c | ||
81 | #define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 | ||
82 | #define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 | ||
83 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 | ||
84 | |||
85 | /* Newer EEPROMs are using a different offset */ | ||
86 | #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ | ||
87 | (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) | ||
88 | |||
89 | #define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) | ||
90 | #define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff)) | ||
91 | #define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff)) | ||
92 | |||
93 | /* calibration settings */ | ||
94 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | ||
95 | #define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) | ||
96 | #define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) | ||
97 | #define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ | ||
98 | |||
99 | /* [3.1 - 3.3] */ | ||
100 | #define AR5K_EEPROM_OBDB0_2GHZ 0x00ec | ||
101 | #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed | ||
102 | |||
103 | /* Misc values available since EEPROM 4.0 */ | ||
104 | #define AR5K_EEPROM_MISC0 0x00c4 | ||
105 | #define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) | ||
106 | #define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) | ||
107 | #define AR5K_EEPROM_MISC1 0x00c5 | ||
108 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | ||
109 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | ||
110 | |||
111 | |||
112 | /* Some EEPROM defines */ | ||
113 | #define AR5K_EEPROM_EEP_SCALE 100 | ||
114 | #define AR5K_EEPROM_EEP_DELTA 10 | ||
115 | #define AR5K_EEPROM_N_MODES 3 | ||
116 | #define AR5K_EEPROM_N_5GHZ_CHAN 10 | ||
117 | #define AR5K_EEPROM_N_2GHZ_CHAN 3 | ||
118 | #define AR5K_EEPROM_MAX_CHAN 10 | ||
119 | #define AR5K_EEPROM_N_PCDAC 11 | ||
120 | #define AR5K_EEPROM_N_TEST_FREQ 8 | ||
121 | #define AR5K_EEPROM_N_EDGES 8 | ||
122 | #define AR5K_EEPROM_N_INTERCEPTS 11 | ||
123 | #define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) | ||
124 | #define AR5K_EEPROM_PCDAC_M 0x3f | ||
125 | #define AR5K_EEPROM_PCDAC_START 1 | ||
126 | #define AR5K_EEPROM_PCDAC_STOP 63 | ||
127 | #define AR5K_EEPROM_PCDAC_STEP 1 | ||
128 | #define AR5K_EEPROM_NON_EDGE_M 0x40 | ||
129 | #define AR5K_EEPROM_CHANNEL_POWER 8 | ||
130 | #define AR5K_EEPROM_N_OBDB 4 | ||
131 | #define AR5K_EEPROM_OBDB_DIS 0xffff | ||
132 | #define AR5K_EEPROM_CHANNEL_DIS 0xff | ||
133 | #define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) | ||
134 | #define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) | ||
135 | #define AR5K_EEPROM_MAX_CTLS 32 | ||
136 | #define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 | ||
137 | #define AR5K_EEPROM_N_XPD0_POINTS 4 | ||
138 | #define AR5K_EEPROM_N_XPD3_POINTS 3 | ||
139 | #define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 | ||
140 | #define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 | ||
141 | #define AR5K_EEPROM_POWER_M 0x3f | ||
142 | #define AR5K_EEPROM_POWER_MIN 0 | ||
143 | #define AR5K_EEPROM_POWER_MAX 3150 | ||
144 | #define AR5K_EEPROM_POWER_STEP 50 | ||
145 | #define AR5K_EEPROM_POWER_TABLE_SIZE 64 | ||
146 | #define AR5K_EEPROM_N_POWER_LOC_11B 4 | ||
147 | #define AR5K_EEPROM_N_POWER_LOC_11G 6 | ||
148 | #define AR5K_EEPROM_I_GAIN 10 | ||
149 | #define AR5K_EEPROM_CCK_OFDM_DELTA 15 | ||
150 | #define AR5K_EEPROM_N_IQ_CAL 2 | ||
151 | |||
152 | #define AR5K_EEPROM_READ(_o, _v) do { \ | ||
153 | ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ | ||
154 | if (ret) \ | ||
155 | return ret; \ | ||
156 | } while (0) | ||
157 | |||
158 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | ||
159 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ | ||
160 | |||
161 | /* Struct to hold EEPROM calibration data */ | ||
162 | struct ath5k_eeprom_info { | ||
163 | u16 ee_magic; | ||
164 | u16 ee_protect; | ||
165 | u16 ee_regdomain; | ||
166 | u16 ee_version; | ||
167 | u16 ee_header; | ||
168 | u16 ee_ant_gain; | ||
169 | u16 ee_misc0; | ||
170 | u16 ee_misc1; | ||
171 | u16 ee_cck_ofdm_gain_delta; | ||
172 | u16 ee_cck_ofdm_power_delta; | ||
173 | u16 ee_scaled_cck_delta; | ||
174 | |||
175 | /* Used for tx thermal adjustment (eeprom_init, rfregs) */ | ||
176 | u16 ee_tx_clip; | ||
177 | u16 ee_pwd_84; | ||
178 | u16 ee_pwd_90; | ||
179 | u16 ee_gain_select; | ||
180 | |||
181 | /* RF Calibration settings (reset, rfregs) */ | ||
182 | u16 ee_i_cal[AR5K_EEPROM_N_MODES]; | ||
183 | u16 ee_q_cal[AR5K_EEPROM_N_MODES]; | ||
184 | u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; | ||
185 | u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; | ||
186 | u16 ee_xr_power[AR5K_EEPROM_N_MODES]; | ||
187 | u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; | ||
188 | u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES]; | ||
189 | u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; | ||
190 | u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
191 | u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
192 | u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; | ||
193 | u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; | ||
194 | u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; | ||
195 | u16 ee_thr_62[AR5K_EEPROM_N_MODES]; | ||
196 | u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; | ||
197 | u16 ee_xpd[AR5K_EEPROM_N_MODES]; | ||
198 | u16 ee_x_gain[AR5K_EEPROM_N_MODES]; | ||
199 | u16 ee_i_gain[AR5K_EEPROM_N_MODES]; | ||
200 | u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; | ||
201 | |||
202 | /* Unused */ | ||
203 | u16 ee_false_detect[AR5K_EEPROM_N_MODES]; | ||
204 | u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN]; | ||
205 | u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/ | ||
206 | |||
207 | /* Conformance test limits (Unused) */ | ||
208 | u16 ee_ctls; | ||
209 | u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; | ||
210 | |||
211 | /* Noise Floor Calibration settings */ | ||
212 | s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; | ||
213 | s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; | ||
214 | s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; | ||
215 | }; | ||
diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath5k/gpio.c new file mode 100644 index 000000000000..b77205adc180 --- /dev/null +++ b/drivers/net/wireless/ath5k/gpio.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /****************\ | ||
20 | GPIO Functions | ||
21 | \****************/ | ||
22 | |||
23 | #include "ath5k.h" | ||
24 | #include "reg.h" | ||
25 | #include "debug.h" | ||
26 | #include "base.h" | ||
27 | |||
28 | /* | ||
29 | * Set led state | ||
30 | */ | ||
31 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | ||
32 | { | ||
33 | u32 led; | ||
34 | /*5210 has different led mode handling*/ | ||
35 | u32 led_5210; | ||
36 | |||
37 | ATH5K_TRACE(ah->ah_sc); | ||
38 | |||
39 | /*Reset led status*/ | ||
40 | if (ah->ah_version != AR5K_AR5210) | ||
41 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
42 | AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); | ||
43 | else | ||
44 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); | ||
45 | |||
46 | /* | ||
47 | * Some blinking values, define at your wish | ||
48 | */ | ||
49 | switch (state) { | ||
50 | case AR5K_LED_SCAN: | ||
51 | case AR5K_LED_AUTH: | ||
52 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; | ||
53 | led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; | ||
54 | break; | ||
55 | |||
56 | case AR5K_LED_INIT: | ||
57 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; | ||
58 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
59 | break; | ||
60 | |||
61 | case AR5K_LED_ASSOC: | ||
62 | case AR5K_LED_RUN: | ||
63 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; | ||
64 | led_5210 = AR5K_PCICFG_LED_ASSOC; | ||
65 | break; | ||
66 | |||
67 | default: | ||
68 | led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; | ||
69 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | /*Write new status to the register*/ | ||
74 | if (ah->ah_version != AR5K_AR5210) | ||
75 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); | ||
76 | else | ||
77 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Set GPIO inputs | ||
82 | */ | ||
83 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | ||
84 | { | ||
85 | ATH5K_TRACE(ah->ah_sc); | ||
86 | if (gpio > AR5K_NUM_GPIO) | ||
87 | return -EINVAL; | ||
88 | |||
89 | ath5k_hw_reg_write(ah, | ||
90 | (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) | ||
91 | | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Set GPIO outputs | ||
98 | */ | ||
99 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | ||
100 | { | ||
101 | ATH5K_TRACE(ah->ah_sc); | ||
102 | if (gpio > AR5K_NUM_GPIO) | ||
103 | return -EINVAL; | ||
104 | |||
105 | ath5k_hw_reg_write(ah, | ||
106 | (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) | ||
107 | | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Get GPIO state | ||
114 | */ | ||
115 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | ||
116 | { | ||
117 | ATH5K_TRACE(ah->ah_sc); | ||
118 | if (gpio > AR5K_NUM_GPIO) | ||
119 | return 0xffffffff; | ||
120 | |||
121 | /* GPIO input magic */ | ||
122 | return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & | ||
123 | 0x1; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Set GPIO state | ||
128 | */ | ||
129 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | ||
130 | { | ||
131 | u32 data; | ||
132 | ATH5K_TRACE(ah->ah_sc); | ||
133 | |||
134 | if (gpio > AR5K_NUM_GPIO) | ||
135 | return -EINVAL; | ||
136 | |||
137 | /* GPIO output magic */ | ||
138 | data = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
139 | |||
140 | data &= ~(1 << gpio); | ||
141 | data |= (val & 1) << gpio; | ||
142 | |||
143 | ath5k_hw_reg_write(ah, data, AR5K_GPIODO); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Initialize the GPIO interrupt (RFKill switch) | ||
150 | */ | ||
151 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | ||
152 | u32 interrupt_level) | ||
153 | { | ||
154 | u32 data; | ||
155 | |||
156 | ATH5K_TRACE(ah->ah_sc); | ||
157 | if (gpio > AR5K_NUM_GPIO) | ||
158 | return; | ||
159 | |||
160 | /* | ||
161 | * Set the GPIO interrupt | ||
162 | */ | ||
163 | data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & | ||
164 | ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | | ||
165 | AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | | ||
166 | (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); | ||
167 | |||
168 | ath5k_hw_reg_write(ah, interrupt_level ? data : | ||
169 | (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); | ||
170 | |||
171 | ah->ah_imr |= AR5K_IMR_GPIO; | ||
172 | |||
173 | /* Enable GPIO interrupts */ | ||
174 | AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); | ||
175 | } | ||
176 | |||
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c deleted file mode 100644 index b987aa1e0f77..000000000000 --- a/drivers/net/wireless/ath5k/hw.c +++ /dev/null | |||
@@ -1,4492 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org> | ||
5 | * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
6 | * Copyright (c) 2007 Pavel Roskin <proski@gnu.org> | ||
7 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
8 | * | ||
9 | * Permission to use, copy, modify, and distribute this software for any | ||
10 | * purpose with or without fee is hereby granted, provided that the above | ||
11 | * copyright notice and this permission notice appear in all copies. | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * HW related functions for Atheros Wireless LAN devices. | ||
25 | */ | ||
26 | |||
27 | #include <linux/pci.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #include "reg.h" | ||
31 | #include "base.h" | ||
32 | #include "debug.h" | ||
33 | |||
34 | /* Prototypes */ | ||
35 | static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); | ||
36 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); | ||
37 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
38 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | ||
39 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
40 | unsigned int, unsigned int); | ||
41 | static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
42 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
43 | unsigned int); | ||
44 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *, | ||
45 | struct ath5k_tx_status *); | ||
46 | static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
47 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | ||
48 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
49 | unsigned int, unsigned int); | ||
50 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *, | ||
51 | struct ath5k_tx_status *); | ||
52 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *, | ||
53 | struct ath5k_rx_status *); | ||
54 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *, | ||
55 | struct ath5k_rx_status *); | ||
56 | static int ath5k_hw_get_capabilities(struct ath5k_hw *); | ||
57 | |||
58 | static int ath5k_eeprom_init(struct ath5k_hw *); | ||
59 | static int ath5k_eeprom_read_mac(struct ath5k_hw *, u8 *); | ||
60 | |||
61 | static int ath5k_hw_enable_pspoll(struct ath5k_hw *, u8 *, u16); | ||
62 | static int ath5k_hw_disable_pspoll(struct ath5k_hw *); | ||
63 | |||
64 | /* | ||
65 | * Enable to overwrite the country code (use "00" for debug) | ||
66 | */ | ||
67 | #if 0 | ||
68 | #define COUNTRYCODE "00" | ||
69 | #endif | ||
70 | |||
71 | /*******************\ | ||
72 | General Functions | ||
73 | \*******************/ | ||
74 | |||
75 | /* | ||
76 | * Functions used internaly | ||
77 | */ | ||
78 | |||
79 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
80 | { | ||
81 | return turbo ? (usec * 80) : (usec * 40); | ||
82 | } | ||
83 | |||
84 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
85 | { | ||
86 | return turbo ? (clock / 80) : (clock / 40); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Check if a register write has been completed | ||
91 | */ | ||
92 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
93 | bool is_set) | ||
94 | { | ||
95 | int i; | ||
96 | u32 data; | ||
97 | |||
98 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
99 | data = ath5k_hw_reg_read(ah, reg); | ||
100 | if (is_set && (data & flag)) | ||
101 | break; | ||
102 | else if ((data & flag) == val) | ||
103 | break; | ||
104 | udelay(15); | ||
105 | } | ||
106 | |||
107 | return (i <= 0) ? -EAGAIN : 0; | ||
108 | } | ||
109 | |||
110 | |||
111 | /***************************************\ | ||
112 | Attach/Detach Functions | ||
113 | \***************************************/ | ||
114 | |||
115 | /* | ||
116 | * Power On Self Test helper function | ||
117 | */ | ||
118 | static int ath5k_hw_post(struct ath5k_hw *ah) | ||
119 | { | ||
120 | |||
121 | int i, c; | ||
122 | u16 cur_reg; | ||
123 | u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; | ||
124 | u32 var_pattern; | ||
125 | u32 static_pattern[4] = { | ||
126 | 0x55555555, 0xaaaaaaaa, | ||
127 | 0x66666666, 0x99999999 | ||
128 | }; | ||
129 | u32 init_val; | ||
130 | u32 cur_val; | ||
131 | |||
132 | for (c = 0; c < 2; c++) { | ||
133 | |||
134 | cur_reg = regs[c]; | ||
135 | |||
136 | /* Save previous value */ | ||
137 | init_val = ath5k_hw_reg_read(ah, cur_reg); | ||
138 | |||
139 | for (i = 0; i < 256; i++) { | ||
140 | var_pattern = i << 16 | i; | ||
141 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
142 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
143 | |||
144 | if (cur_val != var_pattern) { | ||
145 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
146 | return -EAGAIN; | ||
147 | } | ||
148 | |||
149 | /* Found on ndiswrapper dumps */ | ||
150 | var_pattern = 0x0039080f; | ||
151 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
152 | } | ||
153 | |||
154 | for (i = 0; i < 4; i++) { | ||
155 | var_pattern = static_pattern[i]; | ||
156 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
157 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
158 | |||
159 | if (cur_val != var_pattern) { | ||
160 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
161 | return -EAGAIN; | ||
162 | } | ||
163 | |||
164 | /* Found on ndiswrapper dumps */ | ||
165 | var_pattern = 0x003b080f; | ||
166 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
167 | } | ||
168 | |||
169 | /* Restore previous value */ | ||
170 | ath5k_hw_reg_write(ah, init_val, cur_reg); | ||
171 | |||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | |||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Check if the device is supported and initialize the needed structs | ||
180 | */ | ||
181 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | ||
182 | { | ||
183 | struct ath5k_hw *ah; | ||
184 | struct pci_dev *pdev = sc->pdev; | ||
185 | u8 mac[ETH_ALEN]; | ||
186 | int ret; | ||
187 | u32 srev; | ||
188 | |||
189 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
190 | ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
191 | if (ah == NULL) { | ||
192 | ret = -ENOMEM; | ||
193 | ATH5K_ERR(sc, "out of memory\n"); | ||
194 | goto err; | ||
195 | } | ||
196 | |||
197 | ah->ah_sc = sc; | ||
198 | ah->ah_iobase = sc->iobase; | ||
199 | |||
200 | /* | ||
201 | * HW information | ||
202 | */ | ||
203 | |||
204 | ah->ah_op_mode = IEEE80211_IF_TYPE_STA; | ||
205 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | ||
206 | ah->ah_turbo = false; | ||
207 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
208 | ah->ah_imr = 0; | ||
209 | ah->ah_atim_window = 0; | ||
210 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
211 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
212 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | ||
213 | ah->ah_software_retry = false; | ||
214 | ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; | ||
215 | |||
216 | /* | ||
217 | * Set the mac revision based on the pci id | ||
218 | */ | ||
219 | ah->ah_version = mac_version; | ||
220 | |||
221 | /*Fill the ath5k_hw struct with the needed functions*/ | ||
222 | if (ah->ah_version == AR5K_AR5212) | ||
223 | ah->ah_magic = AR5K_EEPROM_MAGIC_5212; | ||
224 | else if (ah->ah_version == AR5K_AR5211) | ||
225 | ah->ah_magic = AR5K_EEPROM_MAGIC_5211; | ||
226 | |||
227 | if (ah->ah_version == AR5K_AR5212) { | ||
228 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | ||
229 | ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc; | ||
230 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; | ||
231 | } else { | ||
232 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | ||
233 | ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc; | ||
234 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | ||
235 | } | ||
236 | |||
237 | if (ah->ah_version == AR5K_AR5212) | ||
238 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; | ||
239 | else if (ah->ah_version <= AR5K_AR5211) | ||
240 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; | ||
241 | |||
242 | /* Bring device out of sleep and reset it's units */ | ||
243 | ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true); | ||
244 | if (ret) | ||
245 | goto err_free; | ||
246 | |||
247 | /* Get MAC, PHY and RADIO revisions */ | ||
248 | srev = ath5k_hw_reg_read(ah, AR5K_SREV); | ||
249 | ah->ah_mac_srev = srev; | ||
250 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | ||
251 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
252 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | ||
253 | 0xffffffff; | ||
254 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | ||
255 | CHANNEL_5GHZ); | ||
256 | |||
257 | if (ah->ah_version == AR5K_AR5210) | ||
258 | ah->ah_radio_2ghz_revision = 0; | ||
259 | else | ||
260 | ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, | ||
261 | CHANNEL_2GHZ); | ||
262 | |||
263 | /* Return on unsuported chips (unsupported eeprom etc) */ | ||
264 | if ((srev >= AR5K_SREV_VER_AR5416) && | ||
265 | (srev < AR5K_SREV_VER_AR2425)) { | ||
266 | ATH5K_ERR(sc, "Device not yet supported.\n"); | ||
267 | ret = -ENODEV; | ||
268 | goto err_free; | ||
269 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
270 | ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); | ||
271 | } | ||
272 | |||
273 | /* Identify single chip solutions */ | ||
274 | if (((srev <= AR5K_SREV_VER_AR5414) && | ||
275 | (srev >= AR5K_SREV_VER_AR2413)) || | ||
276 | (srev == AR5K_SREV_VER_AR2425)) { | ||
277 | ah->ah_single_chip = true; | ||
278 | } else { | ||
279 | ah->ah_single_chip = false; | ||
280 | } | ||
281 | |||
282 | /* Single chip radio */ | ||
283 | if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision) | ||
284 | ah->ah_radio_2ghz_revision = 0; | ||
285 | |||
286 | /* Identify the radio chip*/ | ||
287 | if (ah->ah_version == AR5K_AR5210) { | ||
288 | ah->ah_radio = AR5K_RF5110; | ||
289 | /* | ||
290 | * Register returns 0x0/0x04 for radio revision | ||
291 | * so ath5k_hw_radio_revision doesn't parse the value | ||
292 | * correctly. For now we are based on mac's srev to | ||
293 | * identify RF2425 radio. | ||
294 | */ | ||
295 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
296 | ah->ah_radio = AR5K_RF2425; | ||
297 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; | ||
298 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { | ||
299 | ah->ah_radio = AR5K_RF5111; | ||
300 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; | ||
301 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { | ||
302 | ah->ah_radio = AR5K_RF5112; | ||
303 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
304 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | ||
305 | ah->ah_radio = AR5K_RF2413; | ||
306 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; | ||
307 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { | ||
308 | ah->ah_radio = AR5K_RF5413; | ||
309 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; | ||
310 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { | ||
311 | /* AR5424 */ | ||
312 | if (srev >= AR5K_SREV_VER_AR5424) { | ||
313 | ah->ah_radio = AR5K_RF5413; | ||
314 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; | ||
315 | /* AR2424 */ | ||
316 | } else { | ||
317 | ah->ah_radio = AR5K_RF2413; /* For testing */ | ||
318 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; | ||
319 | } | ||
320 | } | ||
321 | ah->ah_phy = AR5K_PHY(0); | ||
322 | |||
323 | /* | ||
324 | * Write PCI-E power save settings | ||
325 | */ | ||
326 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | ||
327 | ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); | ||
328 | ath5k_hw_reg_write(ah, 0x24924924, 0x4080); | ||
329 | ath5k_hw_reg_write(ah, 0x28000039, 0x4080); | ||
330 | ath5k_hw_reg_write(ah, 0x53160824, 0x4080); | ||
331 | ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); | ||
332 | ath5k_hw_reg_write(ah, 0x001defff, 0x4080); | ||
333 | ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); | ||
334 | ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); | ||
335 | ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); | ||
336 | ath5k_hw_reg_write(ah, 0x00000000, 0x4084); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * POST | ||
341 | */ | ||
342 | ret = ath5k_hw_post(ah); | ||
343 | if (ret) | ||
344 | goto err_free; | ||
345 | |||
346 | /* Write AR5K_PCICFG_UNK on 2112B and later chips */ | ||
347 | if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || | ||
348 | srev > AR5K_SREV_VER_AR2413) { | ||
349 | ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG); | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Get card capabilities, values, ... | ||
354 | */ | ||
355 | ret = ath5k_eeprom_init(ah); | ||
356 | if (ret) { | ||
357 | ATH5K_ERR(sc, "unable to init EEPROM\n"); | ||
358 | goto err_free; | ||
359 | } | ||
360 | |||
361 | /* Get misc capabilities */ | ||
362 | ret = ath5k_hw_get_capabilities(ah); | ||
363 | if (ret) { | ||
364 | ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", | ||
365 | sc->pdev->device); | ||
366 | goto err_free; | ||
367 | } | ||
368 | |||
369 | /* Get MAC address */ | ||
370 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
371 | if (ret) { | ||
372 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
373 | sc->pdev->device); | ||
374 | goto err_free; | ||
375 | } | ||
376 | |||
377 | ath5k_hw_set_lladdr(ah, mac); | ||
378 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | ||
379 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | ||
380 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
381 | ath5k_hw_set_opmode(ah); | ||
382 | |||
383 | ath5k_hw_set_rfgain_opt(ah); | ||
384 | |||
385 | return ah; | ||
386 | err_free: | ||
387 | kfree(ah); | ||
388 | err: | ||
389 | return ERR_PTR(ret); | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Bring up MAC + PHY Chips | ||
394 | */ | ||
395 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | ||
396 | { | ||
397 | struct pci_dev *pdev = ah->ah_sc->pdev; | ||
398 | u32 turbo, mode, clock, bus_flags; | ||
399 | int ret; | ||
400 | |||
401 | turbo = 0; | ||
402 | mode = 0; | ||
403 | clock = 0; | ||
404 | |||
405 | ATH5K_TRACE(ah->ah_sc); | ||
406 | |||
407 | /* Wakeup the device */ | ||
408 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
409 | if (ret) { | ||
410 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | if (ah->ah_version != AR5K_AR5210) { | ||
415 | /* | ||
416 | * Get channel mode flags | ||
417 | */ | ||
418 | |||
419 | if (ah->ah_radio >= AR5K_RF5112) { | ||
420 | mode = AR5K_PHY_MODE_RAD_RF5112; | ||
421 | clock = AR5K_PHY_PLL_RF5112; | ||
422 | } else { | ||
423 | mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ | ||
424 | clock = AR5K_PHY_PLL_RF5111; /*Zero*/ | ||
425 | } | ||
426 | |||
427 | if (flags & CHANNEL_2GHZ) { | ||
428 | mode |= AR5K_PHY_MODE_FREQ_2GHZ; | ||
429 | clock |= AR5K_PHY_PLL_44MHZ; | ||
430 | |||
431 | if (flags & CHANNEL_CCK) { | ||
432 | mode |= AR5K_PHY_MODE_MOD_CCK; | ||
433 | } else if (flags & CHANNEL_OFDM) { | ||
434 | /* XXX Dynamic OFDM/CCK is not supported by the | ||
435 | * AR5211 so we set MOD_OFDM for plain g (no | ||
436 | * CCK headers) operation. We need to test | ||
437 | * this, 5211 might support ofdm-only g after | ||
438 | * all, there are also initial register values | ||
439 | * in the code for g mode (see initvals.c). */ | ||
440 | if (ah->ah_version == AR5K_AR5211) | ||
441 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
442 | else | ||
443 | mode |= AR5K_PHY_MODE_MOD_DYN; | ||
444 | } else { | ||
445 | ATH5K_ERR(ah->ah_sc, | ||
446 | "invalid radio modulation mode\n"); | ||
447 | return -EINVAL; | ||
448 | } | ||
449 | } else if (flags & CHANNEL_5GHZ) { | ||
450 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; | ||
451 | clock |= AR5K_PHY_PLL_40MHZ; | ||
452 | |||
453 | if (flags & CHANNEL_OFDM) | ||
454 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
455 | else { | ||
456 | ATH5K_ERR(ah->ah_sc, | ||
457 | "invalid radio modulation mode\n"); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | } else { | ||
461 | ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); | ||
462 | return -EINVAL; | ||
463 | } | ||
464 | |||
465 | if (flags & CHANNEL_TURBO) | ||
466 | turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; | ||
467 | } else { /* Reset the device */ | ||
468 | |||
469 | /* ...enable Atheros turbo mode if requested */ | ||
470 | if (flags & CHANNEL_TURBO) | ||
471 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, | ||
472 | AR5K_PHY_TURBO); | ||
473 | } | ||
474 | |||
475 | /* reseting PCI on PCI-E cards results card to hang | ||
476 | * and always return 0xffff... so we ingore that flag | ||
477 | * for PCI-E cards */ | ||
478 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | ||
479 | |||
480 | /* Reset chipset */ | ||
481 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
482 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
483 | if (ret) { | ||
484 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); | ||
485 | return -EIO; | ||
486 | } | ||
487 | |||
488 | if (ah->ah_version == AR5K_AR5210) | ||
489 | udelay(2300); | ||
490 | |||
491 | /* ...wakeup again!*/ | ||
492 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
493 | if (ret) { | ||
494 | ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); | ||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | /* ...final warm reset */ | ||
499 | if (ath5k_hw_nic_reset(ah, 0)) { | ||
500 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | ||
501 | return -EIO; | ||
502 | } | ||
503 | |||
504 | if (ah->ah_version != AR5K_AR5210) { | ||
505 | /* ...set the PHY operating mode */ | ||
506 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); | ||
507 | udelay(300); | ||
508 | |||
509 | ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); | ||
510 | ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Free the ath5k_hw struct | ||
518 | */ | ||
519 | void ath5k_hw_detach(struct ath5k_hw *ah) | ||
520 | { | ||
521 | ATH5K_TRACE(ah->ah_sc); | ||
522 | |||
523 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); | ||
524 | |||
525 | if (ah->ah_rf_banks != NULL) | ||
526 | kfree(ah->ah_rf_banks); | ||
527 | |||
528 | /* assume interrupts are down */ | ||
529 | kfree(ah); | ||
530 | } | ||
531 | |||
532 | /****************************\ | ||
533 | Reset function and helpers | ||
534 | \****************************/ | ||
535 | |||
536 | /** | ||
537 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
538 | * | ||
539 | * @ah: the &struct ath5k_hw | ||
540 | * @channel: the currently set channel upon reset | ||
541 | * | ||
542 | * Write the OFDM timings for the AR5212 upon reset. This is a helper for | ||
543 | * ath5k_hw_reset(). This seems to tune the PLL a specified frequency | ||
544 | * depending on the bandwidth of the channel. | ||
545 | * | ||
546 | */ | ||
547 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
548 | struct ieee80211_channel *channel) | ||
549 | { | ||
550 | /* Get exponent and mantissa and set it */ | ||
551 | u32 coef_scaled, coef_exp, coef_man, | ||
552 | ds_coef_exp, ds_coef_man, clock; | ||
553 | |||
554 | if (!(ah->ah_version == AR5K_AR5212) || | ||
555 | !(channel->hw_value & CHANNEL_OFDM)) | ||
556 | BUG(); | ||
557 | |||
558 | /* Seems there are two PLLs, one for baseband sampling and one | ||
559 | * for tuning. Tuning basebands are 40 MHz or 80MHz when in | ||
560 | * turbo. */ | ||
561 | clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40; | ||
562 | coef_scaled = ((5 * (clock << 24)) / 2) / | ||
563 | channel->center_freq; | ||
564 | |||
565 | for (coef_exp = 31; coef_exp > 0; coef_exp--) | ||
566 | if ((coef_scaled >> coef_exp) & 0x1) | ||
567 | break; | ||
568 | |||
569 | if (!coef_exp) | ||
570 | return -EINVAL; | ||
571 | |||
572 | coef_exp = 14 - (coef_exp - 24); | ||
573 | coef_man = coef_scaled + | ||
574 | (1 << (24 - coef_exp - 1)); | ||
575 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
576 | ds_coef_exp = coef_exp - 16; | ||
577 | |||
578 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
579 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
580 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
581 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | |||
587 | /* | ||
588 | * index into rates for control rates, we can set it up like this because | ||
589 | * this is only used for AR5212 and we know it supports G mode | ||
590 | */ | ||
591 | static int control_rates[] = | ||
592 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | ||
593 | |||
594 | /** | ||
595 | * ath5k_hw_write_rate_duration - set rate duration during hw resets | ||
596 | * | ||
597 | * @ah: the &struct ath5k_hw | ||
598 | * @mode: one of enum ath5k_driver_mode | ||
599 | * | ||
600 | * Write the rate duration table upon hw reset. This is a helper for | ||
601 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for | ||
602 | * the hardware for the current mode for each rate. The rates which are capable | ||
603 | * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another | ||
604 | * register for the short preamble ACK timeout calculation. | ||
605 | */ | ||
606 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | ||
607 | unsigned int mode) | ||
608 | { | ||
609 | struct ath5k_softc *sc = ah->ah_sc; | ||
610 | struct ieee80211_rate *rate; | ||
611 | unsigned int i; | ||
612 | |||
613 | /* Write rate duration table */ | ||
614 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | ||
615 | u32 reg; | ||
616 | u16 tx_time; | ||
617 | |||
618 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | ||
619 | |||
620 | /* Set ACK timeout */ | ||
621 | reg = AR5K_RATE_DUR(rate->hw_value); | ||
622 | |||
623 | /* An ACK frame consists of 10 bytes. If you add the FCS, | ||
624 | * which ieee80211_generic_frame_duration() adds, | ||
625 | * its 14 bytes. Note we use the control rate and not the | ||
626 | * actual rate for this rate. See mac80211 tx.c | ||
627 | * ieee80211_duration() for a brief description of | ||
628 | * what rate we should choose to TX ACKs. */ | ||
629 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | ||
630 | sc->vif, 10, rate)); | ||
631 | |||
632 | ath5k_hw_reg_write(ah, tx_time, reg); | ||
633 | |||
634 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | ||
635 | continue; | ||
636 | |||
637 | /* | ||
638 | * We're not distinguishing short preamble here, | ||
639 | * This is true, all we'll get is a longer value here | ||
640 | * which is not necessarilly bad. We could use | ||
641 | * export ieee80211_frame_duration() but that needs to be | ||
642 | * fixed first to be properly used by mac802111 drivers: | ||
643 | * | ||
644 | * - remove erp stuff and let the routine figure ofdm | ||
645 | * erp rates | ||
646 | * - remove passing argument ieee80211_local as | ||
647 | * drivers don't have access to it | ||
648 | * - move drivers using ieee80211_generic_frame_duration() | ||
649 | * to this | ||
650 | */ | ||
651 | ath5k_hw_reg_write(ah, tx_time, | ||
652 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /* | ||
657 | * Main reset function | ||
658 | */ | ||
659 | int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | ||
660 | struct ieee80211_channel *channel, bool change_channel) | ||
661 | { | ||
662 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
663 | struct pci_dev *pdev = ah->ah_sc->pdev; | ||
664 | u32 data, s_seq, s_ant, s_led[3], dma_size; | ||
665 | unsigned int i, mode, freq, ee_mode, ant[2]; | ||
666 | int ret; | ||
667 | |||
668 | ATH5K_TRACE(ah->ah_sc); | ||
669 | |||
670 | s_seq = 0; | ||
671 | s_ant = 0; | ||
672 | ee_mode = 0; | ||
673 | freq = 0; | ||
674 | mode = 0; | ||
675 | |||
676 | /* | ||
677 | * Save some registers before a reset | ||
678 | */ | ||
679 | /*DCU/Antenna selection not available on 5210*/ | ||
680 | if (ah->ah_version != AR5K_AR5210) { | ||
681 | if (change_channel) { | ||
682 | /* Seq number for queue 0 -do this for all queues ? */ | ||
683 | s_seq = ath5k_hw_reg_read(ah, | ||
684 | AR5K_QUEUE_DFS_SEQNUM(0)); | ||
685 | /*Default antenna*/ | ||
686 | s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | ||
687 | } | ||
688 | } | ||
689 | |||
690 | /*GPIOs*/ | ||
691 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; | ||
692 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); | ||
693 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
694 | |||
695 | if (change_channel && ah->ah_rf_banks != NULL) | ||
696 | ath5k_hw_get_rf_gain(ah); | ||
697 | |||
698 | |||
699 | /*Wakeup the device*/ | ||
700 | ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); | ||
701 | if (ret) | ||
702 | return ret; | ||
703 | |||
704 | /* | ||
705 | * Initialize operating mode | ||
706 | */ | ||
707 | ah->ah_op_mode = op_mode; | ||
708 | |||
709 | /* | ||
710 | * 5111/5112 Settings | ||
711 | * 5210 only comes with RF5110 | ||
712 | */ | ||
713 | if (ah->ah_version != AR5K_AR5210) { | ||
714 | if (ah->ah_radio != AR5K_RF5111 && | ||
715 | ah->ah_radio != AR5K_RF5112 && | ||
716 | ah->ah_radio != AR5K_RF5413 && | ||
717 | ah->ah_radio != AR5K_RF2413 && | ||
718 | ah->ah_radio != AR5K_RF2425) { | ||
719 | ATH5K_ERR(ah->ah_sc, | ||
720 | "invalid phy radio: %u\n", ah->ah_radio); | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | |||
724 | switch (channel->hw_value & CHANNEL_MODES) { | ||
725 | case CHANNEL_A: | ||
726 | mode = AR5K_MODE_11A; | ||
727 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
728 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
729 | break; | ||
730 | case CHANNEL_G: | ||
731 | mode = AR5K_MODE_11G; | ||
732 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
733 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
734 | break; | ||
735 | case CHANNEL_B: | ||
736 | mode = AR5K_MODE_11B; | ||
737 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
738 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
739 | break; | ||
740 | case CHANNEL_T: | ||
741 | mode = AR5K_MODE_11A_TURBO; | ||
742 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
743 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
744 | break; | ||
745 | /*Is this ok on 5211 too ?*/ | ||
746 | case CHANNEL_TG: | ||
747 | mode = AR5K_MODE_11G_TURBO; | ||
748 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
749 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
750 | break; | ||
751 | case CHANNEL_XR: | ||
752 | if (ah->ah_version == AR5K_AR5211) { | ||
753 | ATH5K_ERR(ah->ah_sc, | ||
754 | "XR mode not available on 5211"); | ||
755 | return -EINVAL; | ||
756 | } | ||
757 | mode = AR5K_MODE_XR; | ||
758 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
759 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
760 | break; | ||
761 | default: | ||
762 | ATH5K_ERR(ah->ah_sc, | ||
763 | "invalid channel: %d\n", channel->center_freq); | ||
764 | return -EINVAL; | ||
765 | } | ||
766 | |||
767 | /* PHY access enable */ | ||
768 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
769 | |||
770 | } | ||
771 | |||
772 | ret = ath5k_hw_write_initvals(ah, mode, change_channel); | ||
773 | if (ret) | ||
774 | return ret; | ||
775 | |||
776 | /* | ||
777 | * 5211/5212 Specific | ||
778 | */ | ||
779 | if (ah->ah_version != AR5K_AR5210) { | ||
780 | /* | ||
781 | * Write initial RF gain settings | ||
782 | * This should work for both 5111/5112 | ||
783 | */ | ||
784 | ret = ath5k_hw_rfgain(ah, freq); | ||
785 | if (ret) | ||
786 | return ret; | ||
787 | |||
788 | mdelay(1); | ||
789 | |||
790 | /* | ||
791 | * Write some more initial register settings | ||
792 | */ | ||
793 | if (ah->ah_version == AR5K_AR5212) { | ||
794 | ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); | ||
795 | |||
796 | if (channel->hw_value == CHANNEL_G) | ||
797 | if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) | ||
798 | ath5k_hw_reg_write(ah, 0x00f80d80, | ||
799 | 0x994c); | ||
800 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) | ||
801 | ath5k_hw_reg_write(ah, 0x00380140, | ||
802 | 0x994c); | ||
803 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) | ||
804 | ath5k_hw_reg_write(ah, 0x00fc0ec0, | ||
805 | 0x994c); | ||
806 | else /* 2425 */ | ||
807 | ath5k_hw_reg_write(ah, 0x00fc0fc0, | ||
808 | 0x994c); | ||
809 | else | ||
810 | ath5k_hw_reg_write(ah, 0x00000000, 0x994c); | ||
811 | |||
812 | /* Some bits are disabled here, we know nothing about | ||
813 | * register 0xa228 yet, most of the times this ends up | ||
814 | * with a value 0x9b5 -haven't seen any dump with | ||
815 | * a different value- */ | ||
816 | /* Got this from decompiling binary HAL */ | ||
817 | data = ath5k_hw_reg_read(ah, 0xa228); | ||
818 | data &= 0xfffffdff; | ||
819 | ath5k_hw_reg_write(ah, data, 0xa228); | ||
820 | |||
821 | data = ath5k_hw_reg_read(ah, 0xa228); | ||
822 | data &= 0xfffe03ff; | ||
823 | ath5k_hw_reg_write(ah, data, 0xa228); | ||
824 | data = 0; | ||
825 | |||
826 | /* Just write 0x9b5 ? */ | ||
827 | /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ | ||
828 | ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); | ||
829 | ath5k_hw_reg_write(ah, 0x00000000, 0xa254); | ||
830 | ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); | ||
831 | } | ||
832 | |||
833 | /* Fix for first revision of the RF5112 RF chipset */ | ||
834 | if (ah->ah_radio >= AR5K_RF5112 && | ||
835 | ah->ah_radio_5ghz_revision < | ||
836 | AR5K_SREV_RAD_5112A) { | ||
837 | ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, | ||
838 | AR5K_PHY_CCKTXCTL); | ||
839 | if (channel->hw_value & CHANNEL_5GHZ) | ||
840 | data = 0xffb81020; | ||
841 | else | ||
842 | data = 0xffb80d20; | ||
843 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); | ||
844 | data = 0; | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * Set TX power (FIXME) | ||
849 | */ | ||
850 | ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER); | ||
851 | if (ret) | ||
852 | return ret; | ||
853 | |||
854 | /* Write rate duration table only on AR5212 and if | ||
855 | * virtual interface has already been brought up | ||
856 | * XXX: rethink this after new mode changes to | ||
857 | * mac80211 are integrated */ | ||
858 | if (ah->ah_version == AR5K_AR5212 && | ||
859 | ah->ah_sc->vif != NULL) | ||
860 | ath5k_hw_write_rate_duration(ah, mode); | ||
861 | |||
862 | /* | ||
863 | * Write RF registers | ||
864 | */ | ||
865 | ret = ath5k_hw_rfregs(ah, channel, mode); | ||
866 | if (ret) | ||
867 | return ret; | ||
868 | |||
869 | /* | ||
870 | * Configure additional registers | ||
871 | */ | ||
872 | |||
873 | /* Write OFDM timings on 5212*/ | ||
874 | if (ah->ah_version == AR5K_AR5212 && | ||
875 | channel->hw_value & CHANNEL_OFDM) { | ||
876 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
877 | if (ret) | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | /*Enable/disable 802.11b mode on 5111 | ||
882 | (enable 2111 frequency converter + CCK)*/ | ||
883 | if (ah->ah_radio == AR5K_RF5111) { | ||
884 | if (mode == AR5K_MODE_11B) | ||
885 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
886 | AR5K_TXCFG_B_MODE); | ||
887 | else | ||
888 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
889 | AR5K_TXCFG_B_MODE); | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * Set channel and calibrate the PHY | ||
894 | */ | ||
895 | ret = ath5k_hw_channel(ah, channel); | ||
896 | if (ret) | ||
897 | return ret; | ||
898 | |||
899 | /* Set antenna mode */ | ||
900 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL, | ||
901 | ah->ah_antenna[ee_mode][0], 0xfffffc06); | ||
902 | |||
903 | /* | ||
904 | * In case a fixed antenna was set as default | ||
905 | * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE | ||
906 | * registers. | ||
907 | */ | ||
908 | if (s_ant != 0){ | ||
909 | if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ | ||
910 | ant[0] = ant[1] = AR5K_ANT_FIXED_A; | ||
911 | else /* 2 - Aux */ | ||
912 | ant[0] = ant[1] = AR5K_ANT_FIXED_B; | ||
913 | } else { | ||
914 | ant[0] = AR5K_ANT_FIXED_A; | ||
915 | ant[1] = AR5K_ANT_FIXED_B; | ||
916 | } | ||
917 | |||
918 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], | ||
919 | AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
920 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], | ||
921 | AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
922 | |||
923 | /* Commit values from EEPROM */ | ||
924 | if (ah->ah_radio == AR5K_RF5111) | ||
925 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, | ||
926 | AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip); | ||
927 | |||
928 | ath5k_hw_reg_write(ah, | ||
929 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), | ||
930 | AR5K_PHY_NFTHRES); | ||
931 | |||
932 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING, | ||
933 | (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, | ||
934 | 0xffffc07f); | ||
935 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, | ||
936 | (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, | ||
937 | 0xfffc0fff); | ||
938 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, | ||
939 | (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | | ||
940 | ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), | ||
941 | 0xffff0000); | ||
942 | |||
943 | ath5k_hw_reg_write(ah, | ||
944 | (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | | ||
945 | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | | ||
946 | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | | ||
947 | (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); | ||
948 | |||
949 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3, | ||
950 | ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); | ||
951 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF, | ||
952 | (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); | ||
953 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01); | ||
954 | |||
955 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
956 | AR5K_PHY_IQ_CORR_ENABLE | | ||
957 | (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | | ||
958 | ee->ee_q_cal[ee_mode]); | ||
959 | |||
960 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
961 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, | ||
962 | AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, | ||
963 | ee->ee_margin_tx_rx[ee_mode]); | ||
964 | |||
965 | } else { | ||
966 | mdelay(1); | ||
967 | /* Disable phy and wait */ | ||
968 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
969 | mdelay(1); | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * Restore saved values | ||
974 | */ | ||
975 | /*DCU/Antenna selection not available on 5210*/ | ||
976 | if (ah->ah_version != AR5K_AR5210) { | ||
977 | ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0)); | ||
978 | ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); | ||
979 | } | ||
980 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); | ||
981 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); | ||
982 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | ||
983 | |||
984 | /* | ||
985 | * Misc | ||
986 | */ | ||
987 | /* XXX: add ah->aid once mac80211 gives this to us */ | ||
988 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
989 | |||
990 | ath5k_hw_set_opmode(ah); | ||
991 | /*PISR/SISR Not available on 5210*/ | ||
992 | if (ah->ah_version != AR5K_AR5210) { | ||
993 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
994 | /* If we later allow tuning for this, store into sc structure */ | ||
995 | data = AR5K_TUNE_RSSI_THRES | | ||
996 | AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S; | ||
997 | ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR); | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * Set Rx/Tx DMA Configuration | ||
1002 | * | ||
1003 | * Set maximum DMA size (512) except for PCI-E cards since | ||
1004 | * it causes rx overruns and tx errors (tested on 5424 but since | ||
1005 | * rx overruns also occur on 5416/5418 with madwifi we set 128 | ||
1006 | * for all PCI-E cards to be safe). | ||
1007 | * | ||
1008 | * In dumps this is 128 for allchips. | ||
1009 | * | ||
1010 | * XXX: need to check 5210 for this | ||
1011 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
1012 | * guess we can tweak it and see how it goes ;-) | ||
1013 | */ | ||
1014 | dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B; | ||
1015 | if (ah->ah_version != AR5K_AR5210) { | ||
1016 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
1017 | AR5K_TXCFG_SDMAMR, dma_size); | ||
1018 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
1019 | AR5K_RXCFG_SDMAMW, dma_size); | ||
1020 | } | ||
1021 | |||
1022 | /* | ||
1023 | * Enable the PHY and wait until completion | ||
1024 | */ | ||
1025 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
1026 | |||
1027 | /* | ||
1028 | * On 5211+ read activation -> rx delay | ||
1029 | * and use it. | ||
1030 | */ | ||
1031 | if (ah->ah_version != AR5K_AR5210) { | ||
1032 | data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
1033 | AR5K_PHY_RX_DELAY_M; | ||
1034 | data = (channel->hw_value & CHANNEL_CCK) ? | ||
1035 | ((data << 2) / 22) : (data / 10); | ||
1036 | |||
1037 | udelay(100 + (2 * data)); | ||
1038 | data = 0; | ||
1039 | } else { | ||
1040 | mdelay(1); | ||
1041 | } | ||
1042 | |||
1043 | /* | ||
1044 | * Perform ADC test (?) | ||
1045 | */ | ||
1046 | data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
1047 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
1048 | for (i = 0; i <= 20; i++) { | ||
1049 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
1050 | break; | ||
1051 | udelay(200); | ||
1052 | } | ||
1053 | ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1); | ||
1054 | data = 0; | ||
1055 | |||
1056 | /* | ||
1057 | * Start automatic gain calibration | ||
1058 | * | ||
1059 | * During AGC calibration RX path is re-routed to | ||
1060 | * a signal detector so we don't receive anything. | ||
1061 | * | ||
1062 | * This method is used to calibrate some static offsets | ||
1063 | * used together with on-the fly I/Q calibration (the | ||
1064 | * one performed via ath5k_hw_phy_calibrate), that doesn't | ||
1065 | * interrupt rx path. | ||
1066 | * | ||
1067 | * If we are in a noisy environment AGC calibration may time | ||
1068 | * out. | ||
1069 | */ | ||
1070 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1071 | AR5K_PHY_AGCCTL_CAL); | ||
1072 | |||
1073 | /* At the same time start I/Q calibration for QAM constellation | ||
1074 | * -no need for CCK- */ | ||
1075 | ah->ah_calibration = false; | ||
1076 | if (!(mode == AR5K_MODE_11B)) { | ||
1077 | ah->ah_calibration = true; | ||
1078 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
1079 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
1080 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
1081 | AR5K_PHY_IQ_RUN); | ||
1082 | } | ||
1083 | |||
1084 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
1085 | * during ath5k_phy_calibrate) */ | ||
1086 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1087 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
1088 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
1089 | channel->center_freq); | ||
1090 | return -EAGAIN; | ||
1091 | } | ||
1092 | |||
1093 | /* | ||
1094 | * Start noise floor calibration | ||
1095 | * | ||
1096 | * If we run NF calibration before AGC, it always times out. | ||
1097 | * Binary HAL starts NF and AGC calibration at the same time | ||
1098 | * and only waits for AGC to finish. I believe that's wrong because | ||
1099 | * during NF calibration, rx path is also routed to a detector, so if | ||
1100 | * it doesn't finish we won't have RX. | ||
1101 | * | ||
1102 | * XXX: Find an interval that's OK for all cards... | ||
1103 | */ | ||
1104 | ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | ||
1105 | if (ret) | ||
1106 | return ret; | ||
1107 | |||
1108 | /* | ||
1109 | * Reset queues and start beacon timers at the end of the reset routine | ||
1110 | */ | ||
1111 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
1112 | /*No QCU on 5210*/ | ||
1113 | if (ah->ah_version != AR5K_AR5210) | ||
1114 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i); | ||
1115 | |||
1116 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
1117 | if (ret) { | ||
1118 | ATH5K_ERR(ah->ah_sc, | ||
1119 | "failed to reset TX queue #%d\n", i); | ||
1120 | return ret; | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | /* Pre-enable interrupts on 5211/5212*/ | ||
1125 | if (ah->ah_version != AR5K_AR5210) | ||
1126 | ath5k_hw_set_intr(ah, AR5K_INT_RX | AR5K_INT_TX | | ||
1127 | AR5K_INT_FATAL); | ||
1128 | |||
1129 | /* | ||
1130 | * Set RF kill flags if supported by the device (read from the EEPROM) | ||
1131 | * Disable gpio_intr for now since it results system hang. | ||
1132 | * TODO: Handle this in ath5k_intr | ||
1133 | */ | ||
1134 | #if 0 | ||
1135 | if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { | ||
1136 | ath5k_hw_set_gpio_input(ah, 0); | ||
1137 | ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); | ||
1138 | if (ah->ah_gpio[0] == 0) | ||
1139 | ath5k_hw_set_gpio_intr(ah, 0, 1); | ||
1140 | else | ||
1141 | ath5k_hw_set_gpio_intr(ah, 0, 0); | ||
1142 | } | ||
1143 | #endif | ||
1144 | |||
1145 | /* | ||
1146 | * Set the 32MHz reference clock on 5212 phy clock sleep register | ||
1147 | * | ||
1148 | * TODO: Find out how to switch to external 32Khz clock to save power | ||
1149 | */ | ||
1150 | if (ah->ah_version == AR5K_AR5212) { | ||
1151 | ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); | ||
1152 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
1153 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); | ||
1154 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
1155 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
1156 | ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); | ||
1157 | |||
1158 | data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ; | ||
1159 | data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ? | ||
1160 | 0x00000f80 : 0x00001380 ; | ||
1161 | ath5k_hw_reg_write(ah, data, AR5K_USEC_5211); | ||
1162 | data = 0; | ||
1163 | } | ||
1164 | |||
1165 | if (ah->ah_version == AR5K_AR5212) { | ||
1166 | ath5k_hw_reg_write(ah, 0x000100aa, 0x8118); | ||
1167 | ath5k_hw_reg_write(ah, 0x00003210, 0x811c); | ||
1168 | ath5k_hw_reg_write(ah, 0x00000052, 0x8108); | ||
1169 | if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413) | ||
1170 | ath5k_hw_reg_write(ah, 0x00000004, 0x8120); | ||
1171 | } | ||
1172 | |||
1173 | /* | ||
1174 | * Disable beacons and reset the register | ||
1175 | */ | ||
1176 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | | ||
1177 | AR5K_BEACON_RESET_TSF); | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | /* | ||
1183 | * Reset chipset | ||
1184 | */ | ||
1185 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | ||
1186 | { | ||
1187 | int ret; | ||
1188 | u32 mask = val ? val : ~0U; | ||
1189 | |||
1190 | ATH5K_TRACE(ah->ah_sc); | ||
1191 | |||
1192 | /* Read-and-clear RX Descriptor Pointer*/ | ||
1193 | ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
1194 | |||
1195 | /* | ||
1196 | * Reset the device and wait until success | ||
1197 | */ | ||
1198 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); | ||
1199 | |||
1200 | /* Wait at least 128 PCI clocks */ | ||
1201 | udelay(15); | ||
1202 | |||
1203 | if (ah->ah_version == AR5K_AR5210) { | ||
1204 | val &= AR5K_RESET_CTL_CHIP; | ||
1205 | mask &= AR5K_RESET_CTL_CHIP; | ||
1206 | } else { | ||
1207 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
1208 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
1209 | } | ||
1210 | |||
1211 | ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); | ||
1212 | |||
1213 | /* | ||
1214 | * Reset configuration register (for hw byte-swap). Note that this | ||
1215 | * is only set for big endian. We do the necessary magic in | ||
1216 | * AR5K_INIT_CFG. | ||
1217 | */ | ||
1218 | if ((val & AR5K_RESET_CTL_PCU) == 0) | ||
1219 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | ||
1220 | |||
1221 | return ret; | ||
1222 | } | ||
1223 | |||
1224 | /* | ||
1225 | * Power management functions | ||
1226 | */ | ||
1227 | |||
1228 | /* | ||
1229 | * Sleep control | ||
1230 | */ | ||
1231 | int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | ||
1232 | bool set_chip, u16 sleep_duration) | ||
1233 | { | ||
1234 | unsigned int i; | ||
1235 | u32 staid, data; | ||
1236 | |||
1237 | ATH5K_TRACE(ah->ah_sc); | ||
1238 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); | ||
1239 | |||
1240 | switch (mode) { | ||
1241 | case AR5K_PM_AUTO: | ||
1242 | staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; | ||
1243 | /* fallthrough */ | ||
1244 | case AR5K_PM_NETWORK_SLEEP: | ||
1245 | if (set_chip) | ||
1246 | ath5k_hw_reg_write(ah, | ||
1247 | AR5K_SLEEP_CTL_SLE_ALLOW | | ||
1248 | sleep_duration, | ||
1249 | AR5K_SLEEP_CTL); | ||
1250 | |||
1251 | staid |= AR5K_STA_ID1_PWR_SV; | ||
1252 | break; | ||
1253 | |||
1254 | case AR5K_PM_FULL_SLEEP: | ||
1255 | if (set_chip) | ||
1256 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, | ||
1257 | AR5K_SLEEP_CTL); | ||
1258 | |||
1259 | staid |= AR5K_STA_ID1_PWR_SV; | ||
1260 | break; | ||
1261 | |||
1262 | case AR5K_PM_AWAKE: | ||
1263 | |||
1264 | staid &= ~AR5K_STA_ID1_PWR_SV; | ||
1265 | |||
1266 | if (!set_chip) | ||
1267 | goto commit; | ||
1268 | |||
1269 | /* Preserve sleep duration */ | ||
1270 | data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); | ||
1271 | if( data & 0xffc00000 ){ | ||
1272 | data = 0; | ||
1273 | } else { | ||
1274 | data = data & 0xfffcffff; | ||
1275 | } | ||
1276 | |||
1277 | ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); | ||
1278 | udelay(15); | ||
1279 | |||
1280 | for (i = 50; i > 0; i--) { | ||
1281 | /* Check if the chip did wake up */ | ||
1282 | if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & | ||
1283 | AR5K_PCICFG_SPWR_DN) == 0) | ||
1284 | break; | ||
1285 | |||
1286 | /* Wait a bit and retry */ | ||
1287 | udelay(200); | ||
1288 | ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); | ||
1289 | } | ||
1290 | |||
1291 | /* Fail if the chip didn't wake up */ | ||
1292 | if (i <= 0) | ||
1293 | return -EIO; | ||
1294 | |||
1295 | break; | ||
1296 | |||
1297 | default: | ||
1298 | return -EINVAL; | ||
1299 | } | ||
1300 | |||
1301 | commit: | ||
1302 | ah->ah_power_mode = mode; | ||
1303 | ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /***********************\ | ||
1309 | DMA Related Functions | ||
1310 | \***********************/ | ||
1311 | |||
1312 | /* | ||
1313 | * Receive functions | ||
1314 | */ | ||
1315 | |||
1316 | /* | ||
1317 | * Start DMA receive | ||
1318 | */ | ||
1319 | void ath5k_hw_start_rx(struct ath5k_hw *ah) | ||
1320 | { | ||
1321 | ATH5K_TRACE(ah->ah_sc); | ||
1322 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); | ||
1323 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
1324 | } | ||
1325 | |||
1326 | /* | ||
1327 | * Stop DMA receive | ||
1328 | */ | ||
1329 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | ||
1330 | { | ||
1331 | unsigned int i; | ||
1332 | |||
1333 | ATH5K_TRACE(ah->ah_sc); | ||
1334 | ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); | ||
1335 | |||
1336 | /* | ||
1337 | * It may take some time to disable the DMA receive unit | ||
1338 | */ | ||
1339 | for (i = 2000; i > 0 && | ||
1340 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; | ||
1341 | i--) | ||
1342 | udelay(10); | ||
1343 | |||
1344 | return i ? 0 : -EBUSY; | ||
1345 | } | ||
1346 | |||
1347 | /* | ||
1348 | * Get the address of the RX Descriptor | ||
1349 | */ | ||
1350 | u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah) | ||
1351 | { | ||
1352 | return ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
1353 | } | ||
1354 | |||
1355 | /* | ||
1356 | * Set the address of the RX Descriptor | ||
1357 | */ | ||
1358 | void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr) | ||
1359 | { | ||
1360 | ATH5K_TRACE(ah->ah_sc); | ||
1361 | |||
1362 | /*TODO:Shouldn't we check if RX is enabled first ?*/ | ||
1363 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * Transmit functions | ||
1368 | */ | ||
1369 | |||
1370 | /* | ||
1371 | * Start DMA transmit for a specific queue | ||
1372 | * (see also QCU/DCU functions) | ||
1373 | */ | ||
1374 | int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue) | ||
1375 | { | ||
1376 | u32 tx_queue; | ||
1377 | |||
1378 | ATH5K_TRACE(ah->ah_sc); | ||
1379 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1380 | |||
1381 | /* Return if queue is declared inactive */ | ||
1382 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
1383 | return -EIO; | ||
1384 | |||
1385 | if (ah->ah_version == AR5K_AR5210) { | ||
1386 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
1387 | |||
1388 | /* | ||
1389 | * Set the queue by type on 5210 | ||
1390 | */ | ||
1391 | switch (ah->ah_txq[queue].tqi_type) { | ||
1392 | case AR5K_TX_QUEUE_DATA: | ||
1393 | tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; | ||
1394 | break; | ||
1395 | case AR5K_TX_QUEUE_BEACON: | ||
1396 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
1397 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
1398 | AR5K_BSR); | ||
1399 | break; | ||
1400 | case AR5K_TX_QUEUE_CAB: | ||
1401 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
1402 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | | ||
1403 | AR5K_BCR_BDMAE, AR5K_BSR); | ||
1404 | break; | ||
1405 | default: | ||
1406 | return -EINVAL; | ||
1407 | } | ||
1408 | /* Start queue */ | ||
1409 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
1410 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
1411 | } else { | ||
1412 | /* Return if queue is disabled */ | ||
1413 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) | ||
1414 | return -EIO; | ||
1415 | |||
1416 | /* Start queue */ | ||
1417 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); | ||
1418 | } | ||
1419 | |||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | /* | ||
1424 | * Stop DMA transmit for a specific queue | ||
1425 | * (see also QCU/DCU functions) | ||
1426 | */ | ||
1427 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
1428 | { | ||
1429 | unsigned int i = 100; | ||
1430 | u32 tx_queue, pending; | ||
1431 | |||
1432 | ATH5K_TRACE(ah->ah_sc); | ||
1433 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1434 | |||
1435 | /* Return if queue is declared inactive */ | ||
1436 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
1437 | return -EIO; | ||
1438 | |||
1439 | if (ah->ah_version == AR5K_AR5210) { | ||
1440 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
1441 | |||
1442 | /* | ||
1443 | * Set by queue type | ||
1444 | */ | ||
1445 | switch (ah->ah_txq[queue].tqi_type) { | ||
1446 | case AR5K_TX_QUEUE_DATA: | ||
1447 | tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; | ||
1448 | break; | ||
1449 | case AR5K_TX_QUEUE_BEACON: | ||
1450 | case AR5K_TX_QUEUE_CAB: | ||
1451 | /* XXX Fix me... */ | ||
1452 | tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; | ||
1453 | ath5k_hw_reg_write(ah, 0, AR5K_BSR); | ||
1454 | break; | ||
1455 | default: | ||
1456 | return -EINVAL; | ||
1457 | } | ||
1458 | |||
1459 | /* Stop queue */ | ||
1460 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
1461 | ath5k_hw_reg_read(ah, AR5K_CR); | ||
1462 | } else { | ||
1463 | /* | ||
1464 | * Schedule TX disable and wait until queue is empty | ||
1465 | */ | ||
1466 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); | ||
1467 | |||
1468 | /*Check for pending frames*/ | ||
1469 | do { | ||
1470 | pending = ath5k_hw_reg_read(ah, | ||
1471 | AR5K_QUEUE_STATUS(queue)) & | ||
1472 | AR5K_QCU_STS_FRMPENDCNT; | ||
1473 | udelay(100); | ||
1474 | } while (--i && pending); | ||
1475 | |||
1476 | /* Clear register */ | ||
1477 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); | ||
1478 | if (pending) | ||
1479 | return -EBUSY; | ||
1480 | } | ||
1481 | |||
1482 | /* TODO: Check for success else return error */ | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | /* | ||
1487 | * Get the address of the TX Descriptor for a specific queue | ||
1488 | * (see also QCU/DCU functions) | ||
1489 | */ | ||
1490 | u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue) | ||
1491 | { | ||
1492 | u16 tx_reg; | ||
1493 | |||
1494 | ATH5K_TRACE(ah->ah_sc); | ||
1495 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1496 | |||
1497 | /* | ||
1498 | * Get the transmit queue descriptor pointer from the selected queue | ||
1499 | */ | ||
1500 | /*5210 doesn't have QCU*/ | ||
1501 | if (ah->ah_version == AR5K_AR5210) { | ||
1502 | switch (ah->ah_txq[queue].tqi_type) { | ||
1503 | case AR5K_TX_QUEUE_DATA: | ||
1504 | tx_reg = AR5K_NOQCU_TXDP0; | ||
1505 | break; | ||
1506 | case AR5K_TX_QUEUE_BEACON: | ||
1507 | case AR5K_TX_QUEUE_CAB: | ||
1508 | tx_reg = AR5K_NOQCU_TXDP1; | ||
1509 | break; | ||
1510 | default: | ||
1511 | return 0xffffffff; | ||
1512 | } | ||
1513 | } else { | ||
1514 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
1515 | } | ||
1516 | |||
1517 | return ath5k_hw_reg_read(ah, tx_reg); | ||
1518 | } | ||
1519 | |||
1520 | /* | ||
1521 | * Set the address of the TX Descriptor for a specific queue | ||
1522 | * (see also QCU/DCU functions) | ||
1523 | */ | ||
1524 | int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | ||
1525 | { | ||
1526 | u16 tx_reg; | ||
1527 | |||
1528 | ATH5K_TRACE(ah->ah_sc); | ||
1529 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1530 | |||
1531 | /* | ||
1532 | * Set the transmit queue descriptor pointer register by type | ||
1533 | * on 5210 | ||
1534 | */ | ||
1535 | if (ah->ah_version == AR5K_AR5210) { | ||
1536 | switch (ah->ah_txq[queue].tqi_type) { | ||
1537 | case AR5K_TX_QUEUE_DATA: | ||
1538 | tx_reg = AR5K_NOQCU_TXDP0; | ||
1539 | break; | ||
1540 | case AR5K_TX_QUEUE_BEACON: | ||
1541 | case AR5K_TX_QUEUE_CAB: | ||
1542 | tx_reg = AR5K_NOQCU_TXDP1; | ||
1543 | break; | ||
1544 | default: | ||
1545 | return -EINVAL; | ||
1546 | } | ||
1547 | } else { | ||
1548 | /* | ||
1549 | * Set the transmit queue descriptor pointer for | ||
1550 | * the selected queue on QCU for 5211+ | ||
1551 | * (this won't work if the queue is still active) | ||
1552 | */ | ||
1553 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
1554 | return -EIO; | ||
1555 | |||
1556 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
1557 | } | ||
1558 | |||
1559 | /* Set descriptor pointer */ | ||
1560 | ath5k_hw_reg_write(ah, phys_addr, tx_reg); | ||
1561 | |||
1562 | return 0; | ||
1563 | } | ||
1564 | |||
1565 | /* | ||
1566 | * Update tx trigger level | ||
1567 | */ | ||
1568 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | ||
1569 | { | ||
1570 | u32 trigger_level, imr; | ||
1571 | int ret = -EIO; | ||
1572 | |||
1573 | ATH5K_TRACE(ah->ah_sc); | ||
1574 | |||
1575 | /* | ||
1576 | * Disable interrupts by setting the mask | ||
1577 | */ | ||
1578 | imr = ath5k_hw_set_intr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); | ||
1579 | |||
1580 | /*TODO: Boundary check on trigger_level*/ | ||
1581 | trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), | ||
1582 | AR5K_TXCFG_TXFULL); | ||
1583 | |||
1584 | if (!increase) { | ||
1585 | if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) | ||
1586 | goto done; | ||
1587 | } else | ||
1588 | trigger_level += | ||
1589 | ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); | ||
1590 | |||
1591 | /* | ||
1592 | * Update trigger level on success | ||
1593 | */ | ||
1594 | if (ah->ah_version == AR5K_AR5210) | ||
1595 | ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); | ||
1596 | else | ||
1597 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
1598 | AR5K_TXCFG_TXFULL, trigger_level); | ||
1599 | |||
1600 | ret = 0; | ||
1601 | |||
1602 | done: | ||
1603 | /* | ||
1604 | * Restore interrupt mask | ||
1605 | */ | ||
1606 | ath5k_hw_set_intr(ah, imr); | ||
1607 | |||
1608 | return ret; | ||
1609 | } | ||
1610 | |||
1611 | /* | ||
1612 | * Interrupt handling | ||
1613 | */ | ||
1614 | |||
1615 | /* | ||
1616 | * Check if we have pending interrupts | ||
1617 | */ | ||
1618 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | ||
1619 | { | ||
1620 | ATH5K_TRACE(ah->ah_sc); | ||
1621 | return ath5k_hw_reg_read(ah, AR5K_INTPEND); | ||
1622 | } | ||
1623 | |||
1624 | /* | ||
1625 | * Get interrupt mask (ISR) | ||
1626 | */ | ||
1627 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | ||
1628 | { | ||
1629 | u32 data; | ||
1630 | |||
1631 | ATH5K_TRACE(ah->ah_sc); | ||
1632 | |||
1633 | /* | ||
1634 | * Read interrupt status from the Interrupt Status register | ||
1635 | * on 5210 | ||
1636 | */ | ||
1637 | if (ah->ah_version == AR5K_AR5210) { | ||
1638 | data = ath5k_hw_reg_read(ah, AR5K_ISR); | ||
1639 | if (unlikely(data == AR5K_INT_NOCARD)) { | ||
1640 | *interrupt_mask = data; | ||
1641 | return -ENODEV; | ||
1642 | } | ||
1643 | } else { | ||
1644 | /* | ||
1645 | * Read interrupt status from the Read-And-Clear shadow register | ||
1646 | * Note: PISR/SISR Not available on 5210 | ||
1647 | */ | ||
1648 | data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); | ||
1649 | } | ||
1650 | |||
1651 | /* | ||
1652 | * Get abstract interrupt mask (driver-compatible) | ||
1653 | */ | ||
1654 | *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; | ||
1655 | |||
1656 | if (unlikely(data == AR5K_INT_NOCARD)) | ||
1657 | return -ENODEV; | ||
1658 | |||
1659 | if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR)) | ||
1660 | *interrupt_mask |= AR5K_INT_RX; | ||
1661 | |||
1662 | if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR | ||
1663 | | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL)) | ||
1664 | *interrupt_mask |= AR5K_INT_TX; | ||
1665 | |||
1666 | if (ah->ah_version != AR5K_AR5210) { | ||
1667 | /*HIU = Host Interface Unit (PCI etc)*/ | ||
1668 | if (unlikely(data & (AR5K_ISR_HIUERR))) | ||
1669 | *interrupt_mask |= AR5K_INT_FATAL; | ||
1670 | |||
1671 | /*Beacon Not Ready*/ | ||
1672 | if (unlikely(data & (AR5K_ISR_BNR))) | ||
1673 | *interrupt_mask |= AR5K_INT_BNR; | ||
1674 | } | ||
1675 | |||
1676 | /* | ||
1677 | * XXX: BMISS interrupts may occur after association. | ||
1678 | * I found this on 5210 code but it needs testing. If this is | ||
1679 | * true we should disable them before assoc and re-enable them | ||
1680 | * after a successfull assoc + some jiffies. | ||
1681 | */ | ||
1682 | #if 0 | ||
1683 | interrupt_mask &= ~AR5K_INT_BMISS; | ||
1684 | #endif | ||
1685 | |||
1686 | /* | ||
1687 | * In case we didn't handle anything, | ||
1688 | * print the register value. | ||
1689 | */ | ||
1690 | if (unlikely(*interrupt_mask == 0 && net_ratelimit())) | ||
1691 | ATH5K_PRINTF("0x%08x\n", data); | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | /* | ||
1697 | * Set interrupt mask | ||
1698 | */ | ||
1699 | enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) | ||
1700 | { | ||
1701 | enum ath5k_int old_mask, int_mask; | ||
1702 | |||
1703 | /* | ||
1704 | * Disable card interrupts to prevent any race conditions | ||
1705 | * (they will be re-enabled afterwards). | ||
1706 | */ | ||
1707 | ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); | ||
1708 | ath5k_hw_reg_read(ah, AR5K_IER); | ||
1709 | |||
1710 | old_mask = ah->ah_imr; | ||
1711 | |||
1712 | /* | ||
1713 | * Add additional, chipset-dependent interrupt mask flags | ||
1714 | * and write them to the IMR (interrupt mask register). | ||
1715 | */ | ||
1716 | int_mask = new_mask & AR5K_INT_COMMON; | ||
1717 | |||
1718 | if (new_mask & AR5K_INT_RX) | ||
1719 | int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN | | ||
1720 | AR5K_IMR_RXDESC; | ||
1721 | |||
1722 | if (new_mask & AR5K_INT_TX) | ||
1723 | int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC | | ||
1724 | AR5K_IMR_TXURN; | ||
1725 | |||
1726 | if (ah->ah_version != AR5K_AR5210) { | ||
1727 | if (new_mask & AR5K_INT_FATAL) { | ||
1728 | int_mask |= AR5K_IMR_HIUERR; | ||
1729 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT | | ||
1730 | AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR); | ||
1731 | } | ||
1732 | } | ||
1733 | |||
1734 | ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); | ||
1735 | |||
1736 | /* Store new interrupt mask */ | ||
1737 | ah->ah_imr = new_mask; | ||
1738 | |||
1739 | /* ..re-enable interrupts */ | ||
1740 | ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); | ||
1741 | ath5k_hw_reg_read(ah, AR5K_IER); | ||
1742 | |||
1743 | return old_mask; | ||
1744 | } | ||
1745 | |||
1746 | |||
1747 | /*************************\ | ||
1748 | EEPROM access functions | ||
1749 | \*************************/ | ||
1750 | |||
1751 | /* | ||
1752 | * Read from eeprom | ||
1753 | */ | ||
1754 | static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | ||
1755 | { | ||
1756 | u32 status, timeout; | ||
1757 | |||
1758 | ATH5K_TRACE(ah->ah_sc); | ||
1759 | /* | ||
1760 | * Initialize EEPROM access | ||
1761 | */ | ||
1762 | if (ah->ah_version == AR5K_AR5210) { | ||
1763 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
1764 | (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); | ||
1765 | } else { | ||
1766 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
1767 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1768 | AR5K_EEPROM_CMD_READ); | ||
1769 | } | ||
1770 | |||
1771 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
1772 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
1773 | if (status & AR5K_EEPROM_STAT_RDDONE) { | ||
1774 | if (status & AR5K_EEPROM_STAT_RDERR) | ||
1775 | return -EIO; | ||
1776 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | ||
1777 | 0xffff); | ||
1778 | return 0; | ||
1779 | } | ||
1780 | udelay(15); | ||
1781 | } | ||
1782 | |||
1783 | return -ETIMEDOUT; | ||
1784 | } | ||
1785 | |||
1786 | /* | ||
1787 | * Write to eeprom - currently disabled, use at your own risk | ||
1788 | */ | ||
1789 | #if 0 | ||
1790 | static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data) | ||
1791 | { | ||
1792 | |||
1793 | u32 status, timeout; | ||
1794 | |||
1795 | ATH5K_TRACE(ah->ah_sc); | ||
1796 | |||
1797 | /* | ||
1798 | * Initialize eeprom access | ||
1799 | */ | ||
1800 | |||
1801 | if (ah->ah_version == AR5K_AR5210) { | ||
1802 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
1803 | } else { | ||
1804 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1805 | AR5K_EEPROM_CMD_RESET); | ||
1806 | } | ||
1807 | |||
1808 | /* | ||
1809 | * Write data to data register | ||
1810 | */ | ||
1811 | |||
1812 | if (ah->ah_version == AR5K_AR5210) { | ||
1813 | ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset)); | ||
1814 | } else { | ||
1815 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
1816 | ath5k_hw_reg_write(ah, data, AR5K_EEPROM_DATA); | ||
1817 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1818 | AR5K_EEPROM_CMD_WRITE); | ||
1819 | } | ||
1820 | |||
1821 | /* | ||
1822 | * Check status | ||
1823 | */ | ||
1824 | |||
1825 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
1826 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
1827 | if (status & AR5K_EEPROM_STAT_WRDONE) { | ||
1828 | if (status & AR5K_EEPROM_STAT_WRERR) | ||
1829 | return EIO; | ||
1830 | return 0; | ||
1831 | } | ||
1832 | udelay(15); | ||
1833 | } | ||
1834 | |||
1835 | ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!"); | ||
1836 | return -EIO; | ||
1837 | } | ||
1838 | #endif | ||
1839 | |||
1840 | /* | ||
1841 | * Translate binary channel representation in EEPROM to frequency | ||
1842 | */ | ||
1843 | static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, unsigned int mode) | ||
1844 | { | ||
1845 | u16 val; | ||
1846 | |||
1847 | if (bin == AR5K_EEPROM_CHANNEL_DIS) | ||
1848 | return bin; | ||
1849 | |||
1850 | if (mode == AR5K_EEPROM_MODE_11A) { | ||
1851 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
1852 | val = (5 * bin) + 4800; | ||
1853 | else | ||
1854 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | ||
1855 | (bin * 10) + 5100; | ||
1856 | } else { | ||
1857 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
1858 | val = bin + 2300; | ||
1859 | else | ||
1860 | val = bin + 2400; | ||
1861 | } | ||
1862 | |||
1863 | return val; | ||
1864 | } | ||
1865 | |||
1866 | /* | ||
1867 | * Read antenna infos from eeprom | ||
1868 | */ | ||
1869 | static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | ||
1870 | unsigned int mode) | ||
1871 | { | ||
1872 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1873 | u32 o = *offset; | ||
1874 | u16 val; | ||
1875 | int ret, i = 0; | ||
1876 | |||
1877 | AR5K_EEPROM_READ(o++, val); | ||
1878 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | ||
1879 | ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f; | ||
1880 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
1881 | |||
1882 | AR5K_EEPROM_READ(o++, val); | ||
1883 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
1884 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
1885 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
1886 | |||
1887 | AR5K_EEPROM_READ(o++, val); | ||
1888 | ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; | ||
1889 | ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; | ||
1890 | ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; | ||
1891 | |||
1892 | AR5K_EEPROM_READ(o++, val); | ||
1893 | ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; | ||
1894 | ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; | ||
1895 | ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; | ||
1896 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
1897 | |||
1898 | AR5K_EEPROM_READ(o++, val); | ||
1899 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
1900 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
1901 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
1902 | |||
1903 | /* Get antenna modes */ | ||
1904 | ah->ah_antenna[mode][0] = | ||
1905 | (ee->ee_ant_control[mode][0] << 4) | 0x1; | ||
1906 | ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = | ||
1907 | ee->ee_ant_control[mode][1] | | ||
1908 | (ee->ee_ant_control[mode][2] << 6) | | ||
1909 | (ee->ee_ant_control[mode][3] << 12) | | ||
1910 | (ee->ee_ant_control[mode][4] << 18) | | ||
1911 | (ee->ee_ant_control[mode][5] << 24); | ||
1912 | ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = | ||
1913 | ee->ee_ant_control[mode][6] | | ||
1914 | (ee->ee_ant_control[mode][7] << 6) | | ||
1915 | (ee->ee_ant_control[mode][8] << 12) | | ||
1916 | (ee->ee_ant_control[mode][9] << 18) | | ||
1917 | (ee->ee_ant_control[mode][10] << 24); | ||
1918 | |||
1919 | /* return new offset */ | ||
1920 | *offset = o; | ||
1921 | |||
1922 | return 0; | ||
1923 | } | ||
1924 | |||
1925 | /* | ||
1926 | * Read supported modes from eeprom | ||
1927 | */ | ||
1928 | static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | ||
1929 | unsigned int mode) | ||
1930 | { | ||
1931 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1932 | u32 o = *offset; | ||
1933 | u16 val; | ||
1934 | int ret; | ||
1935 | |||
1936 | AR5K_EEPROM_READ(o++, val); | ||
1937 | ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; | ||
1938 | ee->ee_thr_62[mode] = val & 0xff; | ||
1939 | |||
1940 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
1941 | ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; | ||
1942 | |||
1943 | AR5K_EEPROM_READ(o++, val); | ||
1944 | ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; | ||
1945 | ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; | ||
1946 | |||
1947 | AR5K_EEPROM_READ(o++, val); | ||
1948 | ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; | ||
1949 | |||
1950 | if ((val & 0xff) & 0x80) | ||
1951 | ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); | ||
1952 | else | ||
1953 | ee->ee_noise_floor_thr[mode] = val & 0xff; | ||
1954 | |||
1955 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
1956 | ee->ee_noise_floor_thr[mode] = | ||
1957 | mode == AR5K_EEPROM_MODE_11A ? -54 : -1; | ||
1958 | |||
1959 | AR5K_EEPROM_READ(o++, val); | ||
1960 | ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; | ||
1961 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; | ||
1962 | ee->ee_xpd[mode] = val & 0x1; | ||
1963 | |||
1964 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) | ||
1965 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; | ||
1966 | |||
1967 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { | ||
1968 | AR5K_EEPROM_READ(o++, val); | ||
1969 | ee->ee_false_detect[mode] = (val >> 6) & 0x7f; | ||
1970 | |||
1971 | if (mode == AR5K_EEPROM_MODE_11A) | ||
1972 | ee->ee_xr_power[mode] = val & 0x3f; | ||
1973 | else { | ||
1974 | ee->ee_ob[mode][0] = val & 0x7; | ||
1975 | ee->ee_db[mode][0] = (val >> 3) & 0x7; | ||
1976 | } | ||
1977 | } | ||
1978 | |||
1979 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { | ||
1980 | ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; | ||
1981 | ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; | ||
1982 | } else { | ||
1983 | ee->ee_i_gain[mode] = (val >> 13) & 0x7; | ||
1984 | |||
1985 | AR5K_EEPROM_READ(o++, val); | ||
1986 | ee->ee_i_gain[mode] |= (val << 3) & 0x38; | ||
1987 | |||
1988 | if (mode == AR5K_EEPROM_MODE_11G) | ||
1989 | ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; | ||
1990 | } | ||
1991 | |||
1992 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && | ||
1993 | mode == AR5K_EEPROM_MODE_11A) { | ||
1994 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
1995 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
1996 | } | ||
1997 | |||
1998 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 && | ||
1999 | mode == AR5K_EEPROM_MODE_11G) | ||
2000 | ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; | ||
2001 | |||
2002 | /* return new offset */ | ||
2003 | *offset = o; | ||
2004 | |||
2005 | return 0; | ||
2006 | } | ||
2007 | |||
2008 | /* | ||
2009 | * Initialize eeprom & capabilities structs | ||
2010 | */ | ||
2011 | static int ath5k_eeprom_init(struct ath5k_hw *ah) | ||
2012 | { | ||
2013 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
2014 | unsigned int mode, i; | ||
2015 | int ret; | ||
2016 | u32 offset; | ||
2017 | u16 val; | ||
2018 | |||
2019 | /* Initial TX thermal adjustment values */ | ||
2020 | ee->ee_tx_clip = 4; | ||
2021 | ee->ee_pwd_84 = ee->ee_pwd_90 = 1; | ||
2022 | ee->ee_gain_select = 1; | ||
2023 | |||
2024 | /* | ||
2025 | * Read values from EEPROM and store them in the capability structure | ||
2026 | */ | ||
2027 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); | ||
2028 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); | ||
2029 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); | ||
2030 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); | ||
2031 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); | ||
2032 | |||
2033 | /* Return if we have an old EEPROM */ | ||
2034 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | ||
2035 | return 0; | ||
2036 | |||
2037 | #ifdef notyet | ||
2038 | /* | ||
2039 | * Validate the checksum of the EEPROM date. There are some | ||
2040 | * devices with invalid EEPROMs. | ||
2041 | */ | ||
2042 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | ||
2043 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | ||
2044 | cksum ^= val; | ||
2045 | } | ||
2046 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | ||
2047 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | ||
2048 | return -EIO; | ||
2049 | } | ||
2050 | #endif | ||
2051 | |||
2052 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | ||
2053 | ee_ant_gain); | ||
2054 | |||
2055 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
2056 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | ||
2057 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | ||
2058 | } | ||
2059 | |||
2060 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | ||
2061 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); | ||
2062 | ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; | ||
2063 | ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; | ||
2064 | |||
2065 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); | ||
2066 | ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; | ||
2067 | ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; | ||
2068 | } | ||
2069 | |||
2070 | /* | ||
2071 | * Get conformance test limit values | ||
2072 | */ | ||
2073 | offset = AR5K_EEPROM_CTL(ah->ah_ee_version); | ||
2074 | ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version); | ||
2075 | |||
2076 | for (i = 0; i < ee->ee_ctls; i++) { | ||
2077 | AR5K_EEPROM_READ(offset++, val); | ||
2078 | ee->ee_ctl[i] = (val >> 8) & 0xff; | ||
2079 | ee->ee_ctl[i + 1] = val & 0xff; | ||
2080 | } | ||
2081 | |||
2082 | /* | ||
2083 | * Get values for 802.11a (5GHz) | ||
2084 | */ | ||
2085 | mode = AR5K_EEPROM_MODE_11A; | ||
2086 | |||
2087 | ee->ee_turbo_max_power[mode] = | ||
2088 | AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); | ||
2089 | |||
2090 | offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); | ||
2091 | |||
2092 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
2093 | if (ret) | ||
2094 | return ret; | ||
2095 | |||
2096 | AR5K_EEPROM_READ(offset++, val); | ||
2097 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
2098 | ee->ee_ob[mode][3] = (val >> 5) & 0x7; | ||
2099 | ee->ee_db[mode][3] = (val >> 2) & 0x7; | ||
2100 | ee->ee_ob[mode][2] = (val << 1) & 0x7; | ||
2101 | |||
2102 | AR5K_EEPROM_READ(offset++, val); | ||
2103 | ee->ee_ob[mode][2] |= (val >> 15) & 0x1; | ||
2104 | ee->ee_db[mode][2] = (val >> 12) & 0x7; | ||
2105 | ee->ee_ob[mode][1] = (val >> 9) & 0x7; | ||
2106 | ee->ee_db[mode][1] = (val >> 6) & 0x7; | ||
2107 | ee->ee_ob[mode][0] = (val >> 3) & 0x7; | ||
2108 | ee->ee_db[mode][0] = val & 0x7; | ||
2109 | |||
2110 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
2111 | if (ret) | ||
2112 | return ret; | ||
2113 | |||
2114 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) { | ||
2115 | AR5K_EEPROM_READ(offset++, val); | ||
2116 | ee->ee_margin_tx_rx[mode] = val & 0x3f; | ||
2117 | } | ||
2118 | |||
2119 | /* | ||
2120 | * Get values for 802.11b (2.4GHz) | ||
2121 | */ | ||
2122 | mode = AR5K_EEPROM_MODE_11B; | ||
2123 | offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); | ||
2124 | |||
2125 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
2126 | if (ret) | ||
2127 | return ret; | ||
2128 | |||
2129 | AR5K_EEPROM_READ(offset++, val); | ||
2130 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
2131 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
2132 | ee->ee_db[mode][1] = val & 0x7; | ||
2133 | |||
2134 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
2135 | if (ret) | ||
2136 | return ret; | ||
2137 | |||
2138 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
2139 | AR5K_EEPROM_READ(offset++, val); | ||
2140 | ee->ee_cal_pier[mode][0] = | ||
2141 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
2142 | ee->ee_cal_pier[mode][1] = | ||
2143 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
2144 | |||
2145 | AR5K_EEPROM_READ(offset++, val); | ||
2146 | ee->ee_cal_pier[mode][2] = | ||
2147 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
2148 | } | ||
2149 | |||
2150 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
2151 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
2152 | |||
2153 | /* | ||
2154 | * Get values for 802.11g (2.4GHz) | ||
2155 | */ | ||
2156 | mode = AR5K_EEPROM_MODE_11G; | ||
2157 | offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); | ||
2158 | |||
2159 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
2160 | if (ret) | ||
2161 | return ret; | ||
2162 | |||
2163 | AR5K_EEPROM_READ(offset++, val); | ||
2164 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
2165 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
2166 | ee->ee_db[mode][1] = val & 0x7; | ||
2167 | |||
2168 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
2169 | if (ret) | ||
2170 | return ret; | ||
2171 | |||
2172 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
2173 | AR5K_EEPROM_READ(offset++, val); | ||
2174 | ee->ee_cal_pier[mode][0] = | ||
2175 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
2176 | ee->ee_cal_pier[mode][1] = | ||
2177 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
2178 | |||
2179 | AR5K_EEPROM_READ(offset++, val); | ||
2180 | ee->ee_turbo_max_power[mode] = val & 0x7f; | ||
2181 | ee->ee_xr_power[mode] = (val >> 7) & 0x3f; | ||
2182 | |||
2183 | AR5K_EEPROM_READ(offset++, val); | ||
2184 | ee->ee_cal_pier[mode][2] = | ||
2185 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
2186 | |||
2187 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
2188 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
2189 | |||
2190 | AR5K_EEPROM_READ(offset++, val); | ||
2191 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
2192 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
2193 | |||
2194 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | ||
2195 | AR5K_EEPROM_READ(offset++, val); | ||
2196 | ee->ee_cck_ofdm_gain_delta = val & 0xff; | ||
2197 | } | ||
2198 | } | ||
2199 | |||
2200 | /* | ||
2201 | * Read 5GHz EEPROM channels | ||
2202 | */ | ||
2203 | |||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | /* | ||
2208 | * Read the MAC address from eeprom | ||
2209 | */ | ||
2210 | static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
2211 | { | ||
2212 | u8 mac_d[ETH_ALEN]; | ||
2213 | u32 total, offset; | ||
2214 | u16 data; | ||
2215 | int octet, ret; | ||
2216 | |||
2217 | memset(mac, 0, ETH_ALEN); | ||
2218 | memset(mac_d, 0, ETH_ALEN); | ||
2219 | |||
2220 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
2221 | if (ret) | ||
2222 | return ret; | ||
2223 | |||
2224 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
2225 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | ||
2226 | if (ret) | ||
2227 | return ret; | ||
2228 | |||
2229 | total += data; | ||
2230 | mac_d[octet + 1] = data & 0xff; | ||
2231 | mac_d[octet] = data >> 8; | ||
2232 | octet += 2; | ||
2233 | } | ||
2234 | |||
2235 | memcpy(mac, mac_d, ETH_ALEN); | ||
2236 | |||
2237 | if (!total || total == 3 * 0xffff) | ||
2238 | return -EINVAL; | ||
2239 | |||
2240 | return 0; | ||
2241 | } | ||
2242 | |||
2243 | /* | ||
2244 | * Fill the capabilities struct | ||
2245 | */ | ||
2246 | static int ath5k_hw_get_capabilities(struct ath5k_hw *ah) | ||
2247 | { | ||
2248 | u16 ee_header; | ||
2249 | |||
2250 | ATH5K_TRACE(ah->ah_sc); | ||
2251 | /* Capabilities stored in the EEPROM */ | ||
2252 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | ||
2253 | |||
2254 | if (ah->ah_version == AR5K_AR5210) { | ||
2255 | /* | ||
2256 | * Set radio capabilities | ||
2257 | * (The AR5110 only supports the middle 5GHz band) | ||
2258 | */ | ||
2259 | ah->ah_capabilities.cap_range.range_5ghz_min = 5120; | ||
2260 | ah->ah_capabilities.cap_range.range_5ghz_max = 5430; | ||
2261 | ah->ah_capabilities.cap_range.range_2ghz_min = 0; | ||
2262 | ah->ah_capabilities.cap_range.range_2ghz_max = 0; | ||
2263 | |||
2264 | /* Set supported modes */ | ||
2265 | __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); | ||
2266 | __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); | ||
2267 | } else { | ||
2268 | /* | ||
2269 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz | ||
2270 | * XXX and from 2312 to 2732GHz. There are problems with the | ||
2271 | * XXX current ieee80211 implementation because the IEEE | ||
2272 | * XXX channel mapping does not support negative channel | ||
2273 | * XXX numbers (2312MHz is channel -19). Of course, this | ||
2274 | * XXX doesn't matter because these channels are out of range | ||
2275 | * XXX but some regulation domains like MKK (Japan) will | ||
2276 | * XXX support frequencies somewhere around 4.8GHz. | ||
2277 | */ | ||
2278 | |||
2279 | /* | ||
2280 | * Set radio capabilities | ||
2281 | */ | ||
2282 | |||
2283 | if (AR5K_EEPROM_HDR_11A(ee_header)) { | ||
2284 | ah->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */ | ||
2285 | ah->ah_capabilities.cap_range.range_5ghz_max = 6100; | ||
2286 | |||
2287 | /* Set supported modes */ | ||
2288 | __set_bit(AR5K_MODE_11A, | ||
2289 | ah->ah_capabilities.cap_mode); | ||
2290 | __set_bit(AR5K_MODE_11A_TURBO, | ||
2291 | ah->ah_capabilities.cap_mode); | ||
2292 | if (ah->ah_version == AR5K_AR5212) | ||
2293 | __set_bit(AR5K_MODE_11G_TURBO, | ||
2294 | ah->ah_capabilities.cap_mode); | ||
2295 | } | ||
2296 | |||
2297 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | ||
2298 | * connected */ | ||
2299 | if (AR5K_EEPROM_HDR_11B(ee_header) || | ||
2300 | AR5K_EEPROM_HDR_11G(ee_header)) { | ||
2301 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */ | ||
2302 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | ||
2303 | |||
2304 | if (AR5K_EEPROM_HDR_11B(ee_header)) | ||
2305 | __set_bit(AR5K_MODE_11B, | ||
2306 | ah->ah_capabilities.cap_mode); | ||
2307 | |||
2308 | if (AR5K_EEPROM_HDR_11G(ee_header)) | ||
2309 | __set_bit(AR5K_MODE_11G, | ||
2310 | ah->ah_capabilities.cap_mode); | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2314 | /* GPIO */ | ||
2315 | ah->ah_gpio_npins = AR5K_NUM_GPIO; | ||
2316 | |||
2317 | /* Set number of supported TX queues */ | ||
2318 | if (ah->ah_version == AR5K_AR5210) | ||
2319 | ah->ah_capabilities.cap_queues.q_tx_num = | ||
2320 | AR5K_NUM_TX_QUEUES_NOQCU; | ||
2321 | else | ||
2322 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | ||
2323 | |||
2324 | return 0; | ||
2325 | } | ||
2326 | |||
2327 | /*********************************\ | ||
2328 | Protocol Control Unit Functions | ||
2329 | \*********************************/ | ||
2330 | |||
2331 | /* | ||
2332 | * Set Operation mode | ||
2333 | */ | ||
2334 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | ||
2335 | { | ||
2336 | u32 pcu_reg, beacon_reg, low_id, high_id; | ||
2337 | |||
2338 | pcu_reg = 0; | ||
2339 | beacon_reg = 0; | ||
2340 | |||
2341 | ATH5K_TRACE(ah->ah_sc); | ||
2342 | |||
2343 | switch (ah->ah_op_mode) { | ||
2344 | case IEEE80211_IF_TYPE_IBSS: | ||
2345 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA | | ||
2346 | (ah->ah_version == AR5K_AR5210 ? | ||
2347 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2348 | beacon_reg |= AR5K_BCR_ADHOC; | ||
2349 | break; | ||
2350 | |||
2351 | case IEEE80211_IF_TYPE_AP: | ||
2352 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
2353 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA | | ||
2354 | (ah->ah_version == AR5K_AR5210 ? | ||
2355 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2356 | beacon_reg |= AR5K_BCR_AP; | ||
2357 | break; | ||
2358 | |||
2359 | case IEEE80211_IF_TYPE_STA: | ||
2360 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2361 | (ah->ah_version == AR5K_AR5210 ? | ||
2362 | AR5K_STA_ID1_PWR_SV : 0); | ||
2363 | case IEEE80211_IF_TYPE_MNTR: | ||
2364 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2365 | (ah->ah_version == AR5K_AR5210 ? | ||
2366 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2367 | break; | ||
2368 | |||
2369 | default: | ||
2370 | return -EINVAL; | ||
2371 | } | ||
2372 | |||
2373 | /* | ||
2374 | * Set PCU registers | ||
2375 | */ | ||
2376 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | ||
2377 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | ||
2378 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
2379 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
2380 | |||
2381 | /* | ||
2382 | * Set Beacon Control Register on 5210 | ||
2383 | */ | ||
2384 | if (ah->ah_version == AR5K_AR5210) | ||
2385 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | ||
2386 | |||
2387 | return 0; | ||
2388 | } | ||
2389 | |||
2390 | /* | ||
2391 | * BSSID Functions | ||
2392 | */ | ||
2393 | |||
2394 | /* | ||
2395 | * Get station id | ||
2396 | */ | ||
2397 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | ||
2398 | { | ||
2399 | ATH5K_TRACE(ah->ah_sc); | ||
2400 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | ||
2401 | } | ||
2402 | |||
2403 | /* | ||
2404 | * Set station id | ||
2405 | */ | ||
2406 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | ||
2407 | { | ||
2408 | u32 low_id, high_id; | ||
2409 | |||
2410 | ATH5K_TRACE(ah->ah_sc); | ||
2411 | /* Set new station ID */ | ||
2412 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | ||
2413 | |||
2414 | low_id = AR5K_LOW_ID(mac); | ||
2415 | high_id = AR5K_HIGH_ID(mac); | ||
2416 | |||
2417 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
2418 | ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1); | ||
2419 | |||
2420 | return 0; | ||
2421 | } | ||
2422 | |||
2423 | /* | ||
2424 | * Set BSSID | ||
2425 | */ | ||
2426 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | ||
2427 | { | ||
2428 | u32 low_id, high_id; | ||
2429 | u16 tim_offset = 0; | ||
2430 | |||
2431 | /* | ||
2432 | * Set simple BSSID mask on 5212 | ||
2433 | */ | ||
2434 | if (ah->ah_version == AR5K_AR5212) { | ||
2435 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0); | ||
2436 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1); | ||
2437 | } | ||
2438 | |||
2439 | /* | ||
2440 | * Set BSSID which triggers the "SME Join" operation | ||
2441 | */ | ||
2442 | low_id = AR5K_LOW_ID(bssid); | ||
2443 | high_id = AR5K_HIGH_ID(bssid); | ||
2444 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | ||
2445 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | ||
2446 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | ||
2447 | |||
2448 | if (assoc_id == 0) { | ||
2449 | ath5k_hw_disable_pspoll(ah); | ||
2450 | return; | ||
2451 | } | ||
2452 | |||
2453 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | ||
2454 | tim_offset ? tim_offset + 4 : 0); | ||
2455 | |||
2456 | ath5k_hw_enable_pspoll(ah, NULL, 0); | ||
2457 | } | ||
2458 | /** | ||
2459 | * ath5k_hw_set_bssid_mask - set common bits we should listen to | ||
2460 | * | ||
2461 | * The bssid_mask is a utility used by AR5212 hardware to inform the hardware | ||
2462 | * which bits of the interface's MAC address should be looked at when trying | ||
2463 | * to decide which packets to ACK. In station mode every bit matters. In AP | ||
2464 | * mode with a single BSS every bit matters as well. In AP mode with | ||
2465 | * multiple BSSes not every bit matters. | ||
2466 | * | ||
2467 | * @ah: the &struct ath5k_hw | ||
2468 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | ||
2469 | * | ||
2470 | * Note that this is a simple filter and *does* not filter out all | ||
2471 | * relevant frames. Some non-relevant frames will get through, probability | ||
2472 | * jocks are welcomed to compute. | ||
2473 | * | ||
2474 | * When handling multiple BSSes (or VAPs) you can get the BSSID mask by | ||
2475 | * computing the set of: | ||
2476 | * | ||
2477 | * ~ ( MAC XOR BSSID ) | ||
2478 | * | ||
2479 | * When you do this you are essentially computing the common bits. Later it | ||
2480 | * is assumed the harware will "and" (&) the BSSID mask with the MAC address | ||
2481 | * to obtain the relevant bits which should match on the destination frame. | ||
2482 | * | ||
2483 | * Simple example: on your card you have have two BSSes you have created with | ||
2484 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
2485 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
2486 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
2487 | * | ||
2488 | * \ | ||
2489 | * MAC: 0001 | | ||
2490 | * BSSID-01: 0100 | --> Belongs to us | ||
2491 | * BSSID-02: 1001 | | ||
2492 | * / | ||
2493 | * ------------------- | ||
2494 | * BSSID-03: 0110 | --> External | ||
2495 | * ------------------- | ||
2496 | * | ||
2497 | * Our bssid_mask would then be: | ||
2498 | * | ||
2499 | * On loop iteration for BSSID-01: | ||
2500 | * ~(0001 ^ 0100) -> ~(0101) | ||
2501 | * -> 1010 | ||
2502 | * bssid_mask = 1010 | ||
2503 | * | ||
2504 | * On loop iteration for BSSID-02: | ||
2505 | * bssid_mask &= ~(0001 ^ 1001) | ||
2506 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
2507 | * bssid_mask = (1010) & ~(1001) | ||
2508 | * bssid_mask = (1010) & (0110) | ||
2509 | * bssid_mask = 0010 | ||
2510 | * | ||
2511 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
2512 | * significant bit". This is because its the only bit common | ||
2513 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
2514 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
2515 | * or our MAC address (we assume the hardware uses the MAC address). | ||
2516 | * | ||
2517 | * Now, suppose there's an incoming frame for BSSID-03: | ||
2518 | * | ||
2519 | * IFRAME-01: 0110 | ||
2520 | * | ||
2521 | * An easy eye-inspeciton of this already should tell you that this frame | ||
2522 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
2523 | * hardware to only look at the second least significant bit and the | ||
2524 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
2525 | * as 1, which does not match 0. | ||
2526 | * | ||
2527 | * So with IFRAME-01 we *assume* the hardware will do: | ||
2528 | * | ||
2529 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
2530 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
2531 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
2532 | * --> allow = 0 | ||
2533 | * | ||
2534 | * Lets now test a frame that should work: | ||
2535 | * | ||
2536 | * IFRAME-02: 0001 (we should allow) | ||
2537 | * | ||
2538 | * allow = (0001 & 1010) == 1010 | ||
2539 | * | ||
2540 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
2541 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
2542 | * --> allow = (0010) == (0010) | ||
2543 | * --> allow = 1 | ||
2544 | * | ||
2545 | * Other examples: | ||
2546 | * | ||
2547 | * IFRAME-03: 0100 --> allowed | ||
2548 | * IFRAME-04: 1001 --> allowed | ||
2549 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
2550 | * | ||
2551 | */ | ||
2552 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
2553 | { | ||
2554 | u32 low_id, high_id; | ||
2555 | ATH5K_TRACE(ah->ah_sc); | ||
2556 | |||
2557 | if (ah->ah_version == AR5K_AR5212) { | ||
2558 | low_id = AR5K_LOW_ID(mask); | ||
2559 | high_id = AR5K_HIGH_ID(mask); | ||
2560 | |||
2561 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | ||
2562 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | ||
2563 | |||
2564 | return 0; | ||
2565 | } | ||
2566 | |||
2567 | return -EIO; | ||
2568 | } | ||
2569 | |||
2570 | /* | ||
2571 | * Receive start/stop functions | ||
2572 | */ | ||
2573 | |||
2574 | /* | ||
2575 | * Start receive on PCU | ||
2576 | */ | ||
2577 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
2578 | { | ||
2579 | ATH5K_TRACE(ah->ah_sc); | ||
2580 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
2581 | |||
2582 | /* TODO: ANI Support */ | ||
2583 | } | ||
2584 | |||
2585 | /* | ||
2586 | * Stop receive on PCU | ||
2587 | */ | ||
2588 | void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah) | ||
2589 | { | ||
2590 | ATH5K_TRACE(ah->ah_sc); | ||
2591 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
2592 | |||
2593 | /* TODO: ANI Support */ | ||
2594 | } | ||
2595 | |||
2596 | /* | ||
2597 | * RX Filter functions | ||
2598 | */ | ||
2599 | |||
2600 | /* | ||
2601 | * Set multicast filter | ||
2602 | */ | ||
2603 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | ||
2604 | { | ||
2605 | ATH5K_TRACE(ah->ah_sc); | ||
2606 | /* Set the multicat filter */ | ||
2607 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | ||
2608 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | ||
2609 | } | ||
2610 | |||
2611 | /* | ||
2612 | * Set multicast filter by index | ||
2613 | */ | ||
2614 | int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index) | ||
2615 | { | ||
2616 | |||
2617 | ATH5K_TRACE(ah->ah_sc); | ||
2618 | if (index >= 64) | ||
2619 | return -EINVAL; | ||
2620 | else if (index >= 32) | ||
2621 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
2622 | (1 << (index - 32))); | ||
2623 | else | ||
2624 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
2625 | |||
2626 | return 0; | ||
2627 | } | ||
2628 | |||
2629 | /* | ||
2630 | * Clear Multicast filter by index | ||
2631 | */ | ||
2632 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
2633 | { | ||
2634 | |||
2635 | ATH5K_TRACE(ah->ah_sc); | ||
2636 | if (index >= 64) | ||
2637 | return -EINVAL; | ||
2638 | else if (index >= 32) | ||
2639 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
2640 | (1 << (index - 32))); | ||
2641 | else | ||
2642 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
2643 | |||
2644 | return 0; | ||
2645 | } | ||
2646 | |||
2647 | /* | ||
2648 | * Get current rx filter | ||
2649 | */ | ||
2650 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | ||
2651 | { | ||
2652 | u32 data, filter = 0; | ||
2653 | |||
2654 | ATH5K_TRACE(ah->ah_sc); | ||
2655 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); | ||
2656 | |||
2657 | /*Radar detection for 5212*/ | ||
2658 | if (ah->ah_version == AR5K_AR5212) { | ||
2659 | data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); | ||
2660 | |||
2661 | if (data & AR5K_PHY_ERR_FIL_RADAR) | ||
2662 | filter |= AR5K_RX_FILTER_RADARERR; | ||
2663 | if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) | ||
2664 | filter |= AR5K_RX_FILTER_PHYERR; | ||
2665 | } | ||
2666 | |||
2667 | return filter; | ||
2668 | } | ||
2669 | |||
2670 | /* | ||
2671 | * Set rx filter | ||
2672 | */ | ||
2673 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | ||
2674 | { | ||
2675 | u32 data = 0; | ||
2676 | |||
2677 | ATH5K_TRACE(ah->ah_sc); | ||
2678 | |||
2679 | /* Set PHY error filter register on 5212*/ | ||
2680 | if (ah->ah_version == AR5K_AR5212) { | ||
2681 | if (filter & AR5K_RX_FILTER_RADARERR) | ||
2682 | data |= AR5K_PHY_ERR_FIL_RADAR; | ||
2683 | if (filter & AR5K_RX_FILTER_PHYERR) | ||
2684 | data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; | ||
2685 | } | ||
2686 | |||
2687 | /* | ||
2688 | * The AR5210 uses promiscous mode to detect radar activity | ||
2689 | */ | ||
2690 | if (ah->ah_version == AR5K_AR5210 && | ||
2691 | (filter & AR5K_RX_FILTER_RADARERR)) { | ||
2692 | filter &= ~AR5K_RX_FILTER_RADARERR; | ||
2693 | filter |= AR5K_RX_FILTER_PROM; | ||
2694 | } | ||
2695 | |||
2696 | /*Zero length DMA*/ | ||
2697 | if (data) | ||
2698 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
2699 | else | ||
2700 | AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
2701 | |||
2702 | /*Write RX Filter register*/ | ||
2703 | ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); | ||
2704 | |||
2705 | /*Write PHY error filter register on 5212*/ | ||
2706 | if (ah->ah_version == AR5K_AR5212) | ||
2707 | ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); | ||
2708 | |||
2709 | } | ||
2710 | |||
2711 | /* | ||
2712 | * Beacon related functions | ||
2713 | */ | ||
2714 | |||
2715 | /* | ||
2716 | * Get a 32bit TSF | ||
2717 | */ | ||
2718 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
2719 | { | ||
2720 | ATH5K_TRACE(ah->ah_sc); | ||
2721 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
2722 | } | ||
2723 | |||
2724 | /* | ||
2725 | * Get the full 64bit TSF | ||
2726 | */ | ||
2727 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | ||
2728 | { | ||
2729 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
2730 | ATH5K_TRACE(ah->ah_sc); | ||
2731 | |||
2732 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | ||
2733 | } | ||
2734 | |||
2735 | /* | ||
2736 | * Force a TSF reset | ||
2737 | */ | ||
2738 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | ||
2739 | { | ||
2740 | ATH5K_TRACE(ah->ah_sc); | ||
2741 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF); | ||
2742 | } | ||
2743 | |||
2744 | /* | ||
2745 | * Initialize beacon timers | ||
2746 | */ | ||
2747 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | ||
2748 | { | ||
2749 | u32 timer1, timer2, timer3; | ||
2750 | |||
2751 | ATH5K_TRACE(ah->ah_sc); | ||
2752 | /* | ||
2753 | * Set the additional timers by mode | ||
2754 | */ | ||
2755 | switch (ah->ah_op_mode) { | ||
2756 | case IEEE80211_IF_TYPE_STA: | ||
2757 | if (ah->ah_version == AR5K_AR5210) { | ||
2758 | timer1 = 0xffffffff; | ||
2759 | timer2 = 0xffffffff; | ||
2760 | } else { | ||
2761 | timer1 = 0x0000ffff; | ||
2762 | timer2 = 0x0007ffff; | ||
2763 | } | ||
2764 | break; | ||
2765 | |||
2766 | default: | ||
2767 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; | ||
2768 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; | ||
2769 | } | ||
2770 | |||
2771 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | ||
2772 | |||
2773 | /* | ||
2774 | * Set the beacon register and enable all timers. | ||
2775 | * (next beacon, DMA beacon, software beacon, ATIM window time) | ||
2776 | */ | ||
2777 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | ||
2778 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | ||
2779 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | ||
2780 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | ||
2781 | |||
2782 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | | ||
2783 | AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE), | ||
2784 | AR5K_BEACON); | ||
2785 | } | ||
2786 | |||
2787 | #if 0 | ||
2788 | /* | ||
2789 | * Set beacon timers | ||
2790 | */ | ||
2791 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
2792 | const struct ath5k_beacon_state *state) | ||
2793 | { | ||
2794 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
2795 | |||
2796 | /* | ||
2797 | * TODO: should be changed through *state | ||
2798 | * review struct ath5k_beacon_state struct | ||
2799 | * | ||
2800 | * XXX: These are used for cfp period bellow, are they | ||
2801 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
2802 | * get_tsf ? | ||
2803 | */ | ||
2804 | u32 dtim_count = 0; /* XXX */ | ||
2805 | u32 cfp_count = 0; /* XXX */ | ||
2806 | u32 tsf = 0; /* XXX */ | ||
2807 | |||
2808 | ATH5K_TRACE(ah->ah_sc); | ||
2809 | /* Return on an invalid beacon state */ | ||
2810 | if (state->bs_interval < 1) | ||
2811 | return -EINVAL; | ||
2812 | |||
2813 | interval = state->bs_interval; | ||
2814 | dtim = state->bs_dtim_period; | ||
2815 | |||
2816 | /* | ||
2817 | * PCF support? | ||
2818 | */ | ||
2819 | if (state->bs_cfp_period > 0) { | ||
2820 | /* | ||
2821 | * Enable PCF mode and set the CFP | ||
2822 | * (Contention Free Period) and timer registers | ||
2823 | */ | ||
2824 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
2825 | state->bs_interval; | ||
2826 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
2827 | state->bs_interval; | ||
2828 | |||
2829 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
2830 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2831 | AR5K_STA_ID1_PCF); | ||
2832 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
2833 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
2834 | AR5K_CFP_DUR); | ||
2835 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
2836 | next_cfp)) << 3, AR5K_TIMER2); | ||
2837 | } else { | ||
2838 | /* Disable PCF mode */ | ||
2839 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
2840 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2841 | AR5K_STA_ID1_PCF); | ||
2842 | } | ||
2843 | |||
2844 | /* | ||
2845 | * Enable the beacon timer register | ||
2846 | */ | ||
2847 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
2848 | |||
2849 | /* | ||
2850 | * Start the beacon timers | ||
2851 | */ | ||
2852 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &~ | ||
2853 | (AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
2854 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
2855 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
2856 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
2857 | |||
2858 | /* | ||
2859 | * Write new beacon miss threshold, if it appears to be valid | ||
2860 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
2861 | * and return if its not in range. We can test this by reading value and | ||
2862 | * setting value to a largest value and seeing which values register. | ||
2863 | */ | ||
2864 | |||
2865 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
2866 | state->bs_bmiss_threshold); | ||
2867 | |||
2868 | /* | ||
2869 | * Set sleep control register | ||
2870 | * XXX: Didn't find this in 5210 code but since this register | ||
2871 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
2872 | */ | ||
2873 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
2874 | (state->bs_sleep_duration - 3) << 3); | ||
2875 | |||
2876 | /* | ||
2877 | * Set enhanced sleep registers on 5212 | ||
2878 | */ | ||
2879 | if (ah->ah_version == AR5K_AR5212) { | ||
2880 | if (state->bs_sleep_duration > state->bs_interval && | ||
2881 | roundup(state->bs_sleep_duration, interval) == | ||
2882 | state->bs_sleep_duration) | ||
2883 | interval = state->bs_sleep_duration; | ||
2884 | |||
2885 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
2886 | roundup(state->bs_sleep_duration, dtim) == | ||
2887 | state->bs_sleep_duration)) | ||
2888 | dtim = state->bs_sleep_duration; | ||
2889 | |||
2890 | if (interval > dtim) | ||
2891 | return -EINVAL; | ||
2892 | |||
2893 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
2894 | state->bs_next_beacon; | ||
2895 | |||
2896 | ath5k_hw_reg_write(ah, | ||
2897 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
2898 | AR5K_SLEEP0_NEXT_DTIM) | | ||
2899 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
2900 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
2901 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
2902 | |||
2903 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
2904 | AR5K_SLEEP1_NEXT_TIM) | | ||
2905 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
2906 | |||
2907 | ath5k_hw_reg_write(ah, | ||
2908 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
2909 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
2910 | } | ||
2911 | |||
2912 | return 0; | ||
2913 | } | ||
2914 | |||
2915 | /* | ||
2916 | * Reset beacon timers | ||
2917 | */ | ||
2918 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
2919 | { | ||
2920 | ATH5K_TRACE(ah->ah_sc); | ||
2921 | /* | ||
2922 | * Disable beacon timer | ||
2923 | */ | ||
2924 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
2925 | |||
2926 | /* | ||
2927 | * Disable some beacon register values | ||
2928 | */ | ||
2929 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
2930 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
2931 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
2932 | } | ||
2933 | |||
2934 | /* | ||
2935 | * Wait for beacon queue to finish | ||
2936 | */ | ||
2937 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
2938 | { | ||
2939 | unsigned int i; | ||
2940 | int ret; | ||
2941 | |||
2942 | ATH5K_TRACE(ah->ah_sc); | ||
2943 | |||
2944 | /* 5210 doesn't have QCU*/ | ||
2945 | if (ah->ah_version == AR5K_AR5210) { | ||
2946 | /* | ||
2947 | * Wait for beaconn queue to finish by checking | ||
2948 | * Control Register and Beacon Status Register. | ||
2949 | */ | ||
2950 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
2951 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
2952 | || | ||
2953 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
2954 | break; | ||
2955 | udelay(10); | ||
2956 | } | ||
2957 | |||
2958 | /* Timeout... */ | ||
2959 | if (i <= 0) { | ||
2960 | /* | ||
2961 | * Re-schedule the beacon queue | ||
2962 | */ | ||
2963 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
2964 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
2965 | AR5K_BCR); | ||
2966 | |||
2967 | return -EIO; | ||
2968 | } | ||
2969 | ret = 0; | ||
2970 | } else { | ||
2971 | /*5211/5212*/ | ||
2972 | ret = ath5k_hw_register_timeout(ah, | ||
2973 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
2974 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
2975 | |||
2976 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
2977 | return -EIO; | ||
2978 | } | ||
2979 | |||
2980 | return ret; | ||
2981 | } | ||
2982 | #endif | ||
2983 | |||
2984 | /* | ||
2985 | * Update mib counters (statistics) | ||
2986 | */ | ||
2987 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | ||
2988 | struct ieee80211_low_level_stats *stats) | ||
2989 | { | ||
2990 | ATH5K_TRACE(ah->ah_sc); | ||
2991 | |||
2992 | /* Read-And-Clear */ | ||
2993 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | ||
2994 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | ||
2995 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | ||
2996 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | ||
2997 | |||
2998 | /* XXX: Should we use this to track beacon count ? | ||
2999 | * -we read it anyway to clear the register */ | ||
3000 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
3001 | |||
3002 | /* Reset profile count registers on 5212*/ | ||
3003 | if (ah->ah_version == AR5K_AR5212) { | ||
3004 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
3005 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
3006 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
3007 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
3008 | } | ||
3009 | } | ||
3010 | |||
3011 | /** ath5k_hw_set_ack_bitrate - set bitrate for ACKs | ||
3012 | * | ||
3013 | * @ah: the &struct ath5k_hw | ||
3014 | * @high: determines if to use low bit rate or now | ||
3015 | */ | ||
3016 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | ||
3017 | { | ||
3018 | if (ah->ah_version != AR5K_AR5212) | ||
3019 | return; | ||
3020 | else { | ||
3021 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | ||
3022 | if (high) | ||
3023 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
3024 | else | ||
3025 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | ||
3026 | } | ||
3027 | } | ||
3028 | |||
3029 | |||
3030 | /* | ||
3031 | * ACK/CTS Timeouts | ||
3032 | */ | ||
3033 | |||
3034 | /* | ||
3035 | * Set ACK timeout on PCU | ||
3036 | */ | ||
3037 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
3038 | { | ||
3039 | ATH5K_TRACE(ah->ah_sc); | ||
3040 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | ||
3041 | ah->ah_turbo) <= timeout) | ||
3042 | return -EINVAL; | ||
3043 | |||
3044 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | ||
3045 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
3046 | |||
3047 | return 0; | ||
3048 | } | ||
3049 | |||
3050 | /* | ||
3051 | * Read the ACK timeout from PCU | ||
3052 | */ | ||
3053 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
3054 | { | ||
3055 | ATH5K_TRACE(ah->ah_sc); | ||
3056 | |||
3057 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
3058 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | ||
3059 | } | ||
3060 | |||
3061 | /* | ||
3062 | * Set CTS timeout on PCU | ||
3063 | */ | ||
3064 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
3065 | { | ||
3066 | ATH5K_TRACE(ah->ah_sc); | ||
3067 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | ||
3068 | ah->ah_turbo) <= timeout) | ||
3069 | return -EINVAL; | ||
3070 | |||
3071 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | ||
3072 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
3073 | |||
3074 | return 0; | ||
3075 | } | ||
3076 | |||
3077 | /* | ||
3078 | * Read CTS timeout from PCU | ||
3079 | */ | ||
3080 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
3081 | { | ||
3082 | ATH5K_TRACE(ah->ah_sc); | ||
3083 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
3084 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | ||
3085 | } | ||
3086 | |||
3087 | /* | ||
3088 | * Key table (WEP) functions | ||
3089 | */ | ||
3090 | |||
3091 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | ||
3092 | { | ||
3093 | unsigned int i; | ||
3094 | |||
3095 | ATH5K_TRACE(ah->ah_sc); | ||
3096 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
3097 | |||
3098 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | ||
3099 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | ||
3100 | |||
3101 | /* | ||
3102 | * Set NULL encryption on AR5212+ | ||
3103 | * | ||
3104 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | ||
3105 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | ||
3106 | * | ||
3107 | * Note2: Windows driver (ndiswrapper) sets this to | ||
3108 | * 0x00000714 instead of 0x00000007 | ||
3109 | */ | ||
3110 | if (ah->ah_version > AR5K_AR5211) | ||
3111 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
3112 | AR5K_KEYTABLE_TYPE(entry)); | ||
3113 | |||
3114 | return 0; | ||
3115 | } | ||
3116 | |||
3117 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
3118 | { | ||
3119 | ATH5K_TRACE(ah->ah_sc); | ||
3120 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
3121 | |||
3122 | /* Check the validation flag at the end of the entry */ | ||
3123 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
3124 | AR5K_KEYTABLE_VALID; | ||
3125 | } | ||
3126 | |||
3127 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
3128 | const struct ieee80211_key_conf *key, const u8 *mac) | ||
3129 | { | ||
3130 | unsigned int i; | ||
3131 | __le32 key_v[5] = {}; | ||
3132 | u32 keytype; | ||
3133 | |||
3134 | ATH5K_TRACE(ah->ah_sc); | ||
3135 | |||
3136 | /* key->keylen comes in from mac80211 in bytes */ | ||
3137 | |||
3138 | if (key->keylen > AR5K_KEYTABLE_SIZE / 8) | ||
3139 | return -EOPNOTSUPP; | ||
3140 | |||
3141 | switch (key->keylen) { | ||
3142 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */ | ||
3143 | case 40 / 8: | ||
3144 | memcpy(&key_v[0], key->key, 5); | ||
3145 | keytype = AR5K_KEYTABLE_TYPE_40; | ||
3146 | break; | ||
3147 | |||
3148 | /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */ | ||
3149 | case 104 / 8: | ||
3150 | memcpy(&key_v[0], &key->key[0], 6); | ||
3151 | memcpy(&key_v[2], &key->key[6], 6); | ||
3152 | memcpy(&key_v[4], &key->key[12], 1); | ||
3153 | keytype = AR5K_KEYTABLE_TYPE_104; | ||
3154 | break; | ||
3155 | /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */ | ||
3156 | case 128 / 8: | ||
3157 | memcpy(&key_v[0], &key->key[0], 6); | ||
3158 | memcpy(&key_v[2], &key->key[6], 6); | ||
3159 | memcpy(&key_v[4], &key->key[12], 4); | ||
3160 | keytype = AR5K_KEYTABLE_TYPE_128; | ||
3161 | break; | ||
3162 | |||
3163 | default: | ||
3164 | return -EINVAL; /* shouldn't happen */ | ||
3165 | } | ||
3166 | |||
3167 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
3168 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
3169 | AR5K_KEYTABLE_OFF(entry, i)); | ||
3170 | |||
3171 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | ||
3172 | |||
3173 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | ||
3174 | } | ||
3175 | |||
3176 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | ||
3177 | { | ||
3178 | u32 low_id, high_id; | ||
3179 | |||
3180 | ATH5K_TRACE(ah->ah_sc); | ||
3181 | /* Invalid entry (key table overflow) */ | ||
3182 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
3183 | |||
3184 | /* MAC may be NULL if it's a broadcast key. In this case no need to | ||
3185 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | ||
3186 | if (unlikely(mac == NULL)) { | ||
3187 | low_id = 0xffffffff; | ||
3188 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | ||
3189 | } else { | ||
3190 | low_id = AR5K_LOW_ID(mac); | ||
3191 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | ||
3192 | } | ||
3193 | |||
3194 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | ||
3195 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | ||
3196 | |||
3197 | return 0; | ||
3198 | } | ||
3199 | |||
3200 | |||
3201 | /********************************************\ | ||
3202 | Queue Control Unit, DFS Control Unit Functions | ||
3203 | \********************************************/ | ||
3204 | |||
3205 | /* | ||
3206 | * Initialize a transmit queue | ||
3207 | */ | ||
3208 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | ||
3209 | struct ath5k_txq_info *queue_info) | ||
3210 | { | ||
3211 | unsigned int queue; | ||
3212 | int ret; | ||
3213 | |||
3214 | ATH5K_TRACE(ah->ah_sc); | ||
3215 | |||
3216 | /* | ||
3217 | * Get queue by type | ||
3218 | */ | ||
3219 | /*5210 only has 2 queues*/ | ||
3220 | if (ah->ah_version == AR5K_AR5210) { | ||
3221 | switch (queue_type) { | ||
3222 | case AR5K_TX_QUEUE_DATA: | ||
3223 | queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; | ||
3224 | break; | ||
3225 | case AR5K_TX_QUEUE_BEACON: | ||
3226 | case AR5K_TX_QUEUE_CAB: | ||
3227 | queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; | ||
3228 | break; | ||
3229 | default: | ||
3230 | return -EINVAL; | ||
3231 | } | ||
3232 | } else { | ||
3233 | switch (queue_type) { | ||
3234 | case AR5K_TX_QUEUE_DATA: | ||
3235 | for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; | ||
3236 | ah->ah_txq[queue].tqi_type != | ||
3237 | AR5K_TX_QUEUE_INACTIVE; queue++) { | ||
3238 | |||
3239 | if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) | ||
3240 | return -EINVAL; | ||
3241 | } | ||
3242 | break; | ||
3243 | case AR5K_TX_QUEUE_UAPSD: | ||
3244 | queue = AR5K_TX_QUEUE_ID_UAPSD; | ||
3245 | break; | ||
3246 | case AR5K_TX_QUEUE_BEACON: | ||
3247 | queue = AR5K_TX_QUEUE_ID_BEACON; | ||
3248 | break; | ||
3249 | case AR5K_TX_QUEUE_CAB: | ||
3250 | queue = AR5K_TX_QUEUE_ID_CAB; | ||
3251 | break; | ||
3252 | case AR5K_TX_QUEUE_XR_DATA: | ||
3253 | if (ah->ah_version != AR5K_AR5212) | ||
3254 | ATH5K_ERR(ah->ah_sc, | ||
3255 | "XR data queues only supported in" | ||
3256 | " 5212!\n"); | ||
3257 | queue = AR5K_TX_QUEUE_ID_XR_DATA; | ||
3258 | break; | ||
3259 | default: | ||
3260 | return -EINVAL; | ||
3261 | } | ||
3262 | } | ||
3263 | |||
3264 | /* | ||
3265 | * Setup internal queue structure | ||
3266 | */ | ||
3267 | memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); | ||
3268 | ah->ah_txq[queue].tqi_type = queue_type; | ||
3269 | |||
3270 | if (queue_info != NULL) { | ||
3271 | queue_info->tqi_type = queue_type; | ||
3272 | ret = ath5k_hw_setup_tx_queueprops(ah, queue, queue_info); | ||
3273 | if (ret) | ||
3274 | return ret; | ||
3275 | } | ||
3276 | /* | ||
3277 | * We use ah_txq_status to hold a temp value for | ||
3278 | * the Secondary interrupt mask registers on 5211+ | ||
3279 | * check out ath5k_hw_reset_tx_queue | ||
3280 | */ | ||
3281 | AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); | ||
3282 | |||
3283 | return queue; | ||
3284 | } | ||
3285 | |||
3286 | /* | ||
3287 | * Setup a transmit queue | ||
3288 | */ | ||
3289 | int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
3290 | const struct ath5k_txq_info *queue_info) | ||
3291 | { | ||
3292 | ATH5K_TRACE(ah->ah_sc); | ||
3293 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3294 | |||
3295 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3296 | return -EIO; | ||
3297 | |||
3298 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | ||
3299 | |||
3300 | /*XXX: Is this supported on 5210 ?*/ | ||
3301 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | ||
3302 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | ||
3303 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | ||
3304 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | ||
3305 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
3306 | |||
3307 | return 0; | ||
3308 | } | ||
3309 | |||
3310 | /* | ||
3311 | * Get properties for a specific transmit queue | ||
3312 | */ | ||
3313 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
3314 | struct ath5k_txq_info *queue_info) | ||
3315 | { | ||
3316 | ATH5K_TRACE(ah->ah_sc); | ||
3317 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | ||
3318 | return 0; | ||
3319 | } | ||
3320 | |||
3321 | /* | ||
3322 | * Set a transmit queue inactive | ||
3323 | */ | ||
3324 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
3325 | { | ||
3326 | ATH5K_TRACE(ah->ah_sc); | ||
3327 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
3328 | return; | ||
3329 | |||
3330 | /* This queue will be skipped in further operations */ | ||
3331 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | ||
3332 | /*For SIMR setup*/ | ||
3333 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
3334 | } | ||
3335 | |||
3336 | /* | ||
3337 | * Set DFS params for a transmit queue | ||
3338 | */ | ||
3339 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
3340 | { | ||
3341 | u32 cw_min, cw_max, retry_lg, retry_sh; | ||
3342 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | ||
3343 | |||
3344 | ATH5K_TRACE(ah->ah_sc); | ||
3345 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3346 | |||
3347 | tq = &ah->ah_txq[queue]; | ||
3348 | |||
3349 | if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3350 | return 0; | ||
3351 | |||
3352 | if (ah->ah_version == AR5K_AR5210) { | ||
3353 | /* Only handle data queues, others will be ignored */ | ||
3354 | if (tq->tqi_type != AR5K_TX_QUEUE_DATA) | ||
3355 | return 0; | ||
3356 | |||
3357 | /* Set Slot time */ | ||
3358 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3359 | AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, | ||
3360 | AR5K_SLOT_TIME); | ||
3361 | /* Set ACK_CTS timeout */ | ||
3362 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3363 | AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : | ||
3364 | AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); | ||
3365 | /* Set Transmit Latency */ | ||
3366 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3367 | AR5K_INIT_TRANSMIT_LATENCY_TURBO : | ||
3368 | AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); | ||
3369 | /* Set IFS0 */ | ||
3370 | if (ah->ah_turbo) | ||
3371 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | ||
3372 | (ah->ah_aifs + tq->tqi_aifs) * | ||
3373 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
3374 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | ||
3375 | AR5K_IFS0); | ||
3376 | else | ||
3377 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | ||
3378 | (ah->ah_aifs + tq->tqi_aifs) * | ||
3379 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | ||
3380 | AR5K_INIT_SIFS, AR5K_IFS0); | ||
3381 | |||
3382 | /* Set IFS1 */ | ||
3383 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3384 | AR5K_INIT_PROTO_TIME_CNTRL_TURBO : | ||
3385 | AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); | ||
3386 | /* Set AR5K_PHY_SETTLING */ | ||
3387 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3388 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
3389 | | 0x38 : | ||
3390 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
3391 | | 0x1C, | ||
3392 | AR5K_PHY_SETTLING); | ||
3393 | /* Set Frame Control Register */ | ||
3394 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
3395 | (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | | ||
3396 | AR5K_PHY_TURBO_SHORT | 0x2020) : | ||
3397 | (AR5K_PHY_FRAME_CTL_INI | 0x1020), | ||
3398 | AR5K_PHY_FRAME_CTL_5210); | ||
3399 | } | ||
3400 | |||
3401 | /* | ||
3402 | * Calculate cwmin/max by channel mode | ||
3403 | */ | ||
3404 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
3405 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | ||
3406 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
3407 | /*XR is only supported on 5212*/ | ||
3408 | if (IS_CHAN_XR(ah->ah_current_channel) && | ||
3409 | ah->ah_version == AR5K_AR5212) { | ||
3410 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
3411 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
3412 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
3413 | /*B mode is not supported on 5210*/ | ||
3414 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
3415 | ah->ah_version != AR5K_AR5210) { | ||
3416 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
3417 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
3418 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
3419 | } | ||
3420 | |||
3421 | cw_min = 1; | ||
3422 | while (cw_min < ah->ah_cw_min) | ||
3423 | cw_min = (cw_min << 1) | 1; | ||
3424 | |||
3425 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
3426 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
3427 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
3428 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
3429 | |||
3430 | /* | ||
3431 | * Calculate and set retry limits | ||
3432 | */ | ||
3433 | if (ah->ah_software_retry) { | ||
3434 | /* XXX Need to test this */ | ||
3435 | retry_lg = ah->ah_limit_tx_retries; | ||
3436 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? | ||
3437 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; | ||
3438 | } else { | ||
3439 | retry_lg = AR5K_INIT_LG_RETRY; | ||
3440 | retry_sh = AR5K_INIT_SH_RETRY; | ||
3441 | } | ||
3442 | |||
3443 | /*No QCU/DCU [5210]*/ | ||
3444 | if (ah->ah_version == AR5K_AR5210) { | ||
3445 | ath5k_hw_reg_write(ah, | ||
3446 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | ||
3447 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
3448 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | ||
3449 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
3450 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | ||
3451 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | ||
3452 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
3453 | AR5K_NODCU_RETRY_LMT); | ||
3454 | } else { | ||
3455 | /*QCU/DCU [5211+]*/ | ||
3456 | ath5k_hw_reg_write(ah, | ||
3457 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
3458 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | | ||
3459 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
3460 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | | ||
3461 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | | ||
3462 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), | ||
3463 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | ||
3464 | |||
3465 | /*===Rest is also for QCU/DCU only [5211+]===*/ | ||
3466 | |||
3467 | /* | ||
3468 | * Set initial content window (cw_min/cw_max) | ||
3469 | * and arbitrated interframe space (aifs)... | ||
3470 | */ | ||
3471 | ath5k_hw_reg_write(ah, | ||
3472 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | ||
3473 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | ||
3474 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | ||
3475 | AR5K_DCU_LCL_IFS_AIFS), | ||
3476 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | ||
3477 | |||
3478 | /* | ||
3479 | * Set misc registers | ||
3480 | */ | ||
3481 | ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, | ||
3482 | AR5K_QUEUE_MISC(queue)); | ||
3483 | |||
3484 | if (tq->tqi_cbr_period) { | ||
3485 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | ||
3486 | AR5K_QCU_CBRCFG_INTVAL) | | ||
3487 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, | ||
3488 | AR5K_QCU_CBRCFG_ORN_THRES), | ||
3489 | AR5K_QUEUE_CBRCFG(queue)); | ||
3490 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3491 | AR5K_QCU_MISC_FRSHED_CBR); | ||
3492 | if (tq->tqi_cbr_overflow_limit) | ||
3493 | AR5K_REG_ENABLE_BITS(ah, | ||
3494 | AR5K_QUEUE_MISC(queue), | ||
3495 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | ||
3496 | } | ||
3497 | |||
3498 | if (tq->tqi_ready_time) | ||
3499 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | ||
3500 | AR5K_QCU_RDYTIMECFG_INTVAL) | | ||
3501 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
3502 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
3503 | |||
3504 | if (tq->tqi_burst_time) { | ||
3505 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, | ||
3506 | AR5K_DCU_CHAN_TIME_DUR) | | ||
3507 | AR5K_DCU_CHAN_TIME_ENABLE, | ||
3508 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); | ||
3509 | |||
3510 | if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) | ||
3511 | AR5K_REG_ENABLE_BITS(ah, | ||
3512 | AR5K_QUEUE_MISC(queue), | ||
3513 | AR5K_QCU_MISC_RDY_VEOL_POLICY); | ||
3514 | } | ||
3515 | |||
3516 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) | ||
3517 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, | ||
3518 | AR5K_QUEUE_DFS_MISC(queue)); | ||
3519 | |||
3520 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) | ||
3521 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, | ||
3522 | AR5K_QUEUE_DFS_MISC(queue)); | ||
3523 | |||
3524 | /* | ||
3525 | * Set registers by queue type | ||
3526 | */ | ||
3527 | switch (tq->tqi_type) { | ||
3528 | case AR5K_TX_QUEUE_BEACON: | ||
3529 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3530 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
3531 | AR5K_QCU_MISC_CBREXP_BCN | | ||
3532 | AR5K_QCU_MISC_BCN_ENABLE); | ||
3533 | |||
3534 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
3535 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
3536 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | ||
3537 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | ||
3538 | AR5K_DCU_MISC_BCN_ENABLE); | ||
3539 | |||
3540 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
3541 | (AR5K_TUNE_SW_BEACON_RESP - | ||
3542 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
3543 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
3544 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
3545 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
3546 | break; | ||
3547 | |||
3548 | case AR5K_TX_QUEUE_CAB: | ||
3549 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3550 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
3551 | AR5K_QCU_MISC_CBREXP | | ||
3552 | AR5K_QCU_MISC_CBREXP_BCN); | ||
3553 | |||
3554 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
3555 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
3556 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | ||
3557 | break; | ||
3558 | |||
3559 | case AR5K_TX_QUEUE_UAPSD: | ||
3560 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3561 | AR5K_QCU_MISC_CBREXP); | ||
3562 | break; | ||
3563 | |||
3564 | case AR5K_TX_QUEUE_DATA: | ||
3565 | default: | ||
3566 | break; | ||
3567 | } | ||
3568 | |||
3569 | /* | ||
3570 | * Enable interrupts for this tx queue | ||
3571 | * in the secondary interrupt mask registers | ||
3572 | */ | ||
3573 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) | ||
3574 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); | ||
3575 | |||
3576 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) | ||
3577 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); | ||
3578 | |||
3579 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) | ||
3580 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); | ||
3581 | |||
3582 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) | ||
3583 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); | ||
3584 | |||
3585 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) | ||
3586 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); | ||
3587 | |||
3588 | |||
3589 | /* Update secondary interrupt mask registers */ | ||
3590 | ah->ah_txq_imr_txok &= ah->ah_txq_status; | ||
3591 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; | ||
3592 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; | ||
3593 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; | ||
3594 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; | ||
3595 | |||
3596 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, | ||
3597 | AR5K_SIMR0_QCU_TXOK) | | ||
3598 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, | ||
3599 | AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); | ||
3600 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, | ||
3601 | AR5K_SIMR1_QCU_TXERR) | | ||
3602 | AR5K_REG_SM(ah->ah_txq_imr_txeol, | ||
3603 | AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); | ||
3604 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn, | ||
3605 | AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2); | ||
3606 | } | ||
3607 | |||
3608 | return 0; | ||
3609 | } | ||
3610 | |||
3611 | /* | ||
3612 | * Get number of pending frames | ||
3613 | * for a specific queue [5211+] | ||
3614 | */ | ||
3615 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { | ||
3616 | ATH5K_TRACE(ah->ah_sc); | ||
3617 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3618 | |||
3619 | /* Return if queue is declared inactive */ | ||
3620 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3621 | return false; | ||
3622 | |||
3623 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
3624 | if (ah->ah_version == AR5K_AR5210) | ||
3625 | return false; | ||
3626 | |||
3627 | return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; | ||
3628 | } | ||
3629 | |||
3630 | /* | ||
3631 | * Set slot time | ||
3632 | */ | ||
3633 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | ||
3634 | { | ||
3635 | ATH5K_TRACE(ah->ah_sc); | ||
3636 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | ||
3637 | return -EINVAL; | ||
3638 | |||
3639 | if (ah->ah_version == AR5K_AR5210) | ||
3640 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | ||
3641 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
3642 | else | ||
3643 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | ||
3644 | |||
3645 | return 0; | ||
3646 | } | ||
3647 | |||
3648 | /* | ||
3649 | * Get slot time | ||
3650 | */ | ||
3651 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | ||
3652 | { | ||
3653 | ATH5K_TRACE(ah->ah_sc); | ||
3654 | if (ah->ah_version == AR5K_AR5210) | ||
3655 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | ||
3656 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
3657 | else | ||
3658 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | ||
3659 | } | ||
3660 | |||
3661 | |||
3662 | /******************************\ | ||
3663 | Hardware Descriptor Functions | ||
3664 | \******************************/ | ||
3665 | |||
3666 | /* | ||
3667 | * TX Descriptor | ||
3668 | */ | ||
3669 | |||
3670 | /* | ||
3671 | * Initialize the 2-word tx descriptor on 5210/5211 | ||
3672 | */ | ||
3673 | static int | ||
3674 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
3675 | unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, | ||
3676 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | ||
3677 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | ||
3678 | unsigned int rtscts_rate, unsigned int rtscts_duration) | ||
3679 | { | ||
3680 | u32 frame_type; | ||
3681 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
3682 | unsigned int frame_len; | ||
3683 | |||
3684 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
3685 | |||
3686 | /* | ||
3687 | * Validate input | ||
3688 | * - Zero retries don't make sense. | ||
3689 | * - A zero rate will put the HW into a mode where it continously sends | ||
3690 | * noise on the channel, so it is important to avoid this. | ||
3691 | */ | ||
3692 | if (unlikely(tx_tries0 == 0)) { | ||
3693 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
3694 | WARN_ON(1); | ||
3695 | return -EINVAL; | ||
3696 | } | ||
3697 | if (unlikely(tx_rate0 == 0)) { | ||
3698 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3699 | WARN_ON(1); | ||
3700 | return -EINVAL; | ||
3701 | } | ||
3702 | |||
3703 | /* Clear descriptor */ | ||
3704 | memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); | ||
3705 | |||
3706 | /* Setup control descriptor */ | ||
3707 | |||
3708 | /* Verify and set frame length */ | ||
3709 | |||
3710 | /* remove padding we might have added before */ | ||
3711 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | ||
3712 | |||
3713 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | ||
3714 | return -EINVAL; | ||
3715 | |||
3716 | tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; | ||
3717 | |||
3718 | /* Verify and set buffer length */ | ||
3719 | |||
3720 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
3721 | if(type == AR5K_PKT_TYPE_BEACON) | ||
3722 | pkt_len = roundup(pkt_len, 4); | ||
3723 | |||
3724 | if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) | ||
3725 | return -EINVAL; | ||
3726 | |||
3727 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | ||
3728 | |||
3729 | /* | ||
3730 | * Verify and set header length | ||
3731 | * XXX: I only found that on 5210 code, does it work on 5211 ? | ||
3732 | */ | ||
3733 | if (ah->ah_version == AR5K_AR5210) { | ||
3734 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | ||
3735 | return -EINVAL; | ||
3736 | tx_ctl->tx_control_0 |= | ||
3737 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | ||
3738 | } | ||
3739 | |||
3740 | /*Diferences between 5210-5211*/ | ||
3741 | if (ah->ah_version == AR5K_AR5210) { | ||
3742 | switch (type) { | ||
3743 | case AR5K_PKT_TYPE_BEACON: | ||
3744 | case AR5K_PKT_TYPE_PROBE_RESP: | ||
3745 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; | ||
3746 | case AR5K_PKT_TYPE_PIFS: | ||
3747 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | ||
3748 | default: | ||
3749 | frame_type = type /*<< 2 ?*/; | ||
3750 | } | ||
3751 | |||
3752 | tx_ctl->tx_control_0 |= | ||
3753 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | ||
3754 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
3755 | } else { | ||
3756 | tx_ctl->tx_control_0 |= | ||
3757 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | | ||
3758 | AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
3759 | tx_ctl->tx_control_1 |= | ||
3760 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | ||
3761 | } | ||
3762 | #define _TX_FLAGS(_c, _flag) \ | ||
3763 | if (flags & AR5K_TXDESC_##_flag) \ | ||
3764 | tx_ctl->tx_control_##_c |= \ | ||
3765 | AR5K_2W_TX_DESC_CTL##_c##_##_flag | ||
3766 | |||
3767 | _TX_FLAGS(0, CLRDMASK); | ||
3768 | _TX_FLAGS(0, VEOL); | ||
3769 | _TX_FLAGS(0, INTREQ); | ||
3770 | _TX_FLAGS(0, RTSENA); | ||
3771 | _TX_FLAGS(1, NOACK); | ||
3772 | |||
3773 | #undef _TX_FLAGS | ||
3774 | |||
3775 | /* | ||
3776 | * WEP crap | ||
3777 | */ | ||
3778 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
3779 | tx_ctl->tx_control_0 |= | ||
3780 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
3781 | tx_ctl->tx_control_1 |= | ||
3782 | AR5K_REG_SM(key_index, | ||
3783 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
3784 | } | ||
3785 | |||
3786 | /* | ||
3787 | * RTS/CTS Duration [5210 ?] | ||
3788 | */ | ||
3789 | if ((ah->ah_version == AR5K_AR5210) && | ||
3790 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | ||
3791 | tx_ctl->tx_control_1 |= rtscts_duration & | ||
3792 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | ||
3793 | |||
3794 | return 0; | ||
3795 | } | ||
3796 | |||
3797 | /* | ||
3798 | * Initialize the 4-word tx descriptor on 5212 | ||
3799 | */ | ||
3800 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | ||
3801 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | ||
3802 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | ||
3803 | unsigned int tx_tries0, unsigned int key_index, | ||
3804 | unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, | ||
3805 | unsigned int rtscts_duration) | ||
3806 | { | ||
3807 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
3808 | unsigned int frame_len; | ||
3809 | |||
3810 | ATH5K_TRACE(ah->ah_sc); | ||
3811 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
3812 | |||
3813 | /* | ||
3814 | * Validate input | ||
3815 | * - Zero retries don't make sense. | ||
3816 | * - A zero rate will put the HW into a mode where it continously sends | ||
3817 | * noise on the channel, so it is important to avoid this. | ||
3818 | */ | ||
3819 | if (unlikely(tx_tries0 == 0)) { | ||
3820 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
3821 | WARN_ON(1); | ||
3822 | return -EINVAL; | ||
3823 | } | ||
3824 | if (unlikely(tx_rate0 == 0)) { | ||
3825 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3826 | WARN_ON(1); | ||
3827 | return -EINVAL; | ||
3828 | } | ||
3829 | |||
3830 | /* Clear descriptor */ | ||
3831 | memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); | ||
3832 | |||
3833 | /* Setup control descriptor */ | ||
3834 | |||
3835 | /* Verify and set frame length */ | ||
3836 | |||
3837 | /* remove padding we might have added before */ | ||
3838 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | ||
3839 | |||
3840 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | ||
3841 | return -EINVAL; | ||
3842 | |||
3843 | tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | ||
3844 | |||
3845 | /* Verify and set buffer length */ | ||
3846 | |||
3847 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
3848 | if(type == AR5K_PKT_TYPE_BEACON) | ||
3849 | pkt_len = roundup(pkt_len, 4); | ||
3850 | |||
3851 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | ||
3852 | return -EINVAL; | ||
3853 | |||
3854 | tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | ||
3855 | |||
3856 | tx_ctl->tx_control_0 |= | ||
3857 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | ||
3858 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
3859 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | ||
3860 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | ||
3861 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | ||
3862 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | ||
3863 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
3864 | |||
3865 | #define _TX_FLAGS(_c, _flag) \ | ||
3866 | if (flags & AR5K_TXDESC_##_flag) \ | ||
3867 | tx_ctl->tx_control_##_c |= \ | ||
3868 | AR5K_4W_TX_DESC_CTL##_c##_##_flag | ||
3869 | |||
3870 | _TX_FLAGS(0, CLRDMASK); | ||
3871 | _TX_FLAGS(0, VEOL); | ||
3872 | _TX_FLAGS(0, INTREQ); | ||
3873 | _TX_FLAGS(0, RTSENA); | ||
3874 | _TX_FLAGS(0, CTSENA); | ||
3875 | _TX_FLAGS(1, NOACK); | ||
3876 | |||
3877 | #undef _TX_FLAGS | ||
3878 | |||
3879 | /* | ||
3880 | * WEP crap | ||
3881 | */ | ||
3882 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
3883 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
3884 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | ||
3885 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
3886 | } | ||
3887 | |||
3888 | /* | ||
3889 | * RTS/CTS | ||
3890 | */ | ||
3891 | if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { | ||
3892 | if ((flags & AR5K_TXDESC_RTSENA) && | ||
3893 | (flags & AR5K_TXDESC_CTSENA)) | ||
3894 | return -EINVAL; | ||
3895 | tx_ctl->tx_control_2 |= rtscts_duration & | ||
3896 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | ||
3897 | tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | ||
3898 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | ||
3899 | } | ||
3900 | |||
3901 | return 0; | ||
3902 | } | ||
3903 | |||
3904 | /* | ||
3905 | * Initialize a 4-word multirate tx descriptor on 5212 | ||
3906 | */ | ||
3907 | static int | ||
3908 | ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
3909 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, | ||
3910 | unsigned int tx_rate3, u_int tx_tries3) | ||
3911 | { | ||
3912 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
3913 | |||
3914 | /* | ||
3915 | * Rates can be 0 as long as the retry count is 0 too. | ||
3916 | * A zero rate and nonzero retry count will put the HW into a mode where | ||
3917 | * it continously sends noise on the channel, so it is important to | ||
3918 | * avoid this. | ||
3919 | */ | ||
3920 | if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || | ||
3921 | (tx_rate2 == 0 && tx_tries2 != 0) || | ||
3922 | (tx_rate3 == 0 && tx_tries3 != 0))) { | ||
3923 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3924 | WARN_ON(1); | ||
3925 | return -EINVAL; | ||
3926 | } | ||
3927 | |||
3928 | if (ah->ah_version == AR5K_AR5212) { | ||
3929 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
3930 | |||
3931 | #define _XTX_TRIES(_n) \ | ||
3932 | if (tx_tries##_n) { \ | ||
3933 | tx_ctl->tx_control_2 |= \ | ||
3934 | AR5K_REG_SM(tx_tries##_n, \ | ||
3935 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ | ||
3936 | tx_ctl->tx_control_3 |= \ | ||
3937 | AR5K_REG_SM(tx_rate##_n, \ | ||
3938 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ | ||
3939 | } | ||
3940 | |||
3941 | _XTX_TRIES(1); | ||
3942 | _XTX_TRIES(2); | ||
3943 | _XTX_TRIES(3); | ||
3944 | |||
3945 | #undef _XTX_TRIES | ||
3946 | |||
3947 | return 1; | ||
3948 | } | ||
3949 | |||
3950 | return 0; | ||
3951 | } | ||
3952 | |||
3953 | /* | ||
3954 | * Proccess the tx status descriptor on 5210/5211 | ||
3955 | */ | ||
3956 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | ||
3957 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | ||
3958 | { | ||
3959 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
3960 | struct ath5k_hw_tx_status *tx_status; | ||
3961 | |||
3962 | ATH5K_TRACE(ah->ah_sc); | ||
3963 | |||
3964 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
3965 | tx_status = &desc->ud.ds_tx5210.tx_stat; | ||
3966 | |||
3967 | /* No frame has been send or error */ | ||
3968 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | ||
3969 | return -EINPROGRESS; | ||
3970 | |||
3971 | /* | ||
3972 | * Get descriptor status | ||
3973 | */ | ||
3974 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
3975 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
3976 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3977 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
3978 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3979 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
3980 | /*TODO: ts->ts_virtcol + test*/ | ||
3981 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
3982 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
3983 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
3984 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
3985 | ts->ts_antenna = 1; | ||
3986 | ts->ts_status = 0; | ||
3987 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, | ||
3988 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
3989 | |||
3990 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | ||
3991 | if (tx_status->tx_status_0 & | ||
3992 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
3993 | ts->ts_status |= AR5K_TXERR_XRETRY; | ||
3994 | |||
3995 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
3996 | ts->ts_status |= AR5K_TXERR_FIFO; | ||
3997 | |||
3998 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
3999 | ts->ts_status |= AR5K_TXERR_FILT; | ||
4000 | } | ||
4001 | |||
4002 | return 0; | ||
4003 | } | ||
4004 | |||
4005 | /* | ||
4006 | * Proccess a tx descriptor on 5212 | ||
4007 | */ | ||
4008 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | ||
4009 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | ||
4010 | { | ||
4011 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
4012 | struct ath5k_hw_tx_status *tx_status; | ||
4013 | |||
4014 | ATH5K_TRACE(ah->ah_sc); | ||
4015 | |||
4016 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
4017 | tx_status = &desc->ud.ds_tx5212.tx_stat; | ||
4018 | |||
4019 | /* No frame has been send or error */ | ||
4020 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | ||
4021 | return -EINPROGRESS; | ||
4022 | |||
4023 | /* | ||
4024 | * Get descriptor status | ||
4025 | */ | ||
4026 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
4027 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
4028 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
4029 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
4030 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
4031 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
4032 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
4033 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
4034 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
4035 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
4036 | ts->ts_antenna = (tx_status->tx_status_1 & | ||
4037 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | ||
4038 | ts->ts_status = 0; | ||
4039 | |||
4040 | switch (AR5K_REG_MS(tx_status->tx_status_1, | ||
4041 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { | ||
4042 | case 0: | ||
4043 | ts->ts_rate = tx_ctl->tx_control_3 & | ||
4044 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
4045 | break; | ||
4046 | case 1: | ||
4047 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
4048 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | ||
4049 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
4050 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
4051 | break; | ||
4052 | case 2: | ||
4053 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
4054 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
4055 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
4056 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
4057 | break; | ||
4058 | case 3: | ||
4059 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
4060 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
4061 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
4062 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); | ||
4063 | break; | ||
4064 | } | ||
4065 | |||
4066 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | ||
4067 | if (tx_status->tx_status_0 & | ||
4068 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
4069 | ts->ts_status |= AR5K_TXERR_XRETRY; | ||
4070 | |||
4071 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
4072 | ts->ts_status |= AR5K_TXERR_FIFO; | ||
4073 | |||
4074 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
4075 | ts->ts_status |= AR5K_TXERR_FILT; | ||
4076 | } | ||
4077 | |||
4078 | return 0; | ||
4079 | } | ||
4080 | |||
4081 | /* | ||
4082 | * RX Descriptor | ||
4083 | */ | ||
4084 | |||
4085 | /* | ||
4086 | * Initialize an rx descriptor | ||
4087 | */ | ||
4088 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
4089 | u32 size, unsigned int flags) | ||
4090 | { | ||
4091 | struct ath5k_hw_rx_ctl *rx_ctl; | ||
4092 | |||
4093 | ATH5K_TRACE(ah->ah_sc); | ||
4094 | rx_ctl = &desc->ud.ds_rx.rx_ctl; | ||
4095 | |||
4096 | /* | ||
4097 | * Clear the descriptor | ||
4098 | * If we don't clean the status descriptor, | ||
4099 | * while scanning we get too many results, | ||
4100 | * most of them virtual, after some secs | ||
4101 | * of scanning system hangs. M.F. | ||
4102 | */ | ||
4103 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); | ||
4104 | |||
4105 | /* Setup descriptor */ | ||
4106 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | ||
4107 | if (unlikely(rx_ctl->rx_control_1 != size)) | ||
4108 | return -EINVAL; | ||
4109 | |||
4110 | if (flags & AR5K_RXDESC_INTREQ) | ||
4111 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | ||
4112 | |||
4113 | return 0; | ||
4114 | } | ||
4115 | |||
4116 | /* | ||
4117 | * Proccess the rx status descriptor on 5210/5211 | ||
4118 | */ | ||
4119 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | ||
4120 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | ||
4121 | { | ||
4122 | struct ath5k_hw_rx_status *rx_status; | ||
4123 | |||
4124 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
4125 | |||
4126 | /* No frame received / not ready */ | ||
4127 | if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE) | ||
4128 | == 0)) | ||
4129 | return -EINPROGRESS; | ||
4130 | |||
4131 | /* | ||
4132 | * Frame receive status | ||
4133 | */ | ||
4134 | rs->rs_datalen = rx_status->rx_status_0 & | ||
4135 | AR5K_5210_RX_DESC_STATUS0_DATA_LEN; | ||
4136 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
4137 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
4138 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
4139 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); | ||
4140 | rs->rs_antenna = rx_status->rx_status_0 & | ||
4141 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
4142 | rs->rs_more = rx_status->rx_status_0 & | ||
4143 | AR5K_5210_RX_DESC_STATUS0_MORE; | ||
4144 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ | ||
4145 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
4146 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
4147 | rs->rs_status = 0; | ||
4148 | rs->rs_phyerr = 0; | ||
4149 | |||
4150 | /* | ||
4151 | * Key table status | ||
4152 | */ | ||
4153 | if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
4154 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
4155 | AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); | ||
4156 | else | ||
4157 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | ||
4158 | |||
4159 | /* | ||
4160 | * Receive/descriptor errors | ||
4161 | */ | ||
4162 | if ((rx_status->rx_status_1 & | ||
4163 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { | ||
4164 | if (rx_status->rx_status_1 & | ||
4165 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) | ||
4166 | rs->rs_status |= AR5K_RXERR_CRC; | ||
4167 | |||
4168 | if (rx_status->rx_status_1 & | ||
4169 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) | ||
4170 | rs->rs_status |= AR5K_RXERR_FIFO; | ||
4171 | |||
4172 | if (rx_status->rx_status_1 & | ||
4173 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { | ||
4174 | rs->rs_status |= AR5K_RXERR_PHY; | ||
4175 | rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, | ||
4176 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); | ||
4177 | } | ||
4178 | |||
4179 | if (rx_status->rx_status_1 & | ||
4180 | AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
4181 | rs->rs_status |= AR5K_RXERR_DECRYPT; | ||
4182 | } | ||
4183 | |||
4184 | return 0; | ||
4185 | } | ||
4186 | |||
4187 | /* | ||
4188 | * Proccess the rx status descriptor on 5212 | ||
4189 | */ | ||
4190 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | ||
4191 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | ||
4192 | { | ||
4193 | struct ath5k_hw_rx_status *rx_status; | ||
4194 | struct ath5k_hw_rx_error *rx_err; | ||
4195 | |||
4196 | ATH5K_TRACE(ah->ah_sc); | ||
4197 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
4198 | |||
4199 | /* Overlay on error */ | ||
4200 | rx_err = &desc->ud.ds_rx.u.rx_err; | ||
4201 | |||
4202 | /* No frame received / not ready */ | ||
4203 | if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE) | ||
4204 | == 0)) | ||
4205 | return -EINPROGRESS; | ||
4206 | |||
4207 | /* | ||
4208 | * Frame receive status | ||
4209 | */ | ||
4210 | rs->rs_datalen = rx_status->rx_status_0 & | ||
4211 | AR5K_5212_RX_DESC_STATUS0_DATA_LEN; | ||
4212 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
4213 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
4214 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
4215 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); | ||
4216 | rs->rs_antenna = rx_status->rx_status_0 & | ||
4217 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
4218 | rs->rs_more = rx_status->rx_status_0 & | ||
4219 | AR5K_5212_RX_DESC_STATUS0_MORE; | ||
4220 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
4221 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
4222 | rs->rs_status = 0; | ||
4223 | rs->rs_phyerr = 0; | ||
4224 | |||
4225 | /* | ||
4226 | * Key table status | ||
4227 | */ | ||
4228 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
4229 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
4230 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | ||
4231 | else | ||
4232 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | ||
4233 | |||
4234 | /* | ||
4235 | * Receive/descriptor errors | ||
4236 | */ | ||
4237 | if ((rx_status->rx_status_1 & | ||
4238 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { | ||
4239 | if (rx_status->rx_status_1 & | ||
4240 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | ||
4241 | rs->rs_status |= AR5K_RXERR_CRC; | ||
4242 | |||
4243 | if (rx_status->rx_status_1 & | ||
4244 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | ||
4245 | rs->rs_status |= AR5K_RXERR_PHY; | ||
4246 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | ||
4247 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | ||
4248 | } | ||
4249 | |||
4250 | if (rx_status->rx_status_1 & | ||
4251 | AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
4252 | rs->rs_status |= AR5K_RXERR_DECRYPT; | ||
4253 | |||
4254 | if (rx_status->rx_status_1 & | ||
4255 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | ||
4256 | rs->rs_status |= AR5K_RXERR_MIC; | ||
4257 | } | ||
4258 | |||
4259 | return 0; | ||
4260 | } | ||
4261 | |||
4262 | |||
4263 | /****************\ | ||
4264 | GPIO Functions | ||
4265 | \****************/ | ||
4266 | |||
4267 | /* | ||
4268 | * Set led state | ||
4269 | */ | ||
4270 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | ||
4271 | { | ||
4272 | u32 led; | ||
4273 | /*5210 has different led mode handling*/ | ||
4274 | u32 led_5210; | ||
4275 | |||
4276 | ATH5K_TRACE(ah->ah_sc); | ||
4277 | |||
4278 | /*Reset led status*/ | ||
4279 | if (ah->ah_version != AR5K_AR5210) | ||
4280 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
4281 | AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); | ||
4282 | else | ||
4283 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); | ||
4284 | |||
4285 | /* | ||
4286 | * Some blinking values, define at your wish | ||
4287 | */ | ||
4288 | switch (state) { | ||
4289 | case AR5K_LED_SCAN: | ||
4290 | case AR5K_LED_AUTH: | ||
4291 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; | ||
4292 | led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; | ||
4293 | break; | ||
4294 | |||
4295 | case AR5K_LED_INIT: | ||
4296 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; | ||
4297 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
4298 | break; | ||
4299 | |||
4300 | case AR5K_LED_ASSOC: | ||
4301 | case AR5K_LED_RUN: | ||
4302 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; | ||
4303 | led_5210 = AR5K_PCICFG_LED_ASSOC; | ||
4304 | break; | ||
4305 | |||
4306 | default: | ||
4307 | led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; | ||
4308 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
4309 | break; | ||
4310 | } | ||
4311 | |||
4312 | /*Write new status to the register*/ | ||
4313 | if (ah->ah_version != AR5K_AR5210) | ||
4314 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); | ||
4315 | else | ||
4316 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); | ||
4317 | } | ||
4318 | |||
4319 | /* | ||
4320 | * Set GPIO outputs | ||
4321 | */ | ||
4322 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | ||
4323 | { | ||
4324 | ATH5K_TRACE(ah->ah_sc); | ||
4325 | if (gpio > AR5K_NUM_GPIO) | ||
4326 | return -EINVAL; | ||
4327 | |||
4328 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~ | ||
4329 | AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); | ||
4330 | |||
4331 | return 0; | ||
4332 | } | ||
4333 | |||
4334 | /* | ||
4335 | * Set GPIO inputs | ||
4336 | */ | ||
4337 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | ||
4338 | { | ||
4339 | ATH5K_TRACE(ah->ah_sc); | ||
4340 | if (gpio > AR5K_NUM_GPIO) | ||
4341 | return -EINVAL; | ||
4342 | |||
4343 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~ | ||
4344 | AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); | ||
4345 | |||
4346 | return 0; | ||
4347 | } | ||
4348 | |||
4349 | /* | ||
4350 | * Get GPIO state | ||
4351 | */ | ||
4352 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | ||
4353 | { | ||
4354 | ATH5K_TRACE(ah->ah_sc); | ||
4355 | if (gpio > AR5K_NUM_GPIO) | ||
4356 | return 0xffffffff; | ||
4357 | |||
4358 | /* GPIO input magic */ | ||
4359 | return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & | ||
4360 | 0x1; | ||
4361 | } | ||
4362 | |||
4363 | /* | ||
4364 | * Set GPIO state | ||
4365 | */ | ||
4366 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | ||
4367 | { | ||
4368 | u32 data; | ||
4369 | ATH5K_TRACE(ah->ah_sc); | ||
4370 | |||
4371 | if (gpio > AR5K_NUM_GPIO) | ||
4372 | return -EINVAL; | ||
4373 | |||
4374 | /* GPIO output magic */ | ||
4375 | data = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
4376 | |||
4377 | data &= ~(1 << gpio); | ||
4378 | data |= (val & 1) << gpio; | ||
4379 | |||
4380 | ath5k_hw_reg_write(ah, data, AR5K_GPIODO); | ||
4381 | |||
4382 | return 0; | ||
4383 | } | ||
4384 | |||
4385 | /* | ||
4386 | * Initialize the GPIO interrupt (RFKill switch) | ||
4387 | */ | ||
4388 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | ||
4389 | u32 interrupt_level) | ||
4390 | { | ||
4391 | u32 data; | ||
4392 | |||
4393 | ATH5K_TRACE(ah->ah_sc); | ||
4394 | if (gpio > AR5K_NUM_GPIO) | ||
4395 | return; | ||
4396 | |||
4397 | /* | ||
4398 | * Set the GPIO interrupt | ||
4399 | */ | ||
4400 | data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & | ||
4401 | ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | | ||
4402 | AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | | ||
4403 | (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); | ||
4404 | |||
4405 | ath5k_hw_reg_write(ah, interrupt_level ? data : | ||
4406 | (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); | ||
4407 | |||
4408 | ah->ah_imr |= AR5K_IMR_GPIO; | ||
4409 | |||
4410 | /* Enable GPIO interrupts */ | ||
4411 | AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); | ||
4412 | } | ||
4413 | |||
4414 | |||
4415 | |||
4416 | |||
4417 | /****************\ | ||
4418 | Misc functions | ||
4419 | \****************/ | ||
4420 | |||
4421 | int ath5k_hw_get_capability(struct ath5k_hw *ah, | ||
4422 | enum ath5k_capability_type cap_type, | ||
4423 | u32 capability, u32 *result) | ||
4424 | { | ||
4425 | ATH5K_TRACE(ah->ah_sc); | ||
4426 | |||
4427 | switch (cap_type) { | ||
4428 | case AR5K_CAP_NUM_TXQUEUES: | ||
4429 | if (result) { | ||
4430 | if (ah->ah_version == AR5K_AR5210) | ||
4431 | *result = AR5K_NUM_TX_QUEUES_NOQCU; | ||
4432 | else | ||
4433 | *result = AR5K_NUM_TX_QUEUES; | ||
4434 | goto yes; | ||
4435 | } | ||
4436 | case AR5K_CAP_VEOL: | ||
4437 | goto yes; | ||
4438 | case AR5K_CAP_COMPRESSION: | ||
4439 | if (ah->ah_version == AR5K_AR5212) | ||
4440 | goto yes; | ||
4441 | else | ||
4442 | goto no; | ||
4443 | case AR5K_CAP_BURST: | ||
4444 | goto yes; | ||
4445 | case AR5K_CAP_TPC: | ||
4446 | goto yes; | ||
4447 | case AR5K_CAP_BSSIDMASK: | ||
4448 | if (ah->ah_version == AR5K_AR5212) | ||
4449 | goto yes; | ||
4450 | else | ||
4451 | goto no; | ||
4452 | case AR5K_CAP_XR: | ||
4453 | if (ah->ah_version == AR5K_AR5212) | ||
4454 | goto yes; | ||
4455 | else | ||
4456 | goto no; | ||
4457 | default: | ||
4458 | goto no; | ||
4459 | } | ||
4460 | |||
4461 | no: | ||
4462 | return -EINVAL; | ||
4463 | yes: | ||
4464 | return 0; | ||
4465 | } | ||
4466 | |||
4467 | static int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, | ||
4468 | u16 assoc_id) | ||
4469 | { | ||
4470 | ATH5K_TRACE(ah->ah_sc); | ||
4471 | |||
4472 | if (ah->ah_version == AR5K_AR5210) { | ||
4473 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
4474 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
4475 | return 0; | ||
4476 | } | ||
4477 | |||
4478 | return -EIO; | ||
4479 | } | ||
4480 | |||
4481 | static int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) | ||
4482 | { | ||
4483 | ATH5K_TRACE(ah->ah_sc); | ||
4484 | |||
4485 | if (ah->ah_version == AR5K_AR5210) { | ||
4486 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
4487 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
4488 | return 0; | ||
4489 | } | ||
4490 | |||
4491 | return -EIO; | ||
4492 | } | ||
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index 2806b21bf90b..ea2e1a20b499 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Initial register settings functions | 2 | * Initial register settings functions |
3 | * | 3 | * |
4 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | 4 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> |
5 | * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com> | 5 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> |
6 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | 6 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> |
7 | * | 7 | * |
8 | * Permission to use, copy, modify, and distribute this software for any | 8 | * Permission to use, copy, modify, and distribute this software for any |
9 | * purpose with or without fee is hereby granted, provided that the above | 9 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,13 +20,9 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "ath5k.h" | 22 | #include "ath5k.h" |
23 | #include "base.h" | ||
24 | #include "reg.h" | 23 | #include "reg.h" |
25 | 24 | #include "debug.h" | |
26 | /* | 25 | #include "base.h" |
27 | * MAC/PHY REGISTERS | ||
28 | */ | ||
29 | |||
30 | 26 | ||
31 | /* | 27 | /* |
32 | * Mode-independent initial register writes | 28 | * Mode-independent initial register writes |
@@ -65,10 +61,10 @@ static const struct ath5k_ini ar5210_ini[] = { | |||
65 | { AR5K_TXCFG, AR5K_DMASIZE_128B }, | 61 | { AR5K_TXCFG, AR5K_DMASIZE_128B }, |
66 | { AR5K_RXCFG, AR5K_DMASIZE_128B }, | 62 | { AR5K_RXCFG, AR5K_DMASIZE_128B }, |
67 | { AR5K_CFG, AR5K_INIT_CFG }, | 63 | { AR5K_CFG, AR5K_INIT_CFG }, |
68 | { AR5K_TOPS, AR5K_INIT_TOPS }, | 64 | { AR5K_TOPS, 8 }, |
69 | { AR5K_RXNOFRM, AR5K_INIT_RXNOFRM }, | 65 | { AR5K_RXNOFRM, 8 }, |
70 | { AR5K_RPGTO, AR5K_INIT_RPGTO }, | 66 | { AR5K_RPGTO, 0 }, |
71 | { AR5K_TXNOFRM, AR5K_INIT_TXNOFRM }, | 67 | { AR5K_TXNOFRM, 0 }, |
72 | { AR5K_SFR, 0 }, | 68 | { AR5K_SFR, 0 }, |
73 | { AR5K_MIBC, 0 }, | 69 | { AR5K_MIBC, 0 }, |
74 | { AR5K_MISC, 0 }, | 70 | { AR5K_MISC, 0 }, |
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c new file mode 100644 index 000000000000..5a896d1e2a2b --- /dev/null +++ b/drivers/net/wireless/ath5k/pcu.c | |||
@@ -0,0 +1,1002 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org> | ||
5 | * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
6 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> | ||
7 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | ||
8 | * | ||
9 | * Permission to use, copy, modify, and distribute this software for any | ||
10 | * purpose with or without fee is hereby granted, provided that the above | ||
11 | * copyright notice and this permission notice appear in all copies. | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | /*********************************\ | ||
24 | * Protocol Control Unit Functions * | ||
25 | \*********************************/ | ||
26 | |||
27 | #include "ath5k.h" | ||
28 | #include "reg.h" | ||
29 | #include "debug.h" | ||
30 | #include "base.h" | ||
31 | |||
32 | /*******************\ | ||
33 | * Generic functions * | ||
34 | \*******************/ | ||
35 | |||
36 | /** | ||
37 | * ath5k_hw_set_opmode - Set PCU operating mode | ||
38 | * | ||
39 | * @ah: The &struct ath5k_hw | ||
40 | * | ||
41 | * Initialize PCU for the various operating modes (AP/STA etc) | ||
42 | * | ||
43 | * NOTE: ah->ah_op_mode must be set before calling this. | ||
44 | */ | ||
45 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | ||
46 | { | ||
47 | u32 pcu_reg, beacon_reg, low_id, high_id; | ||
48 | |||
49 | pcu_reg = 0; | ||
50 | beacon_reg = 0; | ||
51 | |||
52 | ATH5K_TRACE(ah->ah_sc); | ||
53 | |||
54 | switch (ah->ah_op_mode) { | ||
55 | case IEEE80211_IF_TYPE_IBSS: | ||
56 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA | | ||
57 | (ah->ah_version == AR5K_AR5210 ? | ||
58 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
59 | beacon_reg |= AR5K_BCR_ADHOC; | ||
60 | break; | ||
61 | |||
62 | case IEEE80211_IF_TYPE_AP: | ||
63 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
64 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA | | ||
65 | (ah->ah_version == AR5K_AR5210 ? | ||
66 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
67 | beacon_reg |= AR5K_BCR_AP; | ||
68 | break; | ||
69 | |||
70 | case IEEE80211_IF_TYPE_STA: | ||
71 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
72 | (ah->ah_version == AR5K_AR5210 ? | ||
73 | AR5K_STA_ID1_PWR_SV : 0); | ||
74 | case IEEE80211_IF_TYPE_MNTR: | ||
75 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
76 | (ah->ah_version == AR5K_AR5210 ? | ||
77 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
78 | break; | ||
79 | |||
80 | default: | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Set PCU registers | ||
86 | */ | ||
87 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | ||
88 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | ||
89 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
90 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
91 | |||
92 | /* | ||
93 | * Set Beacon Control Register on 5210 | ||
94 | */ | ||
95 | if (ah->ah_version == AR5K_AR5210) | ||
96 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * ath5k_hw_update - Update mib counters (mac layer statistics) | ||
103 | * | ||
104 | * @ah: The &struct ath5k_hw | ||
105 | * @stats: The &struct ieee80211_low_level_stats we use to track | ||
106 | * statistics on the driver | ||
107 | * | ||
108 | * Reads MIB counters from PCU and updates sw statistics. Must be | ||
109 | * called after a MIB interrupt. | ||
110 | */ | ||
111 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | ||
112 | struct ieee80211_low_level_stats *stats) | ||
113 | { | ||
114 | ATH5K_TRACE(ah->ah_sc); | ||
115 | |||
116 | /* Read-And-Clear */ | ||
117 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | ||
118 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | ||
119 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | ||
120 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | ||
121 | |||
122 | /* XXX: Should we use this to track beacon count ? | ||
123 | * -we read it anyway to clear the register */ | ||
124 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
125 | |||
126 | /* Reset profile count registers on 5212*/ | ||
127 | if (ah->ah_version == AR5K_AR5212) { | ||
128 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
129 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
130 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
131 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * ath5k_hw_set_ack_bitrate - set bitrate for ACKs | ||
137 | * | ||
138 | * @ah: The &struct ath5k_hw | ||
139 | * @high: Flag to determine if we want to use high transmition rate | ||
140 | * for ACKs or not | ||
141 | * | ||
142 | * If high flag is set, we tell hw to use a set of control rates based on | ||
143 | * the current transmition rate (check out control_rates array inside reset.c). | ||
144 | * If not hw just uses the lowest rate available for the current modulation | ||
145 | * scheme being used (1Mbit for CCK and 6Mbits for OFDM). | ||
146 | */ | ||
147 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | ||
148 | { | ||
149 | if (ah->ah_version != AR5K_AR5212) | ||
150 | return; | ||
151 | else { | ||
152 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | ||
153 | if (high) | ||
154 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
155 | else | ||
156 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | /******************\ | ||
162 | * ACK/CTS Timeouts * | ||
163 | \******************/ | ||
164 | |||
165 | /** | ||
166 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec | ||
167 | * | ||
168 | * @ah: The &struct ath5k_hw | ||
169 | */ | ||
170 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
171 | { | ||
172 | ATH5K_TRACE(ah->ah_sc); | ||
173 | |||
174 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
175 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | ||
180 | * | ||
181 | * @ah: The &struct ath5k_hw | ||
182 | * @timeout: Timeout in usec | ||
183 | */ | ||
184 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
185 | { | ||
186 | ATH5K_TRACE(ah->ah_sc); | ||
187 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | ||
188 | ah->ah_turbo) <= timeout) | ||
189 | return -EINVAL; | ||
190 | |||
191 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | ||
192 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec | ||
199 | * | ||
200 | * @ah: The &struct ath5k_hw | ||
201 | */ | ||
202 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
203 | { | ||
204 | ATH5K_TRACE(ah->ah_sc); | ||
205 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
206 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | ||
211 | * | ||
212 | * @ah: The &struct ath5k_hw | ||
213 | * @timeout: Timeout in usec | ||
214 | */ | ||
215 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
216 | { | ||
217 | ATH5K_TRACE(ah->ah_sc); | ||
218 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | ||
219 | ah->ah_turbo) <= timeout) | ||
220 | return -EINVAL; | ||
221 | |||
222 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | ||
223 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | |||
229 | /****************\ | ||
230 | * BSSID handling * | ||
231 | \****************/ | ||
232 | |||
233 | /** | ||
234 | * ath5k_hw_get_lladdr - Get station id | ||
235 | * | ||
236 | * @ah: The &struct ath5k_hw | ||
237 | * @mac: The card's mac address | ||
238 | * | ||
239 | * Initialize ah->ah_sta_id using the mac address provided | ||
240 | * (just a memcpy). | ||
241 | * | ||
242 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw | ||
243 | */ | ||
244 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | ||
245 | { | ||
246 | ATH5K_TRACE(ah->ah_sc); | ||
247 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * ath5k_hw_set_lladdr - Set station id | ||
252 | * | ||
253 | * @ah: The &struct ath5k_hw | ||
254 | * @mac: The card's mac address | ||
255 | * | ||
256 | * Set station id on hw using the provided mac address | ||
257 | */ | ||
258 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | ||
259 | { | ||
260 | u32 low_id, high_id; | ||
261 | |||
262 | ATH5K_TRACE(ah->ah_sc); | ||
263 | /* Set new station ID */ | ||
264 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | ||
265 | |||
266 | low_id = AR5K_LOW_ID(mac); | ||
267 | high_id = AR5K_HIGH_ID(mac); | ||
268 | |||
269 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
270 | ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * ath5k_hw_set_associd - Set BSSID for association | ||
277 | * | ||
278 | * @ah: The &struct ath5k_hw | ||
279 | * @bssid: BSSID | ||
280 | * @assoc_id: Assoc id | ||
281 | * | ||
282 | * Sets the BSSID which trigers the "SME Join" operation | ||
283 | */ | ||
284 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | ||
285 | { | ||
286 | u32 low_id, high_id; | ||
287 | u16 tim_offset = 0; | ||
288 | |||
289 | /* | ||
290 | * Set simple BSSID mask on 5212 | ||
291 | */ | ||
292 | if (ah->ah_version == AR5K_AR5212) { | ||
293 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0); | ||
294 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1); | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Set BSSID which triggers the "SME Join" operation | ||
299 | */ | ||
300 | low_id = AR5K_LOW_ID(bssid); | ||
301 | high_id = AR5K_HIGH_ID(bssid); | ||
302 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | ||
303 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | ||
304 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | ||
305 | |||
306 | if (assoc_id == 0) { | ||
307 | ath5k_hw_disable_pspoll(ah); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | ||
312 | tim_offset ? tim_offset + 4 : 0); | ||
313 | |||
314 | ath5k_hw_enable_pspoll(ah, NULL, 0); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * ath5k_hw_set_bssid_mask - filter out bssids we listen | ||
319 | * | ||
320 | * @ah: the &struct ath5k_hw | ||
321 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | ||
322 | * | ||
323 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | ||
324 | * which bits of the interface's MAC address should be looked at when trying | ||
325 | * to decide which packets to ACK. In station mode and AP mode with a single | ||
326 | * BSS every bit matters since we lock to only one BSS. In AP mode with | ||
327 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | ||
328 | * accept frames for all BSSes and so we tweak some bits of our mac address | ||
329 | * in order to have multiple BSSes. | ||
330 | * | ||
331 | * NOTE: This is a simple filter and does *not* filter out all | ||
332 | * relevant frames. Some frames that are not for us might get ACKed from us | ||
333 | * by PCU because they just match the mask. | ||
334 | * | ||
335 | * When handling multiple BSSes you can get the BSSID mask by computing the | ||
336 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. | ||
337 | * | ||
338 | * When you do this you are essentially computing the common bits of all your | ||
339 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with | ||
340 | * the MAC address to obtain the relevant bits and compare the result with | ||
341 | * (frame's BSSID & mask) to see if they match. | ||
342 | */ | ||
343 | /* | ||
344 | * Simple example: on your card you have have two BSSes you have created with | ||
345 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
346 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
347 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
348 | * | ||
349 | * \ | ||
350 | * MAC: 0001 | | ||
351 | * BSSID-01: 0100 | --> Belongs to us | ||
352 | * BSSID-02: 1001 | | ||
353 | * / | ||
354 | * ------------------- | ||
355 | * BSSID-03: 0110 | --> External | ||
356 | * ------------------- | ||
357 | * | ||
358 | * Our bssid_mask would then be: | ||
359 | * | ||
360 | * On loop iteration for BSSID-01: | ||
361 | * ~(0001 ^ 0100) -> ~(0101) | ||
362 | * -> 1010 | ||
363 | * bssid_mask = 1010 | ||
364 | * | ||
365 | * On loop iteration for BSSID-02: | ||
366 | * bssid_mask &= ~(0001 ^ 1001) | ||
367 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
368 | * bssid_mask = (1010) & ~(1001) | ||
369 | * bssid_mask = (1010) & (0110) | ||
370 | * bssid_mask = 0010 | ||
371 | * | ||
372 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
373 | * significant bit". This is because its the only bit common | ||
374 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
375 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
376 | * or our MAC address (we assume the hardware uses the MAC address). | ||
377 | * | ||
378 | * Now, suppose there's an incoming frame for BSSID-03: | ||
379 | * | ||
380 | * IFRAME-01: 0110 | ||
381 | * | ||
382 | * An easy eye-inspeciton of this already should tell you that this frame | ||
383 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
384 | * hardware to only look at the second least significant bit and the | ||
385 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
386 | * as 1, which does not match 0. | ||
387 | * | ||
388 | * So with IFRAME-01 we *assume* the hardware will do: | ||
389 | * | ||
390 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
391 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
392 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
393 | * --> allow = 0 | ||
394 | * | ||
395 | * Lets now test a frame that should work: | ||
396 | * | ||
397 | * IFRAME-02: 0001 (we should allow) | ||
398 | * | ||
399 | * allow = (0001 & 1010) == 1010 | ||
400 | * | ||
401 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
402 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
403 | * --> allow = (0010) == (0010) | ||
404 | * --> allow = 1 | ||
405 | * | ||
406 | * Other examples: | ||
407 | * | ||
408 | * IFRAME-03: 0100 --> allowed | ||
409 | * IFRAME-04: 1001 --> allowed | ||
410 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
411 | * | ||
412 | */ | ||
413 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
414 | { | ||
415 | u32 low_id, high_id; | ||
416 | ATH5K_TRACE(ah->ah_sc); | ||
417 | |||
418 | if (ah->ah_version == AR5K_AR5212) { | ||
419 | low_id = AR5K_LOW_ID(mask); | ||
420 | high_id = AR5K_HIGH_ID(mask); | ||
421 | |||
422 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | ||
423 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | return -EIO; | ||
429 | } | ||
430 | |||
431 | |||
432 | /************\ | ||
433 | * RX Control * | ||
434 | \************/ | ||
435 | |||
436 | /** | ||
437 | * ath5k_hw_start_rx_pcu - Start RX engine | ||
438 | * | ||
439 | * @ah: The &struct ath5k_hw | ||
440 | * | ||
441 | * Starts RX engine on PCU so that hw can process RXed frames | ||
442 | * (ACK etc). | ||
443 | * | ||
444 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | ||
445 | * TODO: Init ANI here | ||
446 | */ | ||
447 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
448 | { | ||
449 | ATH5K_TRACE(ah->ah_sc); | ||
450 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * at5k_hw_stop_rx_pcu - Stop RX engine | ||
455 | * | ||
456 | * @ah: The &struct ath5k_hw | ||
457 | * | ||
458 | * Stops RX engine on PCU | ||
459 | * | ||
460 | * TODO: Detach ANI here | ||
461 | */ | ||
462 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
463 | { | ||
464 | ATH5K_TRACE(ah->ah_sc); | ||
465 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * Set multicast filter | ||
470 | */ | ||
471 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | ||
472 | { | ||
473 | ATH5K_TRACE(ah->ah_sc); | ||
474 | /* Set the multicat filter */ | ||
475 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | ||
476 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Set multicast filter by index | ||
481 | */ | ||
482 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
483 | { | ||
484 | |||
485 | ATH5K_TRACE(ah->ah_sc); | ||
486 | if (index >= 64) | ||
487 | return -EINVAL; | ||
488 | else if (index >= 32) | ||
489 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
490 | (1 << (index - 32))); | ||
491 | else | ||
492 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * Clear Multicast filter by index | ||
499 | */ | ||
500 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
501 | { | ||
502 | |||
503 | ATH5K_TRACE(ah->ah_sc); | ||
504 | if (index >= 64) | ||
505 | return -EINVAL; | ||
506 | else if (index >= 32) | ||
507 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
508 | (1 << (index - 32))); | ||
509 | else | ||
510 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | /** | ||
516 | * ath5k_hw_get_rx_filter - Get current rx filter | ||
517 | * | ||
518 | * @ah: The &struct ath5k_hw | ||
519 | * | ||
520 | * Returns the RX filter by reading rx filter and | ||
521 | * phy error filter registers. RX filter is used | ||
522 | * to set the allowed frame types that PCU will accept | ||
523 | * and pass to the driver. For a list of frame types | ||
524 | * check out reg.h. | ||
525 | */ | ||
526 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | ||
527 | { | ||
528 | u32 data, filter = 0; | ||
529 | |||
530 | ATH5K_TRACE(ah->ah_sc); | ||
531 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); | ||
532 | |||
533 | /*Radar detection for 5212*/ | ||
534 | if (ah->ah_version == AR5K_AR5212) { | ||
535 | data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); | ||
536 | |||
537 | if (data & AR5K_PHY_ERR_FIL_RADAR) | ||
538 | filter |= AR5K_RX_FILTER_RADARERR; | ||
539 | if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) | ||
540 | filter |= AR5K_RX_FILTER_PHYERR; | ||
541 | } | ||
542 | |||
543 | return filter; | ||
544 | } | ||
545 | |||
546 | /** | ||
547 | * ath5k_hw_set_rx_filter - Set rx filter | ||
548 | * | ||
549 | * @ah: The &struct ath5k_hw | ||
550 | * @filter: RX filter mask (see reg.h) | ||
551 | * | ||
552 | * Sets RX filter register and also handles PHY error filter | ||
553 | * register on 5212 and newer chips so that we have proper PHY | ||
554 | * error reporting. | ||
555 | */ | ||
556 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | ||
557 | { | ||
558 | u32 data = 0; | ||
559 | |||
560 | ATH5K_TRACE(ah->ah_sc); | ||
561 | |||
562 | /* Set PHY error filter register on 5212*/ | ||
563 | if (ah->ah_version == AR5K_AR5212) { | ||
564 | if (filter & AR5K_RX_FILTER_RADARERR) | ||
565 | data |= AR5K_PHY_ERR_FIL_RADAR; | ||
566 | if (filter & AR5K_RX_FILTER_PHYERR) | ||
567 | data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; | ||
568 | } | ||
569 | |||
570 | /* | ||
571 | * The AR5210 uses promiscous mode to detect radar activity | ||
572 | */ | ||
573 | if (ah->ah_version == AR5K_AR5210 && | ||
574 | (filter & AR5K_RX_FILTER_RADARERR)) { | ||
575 | filter &= ~AR5K_RX_FILTER_RADARERR; | ||
576 | filter |= AR5K_RX_FILTER_PROM; | ||
577 | } | ||
578 | |||
579 | /*Zero length DMA*/ | ||
580 | if (data) | ||
581 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
582 | else | ||
583 | AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
584 | |||
585 | /*Write RX Filter register*/ | ||
586 | ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); | ||
587 | |||
588 | /*Write PHY error filter register on 5212*/ | ||
589 | if (ah->ah_version == AR5K_AR5212) | ||
590 | ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); | ||
591 | |||
592 | } | ||
593 | |||
594 | |||
595 | /****************\ | ||
596 | * Beacon control * | ||
597 | \****************/ | ||
598 | |||
599 | /** | ||
600 | * ath5k_hw_get_tsf32 - Get a 32bit TSF | ||
601 | * | ||
602 | * @ah: The &struct ath5k_hw | ||
603 | * | ||
604 | * Returns lower 32 bits of current TSF | ||
605 | */ | ||
606 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
607 | { | ||
608 | ATH5K_TRACE(ah->ah_sc); | ||
609 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
610 | } | ||
611 | |||
612 | /** | ||
613 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | ||
614 | * | ||
615 | * @ah: The &struct ath5k_hw | ||
616 | * | ||
617 | * Returns the current TSF | ||
618 | */ | ||
619 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | ||
620 | { | ||
621 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
622 | ATH5K_TRACE(ah->ah_sc); | ||
623 | |||
624 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | ||
625 | } | ||
626 | |||
627 | /** | ||
628 | * ath5k_hw_reset_tsf - Force a TSF reset | ||
629 | * | ||
630 | * @ah: The &struct ath5k_hw | ||
631 | * | ||
632 | * Forces a TSF reset on PCU | ||
633 | */ | ||
634 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | ||
635 | { | ||
636 | ATH5K_TRACE(ah->ah_sc); | ||
637 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF); | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Initialize beacon timers | ||
642 | */ | ||
643 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | ||
644 | { | ||
645 | u32 timer1, timer2, timer3; | ||
646 | |||
647 | ATH5K_TRACE(ah->ah_sc); | ||
648 | /* | ||
649 | * Set the additional timers by mode | ||
650 | */ | ||
651 | switch (ah->ah_op_mode) { | ||
652 | case IEEE80211_IF_TYPE_STA: | ||
653 | if (ah->ah_version == AR5K_AR5210) { | ||
654 | timer1 = 0xffffffff; | ||
655 | timer2 = 0xffffffff; | ||
656 | } else { | ||
657 | timer1 = 0x0000ffff; | ||
658 | timer2 = 0x0007ffff; | ||
659 | } | ||
660 | break; | ||
661 | |||
662 | default: | ||
663 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; | ||
664 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; | ||
665 | } | ||
666 | |||
667 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | ||
668 | |||
669 | /* | ||
670 | * Set the beacon register and enable all timers. | ||
671 | * (next beacon, DMA beacon, software beacon, ATIM window time) | ||
672 | */ | ||
673 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | ||
674 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | ||
675 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | ||
676 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | ||
677 | |||
678 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | | ||
679 | AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE), | ||
680 | AR5K_BEACON); | ||
681 | } | ||
682 | |||
683 | #if 0 | ||
684 | /* | ||
685 | * Set beacon timers | ||
686 | */ | ||
687 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
688 | const struct ath5k_beacon_state *state) | ||
689 | { | ||
690 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
691 | |||
692 | /* | ||
693 | * TODO: should be changed through *state | ||
694 | * review struct ath5k_beacon_state struct | ||
695 | * | ||
696 | * XXX: These are used for cfp period bellow, are they | ||
697 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
698 | * get_tsf ? | ||
699 | */ | ||
700 | u32 dtim_count = 0; /* XXX */ | ||
701 | u32 cfp_count = 0; /* XXX */ | ||
702 | u32 tsf = 0; /* XXX */ | ||
703 | |||
704 | ATH5K_TRACE(ah->ah_sc); | ||
705 | /* Return on an invalid beacon state */ | ||
706 | if (state->bs_interval < 1) | ||
707 | return -EINVAL; | ||
708 | |||
709 | interval = state->bs_interval; | ||
710 | dtim = state->bs_dtim_period; | ||
711 | |||
712 | /* | ||
713 | * PCF support? | ||
714 | */ | ||
715 | if (state->bs_cfp_period > 0) { | ||
716 | /* | ||
717 | * Enable PCF mode and set the CFP | ||
718 | * (Contention Free Period) and timer registers | ||
719 | */ | ||
720 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
721 | state->bs_interval; | ||
722 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
723 | state->bs_interval; | ||
724 | |||
725 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
726 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
727 | AR5K_STA_ID1_PCF); | ||
728 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
729 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
730 | AR5K_CFP_DUR); | ||
731 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
732 | next_cfp)) << 3, AR5K_TIMER2); | ||
733 | } else { | ||
734 | /* Disable PCF mode */ | ||
735 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
736 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
737 | AR5K_STA_ID1_PCF); | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Enable the beacon timer register | ||
742 | */ | ||
743 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
744 | |||
745 | /* | ||
746 | * Start the beacon timers | ||
747 | */ | ||
748 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & | ||
749 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
750 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
751 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
752 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
753 | |||
754 | /* | ||
755 | * Write new beacon miss threshold, if it appears to be valid | ||
756 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
757 | * and return if its not in range. We can test this by reading value and | ||
758 | * setting value to a largest value and seeing which values register. | ||
759 | */ | ||
760 | |||
761 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
762 | state->bs_bmiss_threshold); | ||
763 | |||
764 | /* | ||
765 | * Set sleep control register | ||
766 | * XXX: Didn't find this in 5210 code but since this register | ||
767 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
768 | */ | ||
769 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
770 | (state->bs_sleep_duration - 3) << 3); | ||
771 | |||
772 | /* | ||
773 | * Set enhanced sleep registers on 5212 | ||
774 | */ | ||
775 | if (ah->ah_version == AR5K_AR5212) { | ||
776 | if (state->bs_sleep_duration > state->bs_interval && | ||
777 | roundup(state->bs_sleep_duration, interval) == | ||
778 | state->bs_sleep_duration) | ||
779 | interval = state->bs_sleep_duration; | ||
780 | |||
781 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
782 | roundup(state->bs_sleep_duration, dtim) == | ||
783 | state->bs_sleep_duration)) | ||
784 | dtim = state->bs_sleep_duration; | ||
785 | |||
786 | if (interval > dtim) | ||
787 | return -EINVAL; | ||
788 | |||
789 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
790 | state->bs_next_beacon; | ||
791 | |||
792 | ath5k_hw_reg_write(ah, | ||
793 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
794 | AR5K_SLEEP0_NEXT_DTIM) | | ||
795 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
796 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
797 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
798 | |||
799 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
800 | AR5K_SLEEP1_NEXT_TIM) | | ||
801 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
802 | |||
803 | ath5k_hw_reg_write(ah, | ||
804 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
805 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
806 | } | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Reset beacon timers | ||
813 | */ | ||
814 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
815 | { | ||
816 | ATH5K_TRACE(ah->ah_sc); | ||
817 | /* | ||
818 | * Disable beacon timer | ||
819 | */ | ||
820 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
821 | |||
822 | /* | ||
823 | * Disable some beacon register values | ||
824 | */ | ||
825 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
826 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
827 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
828 | } | ||
829 | |||
830 | /* | ||
831 | * Wait for beacon queue to finish | ||
832 | */ | ||
833 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
834 | { | ||
835 | unsigned int i; | ||
836 | int ret; | ||
837 | |||
838 | ATH5K_TRACE(ah->ah_sc); | ||
839 | |||
840 | /* 5210 doesn't have QCU*/ | ||
841 | if (ah->ah_version == AR5K_AR5210) { | ||
842 | /* | ||
843 | * Wait for beaconn queue to finish by checking | ||
844 | * Control Register and Beacon Status Register. | ||
845 | */ | ||
846 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
847 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
848 | || | ||
849 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
850 | break; | ||
851 | udelay(10); | ||
852 | } | ||
853 | |||
854 | /* Timeout... */ | ||
855 | if (i <= 0) { | ||
856 | /* | ||
857 | * Re-schedule the beacon queue | ||
858 | */ | ||
859 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
860 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
861 | AR5K_BCR); | ||
862 | |||
863 | return -EIO; | ||
864 | } | ||
865 | ret = 0; | ||
866 | } else { | ||
867 | /*5211/5212*/ | ||
868 | ret = ath5k_hw_register_timeout(ah, | ||
869 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
870 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
871 | |||
872 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
873 | return -EIO; | ||
874 | } | ||
875 | |||
876 | return ret; | ||
877 | } | ||
878 | #endif | ||
879 | |||
880 | |||
881 | /*********************\ | ||
882 | * Key table functions * | ||
883 | \*********************/ | ||
884 | |||
885 | /* | ||
886 | * Reset a key entry on the table | ||
887 | */ | ||
888 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | ||
889 | { | ||
890 | unsigned int i; | ||
891 | |||
892 | ATH5K_TRACE(ah->ah_sc); | ||
893 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
894 | |||
895 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | ||
896 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | ||
897 | |||
898 | /* | ||
899 | * Set NULL encryption on AR5212+ | ||
900 | * | ||
901 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | ||
902 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | ||
903 | * | ||
904 | * Note2: Windows driver (ndiswrapper) sets this to | ||
905 | * 0x00000714 instead of 0x00000007 | ||
906 | */ | ||
907 | if (ah->ah_version > AR5K_AR5211) | ||
908 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
909 | AR5K_KEYTABLE_TYPE(entry)); | ||
910 | |||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | /* | ||
915 | * Check if a table entry is valid | ||
916 | */ | ||
917 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
918 | { | ||
919 | ATH5K_TRACE(ah->ah_sc); | ||
920 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
921 | |||
922 | /* Check the validation flag at the end of the entry */ | ||
923 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
924 | AR5K_KEYTABLE_VALID; | ||
925 | } | ||
926 | |||
927 | /* | ||
928 | * Set a key entry on the table | ||
929 | */ | ||
930 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
931 | const struct ieee80211_key_conf *key, const u8 *mac) | ||
932 | { | ||
933 | unsigned int i; | ||
934 | __le32 key_v[5] = {}; | ||
935 | u32 keytype; | ||
936 | |||
937 | ATH5K_TRACE(ah->ah_sc); | ||
938 | |||
939 | /* key->keylen comes in from mac80211 in bytes */ | ||
940 | |||
941 | if (key->keylen > AR5K_KEYTABLE_SIZE / 8) | ||
942 | return -EOPNOTSUPP; | ||
943 | |||
944 | switch (key->keylen) { | ||
945 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */ | ||
946 | case 40 / 8: | ||
947 | memcpy(&key_v[0], key->key, 5); | ||
948 | keytype = AR5K_KEYTABLE_TYPE_40; | ||
949 | break; | ||
950 | |||
951 | /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */ | ||
952 | case 104 / 8: | ||
953 | memcpy(&key_v[0], &key->key[0], 6); | ||
954 | memcpy(&key_v[2], &key->key[6], 6); | ||
955 | memcpy(&key_v[4], &key->key[12], 1); | ||
956 | keytype = AR5K_KEYTABLE_TYPE_104; | ||
957 | break; | ||
958 | /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */ | ||
959 | case 128 / 8: | ||
960 | memcpy(&key_v[0], &key->key[0], 6); | ||
961 | memcpy(&key_v[2], &key->key[6], 6); | ||
962 | memcpy(&key_v[4], &key->key[12], 4); | ||
963 | keytype = AR5K_KEYTABLE_TYPE_128; | ||
964 | break; | ||
965 | |||
966 | default: | ||
967 | return -EINVAL; /* shouldn't happen */ | ||
968 | } | ||
969 | |||
970 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
971 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
972 | AR5K_KEYTABLE_OFF(entry, i)); | ||
973 | |||
974 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | ||
975 | |||
976 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | ||
977 | } | ||
978 | |||
979 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | ||
980 | { | ||
981 | u32 low_id, high_id; | ||
982 | |||
983 | ATH5K_TRACE(ah->ah_sc); | ||
984 | /* Invalid entry (key table overflow) */ | ||
985 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
986 | |||
987 | /* MAC may be NULL if it's a broadcast key. In this case no need to | ||
988 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | ||
989 | if (unlikely(mac == NULL)) { | ||
990 | low_id = 0xffffffff; | ||
991 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | ||
992 | } else { | ||
993 | low_id = AR5K_LOW_ID(mac); | ||
994 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | ||
995 | } | ||
996 | |||
997 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | ||
998 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index fa0d47faf574..1ea8ed962d26 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * PHY functions | 2 | * PHY functions |
3 | * | 3 | * |
4 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | 4 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> |
5 | * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com> | 5 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> |
6 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | 6 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> |
7 | * | 7 | * |
8 | * Permission to use, copy, modify, and distribute this software for any | 8 | * Permission to use, copy, modify, and distribute this software for any |
9 | * purpose with or without fee is hereby granted, provided that the above | 9 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,6 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define _ATH5K_PHY | ||
23 | |||
22 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
23 | 25 | ||
24 | #include "ath5k.h" | 26 | #include "ath5k.h" |
@@ -2501,3 +2503,5 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power) | |||
2501 | 2503 | ||
2502 | return ath5k_hw_txpower(ah, channel, power); | 2504 | return ath5k_hw_txpower(ah, channel, power); |
2503 | } | 2505 | } |
2506 | |||
2507 | #undef _ATH5K_PHY | ||
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c new file mode 100644 index 000000000000..2e20f7816ca7 --- /dev/null +++ b/drivers/net/wireless/ath5k/qcu.c | |||
@@ -0,0 +1,488 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /********************************************\ | ||
20 | Queue Control Unit, DFS Control Unit Functions | ||
21 | \********************************************/ | ||
22 | |||
23 | #include "ath5k.h" | ||
24 | #include "reg.h" | ||
25 | #include "debug.h" | ||
26 | #include "base.h" | ||
27 | |||
28 | /* | ||
29 | * Get properties for a transmit queue | ||
30 | */ | ||
31 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
32 | struct ath5k_txq_info *queue_info) | ||
33 | { | ||
34 | ATH5K_TRACE(ah->ah_sc); | ||
35 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Set properties for a transmit queue | ||
41 | */ | ||
42 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
43 | const struct ath5k_txq_info *queue_info) | ||
44 | { | ||
45 | ATH5K_TRACE(ah->ah_sc); | ||
46 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
47 | |||
48 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
49 | return -EIO; | ||
50 | |||
51 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | ||
52 | |||
53 | /*XXX: Is this supported on 5210 ?*/ | ||
54 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | ||
55 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | ||
56 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | ||
57 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | ||
58 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Initialize a transmit queue | ||
65 | */ | ||
66 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | ||
67 | struct ath5k_txq_info *queue_info) | ||
68 | { | ||
69 | unsigned int queue; | ||
70 | int ret; | ||
71 | |||
72 | ATH5K_TRACE(ah->ah_sc); | ||
73 | |||
74 | /* | ||
75 | * Get queue by type | ||
76 | */ | ||
77 | /*5210 only has 2 queues*/ | ||
78 | if (ah->ah_version == AR5K_AR5210) { | ||
79 | switch (queue_type) { | ||
80 | case AR5K_TX_QUEUE_DATA: | ||
81 | queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; | ||
82 | break; | ||
83 | case AR5K_TX_QUEUE_BEACON: | ||
84 | case AR5K_TX_QUEUE_CAB: | ||
85 | queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; | ||
86 | break; | ||
87 | default: | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | } else { | ||
91 | switch (queue_type) { | ||
92 | case AR5K_TX_QUEUE_DATA: | ||
93 | for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; | ||
94 | ah->ah_txq[queue].tqi_type != | ||
95 | AR5K_TX_QUEUE_INACTIVE; queue++) { | ||
96 | |||
97 | if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) | ||
98 | return -EINVAL; | ||
99 | } | ||
100 | break; | ||
101 | case AR5K_TX_QUEUE_UAPSD: | ||
102 | queue = AR5K_TX_QUEUE_ID_UAPSD; | ||
103 | break; | ||
104 | case AR5K_TX_QUEUE_BEACON: | ||
105 | queue = AR5K_TX_QUEUE_ID_BEACON; | ||
106 | break; | ||
107 | case AR5K_TX_QUEUE_CAB: | ||
108 | queue = AR5K_TX_QUEUE_ID_CAB; | ||
109 | break; | ||
110 | case AR5K_TX_QUEUE_XR_DATA: | ||
111 | if (ah->ah_version != AR5K_AR5212) | ||
112 | ATH5K_ERR(ah->ah_sc, | ||
113 | "XR data queues only supported in" | ||
114 | " 5212!\n"); | ||
115 | queue = AR5K_TX_QUEUE_ID_XR_DATA; | ||
116 | break; | ||
117 | default: | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Setup internal queue structure | ||
124 | */ | ||
125 | memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); | ||
126 | ah->ah_txq[queue].tqi_type = queue_type; | ||
127 | |||
128 | if (queue_info != NULL) { | ||
129 | queue_info->tqi_type = queue_type; | ||
130 | ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info); | ||
131 | if (ret) | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * We use ah_txq_status to hold a temp value for | ||
137 | * the Secondary interrupt mask registers on 5211+ | ||
138 | * check out ath5k_hw_reset_tx_queue | ||
139 | */ | ||
140 | AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); | ||
141 | |||
142 | return queue; | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Get number of pending frames | ||
147 | * for a specific queue [5211+] | ||
148 | */ | ||
149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | ||
150 | { | ||
151 | ATH5K_TRACE(ah->ah_sc); | ||
152 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
153 | |||
154 | /* Return if queue is declared inactive */ | ||
155 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
156 | return false; | ||
157 | |||
158 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
159 | if (ah->ah_version == AR5K_AR5210) | ||
160 | return false; | ||
161 | |||
162 | return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Set a transmit queue inactive | ||
167 | */ | ||
168 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
169 | { | ||
170 | ATH5K_TRACE(ah->ah_sc); | ||
171 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
172 | return; | ||
173 | |||
174 | /* This queue will be skipped in further operations */ | ||
175 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | ||
176 | /*For SIMR setup*/ | ||
177 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * Set DFS properties for a transmit queue on DCU | ||
182 | */ | ||
183 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
184 | { | ||
185 | u32 cw_min, cw_max, retry_lg, retry_sh; | ||
186 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | ||
187 | |||
188 | ATH5K_TRACE(ah->ah_sc); | ||
189 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
190 | |||
191 | tq = &ah->ah_txq[queue]; | ||
192 | |||
193 | if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
194 | return 0; | ||
195 | |||
196 | if (ah->ah_version == AR5K_AR5210) { | ||
197 | /* Only handle data queues, others will be ignored */ | ||
198 | if (tq->tqi_type != AR5K_TX_QUEUE_DATA) | ||
199 | return 0; | ||
200 | |||
201 | /* Set Slot time */ | ||
202 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
203 | AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, | ||
204 | AR5K_SLOT_TIME); | ||
205 | /* Set ACK_CTS timeout */ | ||
206 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
207 | AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : | ||
208 | AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); | ||
209 | /* Set Transmit Latency */ | ||
210 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
211 | AR5K_INIT_TRANSMIT_LATENCY_TURBO : | ||
212 | AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); | ||
213 | |||
214 | /* Set IFS0 */ | ||
215 | if (ah->ah_turbo) { | ||
216 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | ||
217 | (ah->ah_aifs + tq->tqi_aifs) * | ||
218 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
219 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | ||
220 | AR5K_IFS0); | ||
221 | } else { | ||
222 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | ||
223 | (ah->ah_aifs + tq->tqi_aifs) * | ||
224 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | ||
225 | AR5K_INIT_SIFS, AR5K_IFS0); | ||
226 | } | ||
227 | |||
228 | /* Set IFS1 */ | ||
229 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
230 | AR5K_INIT_PROTO_TIME_CNTRL_TURBO : | ||
231 | AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); | ||
232 | /* Set AR5K_PHY_SETTLING */ | ||
233 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
234 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
235 | | 0x38 : | ||
236 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
237 | | 0x1C, | ||
238 | AR5K_PHY_SETTLING); | ||
239 | /* Set Frame Control Register */ | ||
240 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
241 | (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | | ||
242 | AR5K_PHY_TURBO_SHORT | 0x2020) : | ||
243 | (AR5K_PHY_FRAME_CTL_INI | 0x1020), | ||
244 | AR5K_PHY_FRAME_CTL_5210); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Calculate cwmin/max by channel mode | ||
249 | */ | ||
250 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
251 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | ||
252 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
253 | /*XR is only supported on 5212*/ | ||
254 | if (IS_CHAN_XR(ah->ah_current_channel) && | ||
255 | ah->ah_version == AR5K_AR5212) { | ||
256 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
257 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
258 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
259 | /*B mode is not supported on 5210*/ | ||
260 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
261 | ah->ah_version != AR5K_AR5210) { | ||
262 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
263 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
264 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
265 | } | ||
266 | |||
267 | cw_min = 1; | ||
268 | while (cw_min < ah->ah_cw_min) | ||
269 | cw_min = (cw_min << 1) | 1; | ||
270 | |||
271 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
272 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
273 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
274 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
275 | |||
276 | /* | ||
277 | * Calculate and set retry limits | ||
278 | */ | ||
279 | if (ah->ah_software_retry) { | ||
280 | /* XXX Need to test this */ | ||
281 | retry_lg = ah->ah_limit_tx_retries; | ||
282 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? | ||
283 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; | ||
284 | } else { | ||
285 | retry_lg = AR5K_INIT_LG_RETRY; | ||
286 | retry_sh = AR5K_INIT_SH_RETRY; | ||
287 | } | ||
288 | |||
289 | /*No QCU/DCU [5210]*/ | ||
290 | if (ah->ah_version == AR5K_AR5210) { | ||
291 | ath5k_hw_reg_write(ah, | ||
292 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | ||
293 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
294 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | ||
295 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
296 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | ||
297 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | ||
298 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
299 | AR5K_NODCU_RETRY_LMT); | ||
300 | } else { | ||
301 | /*QCU/DCU [5211+]*/ | ||
302 | ath5k_hw_reg_write(ah, | ||
303 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
304 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | | ||
305 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
306 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | | ||
307 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | | ||
308 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), | ||
309 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | ||
310 | |||
311 | /*===Rest is also for QCU/DCU only [5211+]===*/ | ||
312 | |||
313 | /* | ||
314 | * Set initial content window (cw_min/cw_max) | ||
315 | * and arbitrated interframe space (aifs)... | ||
316 | */ | ||
317 | ath5k_hw_reg_write(ah, | ||
318 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | ||
319 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | ||
320 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | ||
321 | AR5K_DCU_LCL_IFS_AIFS), | ||
322 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | ||
323 | |||
324 | /* | ||
325 | * Set misc registers | ||
326 | */ | ||
327 | ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, | ||
328 | AR5K_QUEUE_MISC(queue)); | ||
329 | |||
330 | if (tq->tqi_cbr_period) { | ||
331 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | ||
332 | AR5K_QCU_CBRCFG_INTVAL) | | ||
333 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, | ||
334 | AR5K_QCU_CBRCFG_ORN_THRES), | ||
335 | AR5K_QUEUE_CBRCFG(queue)); | ||
336 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
337 | AR5K_QCU_MISC_FRSHED_CBR); | ||
338 | if (tq->tqi_cbr_overflow_limit) | ||
339 | AR5K_REG_ENABLE_BITS(ah, | ||
340 | AR5K_QUEUE_MISC(queue), | ||
341 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | ||
342 | } | ||
343 | |||
344 | if (tq->tqi_ready_time) | ||
345 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | ||
346 | AR5K_QCU_RDYTIMECFG_INTVAL) | | ||
347 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
348 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
349 | |||
350 | if (tq->tqi_burst_time) { | ||
351 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, | ||
352 | AR5K_DCU_CHAN_TIME_DUR) | | ||
353 | AR5K_DCU_CHAN_TIME_ENABLE, | ||
354 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); | ||
355 | |||
356 | if (tq->tqi_flags | ||
357 | & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) | ||
358 | AR5K_REG_ENABLE_BITS(ah, | ||
359 | AR5K_QUEUE_MISC(queue), | ||
360 | AR5K_QCU_MISC_RDY_VEOL_POLICY); | ||
361 | } | ||
362 | |||
363 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) | ||
364 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, | ||
365 | AR5K_QUEUE_DFS_MISC(queue)); | ||
366 | |||
367 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) | ||
368 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, | ||
369 | AR5K_QUEUE_DFS_MISC(queue)); | ||
370 | |||
371 | /* | ||
372 | * Set registers by queue type | ||
373 | */ | ||
374 | switch (tq->tqi_type) { | ||
375 | case AR5K_TX_QUEUE_BEACON: | ||
376 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
377 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
378 | AR5K_QCU_MISC_CBREXP_BCN | | ||
379 | AR5K_QCU_MISC_BCN_ENABLE); | ||
380 | |||
381 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
382 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
383 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | ||
384 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | ||
385 | AR5K_DCU_MISC_BCN_ENABLE); | ||
386 | |||
387 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
388 | (AR5K_TUNE_SW_BEACON_RESP - | ||
389 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
390 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
391 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
392 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
393 | break; | ||
394 | |||
395 | case AR5K_TX_QUEUE_CAB: | ||
396 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
397 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
398 | AR5K_QCU_MISC_CBREXP | | ||
399 | AR5K_QCU_MISC_CBREXP_BCN); | ||
400 | |||
401 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
402 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
403 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | ||
404 | break; | ||
405 | |||
406 | case AR5K_TX_QUEUE_UAPSD: | ||
407 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
408 | AR5K_QCU_MISC_CBREXP); | ||
409 | break; | ||
410 | |||
411 | case AR5K_TX_QUEUE_DATA: | ||
412 | default: | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * Enable interrupts for this tx queue | ||
418 | * in the secondary interrupt mask registers | ||
419 | */ | ||
420 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) | ||
421 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); | ||
422 | |||
423 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) | ||
424 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); | ||
425 | |||
426 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) | ||
427 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); | ||
428 | |||
429 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) | ||
430 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); | ||
431 | |||
432 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) | ||
433 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); | ||
434 | |||
435 | |||
436 | /* Update secondary interrupt mask registers */ | ||
437 | ah->ah_txq_imr_txok &= ah->ah_txq_status; | ||
438 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; | ||
439 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; | ||
440 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; | ||
441 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; | ||
442 | |||
443 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, | ||
444 | AR5K_SIMR0_QCU_TXOK) | | ||
445 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, | ||
446 | AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); | ||
447 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, | ||
448 | AR5K_SIMR1_QCU_TXERR) | | ||
449 | AR5K_REG_SM(ah->ah_txq_imr_txeol, | ||
450 | AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); | ||
451 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn, | ||
452 | AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2); | ||
453 | } | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Get slot time from DCU | ||
460 | */ | ||
461 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | ||
462 | { | ||
463 | ATH5K_TRACE(ah->ah_sc); | ||
464 | if (ah->ah_version == AR5K_AR5210) | ||
465 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | ||
466 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
467 | else | ||
468 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | ||
469 | } | ||
470 | |||
471 | /* | ||
472 | * Set slot time on DCU | ||
473 | */ | ||
474 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | ||
475 | { | ||
476 | ATH5K_TRACE(ah->ah_sc); | ||
477 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | ||
478 | return -EINVAL; | ||
479 | |||
480 | if (ah->ah_version == AR5K_AR5210) | ||
481 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | ||
482 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
483 | else | ||
484 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 7562bf173d3e..a98832364448 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com> | 2 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> |
3 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | 3 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> |
4 | * Copyright (c) 2007 Michael Taylor <mike.taylor@apprion.com> | 4 | * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com> |
5 | * | 5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any | 6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -977,98 +977,6 @@ | |||
977 | #define AR5K_EEPROM_BASE 0x6000 | 977 | #define AR5K_EEPROM_BASE 0x6000 |
978 | 978 | ||
979 | /* | 979 | /* |
980 | * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) | ||
981 | */ | ||
982 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ | ||
983 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ | ||
984 | #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ | ||
985 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | ||
986 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | ||
987 | |||
988 | #define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ | ||
989 | #define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ | ||
990 | #define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ | ||
991 | #define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ | ||
992 | #define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 | ||
993 | #define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ | ||
994 | #define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 | ||
995 | #define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ | ||
996 | #define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 | ||
997 | #define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ | ||
998 | #define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 | ||
999 | #define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ | ||
1000 | #define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 | ||
1001 | #define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ | ||
1002 | #define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 | ||
1003 | #define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ | ||
1004 | #define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 | ||
1005 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | ||
1006 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | ||
1007 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | ||
1008 | #define AR5K_EEPROM_INFO_CKSUM 0xffff | ||
1009 | #define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) | ||
1010 | |||
1011 | #define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ | ||
1012 | #define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ | ||
1013 | #define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ | ||
1014 | #define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ | ||
1015 | #define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ | ||
1016 | #define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */ | ||
1017 | #define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ | ||
1018 | #define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ | ||
1019 | #define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ | ||
1020 | #define AR5K_EEPROM_VERSION_4_3 0x4003 | ||
1021 | #define AR5K_EEPROM_VERSION_4_4 0x4004 | ||
1022 | #define AR5K_EEPROM_VERSION_4_5 0x4005 | ||
1023 | #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ | ||
1024 | #define AR5K_EEPROM_VERSION_4_7 0x4007 | ||
1025 | |||
1026 | #define AR5K_EEPROM_MODE_11A 0 | ||
1027 | #define AR5K_EEPROM_MODE_11B 1 | ||
1028 | #define AR5K_EEPROM_MODE_11G 2 | ||
1029 | |||
1030 | #define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ | ||
1031 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) | ||
1032 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) | ||
1033 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) | ||
1034 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | ||
1035 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | ||
1036 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | ||
1037 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */ | ||
1038 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | ||
1039 | |||
1040 | #define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c | ||
1041 | #define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 | ||
1042 | #define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 | ||
1043 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 | ||
1044 | |||
1045 | /* Newer EEPROMs are using a different offset */ | ||
1046 | #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ | ||
1047 | (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) | ||
1048 | |||
1049 | #define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) | ||
1050 | #define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff)) | ||
1051 | #define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff)) | ||
1052 | |||
1053 | /* calibration settings */ | ||
1054 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | ||
1055 | #define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) | ||
1056 | #define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) | ||
1057 | #define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ | ||
1058 | |||
1059 | /* [3.1 - 3.3] */ | ||
1060 | #define AR5K_EEPROM_OBDB0_2GHZ 0x00ec | ||
1061 | #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed | ||
1062 | |||
1063 | /* Misc values available since EEPROM 4.0 */ | ||
1064 | #define AR5K_EEPROM_MISC0 0x00c4 | ||
1065 | #define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) | ||
1066 | #define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) | ||
1067 | #define AR5K_EEPROM_MISC1 0x00c5 | ||
1068 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | ||
1069 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | ||
1070 | |||
1071 | /* | ||
1072 | * EEPROM data register | 980 | * EEPROM data register |
1073 | */ | 981 | */ |
1074 | #define AR5K_EEPROM_DATA_5211 0x6004 | 982 | #define AR5K_EEPROM_DATA_5211 0x6004 |
@@ -1950,13 +1858,13 @@ | |||
1950 | #define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ | 1858 | #define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ |
1951 | 1859 | ||
1952 | /* | 1860 | /* |
1953 | * Desired size register | 1861 | * Desired ADC/PGA size register |
1954 | * (for more infos read ANI patent) | 1862 | * (for more infos read ANI patent) |
1955 | */ | 1863 | */ |
1956 | #define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ | 1864 | #define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ |
1957 | #define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* Mask for ADC desired size */ | 1865 | #define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* Mask for ADC desired size */ |
1958 | #define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* Mask for PGA desired size */ | 1866 | #define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* Mask for PGA desired size */ |
1959 | #define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Mask for Total desired size (?) */ | 1867 | #define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Mask for Total desired size */ |
1960 | 1868 | ||
1961 | /* | 1869 | /* |
1962 | * PHY signal register | 1870 | * PHY signal register |
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c new file mode 100644 index 000000000000..d260fba0180f --- /dev/null +++ b/drivers/net/wireless/ath5k/reset.c | |||
@@ -0,0 +1,925 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
5 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> | ||
6 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #define _ATH5K_RESET | ||
23 | |||
24 | /*****************************\ | ||
25 | Reset functions and helpers | ||
26 | \*****************************/ | ||
27 | |||
28 | #include <linux/pci.h> | ||
29 | #include "ath5k.h" | ||
30 | #include "reg.h" | ||
31 | #include "base.h" | ||
32 | #include "debug.h" | ||
33 | |||
34 | /** | ||
35 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
36 | * | ||
37 | * @ah: the &struct ath5k_hw | ||
38 | * @channel: the currently set channel upon reset | ||
39 | * | ||
40 | * Write the OFDM timings for the AR5212 upon reset. This is a helper for | ||
41 | * ath5k_hw_reset(). This seems to tune the PLL a specified frequency | ||
42 | * depending on the bandwidth of the channel. | ||
43 | * | ||
44 | */ | ||
45 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
46 | struct ieee80211_channel *channel) | ||
47 | { | ||
48 | /* Get exponent and mantissa and set it */ | ||
49 | u32 coef_scaled, coef_exp, coef_man, | ||
50 | ds_coef_exp, ds_coef_man, clock; | ||
51 | |||
52 | if (!(ah->ah_version == AR5K_AR5212) || | ||
53 | !(channel->hw_value & CHANNEL_OFDM)) | ||
54 | BUG(); | ||
55 | |||
56 | /* Seems there are two PLLs, one for baseband sampling and one | ||
57 | * for tuning. Tuning basebands are 40 MHz or 80MHz when in | ||
58 | * turbo. */ | ||
59 | clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40; | ||
60 | coef_scaled = ((5 * (clock << 24)) / 2) / | ||
61 | channel->center_freq; | ||
62 | |||
63 | for (coef_exp = 31; coef_exp > 0; coef_exp--) | ||
64 | if ((coef_scaled >> coef_exp) & 0x1) | ||
65 | break; | ||
66 | |||
67 | if (!coef_exp) | ||
68 | return -EINVAL; | ||
69 | |||
70 | coef_exp = 14 - (coef_exp - 24); | ||
71 | coef_man = coef_scaled + | ||
72 | (1 << (24 - coef_exp - 1)); | ||
73 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
74 | ds_coef_exp = coef_exp - 16; | ||
75 | |||
76 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
77 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
78 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
79 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | |||
85 | /* | ||
86 | * index into rates for control rates, we can set it up like this because | ||
87 | * this is only used for AR5212 and we know it supports G mode | ||
88 | */ | ||
89 | static int control_rates[] = | ||
90 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | ||
91 | |||
92 | /** | ||
93 | * ath5k_hw_write_rate_duration - set rate duration during hw resets | ||
94 | * | ||
95 | * @ah: the &struct ath5k_hw | ||
96 | * @mode: one of enum ath5k_driver_mode | ||
97 | * | ||
98 | * Write the rate duration table upon hw reset. This is a helper for | ||
99 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for | ||
100 | * the hardware for the current mode for each rate. The rates which are capable | ||
101 | * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another | ||
102 | * register for the short preamble ACK timeout calculation. | ||
103 | */ | ||
104 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | ||
105 | unsigned int mode) | ||
106 | { | ||
107 | struct ath5k_softc *sc = ah->ah_sc; | ||
108 | struct ieee80211_rate *rate; | ||
109 | unsigned int i; | ||
110 | |||
111 | /* Write rate duration table */ | ||
112 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | ||
113 | u32 reg; | ||
114 | u16 tx_time; | ||
115 | |||
116 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | ||
117 | |||
118 | /* Set ACK timeout */ | ||
119 | reg = AR5K_RATE_DUR(rate->hw_value); | ||
120 | |||
121 | /* An ACK frame consists of 10 bytes. If you add the FCS, | ||
122 | * which ieee80211_generic_frame_duration() adds, | ||
123 | * its 14 bytes. Note we use the control rate and not the | ||
124 | * actual rate for this rate. See mac80211 tx.c | ||
125 | * ieee80211_duration() for a brief description of | ||
126 | * what rate we should choose to TX ACKs. */ | ||
127 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | ||
128 | sc->vif, 10, rate)); | ||
129 | |||
130 | ath5k_hw_reg_write(ah, tx_time, reg); | ||
131 | |||
132 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | ||
133 | continue; | ||
134 | |||
135 | /* | ||
136 | * We're not distinguishing short preamble here, | ||
137 | * This is true, all we'll get is a longer value here | ||
138 | * which is not necessarilly bad. We could use | ||
139 | * export ieee80211_frame_duration() but that needs to be | ||
140 | * fixed first to be properly used by mac802111 drivers: | ||
141 | * | ||
142 | * - remove erp stuff and let the routine figure ofdm | ||
143 | * erp rates | ||
144 | * - remove passing argument ieee80211_local as | ||
145 | * drivers don't have access to it | ||
146 | * - move drivers using ieee80211_generic_frame_duration() | ||
147 | * to this | ||
148 | */ | ||
149 | ath5k_hw_reg_write(ah, tx_time, | ||
150 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Reset chipset | ||
156 | */ | ||
157 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | ||
158 | { | ||
159 | int ret; | ||
160 | u32 mask = val ? val : ~0U; | ||
161 | |||
162 | ATH5K_TRACE(ah->ah_sc); | ||
163 | |||
164 | /* Read-and-clear RX Descriptor Pointer*/ | ||
165 | ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
166 | |||
167 | /* | ||
168 | * Reset the device and wait until success | ||
169 | */ | ||
170 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); | ||
171 | |||
172 | /* Wait at least 128 PCI clocks */ | ||
173 | udelay(15); | ||
174 | |||
175 | if (ah->ah_version == AR5K_AR5210) { | ||
176 | val &= AR5K_RESET_CTL_CHIP; | ||
177 | mask &= AR5K_RESET_CTL_CHIP; | ||
178 | } else { | ||
179 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
180 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
181 | } | ||
182 | |||
183 | ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); | ||
184 | |||
185 | /* | ||
186 | * Reset configuration register (for hw byte-swap). Note that this | ||
187 | * is only set for big endian. We do the necessary magic in | ||
188 | * AR5K_INIT_CFG. | ||
189 | */ | ||
190 | if ((val & AR5K_RESET_CTL_PCU) == 0) | ||
191 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Sleep control | ||
198 | */ | ||
199 | int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | ||
200 | bool set_chip, u16 sleep_duration) | ||
201 | { | ||
202 | unsigned int i; | ||
203 | u32 staid, data; | ||
204 | |||
205 | ATH5K_TRACE(ah->ah_sc); | ||
206 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); | ||
207 | |||
208 | switch (mode) { | ||
209 | case AR5K_PM_AUTO: | ||
210 | staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; | ||
211 | /* fallthrough */ | ||
212 | case AR5K_PM_NETWORK_SLEEP: | ||
213 | if (set_chip) | ||
214 | ath5k_hw_reg_write(ah, | ||
215 | AR5K_SLEEP_CTL_SLE_ALLOW | | ||
216 | sleep_duration, | ||
217 | AR5K_SLEEP_CTL); | ||
218 | |||
219 | staid |= AR5K_STA_ID1_PWR_SV; | ||
220 | break; | ||
221 | |||
222 | case AR5K_PM_FULL_SLEEP: | ||
223 | if (set_chip) | ||
224 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, | ||
225 | AR5K_SLEEP_CTL); | ||
226 | |||
227 | staid |= AR5K_STA_ID1_PWR_SV; | ||
228 | break; | ||
229 | |||
230 | case AR5K_PM_AWAKE: | ||
231 | |||
232 | staid &= ~AR5K_STA_ID1_PWR_SV; | ||
233 | |||
234 | if (!set_chip) | ||
235 | goto commit; | ||
236 | |||
237 | /* Preserve sleep duration */ | ||
238 | data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); | ||
239 | if (data & 0xffc00000) | ||
240 | data = 0; | ||
241 | else | ||
242 | data = data & 0xfffcffff; | ||
243 | |||
244 | ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); | ||
245 | udelay(15); | ||
246 | |||
247 | for (i = 50; i > 0; i--) { | ||
248 | /* Check if the chip did wake up */ | ||
249 | if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & | ||
250 | AR5K_PCICFG_SPWR_DN) == 0) | ||
251 | break; | ||
252 | |||
253 | /* Wait a bit and retry */ | ||
254 | udelay(200); | ||
255 | ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); | ||
256 | } | ||
257 | |||
258 | /* Fail if the chip didn't wake up */ | ||
259 | if (i <= 0) | ||
260 | return -EIO; | ||
261 | |||
262 | break; | ||
263 | |||
264 | default: | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | commit: | ||
269 | ah->ah_power_mode = mode; | ||
270 | ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Bring up MAC + PHY Chips | ||
277 | */ | ||
278 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | ||
279 | { | ||
280 | struct pci_dev *pdev = ah->ah_sc->pdev; | ||
281 | u32 turbo, mode, clock, bus_flags; | ||
282 | int ret; | ||
283 | |||
284 | turbo = 0; | ||
285 | mode = 0; | ||
286 | clock = 0; | ||
287 | |||
288 | ATH5K_TRACE(ah->ah_sc); | ||
289 | |||
290 | /* Wakeup the device */ | ||
291 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
292 | if (ret) { | ||
293 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | if (ah->ah_version != AR5K_AR5210) { | ||
298 | /* | ||
299 | * Get channel mode flags | ||
300 | */ | ||
301 | |||
302 | if (ah->ah_radio >= AR5K_RF5112) { | ||
303 | mode = AR5K_PHY_MODE_RAD_RF5112; | ||
304 | clock = AR5K_PHY_PLL_RF5112; | ||
305 | } else { | ||
306 | mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ | ||
307 | clock = AR5K_PHY_PLL_RF5111; /*Zero*/ | ||
308 | } | ||
309 | |||
310 | if (flags & CHANNEL_2GHZ) { | ||
311 | mode |= AR5K_PHY_MODE_FREQ_2GHZ; | ||
312 | clock |= AR5K_PHY_PLL_44MHZ; | ||
313 | |||
314 | if (flags & CHANNEL_CCK) { | ||
315 | mode |= AR5K_PHY_MODE_MOD_CCK; | ||
316 | } else if (flags & CHANNEL_OFDM) { | ||
317 | /* XXX Dynamic OFDM/CCK is not supported by the | ||
318 | * AR5211 so we set MOD_OFDM for plain g (no | ||
319 | * CCK headers) operation. We need to test | ||
320 | * this, 5211 might support ofdm-only g after | ||
321 | * all, there are also initial register values | ||
322 | * in the code for g mode (see initvals.c). */ | ||
323 | if (ah->ah_version == AR5K_AR5211) | ||
324 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
325 | else | ||
326 | mode |= AR5K_PHY_MODE_MOD_DYN; | ||
327 | } else { | ||
328 | ATH5K_ERR(ah->ah_sc, | ||
329 | "invalid radio modulation mode\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | } else if (flags & CHANNEL_5GHZ) { | ||
333 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; | ||
334 | clock |= AR5K_PHY_PLL_40MHZ; | ||
335 | |||
336 | if (flags & CHANNEL_OFDM) | ||
337 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
338 | else { | ||
339 | ATH5K_ERR(ah->ah_sc, | ||
340 | "invalid radio modulation mode\n"); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | } else { | ||
344 | ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | if (flags & CHANNEL_TURBO) | ||
349 | turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; | ||
350 | } else { /* Reset the device */ | ||
351 | |||
352 | /* ...enable Atheros turbo mode if requested */ | ||
353 | if (flags & CHANNEL_TURBO) | ||
354 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, | ||
355 | AR5K_PHY_TURBO); | ||
356 | } | ||
357 | |||
358 | /* reseting PCI on PCI-E cards results card to hang | ||
359 | * and always return 0xffff... so we ingore that flag | ||
360 | * for PCI-E cards */ | ||
361 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | ||
362 | |||
363 | /* Reset chipset */ | ||
364 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
365 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
366 | if (ret) { | ||
367 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); | ||
368 | return -EIO; | ||
369 | } | ||
370 | |||
371 | if (ah->ah_version == AR5K_AR5210) | ||
372 | udelay(2300); | ||
373 | |||
374 | /* ...wakeup again!*/ | ||
375 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
376 | if (ret) { | ||
377 | ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); | ||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | /* ...final warm reset */ | ||
382 | if (ath5k_hw_nic_reset(ah, 0)) { | ||
383 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | ||
384 | return -EIO; | ||
385 | } | ||
386 | |||
387 | if (ah->ah_version != AR5K_AR5210) { | ||
388 | /* ...set the PHY operating mode */ | ||
389 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); | ||
390 | udelay(300); | ||
391 | |||
392 | ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); | ||
393 | ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); | ||
394 | } | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * Main reset function | ||
401 | */ | ||
402 | int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | ||
403 | struct ieee80211_channel *channel, bool change_channel) | ||
404 | { | ||
405 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
406 | struct pci_dev *pdev = ah->ah_sc->pdev; | ||
407 | u32 data, s_seq, s_ant, s_led[3], dma_size; | ||
408 | unsigned int i, mode, freq, ee_mode, ant[2]; | ||
409 | int ret; | ||
410 | |||
411 | ATH5K_TRACE(ah->ah_sc); | ||
412 | |||
413 | s_seq = 0; | ||
414 | s_ant = 0; | ||
415 | ee_mode = 0; | ||
416 | freq = 0; | ||
417 | mode = 0; | ||
418 | |||
419 | /* | ||
420 | * Save some registers before a reset | ||
421 | */ | ||
422 | /*DCU/Antenna selection not available on 5210*/ | ||
423 | if (ah->ah_version != AR5K_AR5210) { | ||
424 | if (change_channel) { | ||
425 | /* Seq number for queue 0 -do this for all queues ? */ | ||
426 | s_seq = ath5k_hw_reg_read(ah, | ||
427 | AR5K_QUEUE_DFS_SEQNUM(0)); | ||
428 | /*Default antenna*/ | ||
429 | s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | /*GPIOs*/ | ||
434 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; | ||
435 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); | ||
436 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
437 | |||
438 | if (change_channel && ah->ah_rf_banks != NULL) | ||
439 | ath5k_hw_get_rf_gain(ah); | ||
440 | |||
441 | |||
442 | /*Wakeup the device*/ | ||
443 | ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); | ||
444 | if (ret) | ||
445 | return ret; | ||
446 | |||
447 | /* | ||
448 | * Initialize operating mode | ||
449 | */ | ||
450 | ah->ah_op_mode = op_mode; | ||
451 | |||
452 | /* | ||
453 | * 5111/5112 Settings | ||
454 | * 5210 only comes with RF5110 | ||
455 | */ | ||
456 | if (ah->ah_version != AR5K_AR5210) { | ||
457 | if (ah->ah_radio != AR5K_RF5111 && | ||
458 | ah->ah_radio != AR5K_RF5112 && | ||
459 | ah->ah_radio != AR5K_RF5413 && | ||
460 | ah->ah_radio != AR5K_RF2413 && | ||
461 | ah->ah_radio != AR5K_RF2425) { | ||
462 | ATH5K_ERR(ah->ah_sc, | ||
463 | "invalid phy radio: %u\n", ah->ah_radio); | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | |||
467 | switch (channel->hw_value & CHANNEL_MODES) { | ||
468 | case CHANNEL_A: | ||
469 | mode = AR5K_MODE_11A; | ||
470 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
471 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
472 | break; | ||
473 | case CHANNEL_G: | ||
474 | mode = AR5K_MODE_11G; | ||
475 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
476 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
477 | break; | ||
478 | case CHANNEL_B: | ||
479 | mode = AR5K_MODE_11B; | ||
480 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
481 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
482 | break; | ||
483 | case CHANNEL_T: | ||
484 | mode = AR5K_MODE_11A_TURBO; | ||
485 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
486 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
487 | break; | ||
488 | /*Is this ok on 5211 too ?*/ | ||
489 | case CHANNEL_TG: | ||
490 | mode = AR5K_MODE_11G_TURBO; | ||
491 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
492 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
493 | break; | ||
494 | case CHANNEL_XR: | ||
495 | if (ah->ah_version == AR5K_AR5211) { | ||
496 | ATH5K_ERR(ah->ah_sc, | ||
497 | "XR mode not available on 5211"); | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | mode = AR5K_MODE_XR; | ||
501 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
502 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
503 | break; | ||
504 | default: | ||
505 | ATH5K_ERR(ah->ah_sc, | ||
506 | "invalid channel: %d\n", channel->center_freq); | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | |||
510 | /* PHY access enable */ | ||
511 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
512 | |||
513 | } | ||
514 | |||
515 | ret = ath5k_hw_write_initvals(ah, mode, change_channel); | ||
516 | if (ret) | ||
517 | return ret; | ||
518 | |||
519 | /* | ||
520 | * 5211/5212 Specific | ||
521 | */ | ||
522 | if (ah->ah_version != AR5K_AR5210) { | ||
523 | /* | ||
524 | * Write initial RF gain settings | ||
525 | * This should work for both 5111/5112 | ||
526 | */ | ||
527 | ret = ath5k_hw_rfgain(ah, freq); | ||
528 | if (ret) | ||
529 | return ret; | ||
530 | |||
531 | mdelay(1); | ||
532 | |||
533 | /* | ||
534 | * Write some more initial register settings | ||
535 | */ | ||
536 | if (ah->ah_version == AR5K_AR5212) { | ||
537 | ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); | ||
538 | |||
539 | if (channel->hw_value == CHANNEL_G) | ||
540 | if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) | ||
541 | ath5k_hw_reg_write(ah, 0x00f80d80, | ||
542 | 0x994c); | ||
543 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) | ||
544 | ath5k_hw_reg_write(ah, 0x00380140, | ||
545 | 0x994c); | ||
546 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) | ||
547 | ath5k_hw_reg_write(ah, 0x00fc0ec0, | ||
548 | 0x994c); | ||
549 | else /* 2425 */ | ||
550 | ath5k_hw_reg_write(ah, 0x00fc0fc0, | ||
551 | 0x994c); | ||
552 | else | ||
553 | ath5k_hw_reg_write(ah, 0x00000000, 0x994c); | ||
554 | |||
555 | /* Some bits are disabled here, we know nothing about | ||
556 | * register 0xa228 yet, most of the times this ends up | ||
557 | * with a value 0x9b5 -haven't seen any dump with | ||
558 | * a different value- */ | ||
559 | /* Got this from decompiling binary HAL */ | ||
560 | data = ath5k_hw_reg_read(ah, 0xa228); | ||
561 | data &= 0xfffffdff; | ||
562 | ath5k_hw_reg_write(ah, data, 0xa228); | ||
563 | |||
564 | data = ath5k_hw_reg_read(ah, 0xa228); | ||
565 | data &= 0xfffe03ff; | ||
566 | ath5k_hw_reg_write(ah, data, 0xa228); | ||
567 | data = 0; | ||
568 | |||
569 | /* Just write 0x9b5 ? */ | ||
570 | /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ | ||
571 | ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); | ||
572 | ath5k_hw_reg_write(ah, 0x00000000, 0xa254); | ||
573 | ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); | ||
574 | } | ||
575 | |||
576 | /* Fix for first revision of the RF5112 RF chipset */ | ||
577 | if (ah->ah_radio >= AR5K_RF5112 && | ||
578 | ah->ah_radio_5ghz_revision < | ||
579 | AR5K_SREV_RAD_5112A) { | ||
580 | ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, | ||
581 | AR5K_PHY_CCKTXCTL); | ||
582 | if (channel->hw_value & CHANNEL_5GHZ) | ||
583 | data = 0xffb81020; | ||
584 | else | ||
585 | data = 0xffb80d20; | ||
586 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); | ||
587 | data = 0; | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * Set TX power (FIXME) | ||
592 | */ | ||
593 | ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER); | ||
594 | if (ret) | ||
595 | return ret; | ||
596 | |||
597 | /* Write rate duration table only on AR5212 and if | ||
598 | * virtual interface has already been brought up | ||
599 | * XXX: rethink this after new mode changes to | ||
600 | * mac80211 are integrated */ | ||
601 | if (ah->ah_version == AR5K_AR5212 && | ||
602 | ah->ah_sc->vif != NULL) | ||
603 | ath5k_hw_write_rate_duration(ah, mode); | ||
604 | |||
605 | /* | ||
606 | * Write RF registers | ||
607 | */ | ||
608 | ret = ath5k_hw_rfregs(ah, channel, mode); | ||
609 | if (ret) | ||
610 | return ret; | ||
611 | |||
612 | /* | ||
613 | * Configure additional registers | ||
614 | */ | ||
615 | |||
616 | /* Write OFDM timings on 5212*/ | ||
617 | if (ah->ah_version == AR5K_AR5212 && | ||
618 | channel->hw_value & CHANNEL_OFDM) { | ||
619 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
620 | if (ret) | ||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | /*Enable/disable 802.11b mode on 5111 | ||
625 | (enable 2111 frequency converter + CCK)*/ | ||
626 | if (ah->ah_radio == AR5K_RF5111) { | ||
627 | if (mode == AR5K_MODE_11B) | ||
628 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
629 | AR5K_TXCFG_B_MODE); | ||
630 | else | ||
631 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
632 | AR5K_TXCFG_B_MODE); | ||
633 | } | ||
634 | |||
635 | /* | ||
636 | * Set channel and calibrate the PHY | ||
637 | */ | ||
638 | ret = ath5k_hw_channel(ah, channel); | ||
639 | if (ret) | ||
640 | return ret; | ||
641 | |||
642 | /* Set antenna mode */ | ||
643 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL, | ||
644 | ah->ah_antenna[ee_mode][0], 0xfffffc06); | ||
645 | |||
646 | /* | ||
647 | * In case a fixed antenna was set as default | ||
648 | * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE | ||
649 | * registers. | ||
650 | */ | ||
651 | if (s_ant != 0) { | ||
652 | if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ | ||
653 | ant[0] = ant[1] = AR5K_ANT_FIXED_A; | ||
654 | else /* 2 - Aux */ | ||
655 | ant[0] = ant[1] = AR5K_ANT_FIXED_B; | ||
656 | } else { | ||
657 | ant[0] = AR5K_ANT_FIXED_A; | ||
658 | ant[1] = AR5K_ANT_FIXED_B; | ||
659 | } | ||
660 | |||
661 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], | ||
662 | AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
663 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], | ||
664 | AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
665 | |||
666 | /* Commit values from EEPROM */ | ||
667 | if (ah->ah_radio == AR5K_RF5111) | ||
668 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, | ||
669 | AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip); | ||
670 | |||
671 | ath5k_hw_reg_write(ah, | ||
672 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), | ||
673 | AR5K_PHY_NFTHRES); | ||
674 | |||
675 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING, | ||
676 | (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, | ||
677 | 0xffffc07f); | ||
678 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, | ||
679 | (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, | ||
680 | 0xfffc0fff); | ||
681 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, | ||
682 | (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | | ||
683 | ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), | ||
684 | 0xffff0000); | ||
685 | |||
686 | ath5k_hw_reg_write(ah, | ||
687 | (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | | ||
688 | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | | ||
689 | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | | ||
690 | (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); | ||
691 | |||
692 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3, | ||
693 | ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); | ||
694 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF, | ||
695 | (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); | ||
696 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01); | ||
697 | |||
698 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
699 | AR5K_PHY_IQ_CORR_ENABLE | | ||
700 | (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | | ||
701 | ee->ee_q_cal[ee_mode]); | ||
702 | |||
703 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
704 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, | ||
705 | AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, | ||
706 | ee->ee_margin_tx_rx[ee_mode]); | ||
707 | |||
708 | } else { | ||
709 | mdelay(1); | ||
710 | /* Disable phy and wait */ | ||
711 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
712 | mdelay(1); | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Restore saved values | ||
717 | */ | ||
718 | /*DCU/Antenna selection not available on 5210*/ | ||
719 | if (ah->ah_version != AR5K_AR5210) { | ||
720 | ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0)); | ||
721 | ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); | ||
722 | } | ||
723 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); | ||
724 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); | ||
725 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | ||
726 | |||
727 | /* | ||
728 | * Misc | ||
729 | */ | ||
730 | /* XXX: add ah->aid once mac80211 gives this to us */ | ||
731 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
732 | |||
733 | ath5k_hw_set_opmode(ah); | ||
734 | /*PISR/SISR Not available on 5210*/ | ||
735 | if (ah->ah_version != AR5K_AR5210) { | ||
736 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
737 | /* If we later allow tuning for this, store into sc structure */ | ||
738 | data = AR5K_TUNE_RSSI_THRES | | ||
739 | AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S; | ||
740 | ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR); | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * Set Rx/Tx DMA Configuration | ||
745 | * | ||
746 | * Set maximum DMA size (512) except for PCI-E cards since | ||
747 | * it causes rx overruns and tx errors (tested on 5424 but since | ||
748 | * rx overruns also occur on 5416/5418 with madwifi we set 128 | ||
749 | * for all PCI-E cards to be safe). | ||
750 | * | ||
751 | * In dumps this is 128 for allchips. | ||
752 | * | ||
753 | * XXX: need to check 5210 for this | ||
754 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
755 | * guess we can tweak it and see how it goes ;-) | ||
756 | */ | ||
757 | dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B; | ||
758 | if (ah->ah_version != AR5K_AR5210) { | ||
759 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
760 | AR5K_TXCFG_SDMAMR, dma_size); | ||
761 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
762 | AR5K_RXCFG_SDMAMW, dma_size); | ||
763 | } | ||
764 | |||
765 | /* | ||
766 | * Enable the PHY and wait until completion | ||
767 | */ | ||
768 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
769 | |||
770 | /* | ||
771 | * On 5211+ read activation -> rx delay | ||
772 | * and use it. | ||
773 | */ | ||
774 | if (ah->ah_version != AR5K_AR5210) { | ||
775 | data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
776 | AR5K_PHY_RX_DELAY_M; | ||
777 | data = (channel->hw_value & CHANNEL_CCK) ? | ||
778 | ((data << 2) / 22) : (data / 10); | ||
779 | |||
780 | udelay(100 + (2 * data)); | ||
781 | data = 0; | ||
782 | } else { | ||
783 | mdelay(1); | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * Perform ADC test (?) | ||
788 | */ | ||
789 | data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
790 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
791 | for (i = 0; i <= 20; i++) { | ||
792 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
793 | break; | ||
794 | udelay(200); | ||
795 | } | ||
796 | ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1); | ||
797 | data = 0; | ||
798 | |||
799 | /* | ||
800 | * Start automatic gain calibration | ||
801 | * | ||
802 | * During AGC calibration RX path is re-routed to | ||
803 | * a signal detector so we don't receive anything. | ||
804 | * | ||
805 | * This method is used to calibrate some static offsets | ||
806 | * used together with on-the fly I/Q calibration (the | ||
807 | * one performed via ath5k_hw_phy_calibrate), that doesn't | ||
808 | * interrupt rx path. | ||
809 | * | ||
810 | * If we are in a noisy environment AGC calibration may time | ||
811 | * out. | ||
812 | */ | ||
813 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
814 | AR5K_PHY_AGCCTL_CAL); | ||
815 | |||
816 | /* At the same time start I/Q calibration for QAM constellation | ||
817 | * -no need for CCK- */ | ||
818 | ah->ah_calibration = false; | ||
819 | if (!(mode == AR5K_MODE_11B)) { | ||
820 | ah->ah_calibration = true; | ||
821 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
822 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
823 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
824 | AR5K_PHY_IQ_RUN); | ||
825 | } | ||
826 | |||
827 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
828 | * during ath5k_phy_calibrate) */ | ||
829 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
830 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
831 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
832 | channel->center_freq); | ||
833 | return -EAGAIN; | ||
834 | } | ||
835 | |||
836 | /* | ||
837 | * Start noise floor calibration | ||
838 | * | ||
839 | * If we run NF calibration before AGC, it always times out. | ||
840 | * Binary HAL starts NF and AGC calibration at the same time | ||
841 | * and only waits for AGC to finish. I believe that's wrong because | ||
842 | * during NF calibration, rx path is also routed to a detector, so if | ||
843 | * it doesn't finish we won't have RX. | ||
844 | * | ||
845 | * XXX: Find an interval that's OK for all cards... | ||
846 | */ | ||
847 | ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | ||
848 | if (ret) | ||
849 | return ret; | ||
850 | |||
851 | /* | ||
852 | * Reset queues and start beacon timers at the end of the reset routine | ||
853 | */ | ||
854 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
855 | /*No QCU on 5210*/ | ||
856 | if (ah->ah_version != AR5K_AR5210) | ||
857 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i); | ||
858 | |||
859 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
860 | if (ret) { | ||
861 | ATH5K_ERR(ah->ah_sc, | ||
862 | "failed to reset TX queue #%d\n", i); | ||
863 | return ret; | ||
864 | } | ||
865 | } | ||
866 | |||
867 | /* Pre-enable interrupts on 5211/5212*/ | ||
868 | if (ah->ah_version != AR5K_AR5210) | ||
869 | ath5k_hw_set_imr(ah, AR5K_INT_RX | AR5K_INT_TX | | ||
870 | AR5K_INT_FATAL); | ||
871 | |||
872 | /* | ||
873 | * Set RF kill flags if supported by the device (read from the EEPROM) | ||
874 | * Disable gpio_intr for now since it results system hang. | ||
875 | * TODO: Handle this in ath5k_intr | ||
876 | */ | ||
877 | #if 0 | ||
878 | if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { | ||
879 | ath5k_hw_set_gpio_input(ah, 0); | ||
880 | ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); | ||
881 | if (ah->ah_gpio[0] == 0) | ||
882 | ath5k_hw_set_gpio_intr(ah, 0, 1); | ||
883 | else | ||
884 | ath5k_hw_set_gpio_intr(ah, 0, 0); | ||
885 | } | ||
886 | #endif | ||
887 | |||
888 | /* | ||
889 | * Set the 32MHz reference clock on 5212 phy clock sleep register | ||
890 | * | ||
891 | * TODO: Find out how to switch to external 32Khz clock to save power | ||
892 | */ | ||
893 | if (ah->ah_version == AR5K_AR5212) { | ||
894 | ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); | ||
895 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
896 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); | ||
897 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
898 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
899 | ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); | ||
900 | |||
901 | data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ; | ||
902 | data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ? | ||
903 | 0x00000f80 : 0x00001380 ; | ||
904 | ath5k_hw_reg_write(ah, data, AR5K_USEC_5211); | ||
905 | data = 0; | ||
906 | } | ||
907 | |||
908 | if (ah->ah_version == AR5K_AR5212) { | ||
909 | ath5k_hw_reg_write(ah, 0x000100aa, 0x8118); | ||
910 | ath5k_hw_reg_write(ah, 0x00003210, 0x811c); | ||
911 | ath5k_hw_reg_write(ah, 0x00000052, 0x8108); | ||
912 | if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413) | ||
913 | ath5k_hw_reg_write(ah, 0x00000004, 0x8120); | ||
914 | } | ||
915 | |||
916 | /* | ||
917 | * Disable beacons and reset the register | ||
918 | */ | ||
919 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | | ||
920 | AR5K_BEACON_RESET_TSF); | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | #undef _ATH5K_RESET | ||