]>
Commit | Line | Data |
---|---|---|
89297425 BZ |
1 | /* |
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz | |
3 | ||
4 | Based on the original rt2800pci.c and rt2800usb.c: | |
5 | ||
6 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | |
7 | <http://rt2x00.serialmonkey.com> | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program; if not, write to the | |
21 | Free Software Foundation, Inc., | |
22 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
23 | */ | |
24 | ||
25 | /* | |
26 | Module: rt2800lib | |
27 | Abstract: rt2800 generic device routines. | |
28 | */ | |
29 | ||
30 | #include <linux/kernel.h> | |
31 | #include <linux/module.h> | |
32 | ||
33 | #include "rt2x00.h" | |
34 | #include "rt2800lib.h" | |
35 | #include "rt2800.h" | |
36 | ||
37 | MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); | |
38 | MODULE_DESCRIPTION("rt2800 library"); | |
39 | MODULE_LICENSE("GPL"); | |
40 | ||
41 | /* | |
42 | * Register access. | |
43 | * All access to the CSR registers will go through the methods | |
44 | * rt2800_register_read and rt2800_register_write. | |
45 | * BBP and RF register require indirect register access, | |
46 | * and use the CSR registers BBPCSR and RFCSR to achieve this. | |
47 | * These indirect registers work with busy bits, | |
48 | * and we will try maximal REGISTER_BUSY_COUNT times to access | |
49 | * the register while taking a REGISTER_BUSY_DELAY us delay | |
50 | * between each attampt. When the busy bit is still set at that time, | |
51 | * the access attempt is considered to have failed, | |
52 | * and we will print an error. | |
53 | * The _lock versions must be used if you already hold the csr_mutex | |
54 | */ | |
55 | #define WAIT_FOR_BBP(__dev, __reg) \ | |
56 | rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) | |
57 | #define WAIT_FOR_RFCSR(__dev, __reg) \ | |
58 | rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) | |
59 | #define WAIT_FOR_RF(__dev, __reg) \ | |
60 | rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) | |
61 | #define WAIT_FOR_MCU(__dev, __reg) \ | |
62 | rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \ | |
63 | H2M_MAILBOX_CSR_OWNER, (__reg)) | |
64 | ||
65 | void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, | |
66 | const unsigned int word, const u8 value) | |
67 | { | |
68 | u32 reg; | |
69 | ||
70 | mutex_lock(&rt2x00dev->csr_mutex); | |
71 | ||
72 | /* | |
73 | * Wait until the BBP becomes available, afterwards we | |
74 | * can safely write the new data into the register. | |
75 | */ | |
76 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { | |
77 | reg = 0; | |
78 | rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); | |
79 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | |
80 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | |
81 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); | |
82 | if (rt2x00_intf_is_pci(rt2x00dev)) | |
83 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | |
84 | ||
85 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | |
86 | } | |
87 | ||
88 | mutex_unlock(&rt2x00dev->csr_mutex); | |
89 | } | |
90 | EXPORT_SYMBOL_GPL(rt2800_bbp_write); | |
91 | ||
92 | void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, | |
93 | const unsigned int word, u8 *value) | |
94 | { | |
95 | u32 reg; | |
96 | ||
97 | mutex_lock(&rt2x00dev->csr_mutex); | |
98 | ||
99 | /* | |
100 | * Wait until the BBP becomes available, afterwards we | |
101 | * can safely write the read request into the register. | |
102 | * After the data has been written, we wait until hardware | |
103 | * returns the correct value, if at any time the register | |
104 | * doesn't become available in time, reg will be 0xffffffff | |
105 | * which means we return 0xff to the caller. | |
106 | */ | |
107 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { | |
108 | reg = 0; | |
109 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | |
110 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | |
111 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); | |
112 | if (rt2x00_intf_is_pci(rt2x00dev)) | |
113 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | |
114 | ||
115 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | |
116 | ||
117 | WAIT_FOR_BBP(rt2x00dev, ®); | |
118 | } | |
119 | ||
120 | *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); | |
121 | ||
122 | mutex_unlock(&rt2x00dev->csr_mutex); | |
123 | } | |
124 | EXPORT_SYMBOL_GPL(rt2800_bbp_read); | |
125 | ||
126 | void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev, | |
127 | const unsigned int word, const u8 value) | |
128 | { | |
129 | u32 reg; | |
130 | ||
131 | mutex_lock(&rt2x00dev->csr_mutex); | |
132 | ||
133 | /* | |
134 | * Wait until the RFCSR becomes available, afterwards we | |
135 | * can safely write the new data into the register. | |
136 | */ | |
137 | if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { | |
138 | reg = 0; | |
139 | rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); | |
140 | rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); | |
141 | rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); | |
142 | rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); | |
143 | ||
144 | rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); | |
145 | } | |
146 | ||
147 | mutex_unlock(&rt2x00dev->csr_mutex); | |
148 | } | |
149 | EXPORT_SYMBOL_GPL(rt2800_rfcsr_write); | |
150 | ||
151 | void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev, | |
152 | const unsigned int word, u8 *value) | |
153 | { | |
154 | u32 reg; | |
155 | ||
156 | mutex_lock(&rt2x00dev->csr_mutex); | |
157 | ||
158 | /* | |
159 | * Wait until the RFCSR becomes available, afterwards we | |
160 | * can safely write the read request into the register. | |
161 | * After the data has been written, we wait until hardware | |
162 | * returns the correct value, if at any time the register | |
163 | * doesn't become available in time, reg will be 0xffffffff | |
164 | * which means we return 0xff to the caller. | |
165 | */ | |
166 | if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { | |
167 | reg = 0; | |
168 | rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); | |
169 | rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); | |
170 | rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); | |
171 | ||
172 | rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); | |
173 | ||
174 | WAIT_FOR_RFCSR(rt2x00dev, ®); | |
175 | } | |
176 | ||
177 | *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); | |
178 | ||
179 | mutex_unlock(&rt2x00dev->csr_mutex); | |
180 | } | |
181 | EXPORT_SYMBOL_GPL(rt2800_rfcsr_read); | |
182 | ||
183 | void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, | |
184 | const unsigned int word, const u32 value) | |
185 | { | |
186 | u32 reg; | |
187 | ||
188 | mutex_lock(&rt2x00dev->csr_mutex); | |
189 | ||
190 | /* | |
191 | * Wait until the RF becomes available, afterwards we | |
192 | * can safely write the new data into the register. | |
193 | */ | |
194 | if (WAIT_FOR_RF(rt2x00dev, ®)) { | |
195 | reg = 0; | |
196 | rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); | |
197 | rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); | |
198 | rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); | |
199 | rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); | |
200 | ||
201 | rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); | |
202 | rt2x00_rf_write(rt2x00dev, word, value); | |
203 | } | |
204 | ||
205 | mutex_unlock(&rt2x00dev->csr_mutex); | |
206 | } | |
207 | EXPORT_SYMBOL_GPL(rt2800_rf_write); | |
208 | ||
209 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |
210 | const u8 command, const u8 token, | |
211 | const u8 arg0, const u8 arg1) | |
212 | { | |
213 | u32 reg; | |
214 | ||
215 | if (rt2x00_intf_is_pci(rt2x00dev)) { | |
216 | /* | |
217 | * RT2880 and RT3052 don't support MCU requests. | |
218 | */ | |
219 | if (rt2x00_rt(&rt2x00dev->chip, RT2880) || | |
220 | rt2x00_rt(&rt2x00dev->chip, RT3052)) | |
221 | return; | |
222 | } | |
223 | ||
224 | mutex_lock(&rt2x00dev->csr_mutex); | |
225 | ||
226 | /* | |
227 | * Wait until the MCU becomes available, afterwards we | |
228 | * can safely write the new data into the register. | |
229 | */ | |
230 | if (WAIT_FOR_MCU(rt2x00dev, ®)) { | |
231 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); | |
232 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); | |
233 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); | |
234 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); | |
235 | rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); | |
236 | ||
237 | reg = 0; | |
238 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | |
239 | rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); | |
240 | } | |
241 | ||
242 | mutex_unlock(&rt2x00dev->csr_mutex); | |
243 | } | |
244 | EXPORT_SYMBOL_GPL(rt2800_mcu_request); | |
f4450616 BZ |
245 | |
246 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | |
247 | const struct rt2x00debug rt2800_rt2x00debug = { | |
248 | .owner = THIS_MODULE, | |
249 | .csr = { | |
250 | .read = rt2800_register_read, | |
251 | .write = rt2800_register_write, | |
252 | .flags = RT2X00DEBUGFS_OFFSET, | |
253 | .word_base = CSR_REG_BASE, | |
254 | .word_size = sizeof(u32), | |
255 | .word_count = CSR_REG_SIZE / sizeof(u32), | |
256 | }, | |
257 | .eeprom = { | |
258 | .read = rt2x00_eeprom_read, | |
259 | .write = rt2x00_eeprom_write, | |
260 | .word_base = EEPROM_BASE, | |
261 | .word_size = sizeof(u16), | |
262 | .word_count = EEPROM_SIZE / sizeof(u16), | |
263 | }, | |
264 | .bbp = { | |
265 | .read = rt2800_bbp_read, | |
266 | .write = rt2800_bbp_write, | |
267 | .word_base = BBP_BASE, | |
268 | .word_size = sizeof(u8), | |
269 | .word_count = BBP_SIZE / sizeof(u8), | |
270 | }, | |
271 | .rf = { | |
272 | .read = rt2x00_rf_read, | |
273 | .write = rt2800_rf_write, | |
274 | .word_base = RF_BASE, | |
275 | .word_size = sizeof(u32), | |
276 | .word_count = RF_SIZE / sizeof(u32), | |
277 | }, | |
278 | }; | |
279 | EXPORT_SYMBOL_GPL(rt2800_rt2x00debug); | |
280 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | |
281 | ||
282 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |
283 | { | |
284 | u32 reg; | |
285 | ||
286 | rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | |
287 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | |
288 | } | |
289 | EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); | |
290 | ||
291 | #ifdef CONFIG_RT2X00_LIB_LEDS | |
292 | static void rt2800_brightness_set(struct led_classdev *led_cdev, | |
293 | enum led_brightness brightness) | |
294 | { | |
295 | struct rt2x00_led *led = | |
296 | container_of(led_cdev, struct rt2x00_led, led_dev); | |
297 | unsigned int enabled = brightness != LED_OFF; | |
298 | unsigned int bg_mode = | |
299 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | |
300 | unsigned int polarity = | |
301 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | |
302 | EEPROM_FREQ_LED_POLARITY); | |
303 | unsigned int ledmode = | |
304 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | |
305 | EEPROM_FREQ_LED_MODE); | |
306 | ||
307 | if (led->type == LED_TYPE_RADIO) { | |
308 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | |
309 | enabled ? 0x20 : 0); | |
310 | } else if (led->type == LED_TYPE_ASSOC) { | |
311 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | |
312 | enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); | |
313 | } else if (led->type == LED_TYPE_QUALITY) { | |
314 | /* | |
315 | * The brightness is divided into 6 levels (0 - 5), | |
316 | * The specs tell us the following levels: | |
317 | * 0, 1 ,3, 7, 15, 31 | |
318 | * to determine the level in a simple way we can simply | |
319 | * work with bitshifting: | |
320 | * (1 << level) - 1 | |
321 | */ | |
322 | rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, | |
323 | (1 << brightness / (LED_FULL / 6)) - 1, | |
324 | polarity); | |
325 | } | |
326 | } | |
327 | ||
328 | static int rt2800_blink_set(struct led_classdev *led_cdev, | |
329 | unsigned long *delay_on, unsigned long *delay_off) | |
330 | { | |
331 | struct rt2x00_led *led = | |
332 | container_of(led_cdev, struct rt2x00_led, led_dev); | |
333 | u32 reg; | |
334 | ||
335 | rt2800_register_read(led->rt2x00dev, LED_CFG, ®); | |
336 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); | |
337 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); | |
338 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | |
339 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | |
340 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); | |
341 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | |
342 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | |
343 | rt2800_register_write(led->rt2x00dev, LED_CFG, reg); | |
344 | ||
345 | return 0; | |
346 | } | |
347 | ||
348 | void rt2800_init_led(struct rt2x00_dev *rt2x00dev, | |
349 | struct rt2x00_led *led, enum led_type type) | |
350 | { | |
351 | led->rt2x00dev = rt2x00dev; | |
352 | led->type = type; | |
353 | led->led_dev.brightness_set = rt2800_brightness_set; | |
354 | led->led_dev.blink_set = rt2800_blink_set; | |
355 | led->flags = LED_INITIALIZED; | |
356 | } | |
357 | EXPORT_SYMBOL_GPL(rt2800_init_led); | |
358 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | |
359 | ||
360 | /* | |
361 | * Configuration handlers. | |
362 | */ | |
363 | static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | |
364 | struct rt2x00lib_crypto *crypto, | |
365 | struct ieee80211_key_conf *key) | |
366 | { | |
367 | struct mac_wcid_entry wcid_entry; | |
368 | struct mac_iveiv_entry iveiv_entry; | |
369 | u32 offset; | |
370 | u32 reg; | |
371 | ||
372 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | |
373 | ||
374 | rt2800_register_read(rt2x00dev, offset, ®); | |
375 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | |
376 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | |
377 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | |
378 | (crypto->cmd == SET_KEY) * crypto->cipher); | |
379 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | |
380 | (crypto->cmd == SET_KEY) * crypto->bssidx); | |
381 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | |
382 | rt2800_register_write(rt2x00dev, offset, reg); | |
383 | ||
384 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | |
385 | ||
386 | memset(&iveiv_entry, 0, sizeof(iveiv_entry)); | |
387 | if ((crypto->cipher == CIPHER_TKIP) || | |
388 | (crypto->cipher == CIPHER_TKIP_NO_MIC) || | |
389 | (crypto->cipher == CIPHER_AES)) | |
390 | iveiv_entry.iv[3] |= 0x20; | |
391 | iveiv_entry.iv[3] |= key->keyidx << 6; | |
392 | rt2800_register_multiwrite(rt2x00dev, offset, | |
393 | &iveiv_entry, sizeof(iveiv_entry)); | |
394 | ||
395 | offset = MAC_WCID_ENTRY(key->hw_key_idx); | |
396 | ||
397 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | |
398 | if (crypto->cmd == SET_KEY) | |
399 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | |
400 | rt2800_register_multiwrite(rt2x00dev, offset, | |
401 | &wcid_entry, sizeof(wcid_entry)); | |
402 | } | |
403 | ||
404 | int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, | |
405 | struct rt2x00lib_crypto *crypto, | |
406 | struct ieee80211_key_conf *key) | |
407 | { | |
408 | struct hw_key_entry key_entry; | |
409 | struct rt2x00_field32 field; | |
410 | u32 offset; | |
411 | u32 reg; | |
412 | ||
413 | if (crypto->cmd == SET_KEY) { | |
414 | key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; | |
415 | ||
416 | memcpy(key_entry.key, crypto->key, | |
417 | sizeof(key_entry.key)); | |
418 | memcpy(key_entry.tx_mic, crypto->tx_mic, | |
419 | sizeof(key_entry.tx_mic)); | |
420 | memcpy(key_entry.rx_mic, crypto->rx_mic, | |
421 | sizeof(key_entry.rx_mic)); | |
422 | ||
423 | offset = SHARED_KEY_ENTRY(key->hw_key_idx); | |
424 | rt2800_register_multiwrite(rt2x00dev, offset, | |
425 | &key_entry, sizeof(key_entry)); | |
426 | } | |
427 | ||
428 | /* | |
429 | * The cipher types are stored over multiple registers | |
430 | * starting with SHARED_KEY_MODE_BASE each word will have | |
431 | * 32 bits and contains the cipher types for 2 bssidx each. | |
432 | * Using the correct defines correctly will cause overhead, | |
433 | * so just calculate the correct offset. | |
434 | */ | |
435 | field.bit_offset = 4 * (key->hw_key_idx % 8); | |
436 | field.bit_mask = 0x7 << field.bit_offset; | |
437 | ||
438 | offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); | |
439 | ||
440 | rt2800_register_read(rt2x00dev, offset, ®); | |
441 | rt2x00_set_field32(®, field, | |
442 | (crypto->cmd == SET_KEY) * crypto->cipher); | |
443 | rt2800_register_write(rt2x00dev, offset, reg); | |
444 | ||
445 | /* | |
446 | * Update WCID information | |
447 | */ | |
448 | rt2800_config_wcid_attr(rt2x00dev, crypto, key); | |
449 | ||
450 | return 0; | |
451 | } | |
452 | EXPORT_SYMBOL_GPL(rt2800_config_shared_key); | |
453 | ||
454 | int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |
455 | struct rt2x00lib_crypto *crypto, | |
456 | struct ieee80211_key_conf *key) | |
457 | { | |
458 | struct hw_key_entry key_entry; | |
459 | u32 offset; | |
460 | ||
461 | if (crypto->cmd == SET_KEY) { | |
462 | /* | |
463 | * 1 pairwise key is possible per AID, this means that the AID | |
464 | * equals our hw_key_idx. Make sure the WCID starts _after_ the | |
465 | * last possible shared key entry. | |
466 | */ | |
467 | if (crypto->aid > (256 - 32)) | |
468 | return -ENOSPC; | |
469 | ||
470 | key->hw_key_idx = 32 + crypto->aid; | |
471 | ||
472 | memcpy(key_entry.key, crypto->key, | |
473 | sizeof(key_entry.key)); | |
474 | memcpy(key_entry.tx_mic, crypto->tx_mic, | |
475 | sizeof(key_entry.tx_mic)); | |
476 | memcpy(key_entry.rx_mic, crypto->rx_mic, | |
477 | sizeof(key_entry.rx_mic)); | |
478 | ||
479 | offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | |
480 | rt2800_register_multiwrite(rt2x00dev, offset, | |
481 | &key_entry, sizeof(key_entry)); | |
482 | } | |
483 | ||
484 | /* | |
485 | * Update WCID information | |
486 | */ | |
487 | rt2800_config_wcid_attr(rt2x00dev, crypto, key); | |
488 | ||
489 | return 0; | |
490 | } | |
491 | EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); | |
492 | ||
493 | void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, | |
494 | const unsigned int filter_flags) | |
495 | { | |
496 | u32 reg; | |
497 | ||
498 | /* | |
499 | * Start configuration steps. | |
500 | * Note that the version error will always be dropped | |
501 | * and broadcast frames will always be accepted since | |
502 | * there is no filter for it at this time. | |
503 | */ | |
504 | rt2800_register_read(rt2x00dev, RX_FILTER_CFG, ®); | |
505 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, | |
506 | !(filter_flags & FIF_FCSFAIL)); | |
507 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, | |
508 | !(filter_flags & FIF_PLCPFAIL)); | |
509 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, | |
510 | !(filter_flags & FIF_PROMISC_IN_BSS)); | |
511 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); | |
512 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); | |
513 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, | |
514 | !(filter_flags & FIF_ALLMULTI)); | |
515 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); | |
516 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); | |
517 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, | |
518 | !(filter_flags & FIF_CONTROL)); | |
519 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, | |
520 | !(filter_flags & FIF_CONTROL)); | |
521 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, | |
522 | !(filter_flags & FIF_CONTROL)); | |
523 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, | |
524 | !(filter_flags & FIF_CONTROL)); | |
525 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, | |
526 | !(filter_flags & FIF_CONTROL)); | |
527 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, | |
528 | !(filter_flags & FIF_PSPOLL)); | |
529 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); | |
530 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); | |
531 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, | |
532 | !(filter_flags & FIF_CONTROL)); | |
533 | rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); | |
534 | } | |
535 | EXPORT_SYMBOL_GPL(rt2800_config_filter); | |
536 | ||
537 | void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |
538 | struct rt2x00intf_conf *conf, const unsigned int flags) | |
539 | { | |
540 | unsigned int beacon_base; | |
541 | u32 reg; | |
542 | ||
543 | if (flags & CONFIG_UPDATE_TYPE) { | |
544 | /* | |
545 | * Clear current synchronisation setup. | |
546 | * For the Beacon base registers we only need to clear | |
547 | * the first byte since that byte contains the VALID and OWNER | |
548 | * bits which (when set to 0) will invalidate the entire beacon. | |
549 | */ | |
550 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | |
551 | rt2800_register_write(rt2x00dev, beacon_base, 0); | |
552 | ||
553 | /* | |
554 | * Enable synchronisation. | |
555 | */ | |
556 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | |
557 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | |
558 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | |
559 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | |
560 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | |
561 | } | |
562 | ||
563 | if (flags & CONFIG_UPDATE_MAC) { | |
564 | reg = le32_to_cpu(conf->mac[1]); | |
565 | rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); | |
566 | conf->mac[1] = cpu_to_le32(reg); | |
567 | ||
568 | rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, | |
569 | conf->mac, sizeof(conf->mac)); | |
570 | } | |
571 | ||
572 | if (flags & CONFIG_UPDATE_BSSID) { | |
573 | reg = le32_to_cpu(conf->bssid[1]); | |
574 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); | |
575 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); | |
576 | conf->bssid[1] = cpu_to_le32(reg); | |
577 | ||
578 | rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, | |
579 | conf->bssid, sizeof(conf->bssid)); | |
580 | } | |
581 | } | |
582 | EXPORT_SYMBOL_GPL(rt2800_config_intf); | |
583 | ||
584 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) | |
585 | { | |
586 | u32 reg; | |
587 | ||
588 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | |
589 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); | |
590 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | |
591 | ||
592 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | |
593 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | |
594 | !!erp->short_preamble); | |
595 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, | |
596 | !!erp->short_preamble); | |
597 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | |
598 | ||
599 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | |
600 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, | |
601 | erp->cts_protection ? 2 : 0); | |
602 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | |
603 | ||
604 | rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, | |
605 | erp->basic_rates); | |
606 | rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | |
607 | ||
608 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | |
609 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | |
610 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | |
611 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | |
612 | ||
613 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | |
614 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); | |
615 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); | |
616 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | |
617 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | |
618 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | |
619 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | |
620 | ||
621 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | |
622 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | |
623 | erp->beacon_int * 16); | |
624 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | |
625 | } | |
626 | EXPORT_SYMBOL_GPL(rt2800_config_erp); | |
627 | ||
628 | void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |
629 | { | |
630 | u8 r1; | |
631 | u8 r3; | |
632 | ||
633 | rt2800_bbp_read(rt2x00dev, 1, &r1); | |
634 | rt2800_bbp_read(rt2x00dev, 3, &r3); | |
635 | ||
636 | /* | |
637 | * Configure the TX antenna. | |
638 | */ | |
639 | switch ((int)ant->tx) { | |
640 | case 1: | |
641 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | |
642 | if (rt2x00_intf_is_pci(rt2x00dev)) | |
643 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | |
644 | break; | |
645 | case 2: | |
646 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | |
647 | break; | |
648 | case 3: | |
649 | /* Do nothing */ | |
650 | break; | |
651 | } | |
652 | ||
653 | /* | |
654 | * Configure the RX antenna. | |
655 | */ | |
656 | switch ((int)ant->rx) { | |
657 | case 1: | |
658 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | |
659 | break; | |
660 | case 2: | |
661 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); | |
662 | break; | |
663 | case 3: | |
664 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); | |
665 | break; | |
666 | } | |
667 | ||
668 | rt2800_bbp_write(rt2x00dev, 3, r3); | |
669 | rt2800_bbp_write(rt2x00dev, 1, r1); | |
670 | } | |
671 | EXPORT_SYMBOL_GPL(rt2800_config_ant); | |
672 | ||
673 | static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |
674 | struct rt2x00lib_conf *libconf) | |
675 | { | |
676 | u16 eeprom; | |
677 | short lna_gain; | |
678 | ||
679 | if (libconf->rf.channel <= 14) { | |
680 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | |
681 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); | |
682 | } else if (libconf->rf.channel <= 64) { | |
683 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | |
684 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); | |
685 | } else if (libconf->rf.channel <= 128) { | |
686 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); | |
687 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); | |
688 | } else { | |
689 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); | |
690 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); | |
691 | } | |
692 | ||
693 | rt2x00dev->lna_gain = lna_gain; | |
694 | } | |
695 | ||
696 | static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | |
697 | struct ieee80211_conf *conf, | |
698 | struct rf_channel *rf, | |
699 | struct channel_info *info) | |
700 | { | |
701 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | |
702 | ||
703 | if (rt2x00dev->default_ant.tx == 1) | |
704 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); | |
705 | ||
706 | if (rt2x00dev->default_ant.rx == 1) { | |
707 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); | |
708 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | |
709 | } else if (rt2x00dev->default_ant.rx == 2) | |
710 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | |
711 | ||
712 | if (rf->channel > 14) { | |
713 | /* | |
714 | * When TX power is below 0, we should increase it by 7 to | |
715 | * make it a positive value (Minumum value is -7). | |
716 | * However this means that values between 0 and 7 have | |
717 | * double meaning, and we should set a 7DBm boost flag. | |
718 | */ | |
719 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, | |
720 | (info->tx_power1 >= 0)); | |
721 | ||
722 | if (info->tx_power1 < 0) | |
723 | info->tx_power1 += 7; | |
724 | ||
725 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, | |
726 | TXPOWER_A_TO_DEV(info->tx_power1)); | |
727 | ||
728 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, | |
729 | (info->tx_power2 >= 0)); | |
730 | ||
731 | if (info->tx_power2 < 0) | |
732 | info->tx_power2 += 7; | |
733 | ||
734 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, | |
735 | TXPOWER_A_TO_DEV(info->tx_power2)); | |
736 | } else { | |
737 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, | |
738 | TXPOWER_G_TO_DEV(info->tx_power1)); | |
739 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, | |
740 | TXPOWER_G_TO_DEV(info->tx_power2)); | |
741 | } | |
742 | ||
743 | rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); | |
744 | ||
745 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | |
746 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | |
747 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | |
748 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | |
749 | ||
750 | udelay(200); | |
751 | ||
752 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | |
753 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | |
754 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); | |
755 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | |
756 | ||
757 | udelay(200); | |
758 | ||
759 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | |
760 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | |
761 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | |
762 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | |
763 | } | |
764 | ||
765 | static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | |
766 | struct ieee80211_conf *conf, | |
767 | struct rf_channel *rf, | |
768 | struct channel_info *info) | |
769 | { | |
770 | u8 rfcsr; | |
771 | ||
772 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); | |
773 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3); | |
774 | ||
775 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | |
776 | rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); | |
777 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | |
778 | ||
779 | rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); | |
780 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | |
781 | TXPOWER_G_TO_DEV(info->tx_power1)); | |
782 | rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); | |
783 | ||
784 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | |
785 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | |
786 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | |
787 | ||
788 | rt2800_rfcsr_write(rt2x00dev, 24, | |
789 | rt2x00dev->calibration[conf_is_ht40(conf)]); | |
790 | ||
791 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | |
792 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | |
793 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | |
794 | } | |
795 | ||
796 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |
797 | struct ieee80211_conf *conf, | |
798 | struct rf_channel *rf, | |
799 | struct channel_info *info) | |
800 | { | |
801 | u32 reg; | |
802 | unsigned int tx_pin; | |
803 | u8 bbp; | |
804 | ||
805 | if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | |
806 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); | |
807 | else | |
808 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); | |
809 | ||
810 | /* | |
811 | * Change BBP settings | |
812 | */ | |
813 | rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | |
814 | rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | |
815 | rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | |
816 | rt2800_bbp_write(rt2x00dev, 86, 0); | |
817 | ||
818 | if (rf->channel <= 14) { | |
819 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { | |
820 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | |
821 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | |
822 | } else { | |
823 | rt2800_bbp_write(rt2x00dev, 82, 0x84); | |
824 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | |
825 | } | |
826 | } else { | |
827 | rt2800_bbp_write(rt2x00dev, 82, 0xf2); | |
828 | ||
829 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) | |
830 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | |
831 | else | |
832 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | |
833 | } | |
834 | ||
835 | rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); | |
836 | rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); | |
837 | rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); | |
838 | rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); | |
839 | rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); | |
840 | ||
841 | tx_pin = 0; | |
842 | ||
843 | /* Turn on unused PA or LNA when not using 1T or 1R */ | |
844 | if (rt2x00dev->default_ant.tx != 1) { | |
845 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); | |
846 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); | |
847 | } | |
848 | ||
849 | /* Turn on unused PA or LNA when not using 1T or 1R */ | |
850 | if (rt2x00dev->default_ant.rx != 1) { | |
851 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); | |
852 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); | |
853 | } | |
854 | ||
855 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); | |
856 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); | |
857 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); | |
858 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); | |
859 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); | |
860 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); | |
861 | ||
862 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | |
863 | ||
864 | rt2800_bbp_read(rt2x00dev, 4, &bbp); | |
865 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | |
866 | rt2800_bbp_write(rt2x00dev, 4, bbp); | |
867 | ||
868 | rt2800_bbp_read(rt2x00dev, 3, &bbp); | |
869 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | |
870 | rt2800_bbp_write(rt2x00dev, 3, bbp); | |
871 | ||
872 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | |
873 | if (conf_is_ht40(conf)) { | |
874 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | |
875 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | |
876 | rt2800_bbp_write(rt2x00dev, 73, 0x16); | |
877 | } else { | |
878 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | |
879 | rt2800_bbp_write(rt2x00dev, 70, 0x08); | |
880 | rt2800_bbp_write(rt2x00dev, 73, 0x11); | |
881 | } | |
882 | } | |
883 | ||
884 | msleep(1); | |
885 | } | |
886 | ||
887 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |
888 | const int txpower) | |
889 | { | |
890 | u32 reg; | |
891 | u32 value = TXPOWER_G_TO_DEV(txpower); | |
892 | u8 r1; | |
893 | ||
894 | rt2800_bbp_read(rt2x00dev, 1, &r1); | |
895 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | |
896 | rt2800_bbp_write(rt2x00dev, 1, r1); | |
897 | ||
898 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | |
899 | rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); | |
900 | rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); | |
901 | rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); | |
902 | rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); | |
903 | rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); | |
904 | rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); | |
905 | rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); | |
906 | rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); | |
907 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg); | |
908 | ||
909 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, ®); | |
910 | rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); | |
911 | rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); | |
912 | rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); | |
913 | rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); | |
914 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); | |
915 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); | |
916 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); | |
917 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); | |
918 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg); | |
919 | ||
920 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, ®); | |
921 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); | |
922 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); | |
923 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); | |
924 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); | |
925 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); | |
926 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); | |
927 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); | |
928 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); | |
929 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg); | |
930 | ||
931 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, ®); | |
932 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); | |
933 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); | |
934 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); | |
935 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); | |
936 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); | |
937 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); | |
938 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); | |
939 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); | |
940 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg); | |
941 | ||
942 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, ®); | |
943 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); | |
944 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); | |
945 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); | |
946 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); | |
947 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg); | |
948 | } | |
949 | ||
950 | static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |
951 | struct rt2x00lib_conf *libconf) | |
952 | { | |
953 | u32 reg; | |
954 | ||
955 | rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); | |
956 | rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, | |
957 | libconf->conf->short_frame_max_tx_count); | |
958 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, | |
959 | libconf->conf->long_frame_max_tx_count); | |
960 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | |
961 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | |
962 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | |
963 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | |
964 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); | |
965 | } | |
966 | ||
967 | static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev, | |
968 | struct rt2x00lib_conf *libconf) | |
969 | { | |
970 | enum dev_state state = | |
971 | (libconf->conf->flags & IEEE80211_CONF_PS) ? | |
972 | STATE_SLEEP : STATE_AWAKE; | |
973 | u32 reg; | |
974 | ||
975 | if (state == STATE_SLEEP) { | |
976 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); | |
977 | ||
978 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | |
979 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); | |
980 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, | |
981 | libconf->conf->listen_interval - 1); | |
982 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); | |
983 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | |
984 | ||
985 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | |
986 | } else { | |
987 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | |
988 | ||
989 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | |
990 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | |
991 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | |
992 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | |
993 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | |
994 | } | |
995 | } | |
996 | ||
997 | void rt2800_config(struct rt2x00_dev *rt2x00dev, | |
998 | struct rt2x00lib_conf *libconf, | |
999 | const unsigned int flags) | |
1000 | { | |
1001 | /* Always recalculate LNA gain before changing configuration */ | |
1002 | rt2800_config_lna_gain(rt2x00dev, libconf); | |
1003 | ||
1004 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) | |
1005 | rt2800_config_channel(rt2x00dev, libconf->conf, | |
1006 | &libconf->rf, &libconf->channel); | |
1007 | if (flags & IEEE80211_CONF_CHANGE_POWER) | |
1008 | rt2800_config_txpower(rt2x00dev, libconf->conf->power_level); | |
1009 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | |
1010 | rt2800_config_retry_limit(rt2x00dev, libconf); | |
1011 | if (flags & IEEE80211_CONF_CHANGE_PS) | |
1012 | rt2800_config_ps(rt2x00dev, libconf); | |
1013 | } | |
1014 | EXPORT_SYMBOL_GPL(rt2800_config); | |
1015 | ||
1016 | /* | |
1017 | * Link tuning | |
1018 | */ | |
1019 | void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual) | |
1020 | { | |
1021 | u32 reg; | |
1022 | ||
1023 | /* | |
1024 | * Update FCS error count from register. | |
1025 | */ | |
1026 | rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®); | |
1027 | qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); | |
1028 | } | |
1029 | EXPORT_SYMBOL_GPL(rt2800_link_stats); | |
1030 | ||
1031 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |
1032 | { | |
1033 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | |
1034 | if (rt2x00_intf_is_usb(rt2x00dev) && | |
1035 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) | |
1036 | return 0x1c + (2 * rt2x00dev->lna_gain); | |
1037 | else | |
1038 | return 0x2e + rt2x00dev->lna_gain; | |
1039 | } | |
1040 | ||
1041 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | |
1042 | return 0x32 + (rt2x00dev->lna_gain * 5) / 3; | |
1043 | else | |
1044 | return 0x3a + (rt2x00dev->lna_gain * 5) / 3; | |
1045 | } | |
1046 | ||
1047 | static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | |
1048 | struct link_qual *qual, u8 vgc_level) | |
1049 | { | |
1050 | if (qual->vgc_level != vgc_level) { | |
1051 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | |
1052 | qual->vgc_level = vgc_level; | |
1053 | qual->vgc_level_reg = vgc_level; | |
1054 | } | |
1055 | } | |
1056 | ||
1057 | void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual) | |
1058 | { | |
1059 | rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev)); | |
1060 | } | |
1061 | EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |
1062 | ||
1063 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | |
1064 | const u32 count) | |
1065 | { | |
1066 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | |
1067 | return; | |
1068 | ||
1069 | /* | |
1070 | * When RSSI is better then -80 increase VGC level with 0x10 | |
1071 | */ | |
1072 | rt2800_set_vgc(rt2x00dev, qual, | |
1073 | rt2800_get_default_vgc(rt2x00dev) + | |
1074 | ((qual->rssi > -80) * 0x10)); | |
1075 | } | |
1076 | EXPORT_SYMBOL_GPL(rt2800_link_tuner); |