diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-11-04 12:36:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-06 16:48:58 -0500 |
commit | f445061630c7a4a85193fdef006234f94f71c366 (patch) | |
tree | 518141ce242b2722e532318034525da282dc945b | |
parent | 89297425c2104b187c25d6260a41345c491c8f18 (diff) |
rt2800: add rt2800lib (part two)
Code unification.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 832 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 854 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 856 |
4 files changed, 887 insertions, 1680 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3cbe85434ce3..ba88d643edd3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -242,3 +242,835 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
242 | mutex_unlock(&rt2x00dev->csr_mutex); | 242 | mutex_unlock(&rt2x00dev->csr_mutex); |
243 | } | 243 | } |
244 | EXPORT_SYMBOL_GPL(rt2800_mcu_request); | 244 | EXPORT_SYMBOL_GPL(rt2800_mcu_request); |
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); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 40a7f72e87f5..b07caba37817 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -110,4 +110,29 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
110 | const u8 command, const u8 token, | 110 | const u8 command, const u8 token, |
111 | const u8 arg0, const u8 arg1); | 111 | const u8 arg0, const u8 arg1); |
112 | 112 | ||
113 | extern const struct rt2x00debug rt2800_rt2x00debug; | ||
114 | |||
115 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); | ||
116 | void rt2800_init_led(struct rt2x00_dev *rt2x00dev, | ||
117 | struct rt2x00_led *led, enum led_type type); | ||
118 | int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
119 | struct rt2x00lib_crypto *crypto, | ||
120 | struct ieee80211_key_conf *key); | ||
121 | int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
122 | struct rt2x00lib_crypto *crypto, | ||
123 | struct ieee80211_key_conf *key); | ||
124 | void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, | ||
125 | const unsigned int filter_flags); | ||
126 | void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | ||
127 | struct rt2x00intf_conf *conf, const unsigned int flags); | ||
128 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp); | ||
129 | void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); | ||
130 | void rt2800_config(struct rt2x00_dev *rt2x00dev, | ||
131 | struct rt2x00lib_conf *libconf, | ||
132 | const unsigned int flags); | ||
133 | void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); | ||
134 | void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); | ||
135 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | ||
136 | const u32 count); | ||
137 | |||
113 | #endif /* RT2800LIB_H */ | 138 | #endif /* RT2800LIB_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 90ada5d014fd..cbf8be3057ef 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -187,830 +187,6 @@ static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | |||
187 | } | 187 | } |
188 | #endif /* CONFIG_RT2800PCI_PCI */ | 188 | #endif /* CONFIG_RT2800PCI_PCI */ |
189 | 189 | ||
190 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
191 | static const struct rt2x00debug rt2800pci_rt2x00debug = { | ||
192 | .owner = THIS_MODULE, | ||
193 | .csr = { | ||
194 | .read = rt2800_register_read, | ||
195 | .write = rt2800_register_write, | ||
196 | .flags = RT2X00DEBUGFS_OFFSET, | ||
197 | .word_base = CSR_REG_BASE, | ||
198 | .word_size = sizeof(u32), | ||
199 | .word_count = CSR_REG_SIZE / sizeof(u32), | ||
200 | }, | ||
201 | .eeprom = { | ||
202 | .read = rt2x00_eeprom_read, | ||
203 | .write = rt2x00_eeprom_write, | ||
204 | .word_base = EEPROM_BASE, | ||
205 | .word_size = sizeof(u16), | ||
206 | .word_count = EEPROM_SIZE / sizeof(u16), | ||
207 | }, | ||
208 | .bbp = { | ||
209 | .read = rt2800_bbp_read, | ||
210 | .write = rt2800_bbp_write, | ||
211 | .word_base = BBP_BASE, | ||
212 | .word_size = sizeof(u8), | ||
213 | .word_count = BBP_SIZE / sizeof(u8), | ||
214 | }, | ||
215 | .rf = { | ||
216 | .read = rt2x00_rf_read, | ||
217 | .write = rt2800_rf_write, | ||
218 | .word_base = RF_BASE, | ||
219 | .word_size = sizeof(u32), | ||
220 | .word_count = RF_SIZE / sizeof(u32), | ||
221 | }, | ||
222 | }; | ||
223 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
224 | |||
225 | static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | ||
226 | { | ||
227 | u32 reg; | ||
228 | |||
229 | rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | ||
230 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | ||
231 | } | ||
232 | |||
233 | #ifdef CONFIG_RT2X00_LIB_LEDS | ||
234 | static void rt2800pci_brightness_set(struct led_classdev *led_cdev, | ||
235 | enum led_brightness brightness) | ||
236 | { | ||
237 | struct rt2x00_led *led = | ||
238 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
239 | unsigned int enabled = brightness != LED_OFF; | ||
240 | unsigned int bg_mode = | ||
241 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | ||
242 | unsigned int polarity = | ||
243 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
244 | EEPROM_FREQ_LED_POLARITY); | ||
245 | unsigned int ledmode = | ||
246 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
247 | EEPROM_FREQ_LED_MODE); | ||
248 | |||
249 | if (led->type == LED_TYPE_RADIO) { | ||
250 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
251 | enabled ? 0x20 : 0); | ||
252 | } else if (led->type == LED_TYPE_ASSOC) { | ||
253 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
254 | enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); | ||
255 | } else if (led->type == LED_TYPE_QUALITY) { | ||
256 | /* | ||
257 | * The brightness is divided into 6 levels (0 - 5), | ||
258 | * The specs tell us the following levels: | ||
259 | * 0, 1 ,3, 7, 15, 31 | ||
260 | * to determine the level in a simple way we can simply | ||
261 | * work with bitshifting: | ||
262 | * (1 << level) - 1 | ||
263 | */ | ||
264 | rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, | ||
265 | (1 << brightness / (LED_FULL / 6)) - 1, | ||
266 | polarity); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static int rt2800pci_blink_set(struct led_classdev *led_cdev, | ||
271 | unsigned long *delay_on, | ||
272 | unsigned long *delay_off) | ||
273 | { | ||
274 | struct rt2x00_led *led = | ||
275 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
276 | u32 reg; | ||
277 | |||
278 | rt2800_register_read(led->rt2x00dev, LED_CFG, ®); | ||
279 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); | ||
280 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); | ||
281 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | ||
282 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | ||
283 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); | ||
284 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | ||
285 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | ||
286 | rt2800_register_write(led->rt2x00dev, LED_CFG, reg); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void rt2800pci_init_led(struct rt2x00_dev *rt2x00dev, | ||
292 | struct rt2x00_led *led, | ||
293 | enum led_type type) | ||
294 | { | ||
295 | led->rt2x00dev = rt2x00dev; | ||
296 | led->type = type; | ||
297 | led->led_dev.brightness_set = rt2800pci_brightness_set; | ||
298 | led->led_dev.blink_set = rt2800pci_blink_set; | ||
299 | led->flags = LED_INITIALIZED; | ||
300 | } | ||
301 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | ||
302 | |||
303 | /* | ||
304 | * Configuration handlers. | ||
305 | */ | ||
306 | static void rt2800pci_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | ||
307 | struct rt2x00lib_crypto *crypto, | ||
308 | struct ieee80211_key_conf *key) | ||
309 | { | ||
310 | struct mac_wcid_entry wcid_entry; | ||
311 | struct mac_iveiv_entry iveiv_entry; | ||
312 | u32 offset; | ||
313 | u32 reg; | ||
314 | |||
315 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | ||
316 | |||
317 | rt2800_register_read(rt2x00dev, offset, ®); | ||
318 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | ||
319 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | ||
320 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | ||
321 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
322 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | ||
323 | (crypto->cmd == SET_KEY) * crypto->bssidx); | ||
324 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | ||
325 | rt2800_register_write(rt2x00dev, offset, reg); | ||
326 | |||
327 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | ||
328 | |||
329 | memset(&iveiv_entry, 0, sizeof(iveiv_entry)); | ||
330 | if ((crypto->cipher == CIPHER_TKIP) || | ||
331 | (crypto->cipher == CIPHER_TKIP_NO_MIC) || | ||
332 | (crypto->cipher == CIPHER_AES)) | ||
333 | iveiv_entry.iv[3] |= 0x20; | ||
334 | iveiv_entry.iv[3] |= key->keyidx << 6; | ||
335 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
336 | &iveiv_entry, sizeof(iveiv_entry)); | ||
337 | |||
338 | offset = MAC_WCID_ENTRY(key->hw_key_idx); | ||
339 | |||
340 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | ||
341 | if (crypto->cmd == SET_KEY) | ||
342 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | ||
343 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
344 | &wcid_entry, sizeof(wcid_entry)); | ||
345 | } | ||
346 | |||
347 | static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
348 | struct rt2x00lib_crypto *crypto, | ||
349 | struct ieee80211_key_conf *key) | ||
350 | { | ||
351 | struct hw_key_entry key_entry; | ||
352 | struct rt2x00_field32 field; | ||
353 | u32 offset; | ||
354 | u32 reg; | ||
355 | |||
356 | if (crypto->cmd == SET_KEY) { | ||
357 | key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; | ||
358 | |||
359 | memcpy(key_entry.key, crypto->key, | ||
360 | sizeof(key_entry.key)); | ||
361 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
362 | sizeof(key_entry.tx_mic)); | ||
363 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
364 | sizeof(key_entry.rx_mic)); | ||
365 | |||
366 | offset = SHARED_KEY_ENTRY(key->hw_key_idx); | ||
367 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
368 | &key_entry, sizeof(key_entry)); | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * The cipher types are stored over multiple registers | ||
373 | * starting with SHARED_KEY_MODE_BASE each word will have | ||
374 | * 32 bits and contains the cipher types for 2 bssidx each. | ||
375 | * Using the correct defines correctly will cause overhead, | ||
376 | * so just calculate the correct offset. | ||
377 | */ | ||
378 | field.bit_offset = 4 * (key->hw_key_idx % 8); | ||
379 | field.bit_mask = 0x7 << field.bit_offset; | ||
380 | |||
381 | offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); | ||
382 | |||
383 | rt2800_register_read(rt2x00dev, offset, ®); | ||
384 | rt2x00_set_field32(®, field, | ||
385 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
386 | rt2800_register_write(rt2x00dev, offset, reg); | ||
387 | |||
388 | /* | ||
389 | * Update WCID information | ||
390 | */ | ||
391 | rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int rt2800pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
397 | struct rt2x00lib_crypto *crypto, | ||
398 | struct ieee80211_key_conf *key) | ||
399 | { | ||
400 | struct hw_key_entry key_entry; | ||
401 | u32 offset; | ||
402 | |||
403 | if (crypto->cmd == SET_KEY) { | ||
404 | /* | ||
405 | * 1 pairwise key is possible per AID, this means that the AID | ||
406 | * equals our hw_key_idx. Make sure the WCID starts _after_ the | ||
407 | * last possible shared key entry. | ||
408 | */ | ||
409 | if (crypto->aid > (256 - 32)) | ||
410 | return -ENOSPC; | ||
411 | |||
412 | key->hw_key_idx = 32 + crypto->aid; | ||
413 | |||
414 | |||
415 | memcpy(key_entry.key, crypto->key, | ||
416 | sizeof(key_entry.key)); | ||
417 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
418 | sizeof(key_entry.tx_mic)); | ||
419 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
420 | sizeof(key_entry.rx_mic)); | ||
421 | |||
422 | offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | ||
423 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
424 | &key_entry, sizeof(key_entry)); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * Update WCID information | ||
429 | */ | ||
430 | rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static void rt2800pci_config_filter(struct rt2x00_dev *rt2x00dev, | ||
436 | const unsigned int filter_flags) | ||
437 | { | ||
438 | u32 reg; | ||
439 | |||
440 | /* | ||
441 | * Start configuration steps. | ||
442 | * Note that the version error will always be dropped | ||
443 | * and broadcast frames will always be accepted since | ||
444 | * there is no filter for it at this time. | ||
445 | */ | ||
446 | rt2800_register_read(rt2x00dev, RX_FILTER_CFG, ®); | ||
447 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, | ||
448 | !(filter_flags & FIF_FCSFAIL)); | ||
449 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, | ||
450 | !(filter_flags & FIF_PLCPFAIL)); | ||
451 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, | ||
452 | !(filter_flags & FIF_PROMISC_IN_BSS)); | ||
453 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); | ||
454 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); | ||
455 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, | ||
456 | !(filter_flags & FIF_ALLMULTI)); | ||
457 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); | ||
458 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); | ||
459 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, | ||
460 | !(filter_flags & FIF_CONTROL)); | ||
461 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, | ||
462 | !(filter_flags & FIF_CONTROL)); | ||
463 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, | ||
464 | !(filter_flags & FIF_CONTROL)); | ||
465 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, | ||
466 | !(filter_flags & FIF_CONTROL)); | ||
467 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, | ||
468 | !(filter_flags & FIF_CONTROL)); | ||
469 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, | ||
470 | !(filter_flags & FIF_PSPOLL)); | ||
471 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); | ||
472 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); | ||
473 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, | ||
474 | !(filter_flags & FIF_CONTROL)); | ||
475 | rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); | ||
476 | } | ||
477 | |||
478 | static void rt2800pci_config_intf(struct rt2x00_dev *rt2x00dev, | ||
479 | struct rt2x00_intf *intf, | ||
480 | struct rt2x00intf_conf *conf, | ||
481 | const unsigned int flags) | ||
482 | { | ||
483 | unsigned int beacon_base; | ||
484 | u32 reg; | ||
485 | |||
486 | if (flags & CONFIG_UPDATE_TYPE) { | ||
487 | /* | ||
488 | * Clear current synchronisation setup. | ||
489 | * For the Beacon base registers we only need to clear | ||
490 | * the first byte since that byte contains the VALID and OWNER | ||
491 | * bits which (when set to 0) will invalidate the entire beacon. | ||
492 | */ | ||
493 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
494 | rt2800_register_write(rt2x00dev, beacon_base, 0); | ||
495 | |||
496 | /* | ||
497 | * Enable synchronisation. | ||
498 | */ | ||
499 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
500 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
501 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | ||
502 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
503 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
504 | } | ||
505 | |||
506 | if (flags & CONFIG_UPDATE_MAC) { | ||
507 | reg = le32_to_cpu(conf->mac[1]); | ||
508 | rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); | ||
509 | conf->mac[1] = cpu_to_le32(reg); | ||
510 | |||
511 | rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, | ||
512 | conf->mac, sizeof(conf->mac)); | ||
513 | } | ||
514 | |||
515 | if (flags & CONFIG_UPDATE_BSSID) { | ||
516 | reg = le32_to_cpu(conf->bssid[1]); | ||
517 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); | ||
518 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); | ||
519 | conf->bssid[1] = cpu_to_le32(reg); | ||
520 | |||
521 | rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, | ||
522 | conf->bssid, sizeof(conf->bssid)); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | static void rt2800pci_config_erp(struct rt2x00_dev *rt2x00dev, | ||
527 | struct rt2x00lib_erp *erp) | ||
528 | { | ||
529 | u32 reg; | ||
530 | |||
531 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | ||
532 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); | ||
533 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | ||
534 | |||
535 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | ||
536 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | ||
537 | !!erp->short_preamble); | ||
538 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, | ||
539 | !!erp->short_preamble); | ||
540 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | ||
541 | |||
542 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
543 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, | ||
544 | erp->cts_protection ? 2 : 0); | ||
545 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
546 | |||
547 | rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, | ||
548 | erp->basic_rates); | ||
549 | rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | ||
550 | |||
551 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | ||
552 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | ||
553 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | ||
554 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | ||
555 | |||
556 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | ||
557 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); | ||
558 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); | ||
559 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | ||
560 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | ||
561 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | ||
562 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | ||
563 | |||
564 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
565 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
566 | erp->beacon_int * 16); | ||
567 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
568 | } | ||
569 | |||
570 | static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev, | ||
571 | struct antenna_setup *ant) | ||
572 | { | ||
573 | u8 r1; | ||
574 | u8 r3; | ||
575 | |||
576 | rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
577 | rt2800_bbp_read(rt2x00dev, 3, &r3); | ||
578 | |||
579 | /* | ||
580 | * Configure the TX antenna. | ||
581 | */ | ||
582 | switch ((int)ant->tx) { | ||
583 | case 1: | ||
584 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | ||
585 | if (rt2x00_intf_is_pci(rt2x00dev)) | ||
586 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | ||
587 | break; | ||
588 | case 2: | ||
589 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | ||
590 | break; | ||
591 | case 3: | ||
592 | /* Do nothing */ | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * Configure the RX antenna. | ||
598 | */ | ||
599 | switch ((int)ant->rx) { | ||
600 | case 1: | ||
601 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | ||
602 | break; | ||
603 | case 2: | ||
604 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); | ||
605 | break; | ||
606 | case 3: | ||
607 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | rt2800_bbp_write(rt2x00dev, 3, r3); | ||
612 | rt2800_bbp_write(rt2x00dev, 1, r1); | ||
613 | } | ||
614 | |||
615 | static void rt2800pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, | ||
616 | struct rt2x00lib_conf *libconf) | ||
617 | { | ||
618 | u16 eeprom; | ||
619 | short lna_gain; | ||
620 | |||
621 | if (libconf->rf.channel <= 14) { | ||
622 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
623 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); | ||
624 | } else if (libconf->rf.channel <= 64) { | ||
625 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
626 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); | ||
627 | } else if (libconf->rf.channel <= 128) { | ||
628 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); | ||
629 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); | ||
630 | } else { | ||
631 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); | ||
632 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); | ||
633 | } | ||
634 | |||
635 | rt2x00dev->lna_gain = lna_gain; | ||
636 | } | ||
637 | |||
638 | static void rt2800pci_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | ||
639 | struct ieee80211_conf *conf, | ||
640 | struct rf_channel *rf, | ||
641 | struct channel_info *info) | ||
642 | { | ||
643 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
644 | |||
645 | if (rt2x00dev->default_ant.tx == 1) | ||
646 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); | ||
647 | |||
648 | if (rt2x00dev->default_ant.rx == 1) { | ||
649 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); | ||
650 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
651 | } else if (rt2x00dev->default_ant.rx == 2) | ||
652 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
653 | |||
654 | if (rf->channel > 14) { | ||
655 | /* | ||
656 | * When TX power is below 0, we should increase it by 7 to | ||
657 | * make it a positive value (Minumum value is -7). | ||
658 | * However this means that values between 0 and 7 have | ||
659 | * double meaning, and we should set a 7DBm boost flag. | ||
660 | */ | ||
661 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, | ||
662 | (info->tx_power1 >= 0)); | ||
663 | |||
664 | if (info->tx_power1 < 0) | ||
665 | info->tx_power1 += 7; | ||
666 | |||
667 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, | ||
668 | TXPOWER_A_TO_DEV(info->tx_power1)); | ||
669 | |||
670 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, | ||
671 | (info->tx_power2 >= 0)); | ||
672 | |||
673 | if (info->tx_power2 < 0) | ||
674 | info->tx_power2 += 7; | ||
675 | |||
676 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, | ||
677 | TXPOWER_A_TO_DEV(info->tx_power2)); | ||
678 | } else { | ||
679 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, | ||
680 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
681 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, | ||
682 | TXPOWER_G_TO_DEV(info->tx_power2)); | ||
683 | } | ||
684 | |||
685 | rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); | ||
686 | |||
687 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
688 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
689 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
690 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
691 | |||
692 | udelay(200); | ||
693 | |||
694 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
695 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
696 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); | ||
697 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
698 | |||
699 | udelay(200); | ||
700 | |||
701 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
702 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
703 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
704 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
705 | } | ||
706 | |||
707 | static void rt2800pci_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | ||
708 | struct ieee80211_conf *conf, | ||
709 | struct rf_channel *rf, | ||
710 | struct channel_info *info) | ||
711 | { | ||
712 | u8 rfcsr; | ||
713 | |||
714 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); | ||
715 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3); | ||
716 | |||
717 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | ||
718 | rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); | ||
719 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | ||
720 | |||
721 | rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); | ||
722 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | ||
723 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
724 | rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); | ||
725 | |||
726 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
727 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
728 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
729 | |||
730 | rt2800_rfcsr_write(rt2x00dev, 24, | ||
731 | rt2x00dev->calibration[conf_is_ht40(conf)]); | ||
732 | |||
733 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
734 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | ||
735 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
736 | } | ||
737 | |||
738 | static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, | ||
739 | struct ieee80211_conf *conf, | ||
740 | struct rf_channel *rf, | ||
741 | struct channel_info *info) | ||
742 | { | ||
743 | u32 reg; | ||
744 | unsigned int tx_pin; | ||
745 | u8 bbp; | ||
746 | |||
747 | if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | ||
748 | rt2800pci_config_channel_rt2x(rt2x00dev, conf, rf, info); | ||
749 | else | ||
750 | rt2800pci_config_channel_rt3x(rt2x00dev, conf, rf, info); | ||
751 | |||
752 | /* | ||
753 | * Change BBP settings | ||
754 | */ | ||
755 | rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | ||
756 | rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | ||
757 | rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | ||
758 | rt2800_bbp_write(rt2x00dev, 86, 0); | ||
759 | |||
760 | if (rf->channel <= 14) { | ||
761 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { | ||
762 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | ||
763 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | ||
764 | } else { | ||
765 | rt2800_bbp_write(rt2x00dev, 82, 0x84); | ||
766 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | ||
767 | } | ||
768 | } else { | ||
769 | rt2800_bbp_write(rt2x00dev, 82, 0xf2); | ||
770 | |||
771 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) | ||
772 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | ||
773 | else | ||
774 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | ||
775 | } | ||
776 | |||
777 | rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); | ||
778 | rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
779 | rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); | ||
780 | rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); | ||
781 | rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); | ||
782 | |||
783 | tx_pin = 0; | ||
784 | |||
785 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
786 | if (rt2x00dev->default_ant.tx != 1) { | ||
787 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); | ||
788 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); | ||
789 | } | ||
790 | |||
791 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
792 | if (rt2x00dev->default_ant.rx != 1) { | ||
793 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); | ||
794 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); | ||
795 | } | ||
796 | |||
797 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); | ||
798 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); | ||
799 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); | ||
800 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); | ||
801 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); | ||
802 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); | ||
803 | |||
804 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | ||
805 | |||
806 | rt2800_bbp_read(rt2x00dev, 4, &bbp); | ||
807 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | ||
808 | rt2800_bbp_write(rt2x00dev, 4, bbp); | ||
809 | |||
810 | rt2800_bbp_read(rt2x00dev, 3, &bbp); | ||
811 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
812 | rt2800_bbp_write(rt2x00dev, 3, bbp); | ||
813 | |||
814 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | ||
815 | if (conf_is_ht40(conf)) { | ||
816 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | ||
817 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
818 | rt2800_bbp_write(rt2x00dev, 73, 0x16); | ||
819 | } else { | ||
820 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | ||
821 | rt2800_bbp_write(rt2x00dev, 70, 0x08); | ||
822 | rt2800_bbp_write(rt2x00dev, 73, 0x11); | ||
823 | } | ||
824 | } | ||
825 | |||
826 | msleep(1); | ||
827 | } | ||
828 | |||
829 | static void rt2800pci_config_txpower(struct rt2x00_dev *rt2x00dev, | ||
830 | const int txpower) | ||
831 | { | ||
832 | u32 reg; | ||
833 | u32 value = TXPOWER_G_TO_DEV(txpower); | ||
834 | u8 r1; | ||
835 | |||
836 | rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
837 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | ||
838 | rt2800_bbp_write(rt2x00dev, 1, r1); | ||
839 | |||
840 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | ||
841 | rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); | ||
842 | rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); | ||
843 | rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); | ||
844 | rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); | ||
845 | rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); | ||
846 | rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); | ||
847 | rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); | ||
848 | rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); | ||
849 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg); | ||
850 | |||
851 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, ®); | ||
852 | rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); | ||
853 | rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); | ||
854 | rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); | ||
855 | rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); | ||
856 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); | ||
857 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); | ||
858 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); | ||
859 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); | ||
860 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg); | ||
861 | |||
862 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, ®); | ||
863 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); | ||
864 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); | ||
865 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); | ||
866 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); | ||
867 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); | ||
868 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); | ||
869 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); | ||
870 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); | ||
871 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg); | ||
872 | |||
873 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, ®); | ||
874 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); | ||
875 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); | ||
876 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); | ||
877 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); | ||
878 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); | ||
879 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); | ||
880 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); | ||
881 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); | ||
882 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg); | ||
883 | |||
884 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, ®); | ||
885 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); | ||
886 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); | ||
887 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); | ||
888 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); | ||
889 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg); | ||
890 | } | ||
891 | |||
892 | static void rt2800pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | ||
893 | struct rt2x00lib_conf *libconf) | ||
894 | { | ||
895 | u32 reg; | ||
896 | |||
897 | rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); | ||
898 | rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, | ||
899 | libconf->conf->short_frame_max_tx_count); | ||
900 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, | ||
901 | libconf->conf->long_frame_max_tx_count); | ||
902 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | ||
903 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | ||
904 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | ||
905 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | ||
906 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); | ||
907 | } | ||
908 | |||
909 | static void rt2800pci_config_ps(struct rt2x00_dev *rt2x00dev, | ||
910 | struct rt2x00lib_conf *libconf) | ||
911 | { | ||
912 | enum dev_state state = | ||
913 | (libconf->conf->flags & IEEE80211_CONF_PS) ? | ||
914 | STATE_SLEEP : STATE_AWAKE; | ||
915 | u32 reg; | ||
916 | |||
917 | if (state == STATE_SLEEP) { | ||
918 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); | ||
919 | |||
920 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
921 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); | ||
922 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, | ||
923 | libconf->conf->listen_interval - 1); | ||
924 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); | ||
925 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
926 | |||
927 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
928 | } else { | ||
929 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
930 | |||
931 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
932 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | ||
933 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | ||
934 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | ||
935 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
936 | } | ||
937 | } | ||
938 | |||
939 | static void rt2800pci_config(struct rt2x00_dev *rt2x00dev, | ||
940 | struct rt2x00lib_conf *libconf, | ||
941 | const unsigned int flags) | ||
942 | { | ||
943 | /* Always recalculate LNA gain before changing configuration */ | ||
944 | rt2800pci_config_lna_gain(rt2x00dev, libconf); | ||
945 | |||
946 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) | ||
947 | rt2800pci_config_channel(rt2x00dev, libconf->conf, | ||
948 | &libconf->rf, &libconf->channel); | ||
949 | if (flags & IEEE80211_CONF_CHANGE_POWER) | ||
950 | rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level); | ||
951 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | ||
952 | rt2800pci_config_retry_limit(rt2x00dev, libconf); | ||
953 | if (flags & IEEE80211_CONF_CHANGE_PS) | ||
954 | rt2800pci_config_ps(rt2x00dev, libconf); | ||
955 | } | ||
956 | |||
957 | /* | ||
958 | * Link tuning | ||
959 | */ | ||
960 | static void rt2800pci_link_stats(struct rt2x00_dev *rt2x00dev, | ||
961 | struct link_qual *qual) | ||
962 | { | ||
963 | u32 reg; | ||
964 | |||
965 | /* | ||
966 | * Update FCS error count from register. | ||
967 | */ | ||
968 | rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®); | ||
969 | qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); | ||
970 | } | ||
971 | |||
972 | static u8 rt2800pci_get_default_vgc(struct rt2x00_dev *rt2x00dev) | ||
973 | { | ||
974 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) | ||
975 | return 0x2e + rt2x00dev->lna_gain; | ||
976 | |||
977 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | ||
978 | return 0x32 + (rt2x00dev->lna_gain * 5) / 3; | ||
979 | else | ||
980 | return 0x3a + (rt2x00dev->lna_gain * 5) / 3; | ||
981 | } | ||
982 | |||
983 | static inline void rt2800pci_set_vgc(struct rt2x00_dev *rt2x00dev, | ||
984 | struct link_qual *qual, u8 vgc_level) | ||
985 | { | ||
986 | if (qual->vgc_level != vgc_level) { | ||
987 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | ||
988 | qual->vgc_level = vgc_level; | ||
989 | qual->vgc_level_reg = vgc_level; | ||
990 | } | ||
991 | } | ||
992 | |||
993 | static void rt2800pci_reset_tuner(struct rt2x00_dev *rt2x00dev, | ||
994 | struct link_qual *qual) | ||
995 | { | ||
996 | rt2800pci_set_vgc(rt2x00dev, qual, | ||
997 | rt2800pci_get_default_vgc(rt2x00dev)); | ||
998 | } | ||
999 | |||
1000 | static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev, | ||
1001 | struct link_qual *qual, const u32 count) | ||
1002 | { | ||
1003 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | ||
1004 | return; | ||
1005 | |||
1006 | /* | ||
1007 | * When RSSI is better then -80 increase VGC level with 0x10 | ||
1008 | */ | ||
1009 | rt2800pci_set_vgc(rt2x00dev, qual, | ||
1010 | rt2800pci_get_default_vgc(rt2x00dev) + | ||
1011 | ((qual->rssi > -80) * 0x10)); | ||
1012 | } | ||
1013 | |||
1014 | /* | 190 | /* |
1015 | * Firmware functions | 191 | * Firmware functions |
1016 | */ | 192 | */ |
@@ -2575,9 +1751,9 @@ static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2575 | * Store led settings, for correct led behaviour. | 1751 | * Store led settings, for correct led behaviour. |
2576 | */ | 1752 | */ |
2577 | #ifdef CONFIG_RT2X00_LIB_LEDS | 1753 | #ifdef CONFIG_RT2X00_LIB_LEDS |
2578 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); | 1754 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); |
2579 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); | 1755 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); |
2580 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); | 1756 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); |
2581 | 1757 | ||
2582 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); | 1758 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); |
2583 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | 1759 | #endif /* CONFIG_RT2X00_LIB_LEDS */ |
@@ -2994,23 +2170,23 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
2994 | .get_entry_state = rt2800pci_get_entry_state, | 2170 | .get_entry_state = rt2800pci_get_entry_state, |
2995 | .clear_entry = rt2800pci_clear_entry, | 2171 | .clear_entry = rt2800pci_clear_entry, |
2996 | .set_device_state = rt2800pci_set_device_state, | 2172 | .set_device_state = rt2800pci_set_device_state, |
2997 | .rfkill_poll = rt2800pci_rfkill_poll, | 2173 | .rfkill_poll = rt2800_rfkill_poll, |
2998 | .link_stats = rt2800pci_link_stats, | 2174 | .link_stats = rt2800_link_stats, |
2999 | .reset_tuner = rt2800pci_reset_tuner, | 2175 | .reset_tuner = rt2800_reset_tuner, |
3000 | .link_tuner = rt2800pci_link_tuner, | 2176 | .link_tuner = rt2800_link_tuner, |
3001 | .write_tx_desc = rt2800pci_write_tx_desc, | 2177 | .write_tx_desc = rt2800pci_write_tx_desc, |
3002 | .write_tx_data = rt2x00pci_write_tx_data, | 2178 | .write_tx_data = rt2x00pci_write_tx_data, |
3003 | .write_beacon = rt2800pci_write_beacon, | 2179 | .write_beacon = rt2800pci_write_beacon, |
3004 | .kick_tx_queue = rt2800pci_kick_tx_queue, | 2180 | .kick_tx_queue = rt2800pci_kick_tx_queue, |
3005 | .kill_tx_queue = rt2800pci_kill_tx_queue, | 2181 | .kill_tx_queue = rt2800pci_kill_tx_queue, |
3006 | .fill_rxdone = rt2800pci_fill_rxdone, | 2182 | .fill_rxdone = rt2800pci_fill_rxdone, |
3007 | .config_shared_key = rt2800pci_config_shared_key, | 2183 | .config_shared_key = rt2800_config_shared_key, |
3008 | .config_pairwise_key = rt2800pci_config_pairwise_key, | 2184 | .config_pairwise_key = rt2800_config_pairwise_key, |
3009 | .config_filter = rt2800pci_config_filter, | 2185 | .config_filter = rt2800_config_filter, |
3010 | .config_intf = rt2800pci_config_intf, | 2186 | .config_intf = rt2800_config_intf, |
3011 | .config_erp = rt2800pci_config_erp, | 2187 | .config_erp = rt2800_config_erp, |
3012 | .config_ant = rt2800pci_config_ant, | 2188 | .config_ant = rt2800_config_ant, |
3013 | .config = rt2800pci_config, | 2189 | .config = rt2800_config, |
3014 | }; | 2190 | }; |
3015 | 2191 | ||
3016 | static const struct data_queue_desc rt2800pci_queue_rx = { | 2192 | static const struct data_queue_desc rt2800pci_queue_rx = { |
@@ -3047,7 +2223,7 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
3047 | .lib = &rt2800pci_rt2x00_ops, | 2223 | .lib = &rt2800pci_rt2x00_ops, |
3048 | .hw = &rt2800pci_mac80211_ops, | 2224 | .hw = &rt2800pci_mac80211_ops, |
3049 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 2225 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
3050 | .debugfs = &rt2800pci_rt2x00debug, | 2226 | .debugfs = &rt2800_rt2x00debug, |
3051 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 2227 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |
3052 | }; | 2228 | }; |
3053 | 2229 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6bd646a979af..365f66fe7c68 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -45,832 +45,6 @@ static int modparam_nohwcrypt = 1; | |||
45 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 45 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
47 | 47 | ||
48 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
49 | static const struct rt2x00debug rt2800usb_rt2x00debug = { | ||
50 | .owner = THIS_MODULE, | ||
51 | .csr = { | ||
52 | .read = rt2800_register_read, | ||
53 | .write = rt2800_register_write, | ||
54 | .flags = RT2X00DEBUGFS_OFFSET, | ||
55 | .word_base = CSR_REG_BASE, | ||
56 | .word_size = sizeof(u32), | ||
57 | .word_count = CSR_REG_SIZE / sizeof(u32), | ||
58 | }, | ||
59 | .eeprom = { | ||
60 | .read = rt2x00_eeprom_read, | ||
61 | .write = rt2x00_eeprom_write, | ||
62 | .word_base = EEPROM_BASE, | ||
63 | .word_size = sizeof(u16), | ||
64 | .word_count = EEPROM_SIZE / sizeof(u16), | ||
65 | }, | ||
66 | .bbp = { | ||
67 | .read = rt2800_bbp_read, | ||
68 | .write = rt2800_bbp_write, | ||
69 | .word_base = BBP_BASE, | ||
70 | .word_size = sizeof(u8), | ||
71 | .word_count = BBP_SIZE / sizeof(u8), | ||
72 | }, | ||
73 | .rf = { | ||
74 | .read = rt2x00_rf_read, | ||
75 | .write = rt2800_rf_write, | ||
76 | .word_base = RF_BASE, | ||
77 | .word_size = sizeof(u32), | ||
78 | .word_count = RF_SIZE / sizeof(u32), | ||
79 | }, | ||
80 | }; | ||
81 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
82 | |||
83 | static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) | ||
84 | { | ||
85 | u32 reg; | ||
86 | |||
87 | rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | ||
88 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | ||
89 | } | ||
90 | |||
91 | #ifdef CONFIG_RT2X00_LIB_LEDS | ||
92 | static void rt2800usb_brightness_set(struct led_classdev *led_cdev, | ||
93 | enum led_brightness brightness) | ||
94 | { | ||
95 | struct rt2x00_led *led = | ||
96 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
97 | unsigned int enabled = brightness != LED_OFF; | ||
98 | unsigned int bg_mode = | ||
99 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | ||
100 | unsigned int polarity = | ||
101 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
102 | EEPROM_FREQ_LED_POLARITY); | ||
103 | unsigned int ledmode = | ||
104 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
105 | EEPROM_FREQ_LED_MODE); | ||
106 | |||
107 | if (led->type == LED_TYPE_RADIO) { | ||
108 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
109 | enabled ? 0x20 : 0); | ||
110 | } else if (led->type == LED_TYPE_ASSOC) { | ||
111 | rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
112 | enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); | ||
113 | } else if (led->type == LED_TYPE_QUALITY) { | ||
114 | /* | ||
115 | * The brightness is divided into 6 levels (0 - 5), | ||
116 | * The specs tell us the following levels: | ||
117 | * 0, 1 ,3, 7, 15, 31 | ||
118 | * to determine the level in a simple way we can simply | ||
119 | * work with bitshifting: | ||
120 | * (1 << level) - 1 | ||
121 | */ | ||
122 | rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, | ||
123 | (1 << brightness / (LED_FULL / 6)) - 1, | ||
124 | polarity); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static int rt2800usb_blink_set(struct led_classdev *led_cdev, | ||
129 | unsigned long *delay_on, | ||
130 | unsigned long *delay_off) | ||
131 | { | ||
132 | struct rt2x00_led *led = | ||
133 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
134 | u32 reg; | ||
135 | |||
136 | rt2800_register_read(led->rt2x00dev, LED_CFG, ®); | ||
137 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); | ||
138 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); | ||
139 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | ||
140 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | ||
141 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); | ||
142 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | ||
143 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | ||
144 | rt2800_register_write(led->rt2x00dev, LED_CFG, reg); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, | ||
150 | struct rt2x00_led *led, | ||
151 | enum led_type type) | ||
152 | { | ||
153 | led->rt2x00dev = rt2x00dev; | ||
154 | led->type = type; | ||
155 | led->led_dev.brightness_set = rt2800usb_brightness_set; | ||
156 | led->led_dev.blink_set = rt2800usb_blink_set; | ||
157 | led->flags = LED_INITIALIZED; | ||
158 | } | ||
159 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | ||
160 | |||
161 | /* | ||
162 | * Configuration handlers. | ||
163 | */ | ||
164 | static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | ||
165 | struct rt2x00lib_crypto *crypto, | ||
166 | struct ieee80211_key_conf *key) | ||
167 | { | ||
168 | struct mac_wcid_entry wcid_entry; | ||
169 | struct mac_iveiv_entry iveiv_entry; | ||
170 | u32 offset; | ||
171 | u32 reg; | ||
172 | |||
173 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | ||
174 | |||
175 | rt2800_register_read(rt2x00dev, offset, ®); | ||
176 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | ||
177 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | ||
178 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | ||
179 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
180 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | ||
181 | (crypto->cmd == SET_KEY) * crypto->bssidx); | ||
182 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | ||
183 | rt2800_register_write(rt2x00dev, offset, reg); | ||
184 | |||
185 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | ||
186 | |||
187 | memset(&iveiv_entry, 0, sizeof(iveiv_entry)); | ||
188 | if ((crypto->cipher == CIPHER_TKIP) || | ||
189 | (crypto->cipher == CIPHER_TKIP_NO_MIC) || | ||
190 | (crypto->cipher == CIPHER_AES)) | ||
191 | iveiv_entry.iv[3] |= 0x20; | ||
192 | iveiv_entry.iv[3] |= key->keyidx << 6; | ||
193 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
194 | &iveiv_entry, sizeof(iveiv_entry)); | ||
195 | |||
196 | offset = MAC_WCID_ENTRY(key->hw_key_idx); | ||
197 | |||
198 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | ||
199 | if (crypto->cmd == SET_KEY) | ||
200 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | ||
201 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
202 | &wcid_entry, sizeof(wcid_entry)); | ||
203 | } | ||
204 | |||
205 | static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
206 | struct rt2x00lib_crypto *crypto, | ||
207 | struct ieee80211_key_conf *key) | ||
208 | { | ||
209 | struct hw_key_entry key_entry; | ||
210 | struct rt2x00_field32 field; | ||
211 | u32 offset; | ||
212 | u32 reg; | ||
213 | |||
214 | if (crypto->cmd == SET_KEY) { | ||
215 | key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; | ||
216 | |||
217 | memcpy(key_entry.key, crypto->key, | ||
218 | sizeof(key_entry.key)); | ||
219 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
220 | sizeof(key_entry.tx_mic)); | ||
221 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
222 | sizeof(key_entry.rx_mic)); | ||
223 | |||
224 | offset = SHARED_KEY_ENTRY(key->hw_key_idx); | ||
225 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
226 | &key_entry, sizeof(key_entry)); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * The cipher types are stored over multiple registers | ||
231 | * starting with SHARED_KEY_MODE_BASE each word will have | ||
232 | * 32 bits and contains the cipher types for 2 bssidx each. | ||
233 | * Using the correct defines correctly will cause overhead, | ||
234 | * so just calculate the correct offset. | ||
235 | */ | ||
236 | field.bit_offset = 4 * (key->hw_key_idx % 8); | ||
237 | field.bit_mask = 0x7 << field.bit_offset; | ||
238 | |||
239 | offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); | ||
240 | |||
241 | rt2800_register_read(rt2x00dev, offset, ®); | ||
242 | rt2x00_set_field32(®, field, | ||
243 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
244 | rt2800_register_write(rt2x00dev, offset, reg); | ||
245 | |||
246 | /* | ||
247 | * Update WCID information | ||
248 | */ | ||
249 | rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
255 | struct rt2x00lib_crypto *crypto, | ||
256 | struct ieee80211_key_conf *key) | ||
257 | { | ||
258 | struct hw_key_entry key_entry; | ||
259 | u32 offset; | ||
260 | |||
261 | if (crypto->cmd == SET_KEY) { | ||
262 | /* | ||
263 | * 1 pairwise key is possible per AID, this means that the AID | ||
264 | * equals our hw_key_idx. Make sure the WCID starts _after_ the | ||
265 | * last possible shared key entry. | ||
266 | */ | ||
267 | if (crypto->aid > (256 - 32)) | ||
268 | return -ENOSPC; | ||
269 | |||
270 | key->hw_key_idx = 32 + crypto->aid; | ||
271 | |||
272 | memcpy(key_entry.key, crypto->key, | ||
273 | sizeof(key_entry.key)); | ||
274 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
275 | sizeof(key_entry.tx_mic)); | ||
276 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
277 | sizeof(key_entry.rx_mic)); | ||
278 | |||
279 | offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | ||
280 | rt2800_register_multiwrite(rt2x00dev, offset, | ||
281 | &key_entry, sizeof(key_entry)); | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Update WCID information | ||
286 | */ | ||
287 | rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, | ||
293 | const unsigned int filter_flags) | ||
294 | { | ||
295 | u32 reg; | ||
296 | |||
297 | /* | ||
298 | * Start configuration steps. | ||
299 | * Note that the version error will always be dropped | ||
300 | * and broadcast frames will always be accepted since | ||
301 | * there is no filter for it at this time. | ||
302 | */ | ||
303 | rt2800_register_read(rt2x00dev, RX_FILTER_CFG, ®); | ||
304 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, | ||
305 | !(filter_flags & FIF_FCSFAIL)); | ||
306 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, | ||
307 | !(filter_flags & FIF_PLCPFAIL)); | ||
308 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, | ||
309 | !(filter_flags & FIF_PROMISC_IN_BSS)); | ||
310 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); | ||
311 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); | ||
312 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, | ||
313 | !(filter_flags & FIF_ALLMULTI)); | ||
314 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); | ||
315 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); | ||
316 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, | ||
317 | !(filter_flags & FIF_CONTROL)); | ||
318 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, | ||
319 | !(filter_flags & FIF_CONTROL)); | ||
320 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, | ||
321 | !(filter_flags & FIF_CONTROL)); | ||
322 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, | ||
323 | !(filter_flags & FIF_CONTROL)); | ||
324 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, | ||
325 | !(filter_flags & FIF_CONTROL)); | ||
326 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, | ||
327 | !(filter_flags & FIF_PSPOLL)); | ||
328 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); | ||
329 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); | ||
330 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, | ||
331 | !(filter_flags & FIF_CONTROL)); | ||
332 | rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); | ||
333 | } | ||
334 | |||
335 | static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, | ||
336 | struct rt2x00_intf *intf, | ||
337 | struct rt2x00intf_conf *conf, | ||
338 | const unsigned int flags) | ||
339 | { | ||
340 | unsigned int beacon_base; | ||
341 | u32 reg; | ||
342 | |||
343 | if (flags & CONFIG_UPDATE_TYPE) { | ||
344 | /* | ||
345 | * Clear current synchronisation setup. | ||
346 | * For the Beacon base registers we only need to clear | ||
347 | * the first byte since that byte contains the VALID and OWNER | ||
348 | * bits which (when set to 0) will invalidate the entire beacon. | ||
349 | */ | ||
350 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
351 | rt2800_register_write(rt2x00dev, beacon_base, 0); | ||
352 | |||
353 | /* | ||
354 | * Enable synchronisation. | ||
355 | */ | ||
356 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
357 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
358 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | ||
359 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
360 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
361 | } | ||
362 | |||
363 | if (flags & CONFIG_UPDATE_MAC) { | ||
364 | reg = le32_to_cpu(conf->mac[1]); | ||
365 | rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); | ||
366 | conf->mac[1] = cpu_to_le32(reg); | ||
367 | |||
368 | rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, | ||
369 | conf->mac, sizeof(conf->mac)); | ||
370 | } | ||
371 | |||
372 | if (flags & CONFIG_UPDATE_BSSID) { | ||
373 | reg = le32_to_cpu(conf->bssid[1]); | ||
374 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); | ||
375 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); | ||
376 | conf->bssid[1] = cpu_to_le32(reg); | ||
377 | |||
378 | rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, | ||
379 | conf->bssid, sizeof(conf->bssid)); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, | ||
384 | struct rt2x00lib_erp *erp) | ||
385 | { | ||
386 | u32 reg; | ||
387 | |||
388 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | ||
389 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); | ||
390 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | ||
391 | |||
392 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | ||
393 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | ||
394 | !!erp->short_preamble); | ||
395 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, | ||
396 | !!erp->short_preamble); | ||
397 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | ||
398 | |||
399 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
400 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, | ||
401 | erp->cts_protection ? 2 : 0); | ||
402 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
403 | |||
404 | rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, | ||
405 | erp->basic_rates); | ||
406 | rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | ||
407 | |||
408 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | ||
409 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | ||
410 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | ||
411 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | ||
412 | |||
413 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | ||
414 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); | ||
415 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); | ||
416 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | ||
417 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | ||
418 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | ||
419 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | ||
420 | |||
421 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
422 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
423 | erp->beacon_int * 16); | ||
424 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
425 | } | ||
426 | |||
427 | static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, | ||
428 | struct antenna_setup *ant) | ||
429 | { | ||
430 | u8 r1; | ||
431 | u8 r3; | ||
432 | |||
433 | rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
434 | rt2800_bbp_read(rt2x00dev, 3, &r3); | ||
435 | |||
436 | /* | ||
437 | * Configure the TX antenna. | ||
438 | */ | ||
439 | switch ((int)ant->tx) { | ||
440 | case 1: | ||
441 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | ||
442 | break; | ||
443 | case 2: | ||
444 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | ||
445 | break; | ||
446 | case 3: | ||
447 | /* Do nothing */ | ||
448 | break; | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * Configure the RX antenna. | ||
453 | */ | ||
454 | switch ((int)ant->rx) { | ||
455 | case 1: | ||
456 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | ||
457 | break; | ||
458 | case 2: | ||
459 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); | ||
460 | break; | ||
461 | case 3: | ||
462 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); | ||
463 | break; | ||
464 | } | ||
465 | |||
466 | rt2800_bbp_write(rt2x00dev, 3, r3); | ||
467 | rt2800_bbp_write(rt2x00dev, 1, r1); | ||
468 | } | ||
469 | |||
470 | static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, | ||
471 | struct rt2x00lib_conf *libconf) | ||
472 | { | ||
473 | u16 eeprom; | ||
474 | short lna_gain; | ||
475 | |||
476 | if (libconf->rf.channel <= 14) { | ||
477 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
478 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); | ||
479 | } else if (libconf->rf.channel <= 64) { | ||
480 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
481 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); | ||
482 | } else if (libconf->rf.channel <= 128) { | ||
483 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); | ||
484 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); | ||
485 | } else { | ||
486 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); | ||
487 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); | ||
488 | } | ||
489 | |||
490 | rt2x00dev->lna_gain = lna_gain; | ||
491 | } | ||
492 | |||
493 | static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | ||
494 | struct ieee80211_conf *conf, | ||
495 | struct rf_channel *rf, | ||
496 | struct channel_info *info) | ||
497 | { | ||
498 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
499 | |||
500 | if (rt2x00dev->default_ant.tx == 1) | ||
501 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); | ||
502 | |||
503 | if (rt2x00dev->default_ant.rx == 1) { | ||
504 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); | ||
505 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
506 | } else if (rt2x00dev->default_ant.rx == 2) | ||
507 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
508 | |||
509 | if (rf->channel > 14) { | ||
510 | /* | ||
511 | * When TX power is below 0, we should increase it by 7 to | ||
512 | * make it a positive value (Minumum value is -7). | ||
513 | * However this means that values between 0 and 7 have | ||
514 | * double meaning, and we should set a 7DBm boost flag. | ||
515 | */ | ||
516 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, | ||
517 | (info->tx_power1 >= 0)); | ||
518 | |||
519 | if (info->tx_power1 < 0) | ||
520 | info->tx_power1 += 7; | ||
521 | |||
522 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, | ||
523 | TXPOWER_A_TO_DEV(info->tx_power1)); | ||
524 | |||
525 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, | ||
526 | (info->tx_power2 >= 0)); | ||
527 | |||
528 | if (info->tx_power2 < 0) | ||
529 | info->tx_power2 += 7; | ||
530 | |||
531 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, | ||
532 | TXPOWER_A_TO_DEV(info->tx_power2)); | ||
533 | } else { | ||
534 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, | ||
535 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
536 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, | ||
537 | TXPOWER_G_TO_DEV(info->tx_power2)); | ||
538 | } | ||
539 | |||
540 | rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); | ||
541 | |||
542 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
543 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
544 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
545 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
546 | |||
547 | udelay(200); | ||
548 | |||
549 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
550 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
551 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); | ||
552 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
553 | |||
554 | udelay(200); | ||
555 | |||
556 | rt2800_rf_write(rt2x00dev, 1, rf->rf1); | ||
557 | rt2800_rf_write(rt2x00dev, 2, rf->rf2); | ||
558 | rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
559 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | ||
560 | } | ||
561 | |||
562 | static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | ||
563 | struct ieee80211_conf *conf, | ||
564 | struct rf_channel *rf, | ||
565 | struct channel_info *info) | ||
566 | { | ||
567 | u8 rfcsr; | ||
568 | |||
569 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); | ||
570 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3); | ||
571 | |||
572 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | ||
573 | rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); | ||
574 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | ||
575 | |||
576 | rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); | ||
577 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | ||
578 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
579 | rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); | ||
580 | |||
581 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
582 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
583 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
584 | |||
585 | rt2800_rfcsr_write(rt2x00dev, 24, | ||
586 | rt2x00dev->calibration[conf_is_ht40(conf)]); | ||
587 | |||
588 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
589 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | ||
590 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
591 | } | ||
592 | |||
593 | static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, | ||
594 | struct ieee80211_conf *conf, | ||
595 | struct rf_channel *rf, | ||
596 | struct channel_info *info) | ||
597 | { | ||
598 | u32 reg; | ||
599 | unsigned int tx_pin; | ||
600 | u8 bbp; | ||
601 | |||
602 | if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | ||
603 | rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info); | ||
604 | else | ||
605 | rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info); | ||
606 | |||
607 | /* | ||
608 | * Change BBP settings | ||
609 | */ | ||
610 | rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | ||
611 | rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | ||
612 | rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | ||
613 | rt2800_bbp_write(rt2x00dev, 86, 0); | ||
614 | |||
615 | if (rf->channel <= 14) { | ||
616 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { | ||
617 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | ||
618 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | ||
619 | } else { | ||
620 | rt2800_bbp_write(rt2x00dev, 82, 0x84); | ||
621 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | ||
622 | } | ||
623 | } else { | ||
624 | rt2800_bbp_write(rt2x00dev, 82, 0xf2); | ||
625 | |||
626 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) | ||
627 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | ||
628 | else | ||
629 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | ||
630 | } | ||
631 | |||
632 | rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); | ||
633 | rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
634 | rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); | ||
635 | rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); | ||
636 | rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); | ||
637 | |||
638 | tx_pin = 0; | ||
639 | |||
640 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
641 | if (rt2x00dev->default_ant.tx != 1) { | ||
642 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); | ||
643 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); | ||
644 | } | ||
645 | |||
646 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
647 | if (rt2x00dev->default_ant.rx != 1) { | ||
648 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); | ||
649 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); | ||
650 | } | ||
651 | |||
652 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); | ||
653 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); | ||
654 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); | ||
655 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); | ||
656 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); | ||
657 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); | ||
658 | |||
659 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | ||
660 | |||
661 | rt2800_bbp_read(rt2x00dev, 4, &bbp); | ||
662 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | ||
663 | rt2800_bbp_write(rt2x00dev, 4, bbp); | ||
664 | |||
665 | rt2800_bbp_read(rt2x00dev, 3, &bbp); | ||
666 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
667 | rt2800_bbp_write(rt2x00dev, 3, bbp); | ||
668 | |||
669 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | ||
670 | if (conf_is_ht40(conf)) { | ||
671 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | ||
672 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
673 | rt2800_bbp_write(rt2x00dev, 73, 0x16); | ||
674 | } else { | ||
675 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | ||
676 | rt2800_bbp_write(rt2x00dev, 70, 0x08); | ||
677 | rt2800_bbp_write(rt2x00dev, 73, 0x11); | ||
678 | } | ||
679 | } | ||
680 | |||
681 | msleep(1); | ||
682 | } | ||
683 | |||
684 | static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, | ||
685 | const int txpower) | ||
686 | { | ||
687 | u32 reg; | ||
688 | u32 value = TXPOWER_G_TO_DEV(txpower); | ||
689 | u8 r1; | ||
690 | |||
691 | rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
692 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | ||
693 | rt2800_bbp_write(rt2x00dev, 1, r1); | ||
694 | |||
695 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | ||
696 | rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); | ||
697 | rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); | ||
698 | rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); | ||
699 | rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); | ||
700 | rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); | ||
701 | rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); | ||
702 | rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); | ||
703 | rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); | ||
704 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg); | ||
705 | |||
706 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, ®); | ||
707 | rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); | ||
708 | rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); | ||
709 | rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); | ||
710 | rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); | ||
711 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); | ||
712 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); | ||
713 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); | ||
714 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); | ||
715 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg); | ||
716 | |||
717 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, ®); | ||
718 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); | ||
719 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); | ||
720 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); | ||
721 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); | ||
722 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); | ||
723 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); | ||
724 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); | ||
725 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); | ||
726 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg); | ||
727 | |||
728 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, ®); | ||
729 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); | ||
730 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); | ||
731 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); | ||
732 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); | ||
733 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); | ||
734 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); | ||
735 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); | ||
736 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); | ||
737 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg); | ||
738 | |||
739 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, ®); | ||
740 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); | ||
741 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); | ||
742 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); | ||
743 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); | ||
744 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg); | ||
745 | } | ||
746 | |||
747 | static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, | ||
748 | struct rt2x00lib_conf *libconf) | ||
749 | { | ||
750 | u32 reg; | ||
751 | |||
752 | rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); | ||
753 | rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, | ||
754 | libconf->conf->short_frame_max_tx_count); | ||
755 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, | ||
756 | libconf->conf->long_frame_max_tx_count); | ||
757 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | ||
758 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | ||
759 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | ||
760 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | ||
761 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); | ||
762 | } | ||
763 | |||
764 | static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, | ||
765 | struct rt2x00lib_conf *libconf) | ||
766 | { | ||
767 | enum dev_state state = | ||
768 | (libconf->conf->flags & IEEE80211_CONF_PS) ? | ||
769 | STATE_SLEEP : STATE_AWAKE; | ||
770 | u32 reg; | ||
771 | |||
772 | if (state == STATE_SLEEP) { | ||
773 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); | ||
774 | |||
775 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
776 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); | ||
777 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, | ||
778 | libconf->conf->listen_interval - 1); | ||
779 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); | ||
780 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
781 | |||
782 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
783 | } else { | ||
784 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
785 | |||
786 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
787 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | ||
788 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | ||
789 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | ||
790 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, | ||
795 | struct rt2x00lib_conf *libconf, | ||
796 | const unsigned int flags) | ||
797 | { | ||
798 | /* Always recalculate LNA gain before changing configuration */ | ||
799 | rt2800usb_config_lna_gain(rt2x00dev, libconf); | ||
800 | |||
801 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) | ||
802 | rt2800usb_config_channel(rt2x00dev, libconf->conf, | ||
803 | &libconf->rf, &libconf->channel); | ||
804 | if (flags & IEEE80211_CONF_CHANGE_POWER) | ||
805 | rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); | ||
806 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | ||
807 | rt2800usb_config_retry_limit(rt2x00dev, libconf); | ||
808 | if (flags & IEEE80211_CONF_CHANGE_PS) | ||
809 | rt2800usb_config_ps(rt2x00dev, libconf); | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * Link tuning | ||
814 | */ | ||
815 | static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, | ||
816 | struct link_qual *qual) | ||
817 | { | ||
818 | u32 reg; | ||
819 | |||
820 | /* | ||
821 | * Update FCS error count from register. | ||
822 | */ | ||
823 | rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®); | ||
824 | qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); | ||
825 | } | ||
826 | |||
827 | static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev) | ||
828 | { | ||
829 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | ||
830 | if (rt2x00_intf_is_usb(rt2x00dev) && | ||
831 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) | ||
832 | return 0x1c + (2 * rt2x00dev->lna_gain); | ||
833 | else | ||
834 | return 0x2e + rt2x00dev->lna_gain; | ||
835 | } | ||
836 | |||
837 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | ||
838 | return 0x32 + (rt2x00dev->lna_gain * 5) / 3; | ||
839 | else | ||
840 | return 0x3a + (rt2x00dev->lna_gain * 5) / 3; | ||
841 | } | ||
842 | |||
843 | static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev, | ||
844 | struct link_qual *qual, u8 vgc_level) | ||
845 | { | ||
846 | if (qual->vgc_level != vgc_level) { | ||
847 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | ||
848 | qual->vgc_level = vgc_level; | ||
849 | qual->vgc_level_reg = vgc_level; | ||
850 | } | ||
851 | } | ||
852 | |||
853 | static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev, | ||
854 | struct link_qual *qual) | ||
855 | { | ||
856 | rt2800usb_set_vgc(rt2x00dev, qual, | ||
857 | rt2800usb_get_default_vgc(rt2x00dev)); | ||
858 | } | ||
859 | |||
860 | static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev, | ||
861 | struct link_qual *qual, const u32 count) | ||
862 | { | ||
863 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | ||
864 | return; | ||
865 | |||
866 | /* | ||
867 | * When RSSI is better then -80 increase VGC level with 0x10 | ||
868 | */ | ||
869 | rt2800usb_set_vgc(rt2x00dev, qual, | ||
870 | rt2800usb_get_default_vgc(rt2x00dev) + | ||
871 | ((qual->rssi > -80) * 0x10)); | ||
872 | } | ||
873 | |||
874 | /* | 48 | /* |
875 | * Firmware functions | 49 | * Firmware functions |
876 | */ | 50 | */ |
@@ -2205,9 +1379,9 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2205 | * Store led settings, for correct led behaviour. | 1379 | * Store led settings, for correct led behaviour. |
2206 | */ | 1380 | */ |
2207 | #ifdef CONFIG_RT2X00_LIB_LEDS | 1381 | #ifdef CONFIG_RT2X00_LIB_LEDS |
2208 | rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); | 1382 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); |
2209 | rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); | 1383 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); |
2210 | rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); | 1384 | rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); |
2211 | 1385 | ||
2212 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, | 1386 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, |
2213 | &rt2x00dev->led_mcu_reg); | 1387 | &rt2x00dev->led_mcu_reg); |
@@ -2645,10 +1819,10 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
2645 | .uninitialize = rt2x00usb_uninitialize, | 1819 | .uninitialize = rt2x00usb_uninitialize, |
2646 | .clear_entry = rt2x00usb_clear_entry, | 1820 | .clear_entry = rt2x00usb_clear_entry, |
2647 | .set_device_state = rt2800usb_set_device_state, | 1821 | .set_device_state = rt2800usb_set_device_state, |
2648 | .rfkill_poll = rt2800usb_rfkill_poll, | 1822 | .rfkill_poll = rt2800_rfkill_poll, |
2649 | .link_stats = rt2800usb_link_stats, | 1823 | .link_stats = rt2800_link_stats, |
2650 | .reset_tuner = rt2800usb_reset_tuner, | 1824 | .reset_tuner = rt2800_reset_tuner, |
2651 | .link_tuner = rt2800usb_link_tuner, | 1825 | .link_tuner = rt2800_link_tuner, |
2652 | .write_tx_desc = rt2800usb_write_tx_desc, | 1826 | .write_tx_desc = rt2800usb_write_tx_desc, |
2653 | .write_tx_data = rt2x00usb_write_tx_data, | 1827 | .write_tx_data = rt2x00usb_write_tx_data, |
2654 | .write_beacon = rt2800usb_write_beacon, | 1828 | .write_beacon = rt2800usb_write_beacon, |
@@ -2656,13 +1830,13 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
2656 | .kick_tx_queue = rt2800usb_kick_tx_queue, | 1830 | .kick_tx_queue = rt2800usb_kick_tx_queue, |
2657 | .kill_tx_queue = rt2x00usb_kill_tx_queue, | 1831 | .kill_tx_queue = rt2x00usb_kill_tx_queue, |
2658 | .fill_rxdone = rt2800usb_fill_rxdone, | 1832 | .fill_rxdone = rt2800usb_fill_rxdone, |
2659 | .config_shared_key = rt2800usb_config_shared_key, | 1833 | .config_shared_key = rt2800_config_shared_key, |
2660 | .config_pairwise_key = rt2800usb_config_pairwise_key, | 1834 | .config_pairwise_key = rt2800_config_pairwise_key, |
2661 | .config_filter = rt2800usb_config_filter, | 1835 | .config_filter = rt2800_config_filter, |
2662 | .config_intf = rt2800usb_config_intf, | 1836 | .config_intf = rt2800_config_intf, |
2663 | .config_erp = rt2800usb_config_erp, | 1837 | .config_erp = rt2800_config_erp, |
2664 | .config_ant = rt2800usb_config_ant, | 1838 | .config_ant = rt2800_config_ant, |
2665 | .config = rt2800usb_config, | 1839 | .config = rt2800_config, |
2666 | }; | 1840 | }; |
2667 | 1841 | ||
2668 | static const struct data_queue_desc rt2800usb_queue_rx = { | 1842 | static const struct data_queue_desc rt2800usb_queue_rx = { |
@@ -2699,7 +1873,7 @@ static const struct rt2x00_ops rt2800usb_ops = { | |||
2699 | .lib = &rt2800usb_rt2x00_ops, | 1873 | .lib = &rt2800usb_rt2x00_ops, |
2700 | .hw = &rt2800usb_mac80211_ops, | 1874 | .hw = &rt2800usb_mac80211_ops, |
2701 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 1875 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
2702 | .debugfs = &rt2800usb_rt2x00debug, | 1876 | .debugfs = &rt2800_rt2x00debug, |
2703 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 1877 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |
2704 | }; | 1878 | }; |
2705 | 1879 | ||