aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig12
-rw-r--r--drivers/net/wireless/Makefile3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c34
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c5
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c5
-rw-r--r--drivers/net/wireless/rtl8187.h145
-rw-r--r--drivers/net/wireless/rtl8187_dev.c731
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c745
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h44
-rw-r--r--drivers/net/wireless/rtl818x.h226
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c21
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h28
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c534
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
24 files changed, 2506 insertions, 51 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa2399cbd5c..ae27af0141c 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -546,6 +546,18 @@ config USB_ZD1201
546 To compile this driver as a module, choose M here: the 546 To compile this driver as a module, choose M here: the
547 module will be called zd1201. 547 module will be called zd1201.
548 548
549config RTL8187
550 tristate "Realtek 8187 USB support"
551 depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
552 select EEPROM_93CX6
553 ---help---
554 This is a driver for RTL8187 based cards.
555 These are USB based chips found in cards such as:
556
557 Netgear WG111v2
558
559 Thanks to Realtek for their support!
560
549source "drivers/net/wireless/hostap/Kconfig" 561source "drivers/net/wireless/hostap/Kconfig"
550source "drivers/net/wireless/bcm43xx/Kconfig" 562source "drivers/net/wireless/bcm43xx/Kconfig"
551source "drivers/net/wireless/zd1211rw/Kconfig" 563source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d2124602263..ef35bc6c4a2 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
44 44
45obj-$(CONFIG_USB_ZD1201) += zd1201.o 45obj-$(CONFIG_USB_ZD1201) += zd1201.o
46obj-$(CONFIG_LIBERTAS_USB) += libertas/ 46obj-$(CONFIG_LIBERTAS_USB) += libertas/
47
48rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
49obj-$(CONFIG_RTL8187) += rtl8187.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e34870..d779199c30d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
1638 return; 1638 return;
1639 } 1639 }
1640 1640
1641 if (phy->analog > 1) { 1641 if (phy->analog == 1) {
1642 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; 1642 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
1643 value |= (baseband_attenuation << 2) & 0x003C; 1643 value |= (baseband_attenuation << 2) & 0x003C;
1644 } else { 1644 } else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd54d0e..90900525379 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
326 char *p = page; 326 char *p = page;
327 struct ap_data *ap = (struct ap_data *) data; 327 struct ap_data *ap = (struct ap_data *) data;
328 char *policy_txt; 328 char *policy_txt;
329 struct list_head *ptr;
330 struct mac_entry *entry; 329 struct mac_entry *entry;
331 330
332 if (off != 0) { 331 if (off != 0) {
@@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
352 p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); 351 p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
353 p += sprintf(p, "MAC list:\n"); 352 p += sprintf(p, "MAC list:\n");
354 spin_lock_bh(&ap->mac_restrictions.lock); 353 spin_lock_bh(&ap->mac_restrictions.lock);
355 for (ptr = ap->mac_restrictions.mac_list.next; 354 list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
356 ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
357 if (p - page > PAGE_SIZE - 80) { 355 if (p - page > PAGE_SIZE - 80) {
358 p += sprintf(p, "All entries did not fit one page.\n"); 356 p += sprintf(p, "All entries did not fit one page.\n");
359 break; 357 break;
360 } 358 }
361 359
362 entry = list_entry(ptr, struct mac_entry, list);
363 p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr)); 360 p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
364 } 361 }
365 spin_unlock_bh(&ap->mac_restrictions.lock); 362 spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
413static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, 410static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
414 u8 *mac) 411 u8 *mac)
415{ 412{
416 struct list_head *ptr;
417 struct mac_entry *entry; 413 struct mac_entry *entry;
418 int found = 0; 414 int found = 0;
419 415
@@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
421 return 0; 417 return 0;
422 418
423 spin_lock_bh(&mac_restrictions->lock); 419 spin_lock_bh(&mac_restrictions->lock);
424 for (ptr = mac_restrictions->mac_list.next; 420 list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
425 ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
426 entry = list_entry(ptr, struct mac_entry, list);
427
428 if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { 421 if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
429 found = 1; 422 found = 1;
430 break; 423 break;
@@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
519{ 512{
520 char *p = page; 513 char *p = page;
521 struct ap_data *ap = (struct ap_data *) data; 514 struct ap_data *ap = (struct ap_data *) data;
522 struct list_head *ptr; 515 struct sta_info *sta;
523 int i; 516 int i;
524 517
525 if (off > PROC_LIMIT) { 518 if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
529 522
530 p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); 523 p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
531 spin_lock_bh(&ap->sta_table_lock); 524 spin_lock_bh(&ap->sta_table_lock);
532 for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { 525 list_for_each_entry(sta, &ap->sta_list, list) {
533 struct sta_info *sta = (struct sta_info *) ptr;
534
535 if (!sta->ap) 526 if (!sta->ap)
536 continue; 527 continue;
537 528
@@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
861 852
862void hostap_free_data(struct ap_data *ap) 853void hostap_free_data(struct ap_data *ap)
863{ 854{
864 struct list_head *n, *ptr; 855 struct sta_info *n, *sta;
865 856
866 if (ap == NULL || !ap->initialized) { 857 if (ap == NULL || !ap->initialized) {
867 printk(KERN_DEBUG "hostap_free_data: ap has not yet been " 858 printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
875 ap->crypt = ap->crypt_priv = NULL; 866 ap->crypt = ap->crypt_priv = NULL;
876#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ 867#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
877 868
878 list_for_each_safe(ptr, n, &ap->sta_list) { 869 list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
879 struct sta_info *sta = list_entry(ptr, struct sta_info, list);
880 ap_sta_hash_del(ap, sta); 870 ap_sta_hash_del(ap, sta);
881 list_del(&sta->list); 871 list_del(&sta->list);
882 if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) 872 if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
2704 2694
2705 if (hdr->addr1[0] & 0x01) { 2695 if (hdr->addr1[0] & 0x01) {
2706 /* broadcast/multicast frame - no AP related processing */ 2696 /* broadcast/multicast frame - no AP related processing */
2697 if (local->ap->num_sta <= 0)
2698 ret = AP_TX_DROP;
2707 goto out; 2699 goto out;
2708 } 2700 }
2709 2701
@@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
3198 3190
3199void hostap_update_rates(local_info_t *local) 3191void hostap_update_rates(local_info_t *local)
3200{ 3192{
3201 struct list_head *ptr; 3193 struct sta_info *sta;
3202 struct ap_data *ap = local->ap; 3194 struct ap_data *ap = local->ap;
3203 3195
3204 if (!ap) 3196 if (!ap)
3205 return; 3197 return;
3206 3198
3207 spin_lock_bh(&ap->sta_table_lock); 3199 spin_lock_bh(&ap->sta_table_lock);
3208 for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { 3200 list_for_each_entry(sta, &ap->sta_list, list) {
3209 struct sta_info *sta = (struct sta_info *) ptr;
3210 prism2_check_tx_rates(sta); 3201 prism2_check_tx_rates(sta);
3211 } 3202 }
3212 spin_unlock_bh(&ap->sta_table_lock); 3203 spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
3242void hostap_add_wds_links(local_info_t *local) 3233void hostap_add_wds_links(local_info_t *local)
3243{ 3234{
3244 struct ap_data *ap = local->ap; 3235 struct ap_data *ap = local->ap;
3245 struct list_head *ptr; 3236 struct sta_info *sta;
3246 3237
3247 spin_lock_bh(&ap->sta_table_lock); 3238 spin_lock_bh(&ap->sta_table_lock);
3248 list_for_each(ptr, &ap->sta_list) { 3239 list_for_each_entry(sta, &ap->sta_list, list) {
3249 struct sta_info *sta = list_entry(ptr, struct sta_info, list);
3250 if (sta->ap) 3240 if (sta->ap)
3251 hostap_wds_link_oper(local, sta->addr, WDS_ADD); 3241 hostap_wds_link_oper(local, sta->addr, WDS_ADD);
3252 } 3242 }
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5aebb5..30acd39d76a 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
1#ifndef HOSTAP_CONFIG_H 1#ifndef HOSTAP_CONFIG_H
2#define HOSTAP_CONFIG_H 2#define HOSTAP_CONFIG_H
3 3
4#define PRISM2_VERSION "0.4.4-kernel"
5
6/* In the previous versions of Host AP driver, support for user space version 4/* In the previous versions of Host AP driver, support for user space version
7 * of IEEE 802.11 management (hostapd) used to be disabled in the default 5 * of IEEE 802.11 management (hostapd) used to be disabled in the default
8 * configuration. From now on, support for hostapd is always included and it is 6 * configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b62e4..30e723f6597 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
22#include "hostap_wlan.h" 22#include "hostap_wlan.h"
23 23
24 24
25static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
26static dev_info_t dev_info = "hostap_cs"; 25static dev_info_t dev_info = "hostap_cs";
27 26
28MODULE_AUTHOR("Jouni Malinen"); 27MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
30 "cards (PC Card)."); 29 "cards (PC Card).");
31MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)"); 30MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
32MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
33MODULE_VERSION(PRISM2_VERSION);
34 32
35 33
36static int ignore_cis_vcc; 34static int ignore_cis_vcc;
@@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
910 908
911static int __init init_prism2_pccard(void) 909static int __init init_prism2_pccard(void)
912{ 910{
913 printk(KERN_INFO "%s: %s\n", dev_info, version);
914 return pcmcia_register_driver(&hostap_driver); 911 return pcmcia_register_driver(&hostap_driver);
915} 912}
916 913
917static void __exit exit_prism2_pccard(void) 914static void __exit exit_prism2_pccard(void)
918{ 915{
919 pcmcia_unregister_driver(&hostap_driver); 916 pcmcia_unregister_driver(&hostap_driver);
920 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
921} 917}
922 918
923 919
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f71b9e..8c71077d653 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
3893 local = iface->local; 3893 local = iface->local;
3894 3894
3895 strncpy(info->driver, "hostap", sizeof(info->driver) - 1); 3895 strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
3896 strncpy(info->version, PRISM2_VERSION,
3897 sizeof(info->version) - 1);
3898 snprintf(info->fw_version, sizeof(info->fw_version) - 1, 3896 snprintf(info->fw_version, sizeof(info->fw_version) - 1,
3899 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff, 3897 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
3900 (local->sta_fw_ver >> 8) & 0xff, 3898 (local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426cf6a..446de51bab7 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
37MODULE_AUTHOR("Jouni Malinen"); 37MODULE_AUTHOR("Jouni Malinen");
38MODULE_DESCRIPTION("Host AP common routines"); 38MODULE_DESCRIPTION("Host AP common routines");
39MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
40MODULE_VERSION(PRISM2_VERSION);
41 40
42#define TX_TIMEOUT (2 * HZ) 41#define TX_TIMEOUT (2 * HZ)
43 42
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899ed4bb..0cd48d151f5 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
20#include "hostap_wlan.h" 20#include "hostap_wlan.h"
21 21
22 22
23static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
24static char *dev_info = "hostap_pci"; 23static char *dev_info = "hostap_pci";
25 24
26 25
@@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
29 "PCI cards."); 28 "PCI cards.");
30MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); 29MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
31MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
32MODULE_VERSION(PRISM2_VERSION);
33 31
34 32
35/* struct local_info::hw_priv */ 33/* struct local_info::hw_priv */
@@ -462,8 +460,6 @@ static struct pci_driver prism2_pci_drv_id = {
462 460
463static int __init init_prism2_pci(void) 461static int __init init_prism2_pci(void)
464{ 462{
465 printk(KERN_INFO "%s: %s\n", dev_info, version);
466
467 return pci_register_driver(&prism2_pci_drv_id); 463 return pci_register_driver(&prism2_pci_drv_id);
468} 464}
469 465
@@ -471,7 +467,6 @@ static int __init init_prism2_pci(void)
471static void __exit exit_prism2_pci(void) 467static void __exit exit_prism2_pci(void)
472{ 468{
473 pci_unregister_driver(&prism2_pci_drv_id); 469 pci_unregister_driver(&prism2_pci_drv_id);
474 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
475} 470}
476 471
477 472
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ecdb24..0183df757b3 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
23#include "hostap_wlan.h" 23#include "hostap_wlan.h"
24 24
25 25
26static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
27static char *dev_info = "hostap_plx"; 26static char *dev_info = "hostap_plx";
28 27
29 28
@@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
32 "cards (PLX)."); 31 "cards (PLX).");
33MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)"); 32MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
34MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
35MODULE_VERSION(PRISM2_VERSION);
36 34
37 35
38static int ignore_cis; 36static int ignore_cis;
@@ -623,8 +621,6 @@ static struct pci_driver prism2_plx_drv_id = {
623 621
624static int __init init_prism2_plx(void) 622static int __init init_prism2_plx(void)
625{ 623{
626 printk(KERN_INFO "%s: %s\n", dev_info, version);
627
628 return pci_register_driver(&prism2_plx_drv_id); 624 return pci_register_driver(&prism2_plx_drv_id);
629} 625}
630 626
@@ -632,7 +628,6 @@ static int __init init_prism2_plx(void)
632static void __exit exit_prism2_plx(void) 628static void __exit exit_prism2_plx(void)
633{ 629{
634 pci_unregister_driver(&prism2_plx_drv_id); 630 pci_unregister_driver(&prism2_plx_drv_id);
635 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
636} 631}
637 632
638 633
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 00000000000..6124e467b15
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
1/*
2 * Definitions for RTL8187 hardware
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef RTL8187_H
16#define RTL8187_H
17
18#include "rtl818x.h"
19
20#define RTL8187_EEPROM_TXPWR_BASE 0x05
21#define RTL8187_EEPROM_MAC_ADDR 0x07
22#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
23#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
24#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
25
26#define RTL8187_REQT_READ 0xC0
27#define RTL8187_REQT_WRITE 0x40
28#define RTL8187_REQ_GET_REG 0x05
29#define RTL8187_REQ_SET_REG 0x05
30
31#define RTL8187_MAX_RX 0x9C4
32
33struct rtl8187_rx_info {
34 struct urb *urb;
35 struct ieee80211_hw *dev;
36};
37
38struct rtl8187_rx_hdr {
39 __le16 len;
40 __le16 rate;
41 u8 noise;
42 u8 signal;
43 u8 agc;
44 u8 reserved;
45 __le64 mac_time;
46} __attribute__((packed));
47
48struct rtl8187_tx_info {
49 struct ieee80211_tx_control *control;
50 struct urb *urb;
51 struct ieee80211_hw *dev;
52};
53
54struct rtl8187_tx_hdr {
55 __le32 flags;
56#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
57#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
58#define RTL8187_TX_FLAG_CTS (1 << 18)
59#define RTL8187_TX_FLAG_RTS (1 << 23)
60 __le16 rts_duration;
61 __le16 len;
62 __le32 retry;
63} __attribute__((packed));
64
65struct rtl8187_priv {
66 /* common between rtl818x drivers */
67 struct rtl818x_csr *map;
68 void (*rf_init)(struct ieee80211_hw *);
69 int mode;
70
71 /* rtl8187 specific */
72 struct ieee80211_channel channels[14];
73 struct ieee80211_rate rates[12];
74 struct ieee80211_hw_mode modes[2];
75 struct usb_device *udev;
76 u8 *hwaddr;
77 u16 txpwr_base;
78 u8 asic_rev;
79 struct sk_buff_head rx_queue;
80};
81
82void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
83
84static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
85{
86 u8 val;
87
88 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
89 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
90 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
91
92 return val;
93}
94
95static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
96{
97 __le16 val;
98
99 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
100 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
101 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
102
103 return le16_to_cpu(val);
104}
105
106static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
107{
108 __le32 val;
109
110 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
111 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
112 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
113
114 return le32_to_cpu(val);
115}
116
117static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
118 u8 *addr, u8 val)
119{
120 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
121 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
122 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
123}
124
125static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
126 __le16 *addr, u16 val)
127{
128 __le16 buf = cpu_to_le16(val);
129
130 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
131 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
132 (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
133}
134
135static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
136 __le32 *addr, u32 val)
137{
138 __le32 buf = cpu_to_le32(val);
139
140 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
141 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
142 (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
143}
144
145#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 00000000000..cea85894b7f
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
1/*
2 * Linux device driver for RTL8187
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
10 * Magic delays and register offsets below are taken from the original
11 * r8187 driver sources. Thanks to Realtek for their support!
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/init.h>
19#include <linux/usb.h>
20#include <linux/delay.h>
21#include <linux/etherdevice.h>
22#include <linux/eeprom_93cx6.h>
23#include <net/mac80211.h>
24
25#include "rtl8187.h"
26#include "rtl8187_rtl8225.h"
27
28MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
29MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
30MODULE_DESCRIPTION("RTL8187 USB wireless driver");
31MODULE_LICENSE("GPL");
32
33static struct usb_device_id rtl8187_table[] __devinitdata = {
34 /* Realtek */
35 {USB_DEVICE(0x0bda, 0x8187)},
36 /* Netgear */
37 {USB_DEVICE(0x0846, 0x6100)},
38 {USB_DEVICE(0x0846, 0x6a00)},
39 {}
40};
41
42MODULE_DEVICE_TABLE(usb, rtl8187_table);
43
44void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
45{
46 struct rtl8187_priv *priv = dev->priv;
47
48 data <<= 8;
49 data |= addr | 0x80;
50
51 rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
52 rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
53 rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
54 rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
55
56 msleep(1);
57}
58
59static void rtl8187_tx_cb(struct urb *urb)
60{
61 struct ieee80211_tx_status status = { {0} };
62 struct sk_buff *skb = (struct sk_buff *)urb->context;
63 struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
64
65 usb_free_urb(info->urb);
66 if (info->control)
67 memcpy(&status.control, info->control, sizeof(status.control));
68 kfree(info->control);
69 skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
70 status.flags |= IEEE80211_TX_STATUS_ACK;
71 ieee80211_tx_status_irqsafe(info->dev, skb, &status);
72}
73
74static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
75 struct ieee80211_tx_control *control)
76{
77 struct rtl8187_priv *priv = dev->priv;
78 struct rtl8187_tx_hdr *hdr;
79 struct rtl8187_tx_info *info;
80 struct urb *urb;
81 u32 tmp;
82
83 urb = usb_alloc_urb(0, GFP_ATOMIC);
84 if (!urb) {
85 kfree_skb(skb);
86 return 0;
87 }
88
89 hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
90 tmp = skb->len - sizeof(*hdr);
91 tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
92 tmp |= control->rts_cts_rate << 19;
93 tmp |= control->tx_rate << 24;
94 if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
95 tmp |= RTL8187_TX_FLAG_MORE_FRAG;
96 if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
97 tmp |= RTL8187_TX_FLAG_RTS;
98 hdr->rts_duration =
99 ieee80211_rts_duration(dev, skb->len, control);
100 }
101 if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
102 tmp |= RTL8187_TX_FLAG_CTS;
103 hdr->flags = cpu_to_le32(tmp);
104 hdr->len = 0;
105 tmp = control->retry_limit << 8;
106 hdr->retry = cpu_to_le32(tmp);
107
108 info = (struct rtl8187_tx_info *)skb->cb;
109 info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
110 info->urb = urb;
111 info->dev = dev;
112 usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
113 hdr, skb->len, rtl8187_tx_cb, skb);
114 usb_submit_urb(urb, GFP_ATOMIC);
115
116 return 0;
117}
118
119static void rtl8187_rx_cb(struct urb *urb)
120{
121 struct sk_buff *skb = (struct sk_buff *)urb->context;
122 struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
123 struct ieee80211_hw *dev = info->dev;
124 struct rtl8187_priv *priv = dev->priv;
125 struct rtl8187_rx_hdr *hdr;
126 struct ieee80211_rx_status rx_status = { 0 };
127 int rate, signal;
128
129 spin_lock(&priv->rx_queue.lock);
130 if (skb->next)
131 __skb_unlink(skb, &priv->rx_queue);
132 else {
133 spin_unlock(&priv->rx_queue.lock);
134 return;
135 }
136 spin_unlock(&priv->rx_queue.lock);
137
138 if (unlikely(urb->status)) {
139 usb_free_urb(urb);
140 dev_kfree_skb_irq(skb);
141 return;
142 }
143
144 skb_put(skb, urb->actual_length);
145 hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
146 skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
147
148 signal = hdr->agc >> 1;
149 rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
150 if (rate > 3) { /* OFDM rate */
151 if (signal > 90)
152 signal = 90;
153 else if (signal < 25)
154 signal = 25;
155 signal = 90 - signal;
156 } else { /* CCK rate */
157 if (signal > 95)
158 signal = 95;
159 else if (signal < 30)
160 signal = 30;
161 signal = 95 - signal;
162 }
163
164 rx_status.antenna = (hdr->signal >> 7) & 1;
165 rx_status.signal = 64 - min(hdr->noise, (u8)64);
166 rx_status.ssi = signal;
167 rx_status.rate = rate;
168 rx_status.freq = dev->conf.freq;
169 rx_status.channel = dev->conf.channel;
170 rx_status.phymode = dev->conf.phymode;
171 rx_status.mactime = le64_to_cpu(hdr->mac_time);
172 ieee80211_rx_irqsafe(dev, skb, &rx_status);
173
174 skb = dev_alloc_skb(RTL8187_MAX_RX);
175 if (unlikely(!skb)) {
176 usb_free_urb(urb);
177 /* TODO check rx queue length and refill *somewhere* */
178 return;
179 }
180
181 info = (struct rtl8187_rx_info *)skb->cb;
182 info->urb = urb;
183 info->dev = dev;
184 urb->transfer_buffer = skb_tail_pointer(skb);
185 urb->context = skb;
186 skb_queue_tail(&priv->rx_queue, skb);
187
188 usb_submit_urb(urb, GFP_ATOMIC);
189}
190
191static int rtl8187_init_urbs(struct ieee80211_hw *dev)
192{
193 struct rtl8187_priv *priv = dev->priv;
194 struct urb *entry;
195 struct sk_buff *skb;
196 struct rtl8187_rx_info *info;
197
198 while (skb_queue_len(&priv->rx_queue) < 8) {
199 skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
200 if (!skb)
201 break;
202 entry = usb_alloc_urb(0, GFP_KERNEL);
203 if (!entry) {
204 kfree_skb(skb);
205 break;
206 }
207 usb_fill_bulk_urb(entry, priv->udev,
208 usb_rcvbulkpipe(priv->udev, 1),
209 skb_tail_pointer(skb),
210 RTL8187_MAX_RX, rtl8187_rx_cb, skb);
211 info = (struct rtl8187_rx_info *)skb->cb;
212 info->urb = entry;
213 info->dev = dev;
214 skb_queue_tail(&priv->rx_queue, skb);
215 usb_submit_urb(entry, GFP_KERNEL);
216 }
217
218 return 0;
219}
220
221static int rtl8187_init_hw(struct ieee80211_hw *dev)
222{
223 struct rtl8187_priv *priv = dev->priv;
224 u8 reg;
225 int i;
226
227 /* reset */
228 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
229 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
230 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
231 rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
232 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
233 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
234 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
235
236 rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
237
238 msleep(200);
239 rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
240 rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
241 rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
242 msleep(200);
243
244 reg = rtl818x_ioread8(priv, &priv->map->CMD);
245 reg &= (1 << 1);
246 reg |= RTL818X_CMD_RESET;
247 rtl818x_iowrite8(priv, &priv->map->CMD, reg);
248
249 i = 10;
250 do {
251 msleep(2);
252 if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
253 RTL818X_CMD_RESET))
254 break;
255 } while (--i);
256
257 if (!i) {
258 printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
259 return -ETIMEDOUT;
260 }
261
262 /* reload registers from eeprom */
263 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
264
265 i = 10;
266 do {
267 msleep(4);
268 if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
269 RTL818X_EEPROM_CMD_CONFIG))
270 break;
271 } while (--i);
272
273 if (!i) {
274 printk(KERN_ERR "%s: eeprom reset timeout!\n",
275 wiphy_name(dev->wiphy));
276 return -ETIMEDOUT;
277 }
278
279 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
280 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
281 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
282 rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
283 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
284 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
285 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
286
287 /* setup card */
288 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
289 rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
290
291 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
292 rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
293 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
294
295 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
296 for (i = 0; i < ETH_ALEN; i++)
297 rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
298
299 rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
300 reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
301 reg &= 0x3F;
302 reg |= 0x80;
303 rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
304
305 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
306
307 rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
308 rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
309 rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
310
311 // TODO: set RESP_RATE and BRSR properly
312 rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
313 rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
314
315 /* host_usb_init */
316 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
317 rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
318 reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
319 rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
320 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
321 rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
322 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
323 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
324 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
325 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
326 msleep(100);
327
328 rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
329 rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
330 rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
331 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
332 rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
333 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
334 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
335 msleep(100);
336
337 priv->rf_init(dev);
338
339 rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
340 reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
341 rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
342 rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
343 rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
344 rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
345 rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
346
347 return 0;
348}
349
350static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
351{
352 u32 reg;
353 struct rtl8187_priv *priv = dev->priv;
354
355 reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
356 /* Enable TX loopback on MAC level to avoid TX during channel
357 * changes, as this has be seen to causes problems and the
358 * card will stop work until next reset
359 */
360 rtl818x_iowrite32(priv, &priv->map->TX_CONF,
361 reg | RTL818X_TX_CONF_LOOPBACK_MAC);
362 msleep(10);
363 rtl8225_rf_set_channel(dev, channel);
364 msleep(10);
365 rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
366}
367
368static int rtl8187_open(struct ieee80211_hw *dev)
369{
370 struct rtl8187_priv *priv = dev->priv;
371 u32 reg;
372 int ret;
373
374 ret = rtl8187_init_hw(dev);
375 if (ret)
376 return ret;
377
378 rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
379
380 rtl8187_init_urbs(dev);
381
382 reg = RTL818X_RX_CONF_ONLYERLPKT |
383 RTL818X_RX_CONF_RX_AUTORESETPHY |
384 RTL818X_RX_CONF_BSSID |
385 RTL818X_RX_CONF_MGMT |
386 RTL818X_RX_CONF_CTRL |
387 RTL818X_RX_CONF_DATA |
388 (7 << 13 /* RX FIFO threshold NONE */) |
389 (7 << 10 /* MAX RX DMA */) |
390 RTL818X_RX_CONF_BROADCAST |
391 RTL818X_RX_CONF_MULTICAST |
392 RTL818X_RX_CONF_NICMAC;
393 if (priv->mode == IEEE80211_IF_TYPE_MNTR)
394 reg |= RTL818X_RX_CONF_MONITOR;
395
396 rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
397
398 reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
399 reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
400 reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
401 rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
402
403 reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
404 reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
405 reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
406 reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
407 rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
408
409 reg = RTL818X_TX_CONF_CW_MIN |
410 (7 << 21 /* MAX TX DMA */) |
411 RTL818X_TX_CONF_NO_ICV;
412 rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
413
414 reg = rtl818x_ioread8(priv, &priv->map->CMD);
415 reg |= RTL818X_CMD_TX_ENABLE;
416 reg |= RTL818X_CMD_RX_ENABLE;
417 rtl818x_iowrite8(priv, &priv->map->CMD, reg);
418
419 return 0;
420}
421
422static int rtl8187_stop(struct ieee80211_hw *dev)
423{
424 struct rtl8187_priv *priv = dev->priv;
425 struct rtl8187_rx_info *info;
426 struct sk_buff *skb;
427 u32 reg;
428
429 rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
430
431 reg = rtl818x_ioread8(priv, &priv->map->CMD);
432 reg &= ~RTL818X_CMD_TX_ENABLE;
433 reg &= ~RTL818X_CMD_RX_ENABLE;
434 rtl818x_iowrite8(priv, &priv->map->CMD, reg);
435
436 rtl8225_rf_stop(dev);
437
438 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
439 reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
440 rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
441 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
442
443 while ((skb = skb_dequeue(&priv->rx_queue))) {
444 info = (struct rtl8187_rx_info *)skb->cb;
445 usb_kill_urb(info->urb);
446 kfree_skb(skb);
447 }
448 return 0;
449}
450
451static int rtl8187_add_interface(struct ieee80211_hw *dev,
452 struct ieee80211_if_init_conf *conf)
453{
454 struct rtl8187_priv *priv = dev->priv;
455
456 /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
457 if (priv->mode != IEEE80211_IF_TYPE_MGMT)
458 return -1;
459
460 switch (conf->type) {
461 case IEEE80211_IF_TYPE_STA:
462 case IEEE80211_IF_TYPE_MNTR:
463 priv->mode = conf->type;
464 break;
465 default:
466 return -EOPNOTSUPP;
467 }
468
469 priv->hwaddr = conf->mac_addr;
470
471 return 0;
472}
473
474static void rtl8187_remove_interface(struct ieee80211_hw *dev,
475 struct ieee80211_if_init_conf *conf)
476{
477 struct rtl8187_priv *priv = dev->priv;
478 priv->mode = IEEE80211_IF_TYPE_MGMT;
479}
480
481static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
482{
483 struct rtl8187_priv *priv = dev->priv;
484 rtl8187_set_channel(dev, conf->channel);
485
486 rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
487
488 if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
489 rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
490 rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
491 rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
492 rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
493 } else {
494 rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
495 rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
496 rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
497 rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
498 }
499
500 rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
501 rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
502 rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
503 rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
504 return 0;
505}
506
507static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
508 struct ieee80211_if_conf *conf)
509{
510 struct rtl8187_priv *priv = dev->priv;
511 int i;
512
513 for (i = 0; i < ETH_ALEN; i++)
514 rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
515
516 if (is_valid_ether_addr(conf->bssid))
517 rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
518 else
519 rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
520
521 return 0;
522}
523
524static const struct ieee80211_ops rtl8187_ops = {
525 .tx = rtl8187_tx,
526 .open = rtl8187_open,
527 .stop = rtl8187_stop,
528 .add_interface = rtl8187_add_interface,
529 .remove_interface = rtl8187_remove_interface,
530 .config = rtl8187_config,
531 .config_interface = rtl8187_config_interface,
532};
533
534static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
535{
536 struct ieee80211_hw *dev = eeprom->data;
537 struct rtl8187_priv *priv = dev->priv;
538 u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
539
540 eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
541 eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
542 eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
543 eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
544}
545
546static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
547{
548 struct ieee80211_hw *dev = eeprom->data;
549 struct rtl8187_priv *priv = dev->priv;
550 u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
551
552 if (eeprom->reg_data_in)
553 reg |= RTL818X_EEPROM_CMD_WRITE;
554 if (eeprom->reg_data_out)
555 reg |= RTL818X_EEPROM_CMD_READ;
556 if (eeprom->reg_data_clock)
557 reg |= RTL818X_EEPROM_CMD_CK;
558 if (eeprom->reg_chip_select)
559 reg |= RTL818X_EEPROM_CMD_CS;
560
561 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
562 udelay(10);
563}
564
565static int __devinit rtl8187_probe(struct usb_interface *intf,
566 const struct usb_device_id *id)
567{
568 struct usb_device *udev = interface_to_usbdev(intf);
569 struct ieee80211_hw *dev;
570 struct rtl8187_priv *priv;
571 struct eeprom_93cx6 eeprom;
572 struct ieee80211_channel *channel;
573 u16 txpwr, reg;
574 int err, i;
575
576 dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
577 if (!dev) {
578 printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
579 return -ENOMEM;
580 }
581
582 priv = dev->priv;
583
584 SET_IEEE80211_DEV(dev, &intf->dev);
585 usb_set_intfdata(intf, dev);
586 priv->udev = udev;
587
588 usb_get_dev(udev);
589
590 skb_queue_head_init(&priv->rx_queue);
591 memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
592 memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
593 priv->map = (struct rtl818x_csr *)0xFF00;
594 priv->modes[0].mode = MODE_IEEE80211G;
595 priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
596 priv->modes[0].rates = priv->rates;
597 priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
598 priv->modes[0].channels = priv->channels;
599 priv->modes[1].mode = MODE_IEEE80211B;
600 priv->modes[1].num_rates = 4;
601 priv->modes[1].rates = priv->rates;
602 priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
603 priv->modes[1].channels = priv->channels;
604 priv->mode = IEEE80211_IF_TYPE_MGMT;
605 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
606 IEEE80211_HW_RX_INCLUDES_FCS |
607 IEEE80211_HW_WEP_INCLUDE_IV |
608 IEEE80211_HW_DATA_NULLFUNC_ACK;
609 dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
610 dev->queues = 1;
611 dev->max_rssi = 65;
612 dev->max_signal = 64;
613
614 for (i = 0; i < 2; i++)
615 if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
616 goto err_free_dev;
617
618 eeprom.data = dev;
619 eeprom.register_read = rtl8187_eeprom_register_read;
620 eeprom.register_write = rtl8187_eeprom_register_write;
621 if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
622 eeprom.width = PCI_EEPROM_WIDTH_93C66;
623 else
624 eeprom.width = PCI_EEPROM_WIDTH_93C46;
625
626 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
627 udelay(10);
628
629 eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
630 (__le16 __force *)dev->wiphy->perm_addr, 3);
631 if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
632 printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
633 "generated MAC address\n");
634 random_ether_addr(dev->wiphy->perm_addr);
635 }
636
637 channel = priv->channels;
638 for (i = 0; i < 3; i++) {
639 eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
640 &txpwr);
641 (*channel++).val = txpwr & 0xFF;
642 (*channel++).val = txpwr >> 8;
643 }
644 for (i = 0; i < 2; i++) {
645 eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
646 &txpwr);
647 (*channel++).val = txpwr & 0xFF;
648 (*channel++).val = txpwr >> 8;
649 }
650 for (i = 0; i < 2; i++) {
651 eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
652 &txpwr);
653 (*channel++).val = txpwr & 0xFF;
654 (*channel++).val = txpwr >> 8;
655 }
656
657 eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
658 &priv->txpwr_base);
659
660 reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
661 rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
662 /* 0 means asic B-cut, we should use SW 3 wire
663 * bit-by-bit banging for radio. 1 means we can use
664 * USB specific request to write radio registers */
665 priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
666 rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
667 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
668
669 rtl8225_write(dev, 0, 0x1B7);
670
671 if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
672 priv->rf_init = rtl8225_rf_init;
673 else
674 priv->rf_init = rtl8225z2_rf_init;
675
676 rtl8225_write(dev, 0, 0x0B7);
677
678 err = ieee80211_register_hw(dev);
679 if (err) {
680 printk(KERN_ERR "rtl8187: Cannot register device\n");
681 goto err_free_dev;
682 }
683
684 printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
685 wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
686 priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
687 "rtl8225" : "rtl8225z2");
688
689 return 0;
690
691 err_free_dev:
692 ieee80211_free_hw(dev);
693 usb_set_intfdata(intf, NULL);
694 usb_put_dev(udev);
695 return err;
696}
697
698static void __devexit rtl8187_disconnect(struct usb_interface *intf)
699{
700 struct ieee80211_hw *dev = usb_get_intfdata(intf);
701 struct rtl8187_priv *priv;
702
703 if (!dev)
704 return;
705
706 ieee80211_unregister_hw(dev);
707
708 priv = dev->priv;
709 usb_put_dev(interface_to_usbdev(intf));
710 ieee80211_free_hw(dev);
711}
712
713static struct usb_driver rtl8187_driver = {
714 .name = KBUILD_MODNAME,
715 .id_table = rtl8187_table,
716 .probe = rtl8187_probe,
717 .disconnect = rtl8187_disconnect,
718};
719
720static int __init rtl8187_init(void)
721{
722 return usb_register(&rtl8187_driver);
723}
724
725static void __exit rtl8187_exit(void)
726{
727 usb_deregister(&rtl8187_driver);
728}
729
730module_init(rtl8187_init);
731module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 00000000000..e25a09f1b06
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
1/*
2 * Radio tuning for RTL8225 on RTL8187
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
10 * Magic delays, register offsets, and phy value tables below are
11 * taken from the original r8187 driver sources. Thanks to Realtek
12 * for their support!
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/init.h>
20#include <linux/usb.h>
21#include <net/mac80211.h>
22
23#include "rtl8187.h"
24#include "rtl8187_rtl8225.h"
25
26static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
27{
28 struct rtl8187_priv *priv = dev->priv;
29 u16 reg80, reg84, reg82;
30 u32 bangdata;
31 int i;
32
33 bangdata = (data << 4) | (addr & 0xf);
34
35 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
36 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
37
38 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
39
40 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
41 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
42 udelay(10);
43
44 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
45 udelay(2);
46 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
47 udelay(10);
48
49 for (i = 15; i >= 0; i--) {
50 u16 reg = reg80 | (bangdata & (1 << i)) >> i;
51
52 if (i & 1)
53 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
54
55 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
56 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
57
58 if (!(i & 1))
59 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
60 }
61
62 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
63 udelay(10);
64
65 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
66 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
67 msleep(2);
68}
69
70static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
71{
72 struct rtl8187_priv *priv = dev->priv;
73 u16 reg80, reg82, reg84;
74
75 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
76 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
77 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
78
79 reg80 &= ~(0x3 << 2);
80 reg84 &= ~0xF;
81
82 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
83 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
84 udelay(10);
85
86 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
87 udelay(2);
88
89 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
90 udelay(10);
91
92 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
93 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
94 addr, 0x8225, &data, sizeof(data), HZ / 2);
95
96 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
97 udelay(10);
98
99 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
100 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
101 msleep(2);
102}
103
104void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
105{
106 struct rtl8187_priv *priv = dev->priv;
107
108 if (priv->asic_rev)
109 rtl8225_write_8051(dev, addr, data);
110 else
111 rtl8225_write_bitbang(dev, addr, data);
112}
113
114u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
115{
116 struct rtl8187_priv *priv = dev->priv;
117 u16 reg80, reg82, reg84, out;
118 int i;
119
120 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
121 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
122 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
123
124 reg80 &= ~0xF;
125
126 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
127 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
128
129 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
130 udelay(4);
131 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
132 udelay(5);
133
134 for (i = 4; i >= 0; i--) {
135 u16 reg = reg80 | ((addr >> i) & 1);
136
137 if (!(i & 1)) {
138 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
139 udelay(1);
140 }
141
142 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
143 reg | (1 << 1));
144 udelay(2);
145 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
146 reg | (1 << 1));
147 udelay(2);
148
149 if (i & 1) {
150 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
151 udelay(1);
152 }
153 }
154
155 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
156 reg80 | (1 << 3) | (1 << 1));
157 udelay(2);
158 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
159 reg80 | (1 << 3));
160 udelay(2);
161 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
162 reg80 | (1 << 3));
163 udelay(2);
164
165 out = 0;
166 for (i = 11; i >= 0; i--) {
167 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
168 reg80 | (1 << 3));
169 udelay(1);
170 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
171 reg80 | (1 << 3) | (1 << 1));
172 udelay(2);
173 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
174 reg80 | (1 << 3) | (1 << 1));
175 udelay(2);
176 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
177 reg80 | (1 << 3) | (1 << 1));
178 udelay(2);
179
180 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
181 out |= 1 << i;
182
183 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
184 reg80 | (1 << 3));
185 udelay(2);
186 }
187
188 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
189 reg80 | (1 << 3) | (1 << 2));
190 udelay(2);
191
192 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
193 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
194 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
195
196 return out;
197}
198
199static const u16 rtl8225bcd_rxgain[] = {
200 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
201 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
202 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
203 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
204 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
205 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
206 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
207 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
208 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
209 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
210 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
211 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
212};
213
214static const u8 rtl8225_agc[] = {
215 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
216 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
217 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
218 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
219 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
220 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
221 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
222 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
223 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
224 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
225 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
226 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
227 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
228 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
229 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
230 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
231};
232
233static const u8 rtl8225_gain[] = {
234 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
235 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
236 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
237 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
238 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
239 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
240 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
241};
242
243static const u8 rtl8225_threshold[] = {
244 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
245};
246
247static const u8 rtl8225_tx_gain_cck_ofdm[] = {
248 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
249};
250
251static const u8 rtl8225_tx_power_cck[] = {
252 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
253 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
254 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
255 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
256 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
257 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
258};
259
260static const u8 rtl8225_tx_power_cck_ch14[] = {
261 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
262 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
263 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
264 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
265 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
266 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
267};
268
269static const u8 rtl8225_tx_power_ofdm[] = {
270 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
271};
272
273static const u32 rtl8225_chan[] = {
274 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
275 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
276};
277
278static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
279{
280 struct rtl8187_priv *priv = dev->priv;
281 u8 cck_power, ofdm_power;
282 const u8 *tmp;
283 u32 reg;
284 int i;
285
286 cck_power = priv->channels[channel - 1].val & 0xF;
287 ofdm_power = priv->channels[channel - 1].val >> 4;
288
289 cck_power = min(cck_power, (u8)11);
290 ofdm_power = min(ofdm_power, (u8)35);
291
292 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
293 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
294
295 if (channel == 14)
296 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
297 else
298 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
299
300 for (i = 0; i < 8; i++)
301 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
302
303 msleep(1); // FIXME: optional?
304
305 /* anaparam2 on */
306 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
307 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
308 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
309 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
310 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
311 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
312
313 rtl8225_write_phy_ofdm(dev, 2, 0x42);
314 rtl8225_write_phy_ofdm(dev, 6, 0x00);
315 rtl8225_write_phy_ofdm(dev, 8, 0x00);
316
317 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
318 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
319
320 tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
321
322 rtl8225_write_phy_ofdm(dev, 5, *tmp);
323 rtl8225_write_phy_ofdm(dev, 7, *tmp);
324
325 msleep(1);
326}
327
328void rtl8225_rf_init(struct ieee80211_hw *dev)
329{
330 struct rtl8187_priv *priv = dev->priv;
331 int i;
332
333 rtl8225_write(dev, 0x0, 0x067); msleep(1);
334 rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
335 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
336 rtl8225_write(dev, 0x3, 0x441); msleep(1);
337 rtl8225_write(dev, 0x4, 0x486); msleep(1);
338 rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
339 rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
340 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
341 rtl8225_write(dev, 0x8, 0x01F); msleep(1);
342 rtl8225_write(dev, 0x9, 0x334); msleep(1);
343 rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
344 rtl8225_write(dev, 0xB, 0x391); msleep(1);
345 rtl8225_write(dev, 0xC, 0x050); msleep(1);
346 rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
347 rtl8225_write(dev, 0xE, 0x029); msleep(1);
348 rtl8225_write(dev, 0xF, 0x914); msleep(100);
349
350 rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
351 rtl8225_write(dev, 0x2, 0x44D); msleep(200);
352
353 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
354 rtl8225_write(dev, 0x02, 0x0c4d);
355 msleep(200);
356 rtl8225_write(dev, 0x02, 0x044d);
357 msleep(100);
358 if (!(rtl8225_read(dev, 6) & (1 << 7)))
359 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
360 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
361 }
362
363 rtl8225_write(dev, 0x0, 0x127);
364
365 for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
366 rtl8225_write(dev, 0x1, i + 1);
367 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
368 }
369
370 rtl8225_write(dev, 0x0, 0x027);
371 rtl8225_write(dev, 0x0, 0x22F);
372
373 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
374 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
375 msleep(1);
376 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
377 msleep(1);
378 }
379
380 msleep(1);
381
382 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
383 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
384 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
385 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
386 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
387 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
388 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
389 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
390 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
391 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
392 rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
393 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
394 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
395 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
396 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
397 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
398 rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
399 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
400 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
401 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
402 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
403 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
404 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
405 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
406 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
407 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
408 rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
409 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
410 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
411 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
412 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
413 rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
414 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
415 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
416 rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
417 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
418 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
419
420 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
421 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
422 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
423 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
424
425 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
426 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
427 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
428 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
429 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
430 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
431 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
432 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
433 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
434 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
435 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
436 rtl8225_write_phy_cck(dev, 0x19, 0x00);
437 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
438 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
439 rtl8225_write_phy_cck(dev, 0x40, 0x86);
440 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
441 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
442 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
443 rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
444 rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
445 rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
446 rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
447 rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
448 rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
449 rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
450 rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
451 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
452
453 rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
454
455 rtl8225_rf_set_tx_power(dev, 1);
456
457 /* RX antenna default to A */
458 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
459 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
460
461 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
462 msleep(1);
463 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
464
465 /* set sensitivity */
466 rtl8225_write(dev, 0x0c, 0x50);
467 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
468 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
469 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
470 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
471 rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
472}
473
474static const u8 rtl8225z2_tx_power_cck_ch14[] = {
475 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
476};
477
478static const u8 rtl8225z2_tx_power_cck[] = {
479 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
480};
481
482static const u8 rtl8225z2_tx_power_ofdm[] = {
483 0x42, 0x00, 0x40, 0x00, 0x40
484};
485
486static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
487 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
488 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
489 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
490 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
491 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
492 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
493};
494
495static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
496{
497 struct rtl8187_priv *priv = dev->priv;
498 u8 cck_power, ofdm_power;
499 const u8 *tmp;
500 u32 reg;
501 int i;
502
503 cck_power = priv->channels[channel - 1].val & 0xF;
504 ofdm_power = priv->channels[channel - 1].val >> 4;
505
506 cck_power = min(cck_power, (u8)15);
507 cck_power += priv->txpwr_base & 0xF;
508 cck_power = min(cck_power, (u8)35);
509
510 ofdm_power = min(ofdm_power, (u8)15);
511 ofdm_power += priv->txpwr_base >> 4;
512 ofdm_power = min(ofdm_power, (u8)35);
513
514 if (channel == 14)
515 tmp = rtl8225z2_tx_power_cck_ch14;
516 else
517 tmp = rtl8225z2_tx_power_cck;
518
519 for (i = 0; i < 8; i++)
520 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
521
522 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
523 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
524 msleep(1);
525
526 /* anaparam2 on */
527 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
528 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
529 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
530 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
531 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
532 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
533
534 rtl8225_write_phy_ofdm(dev, 2, 0x42);
535 rtl8225_write_phy_ofdm(dev, 5, 0x00);
536 rtl8225_write_phy_ofdm(dev, 6, 0x40);
537 rtl8225_write_phy_ofdm(dev, 7, 0x00);
538 rtl8225_write_phy_ofdm(dev, 8, 0x40);
539
540 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
541 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
542 msleep(1);
543}
544
545static const u16 rtl8225z2_rxgain[] = {
546 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
547 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
548 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
549 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
550 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
551 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
552 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
553 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
554 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
555 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
556 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
557 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
558};
559
560static const u8 rtl8225z2_gain_bg[] = {
561 0x23, 0x15, 0xa5, /* -82-1dBm */
562 0x23, 0x15, 0xb5, /* -82-2dBm */
563 0x23, 0x15, 0xc5, /* -82-3dBm */
564 0x33, 0x15, 0xc5, /* -78dBm */
565 0x43, 0x15, 0xc5, /* -74dBm */
566 0x53, 0x15, 0xc5, /* -70dBm */
567 0x63, 0x15, 0xc5 /* -66dBm */
568};
569
570void rtl8225z2_rf_init(struct ieee80211_hw *dev)
571{
572 struct rtl8187_priv *priv = dev->priv;
573 int i;
574
575 rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
576 rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
577 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
578 rtl8225_write(dev, 0x3, 0x441); msleep(1);
579 rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
580 rtl8225_write(dev, 0x5, 0xC72); msleep(1);
581 rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
582 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
583 rtl8225_write(dev, 0x8, 0x03F); msleep(1);
584 rtl8225_write(dev, 0x9, 0x335); msleep(1);
585 rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
586 rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
587 rtl8225_write(dev, 0xc, 0x850); msleep(1);
588 rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
589 rtl8225_write(dev, 0xe, 0x02B); msleep(1);
590 rtl8225_write(dev, 0xf, 0x114); msleep(100);
591
592 rtl8225_write(dev, 0x0, 0x1B7);
593
594 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
595 rtl8225_write(dev, 0x1, i + 1);
596 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
597 }
598
599 rtl8225_write(dev, 0x3, 0x080);
600 rtl8225_write(dev, 0x5, 0x004);
601 rtl8225_write(dev, 0x0, 0x0B7);
602 rtl8225_write(dev, 0x2, 0xc4D);
603
604 msleep(200);
605 rtl8225_write(dev, 0x2, 0x44D);
606 msleep(100);
607
608 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
609 rtl8225_write(dev, 0x02, 0x0C4D);
610 msleep(200);
611 rtl8225_write(dev, 0x02, 0x044D);
612 msleep(100);
613 if (!(rtl8225_read(dev, 6) & (1 << 7)))
614 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
615 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
616 }
617
618 msleep(200);
619
620 rtl8225_write(dev, 0x0, 0x2BF);
621
622 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
623 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
624 msleep(1);
625 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
626 msleep(1);
627 }
628
629 msleep(1);
630
631 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
632 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
633 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
634 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
635 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
636 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
637 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
638 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
639 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
640 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
641 rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
642 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
643 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
644 rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
645 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
646 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
647 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
648 rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
649 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
650 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
651 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
652 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
653 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
654 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
655 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
656 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
657 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
658 rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
659 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
660 rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
661 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
662 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
663 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
664 rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
665 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
666 rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
667 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
668 rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
669 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
670 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
671
672 rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
673 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
674 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
675 rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
676
677 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
678 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
679 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
680 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
681 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
682 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
683 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
684 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
685 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
686 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
687 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
688 rtl8225_write_phy_cck(dev, 0x19, 0x00);
689 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
690 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
691 rtl8225_write_phy_cck(dev, 0x40, 0x86);
692 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
693 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
694 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
695 rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
696 rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
697 rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
698 rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
699 rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
700 rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
701 rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
702 rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
703 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
704
705 rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
706
707 rtl8225z2_rf_set_tx_power(dev, 1);
708
709 /* RX antenna default to A */
710 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
711 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
712
713 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
714 msleep(1);
715 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
716}
717
718void rtl8225_rf_stop(struct ieee80211_hw *dev)
719{
720 u8 reg;
721 struct rtl8187_priv *priv = dev->priv;
722
723 rtl8225_write(dev, 0x4, 0x1f); msleep(1);
724
725 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
726 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
727 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
728 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
729 rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
730 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
731 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
732}
733
734void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
735{
736 struct rtl8187_priv *priv = dev->priv;
737
738 if (priv->rf_init == rtl8225_rf_init)
739 rtl8225_rf_set_tx_power(dev, channel);
740 else
741 rtl8225z2_rf_set_tx_power(dev, channel);
742
743 rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
744 msleep(10);
745}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 00000000000..798ba4a9737
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
1/*
2 * Radio tuning definitions for RTL8225 on RTL8187
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef RTL8187_RTL8225_H
16#define RTL8187_RTL8225_H
17
18#define RTL8225_ANAPARAM_ON 0xa0000a59
19#define RTL8225_ANAPARAM2_ON 0x860c7312
20#define RTL8225_ANAPARAM_OFF 0xa00beb59
21#define RTL8225_ANAPARAM2_OFF 0x840dec11
22
23void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
24u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
25
26void rtl8225_rf_init(struct ieee80211_hw *);
27void rtl8225z2_rf_init(struct ieee80211_hw *);
28void rtl8225_rf_stop(struct ieee80211_hw *);
29void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
30
31
32static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
33 u8 addr, u32 data)
34{
35 rtl8187_write_phy(dev, addr, data);
36}
37
38static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
39 u8 addr, u32 data)
40{
41 rtl8187_write_phy(dev, addr, data | 0x10000);
42}
43
44#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 00000000000..283de30628e
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
1/*
2 * Definitions for RTL818x hardware
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef RTL818X_H
16#define RTL818X_H
17
18struct rtl818x_csr {
19 u8 MAC[6];
20 u8 reserved_0[2];
21 __le32 MAR[2];
22 u8 RX_FIFO_COUNT;
23 u8 reserved_1;
24 u8 TX_FIFO_COUNT;
25 u8 BQREQ;
26 u8 reserved_2[4];
27 __le32 TSFT[2];
28 __le32 TLPDA;
29 __le32 TNPDA;
30 __le32 THPDA;
31 __le16 BRSR;
32 u8 BSSID[6];
33 u8 RESP_RATE;
34 u8 EIFS;
35 u8 reserved_3[1];
36 u8 CMD;
37#define RTL818X_CMD_TX_ENABLE (1 << 2)
38#define RTL818X_CMD_RX_ENABLE (1 << 3)
39#define RTL818X_CMD_RESET (1 << 4)
40 u8 reserved_4[4];
41 __le16 INT_MASK;
42 __le16 INT_STATUS;
43#define RTL818X_INT_RX_OK (1 << 0)
44#define RTL818X_INT_RX_ERR (1 << 1)
45#define RTL818X_INT_TXL_OK (1 << 2)
46#define RTL818X_INT_TXL_ERR (1 << 3)
47#define RTL818X_INT_RX_DU (1 << 4)
48#define RTL818X_INT_RX_FO (1 << 5)
49#define RTL818X_INT_TXN_OK (1 << 6)
50#define RTL818X_INT_TXN_ERR (1 << 7)
51#define RTL818X_INT_TXH_OK (1 << 8)
52#define RTL818X_INT_TXH_ERR (1 << 9)
53#define RTL818X_INT_TXB_OK (1 << 10)
54#define RTL818X_INT_TXB_ERR (1 << 11)
55#define RTL818X_INT_ATIM (1 << 12)
56#define RTL818X_INT_BEACON (1 << 13)
57#define RTL818X_INT_TIME_OUT (1 << 14)
58#define RTL818X_INT_TX_FO (1 << 15)
59 __le32 TX_CONF;
60#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
61#define RTL818X_TX_CONF_NO_ICV (1 << 19)
62#define RTL818X_TX_CONF_DISCW (1 << 20)
63#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
64#define RTL818X_TX_CONF_R8180_F (3 << 25)
65#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
66#define RTL818X_TX_CONF_R8185_D (5 << 25)
67#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
68#define RTL818X_TX_CONF_CW_MIN (1 << 31)
69 __le32 RX_CONF;
70#define RTL818X_RX_CONF_MONITOR (1 << 0)
71#define RTL818X_RX_CONF_NICMAC (1 << 1)
72#define RTL818X_RX_CONF_MULTICAST (1 << 2)
73#define RTL818X_RX_CONF_BROADCAST (1 << 3)
74#define RTL818X_RX_CONF_DATA (1 << 18)
75#define RTL818X_RX_CONF_CTRL (1 << 19)
76#define RTL818X_RX_CONF_MGMT (1 << 20)
77#define RTL818X_RX_CONF_BSSID (1 << 23)
78#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
79#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
80 __le32 INT_TIMEOUT;
81 __le32 TBDA;
82 u8 EEPROM_CMD;
83#define RTL818X_EEPROM_CMD_READ (1 << 0)
84#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
85#define RTL818X_EEPROM_CMD_CK (1 << 2)
86#define RTL818X_EEPROM_CMD_CS (1 << 3)
87#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
88#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
89#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
90#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
91 u8 CONFIG0;
92 u8 CONFIG1;
93 u8 CONFIG2;
94 __le32 ANAPARAM;
95 u8 MSR;
96#define RTL818X_MSR_NO_LINK (0 << 2)
97#define RTL818X_MSR_ADHOC (1 << 2)
98#define RTL818X_MSR_INFRA (2 << 2)
99 u8 CONFIG3;
100#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
101 u8 CONFIG4;
102#define RTL818X_CONFIG4_POWEROFF (1 << 6)
103#define RTL818X_CONFIG4_VCOOFF (1 << 7)
104 u8 TESTR;
105 u8 reserved_9[2];
106 __le16 PGSELECT;
107 __le32 ANAPARAM2;
108 u8 reserved_10[12];
109 __le16 BEACON_INTERVAL;
110 __le16 ATIM_WND;
111 __le16 BEACON_INTERVAL_TIME;
112 __le16 ATIMTR_INTERVAL;
113 u8 reserved_11[4];
114 u8 PHY[4];
115 __le16 RFPinsOutput;
116 __le16 RFPinsEnable;
117 __le16 RFPinsSelect;
118 __le16 RFPinsInput;
119 __le32 RF_PARA;
120 __le32 RF_TIMING;
121 u8 GP_ENABLE;
122 u8 GPIO;
123 u8 reserved_12[10];
124 u8 TX_AGC_CTL;
125#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
126#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
127#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
128 u8 TX_GAIN_CCK;
129 u8 TX_GAIN_OFDM;
130 u8 TX_ANTENNA;
131 u8 reserved_13[16];
132 u8 WPA_CONF;
133 u8 reserved_14[3];
134 u8 SIFS;
135 u8 DIFS;
136 u8 SLOT;
137 u8 reserved_15[5];
138 u8 CW_CONF;
139#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
140#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
141 u8 CW_VAL;
142 u8 RATE_FALLBACK;
143 u8 reserved_16[25];
144 u8 CONFIG5;
145 u8 TX_DMA_POLLING;
146 u8 reserved_17[2];
147 __le16 CWR;
148 u8 RETRY_CTR;
149 u8 reserved_18[5];
150 __le32 RDSAR;
151 u8 reserved_19[18];
152 u16 TALLY_CNT;
153 u8 TALLY_SEL;
154} __attribute__((packed));
155
156static const struct ieee80211_rate rtl818x_rates[] = {
157 { .rate = 10,
158 .val = 0,
159 .flags = IEEE80211_RATE_CCK },
160 { .rate = 20,
161 .val = 1,
162 .flags = IEEE80211_RATE_CCK },
163 { .rate = 55,
164 .val = 2,
165 .flags = IEEE80211_RATE_CCK },
166 { .rate = 110,
167 .val = 3,
168 .flags = IEEE80211_RATE_CCK },
169 { .rate = 60,
170 .val = 4,
171 .flags = IEEE80211_RATE_OFDM },
172 { .rate = 90,
173 .val = 5,
174 .flags = IEEE80211_RATE_OFDM },
175 { .rate = 120,
176 .val = 6,
177 .flags = IEEE80211_RATE_OFDM },
178 { .rate = 180,
179 .val = 7,
180 .flags = IEEE80211_RATE_OFDM },
181 { .rate = 240,
182 .val = 8,
183 .flags = IEEE80211_RATE_OFDM },
184 { .rate = 360,
185 .val = 9,
186 .flags = IEEE80211_RATE_OFDM },
187 { .rate = 480,
188 .val = 10,
189 .flags = IEEE80211_RATE_OFDM },
190 { .rate = 540,
191 .val = 11,
192 .flags = IEEE80211_RATE_OFDM },
193};
194
195static const struct ieee80211_channel rtl818x_channels[] = {
196 { .chan = 1,
197 .freq = 2412},
198 { .chan = 2,
199 .freq = 2417},
200 { .chan = 3,
201 .freq = 2422},
202 { .chan = 4,
203 .freq = 2427},
204 { .chan = 5,
205 .freq = 2432},
206 { .chan = 6,
207 .freq = 2437},
208 { .chan = 7,
209 .freq = 2442},
210 { .chan = 8,
211 .freq = 2447},
212 { .chan = 9,
213 .freq = 2452},
214 { .chan = 10,
215 .freq = 2457},
216 { .chan = 11,
217 .freq = 2462},
218 { .chan = 12,
219 .freq = 2467},
220 { .chan = 13,
221 .freq = 2472},
222 { .chan = 14,
223 .freq = 2484}
224};
225
226#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5be63..4d505903352 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
3zd1211rw-objs := zd_chip.o zd_ieee80211.o \ 3zd1211rw-objs := zd_chip.o zd_ieee80211.o \
4 zd_mac.o zd_netdev.o \ 4 zd_mac.o zd_netdev.o \
5 zd_rf_al2230.o zd_rf_rf2959.o \ 5 zd_rf_al2230.o zd_rf_rf2959.o \
6 zd_rf_al7230b.o \ 6 zd_rf_al7230b.o zd_rf_uw2453.o \
7 zd_rf.o zd_usb.o zd_util.o 7 zd_rf.o zd_usb.o zd_util.o
8 8
9ifeq ($(CONFIG_ZD1211RW_DEBUG),y) 9ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a2670..5b624bfc01a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
1253{ 1253{
1254 int r; 1254 int r;
1255 1255
1256 if (!zd_rf_should_update_pwr_int(&chip->rf))
1257 return 0;
1258
1256 r = update_pwr_int(chip, channel); 1259 r = update_pwr_int(chip, channel);
1257 if (r) 1260 if (r)
1258 return r; 1261 return r;
@@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
1283 int r; 1286 int r;
1284 u32 value; 1287 u32 value;
1285 1288
1286 if (!chip->patch_cck_gain) 1289 if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
1287 return 0; 1290 return 0;
1288 1291
1289 ZD_ASSERT(mutex_is_locked(&chip->mutex)); 1292 ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6da0d..79d0288c193 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
608#define CR_ZD1211B_TXOP CTL_REG(0x0b20) 608#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
609#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) 609#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
610 610
611/* Used to detect PLL lock */
612#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
613
611#define CWIN_SIZE 0x007f043f 614#define CWIN_SIZE 0x007f043f
612 615
613 616
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23bcd6c..7407409b60b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
52void zd_rf_init(struct zd_rf *rf) 52void zd_rf_init(struct zd_rf *rf)
53{ 53{
54 memset(rf, 0, sizeof(*rf)); 54 memset(rf, 0, sizeof(*rf));
55
56 /* default to update channel integration, as almost all RF's do want
57 * this */
58 rf->update_channel_int = 1;
55} 59}
56 60
57void zd_rf_clear(struct zd_rf *rf) 61void zd_rf_clear(struct zd_rf *rf)
58{ 62{
63 if (rf->clear)
64 rf->clear(rf);
59 ZD_MEMCLEAR(rf, sizeof(*rf)); 65 ZD_MEMCLEAR(rf, sizeof(*rf));
60} 66}
61 67
62int zd_rf_init_hw(struct zd_rf *rf, u8 type) 68int zd_rf_init_hw(struct zd_rf *rf, u8 type)
63{ 69{
64 int r, t; 70 int r = 0;
71 int t;
65 struct zd_chip *chip = zd_rf_to_chip(rf); 72 struct zd_chip *chip = zd_rf_to_chip(rf);
66 73
67 ZD_ASSERT(mutex_is_locked(&chip->mutex)); 74 ZD_ASSERT(mutex_is_locked(&chip->mutex));
68 switch (type) { 75 switch (type) {
69 case RF2959_RF: 76 case RF2959_RF:
70 r = zd_rf_init_rf2959(rf); 77 r = zd_rf_init_rf2959(rf);
71 if (r)
72 return r;
73 break; 78 break;
74 case AL2230_RF: 79 case AL2230_RF:
75 r = zd_rf_init_al2230(rf); 80 r = zd_rf_init_al2230(rf);
76 if (r)
77 return r;
78 break; 81 break;
79 case AL7230B_RF: 82 case AL7230B_RF:
80 r = zd_rf_init_al7230b(rf); 83 r = zd_rf_init_al7230b(rf);
81 if (r) 84 break;
82 return r; 85 case UW2453_RF:
86 r = zd_rf_init_uw2453(rf);
83 break; 87 break;
84 default: 88 default:
85 dev_err(zd_chip_dev(chip), 89 dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
88 return -ENODEV; 92 return -ENODEV;
89 } 93 }
90 94
95 if (r)
96 return r;
97
91 rf->type = type; 98 rf->type = type;
92 99
93 r = zd_chip_lock_phy_regs(chip); 100 r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc105ce6..c6dfd8227f6 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@ struct zd_rf {
48 48
49 u8 channel; 49 u8 channel;
50 50
51 /* whether channel integration and calibration should be updated
52 * defaults to 1 (yes) */
53 u8 update_channel_int:1;
54
55 /* whether CR47 should be patched from the EEPROM, if the appropriate
56 * flag is set in the POD. The vendor driver suggests that this should
57 * be done for all RF's, but a bug in their code prevents but their
58 * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
59 u8 patch_cck_gain:1;
60
61 /* private RF driver data */
62 void *priv;
63
51 /* RF-specific functions */ 64 /* RF-specific functions */
52 int (*init_hw)(struct zd_rf *rf); 65 int (*init_hw)(struct zd_rf *rf);
53 int (*set_channel)(struct zd_rf *rf, u8 channel); 66 int (*set_channel)(struct zd_rf *rf, u8 channel);
54 int (*switch_radio_on)(struct zd_rf *rf); 67 int (*switch_radio_on)(struct zd_rf *rf);
55 int (*switch_radio_off)(struct zd_rf *rf); 68 int (*switch_radio_off)(struct zd_rf *rf);
56 int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel); 69 int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
70 void (*clear)(struct zd_rf *rf);
57}; 71};
58 72
59const char *zd_rf_name(u8 type); 73const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
71int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); 85int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
72int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); 86int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
73 87
88static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
89{
90 return rf->update_channel_int;
91}
92
93static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
94{
95 return rf->patch_cck_gain;
96}
97
98int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
99int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
100
74/* Functions for individual RF chips */ 101/* Functions for individual RF chips */
75 102
76int zd_rf_init_rf2959(struct zd_rf *rf); 103int zd_rf_init_rf2959(struct zd_rf *rf);
77int zd_rf_init_al2230(struct zd_rf *rf); 104int zd_rf_init_al2230(struct zd_rf *rf);
78int zd_rf_init_al7230b(struct zd_rf *rf); 105int zd_rf_init_al7230b(struct zd_rf *rf);
106int zd_rf_init_uw2453(struct zd_rf *rf);
79 107
80#endif /* _ZD_RF_H */ 108#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392acfed..e7a4ecf7b6e 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
432 rf->switch_radio_on = zd1211_al2230_switch_radio_on; 432 rf->switch_radio_on = zd1211_al2230_switch_radio_on;
433 } 433 }
434 rf->patch_6m_band_edge = zd_rf_generic_patch_6m; 434 rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
435 rf->patch_cck_gain = 1;
435 return 0; 436 return 0;
436} 437}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9ddc6a7..f4e8b6ada85 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
483 rf->switch_radio_on = zd1211_al7230b_switch_radio_on; 483 rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
484 rf->set_channel = zd1211_al7230b_set_channel; 484 rf->set_channel = zd1211_al7230b_set_channel;
485 rf->patch_6m_band_edge = zd_rf_generic_patch_6m; 485 rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
486 rf->patch_cck_gain = 1;
486 } 487 }
487 488
488 rf->switch_radio_off = al7230b_switch_radio_off; 489 rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 00000000000..414e40d571a
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
1/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#include <linux/kernel.h>
19
20#include "zd_rf.h"
21#include "zd_usb.h"
22#include "zd_chip.h"
23
24/* This RF programming code is based upon the code found in v2.16.0.0 of the
25 * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
26 * for this RF on their website, so we're able to understand more than
27 * usual as to what is going on. Thumbs up for Ubec for doing that. */
28
29/* The 3-wire serial interface provides access to 8 write-only registers.
30 * The data format is a 4 bit register address followed by a 20 bit value. */
31#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
32
33/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
34 * fractional divide ratio) and 3 (VCO config).
35 *
36 * We configure the RF to produce an interrupt when the PLL is locked onto
37 * the configured frequency. During initialization, we run through a variety
38 * of different VCO configurations on channel 1 until we detect a PLL lock.
39 * When this happens, we remember which VCO configuration produced the lock
40 * and use it later. Actually, we use the configuration *after* the one that
41 * produced the lock, which seems odd, but it works.
42 *
43 * If we do not see a PLL lock on any standard VCO config, we fall back on an
44 * autocal configuration, which has a fixed (as opposed to per-channel) VCO
45 * config and different synth values from the standard set (divide ratio
46 * is still shared with the standard set). */
47
48/* The per-channel synth values for all standard VCO configurations. These get
49 * written to register 1. */
50static const u8 uw2453_std_synth[] = {
51 RF_CHANNEL( 1) = 0x47,
52 RF_CHANNEL( 2) = 0x47,
53 RF_CHANNEL( 3) = 0x67,
54 RF_CHANNEL( 4) = 0x67,
55 RF_CHANNEL( 5) = 0x67,
56 RF_CHANNEL( 6) = 0x67,
57 RF_CHANNEL( 7) = 0x57,
58 RF_CHANNEL( 8) = 0x57,
59 RF_CHANNEL( 9) = 0x57,
60 RF_CHANNEL(10) = 0x57,
61 RF_CHANNEL(11) = 0x77,
62 RF_CHANNEL(12) = 0x77,
63 RF_CHANNEL(13) = 0x77,
64 RF_CHANNEL(14) = 0x4f,
65};
66
67/* This table stores the synthesizer fractional divide ratio for *all* VCO
68 * configurations (both standard and autocal). These get written to register 2.
69 */
70static const u16 uw2453_synth_divide[] = {
71 RF_CHANNEL( 1) = 0x999,
72 RF_CHANNEL( 2) = 0x99b,
73 RF_CHANNEL( 3) = 0x998,
74 RF_CHANNEL( 4) = 0x99a,
75 RF_CHANNEL( 5) = 0x999,
76 RF_CHANNEL( 6) = 0x99b,
77 RF_CHANNEL( 7) = 0x998,
78 RF_CHANNEL( 8) = 0x99a,
79 RF_CHANNEL( 9) = 0x999,
80 RF_CHANNEL(10) = 0x99b,
81 RF_CHANNEL(11) = 0x998,
82 RF_CHANNEL(12) = 0x99a,
83 RF_CHANNEL(13) = 0x999,
84 RF_CHANNEL(14) = 0xccc,
85};
86
87/* Here is the data for all the standard VCO configurations. We shrink our
88 * table a little by observing that both channels in a consecutive pair share
89 * the same value. We also observe that the high 4 bits ([0:3] in the specs)
90 * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
91 * below. */
92#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
93#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
94static const u16 uw2453_std_vco_cfg[][7] = {
95 { /* table 1 */
96 RF_CHANPAIR( 1, 2) = 0x664d,
97 RF_CHANPAIR( 3, 4) = 0x604d,
98 RF_CHANPAIR( 5, 6) = 0x6675,
99 RF_CHANPAIR( 7, 8) = 0x6475,
100 RF_CHANPAIR( 9, 10) = 0x6655,
101 RF_CHANPAIR(11, 12) = 0x6455,
102 RF_CHANPAIR(13, 14) = 0x6665,
103 },
104 { /* table 2 */
105 RF_CHANPAIR( 1, 2) = 0x666d,
106 RF_CHANPAIR( 3, 4) = 0x606d,
107 RF_CHANPAIR( 5, 6) = 0x664d,
108 RF_CHANPAIR( 7, 8) = 0x644d,
109 RF_CHANPAIR( 9, 10) = 0x6675,
110 RF_CHANPAIR(11, 12) = 0x6475,
111 RF_CHANPAIR(13, 14) = 0x6655,
112 },
113 { /* table 3 */
114 RF_CHANPAIR( 1, 2) = 0x665d,
115 RF_CHANPAIR( 3, 4) = 0x605d,
116 RF_CHANPAIR( 5, 6) = 0x666d,
117 RF_CHANPAIR( 7, 8) = 0x646d,
118 RF_CHANPAIR( 9, 10) = 0x664d,
119 RF_CHANPAIR(11, 12) = 0x644d,
120 RF_CHANPAIR(13, 14) = 0x6675,
121 },
122 { /* table 4 */
123 RF_CHANPAIR( 1, 2) = 0x667d,
124 RF_CHANPAIR( 3, 4) = 0x607d,
125 RF_CHANPAIR( 5, 6) = 0x665d,
126 RF_CHANPAIR( 7, 8) = 0x645d,
127 RF_CHANPAIR( 9, 10) = 0x666d,
128 RF_CHANPAIR(11, 12) = 0x646d,
129 RF_CHANPAIR(13, 14) = 0x664d,
130 },
131 { /* table 5 */
132 RF_CHANPAIR( 1, 2) = 0x6643,
133 RF_CHANPAIR( 3, 4) = 0x6043,
134 RF_CHANPAIR( 5, 6) = 0x667d,
135 RF_CHANPAIR( 7, 8) = 0x647d,
136 RF_CHANPAIR( 9, 10) = 0x665d,
137 RF_CHANPAIR(11, 12) = 0x645d,
138 RF_CHANPAIR(13, 14) = 0x666d,
139 },
140 { /* table 6 */
141 RF_CHANPAIR( 1, 2) = 0x6663,
142 RF_CHANPAIR( 3, 4) = 0x6063,
143 RF_CHANPAIR( 5, 6) = 0x6643,
144 RF_CHANPAIR( 7, 8) = 0x6443,
145 RF_CHANPAIR( 9, 10) = 0x667d,
146 RF_CHANPAIR(11, 12) = 0x647d,
147 RF_CHANPAIR(13, 14) = 0x665d,
148 },
149 { /* table 7 */
150 RF_CHANPAIR( 1, 2) = 0x6653,
151 RF_CHANPAIR( 3, 4) = 0x6053,
152 RF_CHANPAIR( 5, 6) = 0x6663,
153 RF_CHANPAIR( 7, 8) = 0x6463,
154 RF_CHANPAIR( 9, 10) = 0x6643,
155 RF_CHANPAIR(11, 12) = 0x6443,
156 RF_CHANPAIR(13, 14) = 0x667d,
157 },
158 { /* table 8 */
159 RF_CHANPAIR( 1, 2) = 0x6673,
160 RF_CHANPAIR( 3, 4) = 0x6073,
161 RF_CHANPAIR( 5, 6) = 0x6653,
162 RF_CHANPAIR( 7, 8) = 0x6453,
163 RF_CHANPAIR( 9, 10) = 0x6663,
164 RF_CHANPAIR(11, 12) = 0x6463,
165 RF_CHANPAIR(13, 14) = 0x6643,
166 },
167 { /* table 9 */
168 RF_CHANPAIR( 1, 2) = 0x664b,
169 RF_CHANPAIR( 3, 4) = 0x604b,
170 RF_CHANPAIR( 5, 6) = 0x6673,
171 RF_CHANPAIR( 7, 8) = 0x6473,
172 RF_CHANPAIR( 9, 10) = 0x6653,
173 RF_CHANPAIR(11, 12) = 0x6453,
174 RF_CHANPAIR(13, 14) = 0x6663,
175 },
176 { /* table 10 */
177 RF_CHANPAIR( 1, 2) = 0x666b,
178 RF_CHANPAIR( 3, 4) = 0x606b,
179 RF_CHANPAIR( 5, 6) = 0x664b,
180 RF_CHANPAIR( 7, 8) = 0x644b,
181 RF_CHANPAIR( 9, 10) = 0x6673,
182 RF_CHANPAIR(11, 12) = 0x6473,
183 RF_CHANPAIR(13, 14) = 0x6653,
184 },
185 { /* table 11 */
186 RF_CHANPAIR( 1, 2) = 0x665b,
187 RF_CHANPAIR( 3, 4) = 0x605b,
188 RF_CHANPAIR( 5, 6) = 0x666b,
189 RF_CHANPAIR( 7, 8) = 0x646b,
190 RF_CHANPAIR( 9, 10) = 0x664b,
191 RF_CHANPAIR(11, 12) = 0x644b,
192 RF_CHANPAIR(13, 14) = 0x6673,
193 },
194
195};
196
197/* The per-channel synth values for autocal. These get written to register 1. */
198static const u16 uw2453_autocal_synth[] = {
199 RF_CHANNEL( 1) = 0x6847,
200 RF_CHANNEL( 2) = 0x6847,
201 RF_CHANNEL( 3) = 0x6867,
202 RF_CHANNEL( 4) = 0x6867,
203 RF_CHANNEL( 5) = 0x6867,
204 RF_CHANNEL( 6) = 0x6867,
205 RF_CHANNEL( 7) = 0x6857,
206 RF_CHANNEL( 8) = 0x6857,
207 RF_CHANNEL( 9) = 0x6857,
208 RF_CHANNEL(10) = 0x6857,
209 RF_CHANNEL(11) = 0x6877,
210 RF_CHANNEL(12) = 0x6877,
211 RF_CHANNEL(13) = 0x6877,
212 RF_CHANNEL(14) = 0x684f,
213};
214
215/* The VCO configuration for autocal (all channels) */
216static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
217
218/* TX gain settings. The array index corresponds to the TX power integration
219 * values found in the EEPROM. The values get written to register 7. */
220static u32 uw2453_txgain[] = {
221 [0x00] = 0x0e313,
222 [0x01] = 0x0fb13,
223 [0x02] = 0x0e093,
224 [0x03] = 0x0f893,
225 [0x04] = 0x0ea93,
226 [0x05] = 0x1f093,
227 [0x06] = 0x1f493,
228 [0x07] = 0x1f693,
229 [0x08] = 0x1f393,
230 [0x09] = 0x1f35b,
231 [0x0a] = 0x1e6db,
232 [0x0b] = 0x1ff3f,
233 [0x0c] = 0x1ffff,
234 [0x0d] = 0x361d7,
235 [0x0e] = 0x37fbf,
236 [0x0f] = 0x3ff8b,
237 [0x10] = 0x3ff33,
238 [0x11] = 0x3fb3f,
239 [0x12] = 0x3ffff,
240};
241
242/* RF-specific structure */
243struct uw2453_priv {
244 /* index into synth/VCO config tables where PLL lock was found
245 * -1 means autocal */
246 int config;
247};
248
249#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
250
251static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
252 bool autocal)
253{
254 int r;
255 int idx = channel - 1;
256 u32 val;
257
258 if (autocal)
259 val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
260 else
261 val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
262
263 r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
264 if (r)
265 return r;
266
267 return zd_rfwrite_locked(chip,
268 UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
269}
270
271static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
272{
273 /* vendor driver always sets these upper bits even though the specs say
274 * they are reserved */
275 u32 val = 0x40000 | value;
276 return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
277}
278
279static int uw2453_init_mode(struct zd_chip *chip)
280{
281 static const u32 rv[] = {
282 UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
283 UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
284 UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
285 UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
286 };
287
288 return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
289}
290
291static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
292{
293 u8 int_value = chip->pwr_int_values[channel - 1];
294
295 if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
296 dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
297 "int value %x on channel %d\n", int_value, channel);
298 return 0;
299 }
300
301 return zd_rfwrite_locked(chip,
302 UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
303}
304
305static int uw2453_init_hw(struct zd_rf *rf)
306{
307 int i, r;
308 int found_config = -1;
309 u16 intr_status;
310 struct zd_chip *chip = zd_rf_to_chip(rf);
311
312 static const struct zd_ioreq16 ioreqs[] = {
313 { CR10, 0x89 }, { CR15, 0x20 },
314 { CR17, 0x28 }, /* 6112 no change */
315 { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
316 { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
317 { CR33, 0x28 }, { CR34, 0x30 },
318 { CR35, 0x43 }, /* 6112 3e->43 */
319 { CR41, 0x24 }, { CR44, 0x32 },
320 { CR46, 0x92 }, /* 6112 96->92 */
321 { CR47, 0x1e },
322 { CR48, 0x04 }, /* 5602 Roger */
323 { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
324 { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
325 { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
326 { CR99, 0x28 }, { CR100, 0x02 },
327 { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
328 { CR102, 0x27 },
329 { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
330 { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
331 { CR109, 0x13 },
332 { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
333 { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
334 { CR114, 0x23 }, /* 6221 27->23 */
335 { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
336 { CR116, 0x24 }, /* 6220 1c->24 */
337 { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
338 { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
339 { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
340 { CR120, 0x4f },
341 { CR121, 0x1f }, /* 6220 4f->1f */
342 { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
343 { CR126, 0x6c }, { CR127, 0x03 },
344 { CR128, 0x14 }, /* 6302 12->11 */
345 { CR129, 0x12 }, /* 6301 10->0f */
346 { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
347 { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
348 { CR253, 0xff },
349 };
350
351 static const u32 rv[] = {
352 UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
353 UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
354 UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
355 UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
356
357 /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
358 * RSSI circuit powered down, reduced RSSI range */
359 UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
360
361 /* synthesizer configuration for channel 1 */
362 UW2453_REGWRITE(1, 0x47),
363 UW2453_REGWRITE(2, 0x999),
364
365 /* disable manual VCO band selection */
366 UW2453_REGWRITE(3, 0x7602),
367
368 /* enable manual VCO band selection, configure current level */
369 UW2453_REGWRITE(3, 0x46063),
370 };
371
372 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
373 if (r)
374 return r;
375
376 r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
377 if (r)
378 return r;
379
380 r = uw2453_init_mode(chip);
381 if (r)
382 return r;
383
384 /* Try all standard VCO configuration settings on channel 1 */
385 for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
386 /* Configure synthesizer for channel 1 */
387 r = uw2453_synth_set_channel(chip, 1, false);
388 if (r)
389 return r;
390
391 /* Write VCO config */
392 r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
393 if (r)
394 return r;
395
396 /* ack interrupt event */
397 r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
398 if (r)
399 return r;
400
401 /* check interrupt status */
402 r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
403 if (r)
404 return r;
405
406 if (!intr_status & 0xf) {
407 dev_dbg_f(zd_chip_dev(chip),
408 "PLL locked on configuration %d\n", i);
409 found_config = i;
410 break;
411 }
412 }
413
414 if (found_config == -1) {
415 /* autocal */
416 dev_dbg_f(zd_chip_dev(chip),
417 "PLL did not lock, using autocal\n");
418
419 r = uw2453_synth_set_channel(chip, 1, true);
420 if (r)
421 return r;
422
423 r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
424 if (r)
425 return r;
426 }
427
428 /* To match the vendor driver behaviour, we use the configuration after
429 * the one that produced a lock. */
430 UW2453_PRIV(rf)->config = found_config + 1;
431
432 return zd_iowrite16_locked(chip, 0x06, CR203);
433}
434
435static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
436{
437 int r;
438 u16 vco_cfg;
439 int config = UW2453_PRIV(rf)->config;
440 bool autocal = (config == -1);
441 struct zd_chip *chip = zd_rf_to_chip(rf);
442
443 static const struct zd_ioreq16 ioreqs[] = {
444 { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
445 { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
446 };
447
448 r = uw2453_synth_set_channel(chip, channel, autocal);
449 if (r)
450 return r;
451
452 if (autocal)
453 vco_cfg = UW2453_AUTOCAL_VCO_CFG;
454 else
455 vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
456
457 r = uw2453_write_vco_cfg(chip, vco_cfg);
458 if (r)
459 return r;
460
461 r = uw2453_init_mode(chip);
462 if (r)
463 return r;
464
465 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
466 if (r)
467 return r;
468
469 r = uw2453_set_tx_gain_level(chip, channel);
470 if (r)
471 return r;
472
473 return zd_iowrite16_locked(chip, 0x06, CR203);
474}
475
476static int uw2453_switch_radio_on(struct zd_rf *rf)
477{
478 int r;
479 struct zd_chip *chip = zd_rf_to_chip(rf);
480 struct zd_ioreq16 ioreqs[] = {
481 { CR11, 0x00 }, { CR251, 0x3f },
482 };
483
484 /* enter RXTX mode */
485 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
486 if (r)
487 return r;
488
489 if (chip->is_zd1211b)
490 ioreqs[1].value = 0x7f;
491
492 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
493}
494
495static int uw2453_switch_radio_off(struct zd_rf *rf)
496{
497 int r;
498 struct zd_chip *chip = zd_rf_to_chip(rf);
499 static const struct zd_ioreq16 ioreqs[] = {
500 { CR11, 0x04 }, { CR251, 0x2f },
501 };
502
503 /* enter IDLE mode */
504 /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
505 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
506 if (r)
507 return r;
508
509 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
510}
511
512static void uw2453_clear(struct zd_rf *rf)
513{
514 kfree(rf->priv);
515}
516
517int zd_rf_init_uw2453(struct zd_rf *rf)
518{
519 rf->init_hw = uw2453_init_hw;
520 rf->set_channel = uw2453_set_channel;
521 rf->switch_radio_on = uw2453_switch_radio_on;
522 rf->switch_radio_off = uw2453_switch_radio_off;
523 rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
524 rf->clear = uw2453_clear;
525 /* we have our own TX integration code */
526 rf->update_channel_int = 0;
527
528 rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
529 if (rf->priv == NULL)
530 return -ENOMEM;
531
532 return 0;
533}
534
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549d0ce..740a2194fdd 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
54 { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, 54 { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
55 { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, 55 { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
56 { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, 56 { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
57 { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
57 /* ZD1211B */ 58 /* ZD1211B */
58 { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, 59 { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
59 { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, 60 { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },