aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Wu <flamingice@sourmilk.net>2007-05-14 01:41:02 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-08 22:16:36 -0400
commit605bebe23bf6ac66c0a717e663a7baa2f981294d (patch)
treec40d4aeaddd7996b8c69da6edd1c8269c60debb1
parent4b914dc0493edff19ff698a18198a173a14ba9d2 (diff)
[PATCH] Add rtl8187 wireless driver
This patch adds a mac80211 based wireless driver for the rtl8187 USB wireless card. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--MAINTAINERS10
-rw-r--r--drivers/net/wireless/Kconfig12
-rw-r--r--drivers/net/wireless/Makefile3
-rw-r--r--drivers/net/wireless/rtl8187.h131
-rw-r--r--drivers/net/wireless/rtl8187_dev.c731
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c744
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h30
-rw-r--r--drivers/net/wireless/rtl818x.h212
8 files changed, 1873 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index df40a4ec87fb..2c1dfb271613 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3049,6 +3049,16 @@ S: Maintained
3049RISCOM8 DRIVER 3049RISCOM8 DRIVER
3050S: Orphan 3050S: Orphan
3051 3051
3052RTL818X WIRELESS DRIVER
3053P: Michael Wu
3054M: flamingice@sourmilk.net
3055P: Andrea Merello
3056M: andreamrl@tiscali.it
3057L: linux-wireless@vger.kernel.org
3058W: http://linuxwireless.org/
3059T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
3060S: Maintained
3061
3052S3 SAVAGE FRAMEBUFFER DRIVER 3062S3 SAVAGE FRAMEBUFFER DRIVER
3053P: Antonino Daplas 3063P: Antonino Daplas
3054M: adaplas@gmail.com 3064M: adaplas@gmail.com
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa2399cbd5ca..ae27af0141c0 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 d2124602263b..ef35bc6c4a22 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/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 000000000000..41d0aac3e27e
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,131 @@
1#ifndef RTL8187_H
2#define RTL8187_H
3
4#include "rtl818x.h"
5
6#define RTL8187_EEPROM_TXPWR_BASE 0x05
7#define RTL8187_EEPROM_MAC_ADDR 0x07
8#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
9#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
10#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
11
12#define RTL8187_REQT_READ 0xC0
13#define RTL8187_REQT_WRITE 0x40
14#define RTL8187_REQ_GET_REG 0x05
15#define RTL8187_REQ_SET_REG 0x05
16
17#define RTL8187_MAX_RX 0x9C4
18
19struct rtl8187_rx_info {
20 struct urb *urb;
21 struct ieee80211_hw *dev;
22};
23
24struct rtl8187_rx_hdr {
25 __le16 len;
26 __le16 rate;
27 u8 noise;
28 u8 signal;
29 u8 agc;
30 u8 reserved;
31 __le64 mac_time;
32} __attribute__((packed));
33
34struct rtl8187_tx_info {
35 struct ieee80211_tx_control *control;
36 struct urb *urb;
37 struct ieee80211_hw *dev;
38};
39
40struct rtl8187_tx_hdr {
41 __le32 flags;
42#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
43#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
44#define RTL8187_TX_FLAG_CTS (1 << 18)
45#define RTL8187_TX_FLAG_RTS (1 << 23)
46 __le16 rts_duration;
47 __le16 len;
48 __le32 retry;
49} __attribute__((packed));
50
51struct rtl8187_priv {
52 /* common between rtl818x drivers */
53 struct rtl818x_csr *map;
54 void (*rf_init)(struct ieee80211_hw *);
55 int mode;
56
57 /* rtl8187 specific */
58 struct ieee80211_channel channels[14];
59 struct ieee80211_rate rates[12];
60 struct ieee80211_hw_mode modes[2];
61 struct usb_device *udev;
62 u8 *hwaddr;
63 u16 txpwr_base;
64 u8 asic_rev;
65 struct sk_buff_head rx_queue;
66};
67
68void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
69
70static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
71{
72 u8 val;
73
74 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
75 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
76 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
77
78 return val;
79}
80
81static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
82{
83 __le16 val;
84
85 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
86 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
87 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
88
89 return le16_to_cpu(val);
90}
91
92static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
93{
94 __le32 val;
95
96 usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
97 RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
98 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
99
100 return le32_to_cpu(val);
101}
102
103static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
104 u8 *addr, u8 val)
105{
106 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
107 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
108 (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
109}
110
111static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
112 __le16 *addr, u16 val)
113{
114 __le16 buf = cpu_to_le16(val);
115
116 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
117 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
118 (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
119}
120
121static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
122 __le32 *addr, u32 val)
123{
124 __le32 buf = cpu_to_le32(val);
125
126 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
127 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
128 (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
129}
130
131#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 000000000000..83656107b97e
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
1
2/*
3 * Linux device driver for RTL8187
4 *
5 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
6 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
7 *
8 * Based on the r8187 driver, which is:
9 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
10 *
11 * 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 000000000000..c3f5bf543c90
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,744 @@
1
2/*
3 * Radio tuning for RTL8225 on RTL8187
4 *
5 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
6 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
7 *
8 * Based on the r8187 driver, which is:
9 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
10 *
11 * 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 <net/mac80211.h>
21
22#include "rtl8187.h"
23#include "rtl8187_rtl8225.h"
24
25static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
26{
27 struct rtl8187_priv *priv = dev->priv;
28 u16 reg80, reg84, reg82;
29 u32 bangdata;
30 int i;
31
32 bangdata = (data << 4) | (addr & 0xf);
33
34 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
35 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
36
37 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
38
39 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
40 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
41 udelay(10);
42
43 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
44 udelay(2);
45 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
46 udelay(10);
47
48 for (i = 15; i >= 0; i--) {
49 u16 reg = reg80 | (bangdata & (1 << i)) >> i;
50
51 if (i & 1)
52 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
53
54 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
55 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
56
57 if (!(i & 1))
58 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
59 }
60
61 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
62 udelay(10);
63
64 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
65 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
66 msleep(2);
67}
68
69static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
70{
71 struct rtl8187_priv *priv = dev->priv;
72 u16 reg80, reg82, reg84;
73
74 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
75 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
76 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
77
78 reg80 &= ~(0x3 << 2);
79 reg84 &= ~0xF;
80
81 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
82 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
83 udelay(10);
84
85 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
86 udelay(2);
87
88 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
89 udelay(10);
90
91 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
92 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
93 addr, 0x8225, &data, sizeof(data), HZ / 2);
94
95 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
96 udelay(10);
97
98 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
99 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
100 msleep(2);
101}
102
103void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
104{
105 struct rtl8187_priv *priv = dev->priv;
106
107 if (priv->asic_rev)
108 rtl8225_write_8051(dev, addr, data);
109 else
110 rtl8225_write_bitbang(dev, addr, data);
111}
112
113u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
114{
115 struct rtl8187_priv *priv = dev->priv;
116 u16 reg80, reg82, reg84, out;
117 int i;
118
119 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
120 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
121 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
122
123 reg80 &= ~0xF;
124
125 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
126 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
127
128 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
129 udelay(4);
130 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
131 udelay(5);
132
133 for (i = 4; i >= 0; i--) {
134 u16 reg = reg80 | ((addr >> i) & 1);
135
136 if (!(i & 1)) {
137 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
138 udelay(1);
139 }
140
141 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
142 reg | (1 << 1));
143 udelay(2);
144 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
145 reg | (1 << 1));
146 udelay(2);
147
148 if (i & 1) {
149 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
150 udelay(1);
151 }
152 }
153
154 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
155 reg80 | (1 << 3) | (1 << 1));
156 udelay(2);
157 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
158 reg80 | (1 << 3));
159 udelay(2);
160 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
161 reg80 | (1 << 3));
162 udelay(2);
163
164 out = 0;
165 for (i = 11; i >= 0; i--) {
166 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
167 reg80 | (1 << 3));
168 udelay(1);
169 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
170 reg80 | (1 << 3) | (1 << 1));
171 udelay(2);
172 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
173 reg80 | (1 << 3) | (1 << 1));
174 udelay(2);
175 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
176 reg80 | (1 << 3) | (1 << 1));
177 udelay(2);
178
179 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
180 out |= 1 << i;
181
182 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
183 reg80 | (1 << 3));
184 udelay(2);
185 }
186
187 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
188 reg80 | (1 << 3) | (1 << 2));
189 udelay(2);
190
191 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
192 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
193 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
194
195 return out;
196}
197
198static const u16 rtl8225bcd_rxgain[] = {
199 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
200 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
201 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
202 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
203 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
204 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
205 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
206 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
207 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
208 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
209 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
210 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
211};
212
213static const u8 rtl8225_agc[] = {
214 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
215 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
216 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
217 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
218 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
219 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
220 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
221 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
222 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
223 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
224 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
225 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
226 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
227 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
228 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
229 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
230};
231
232static const u8 rtl8225_gain[] = {
233 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
234 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
235 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
236 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
237 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
238 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
239 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
240};
241
242static const u8 rtl8225_threshold[] = {
243 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
244};
245
246static const u8 rtl8225_tx_gain_cck_ofdm[] = {
247 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
248};
249
250static const u8 rtl8225_tx_power_cck[] = {
251 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
252 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
253 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
254 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
255 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
256 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
257};
258
259static const u8 rtl8225_tx_power_cck_ch14[] = {
260 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
261 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
262 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
263 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
264 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
265 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
266};
267
268static const u8 rtl8225_tx_power_ofdm[] = {
269 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
270};
271
272static const u32 rtl8225_chan[] = {
273 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
274 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
275};
276
277static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
278{
279 struct rtl8187_priv *priv = dev->priv;
280 u8 cck_power, ofdm_power;
281 const u8 *tmp;
282 u32 reg;
283 int i;
284
285 cck_power = priv->channels[channel - 1].val & 0xF;
286 ofdm_power = priv->channels[channel - 1].val >> 4;
287
288 cck_power = min(cck_power, (u8)11);
289 ofdm_power = min(ofdm_power, (u8)35);
290
291 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
292 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
293
294 if (channel == 14)
295 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
296 else
297 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
298
299 for (i = 0; i < 8; i++)
300 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
301
302 msleep(1); // FIXME: optional?
303
304 /* anaparam2 on */
305 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
306 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
307 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
308 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
309 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
310 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
311
312 rtl8225_write_phy_ofdm(dev, 2, 0x42);
313 rtl8225_write_phy_ofdm(dev, 6, 0x00);
314 rtl8225_write_phy_ofdm(dev, 8, 0x00);
315
316 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
317 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
318
319 tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
320
321 rtl8225_write_phy_ofdm(dev, 5, *tmp);
322 rtl8225_write_phy_ofdm(dev, 7, *tmp);
323
324 msleep(1);
325}
326
327void rtl8225_rf_init(struct ieee80211_hw *dev)
328{
329 struct rtl8187_priv *priv = dev->priv;
330 int i;
331
332 rtl8225_write(dev, 0x0, 0x067); msleep(1);
333 rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
334 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
335 rtl8225_write(dev, 0x3, 0x441); msleep(1);
336 rtl8225_write(dev, 0x4, 0x486); msleep(1);
337 rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
338 rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
339 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
340 rtl8225_write(dev, 0x8, 0x01F); msleep(1);
341 rtl8225_write(dev, 0x9, 0x334); msleep(1);
342 rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
343 rtl8225_write(dev, 0xB, 0x391); msleep(1);
344 rtl8225_write(dev, 0xC, 0x050); msleep(1);
345 rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
346 rtl8225_write(dev, 0xE, 0x029); msleep(1);
347 rtl8225_write(dev, 0xF, 0x914); msleep(100);
348
349 rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
350 rtl8225_write(dev, 0x2, 0x44D); msleep(200);
351
352 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
353 rtl8225_write(dev, 0x02, 0x0c4d);
354 msleep(200);
355 rtl8225_write(dev, 0x02, 0x044d);
356 msleep(100);
357 if (!(rtl8225_read(dev, 6) & (1 << 7)))
358 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
359 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
360 }
361
362 rtl8225_write(dev, 0x0, 0x127);
363
364 for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
365 rtl8225_write(dev, 0x1, i + 1);
366 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
367 }
368
369 rtl8225_write(dev, 0x0, 0x027);
370 rtl8225_write(dev, 0x0, 0x22F);
371
372 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
373 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
374 msleep(1);
375 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
376 msleep(1);
377 }
378
379 msleep(1);
380
381 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
382 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
383 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
384 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
385 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
386 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
387 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
388 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
389 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
390 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
391 rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
392 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
393 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
394 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
395 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
396 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
397 rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
398 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
399 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
400 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
401 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
402 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
403 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
404 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
405 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
406 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
407 rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
408 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
409 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
410 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
411 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
412 rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
413 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
414 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
415 rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
416 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
417 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
418
419 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
420 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
421 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
422 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
423
424 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
425 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
426 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
427 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
428 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
429 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
430 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
431 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
432 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
433 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
434 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
435 rtl8225_write_phy_cck(dev, 0x19, 0x00);
436 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
437 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
438 rtl8225_write_phy_cck(dev, 0x40, 0x86);
439 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
440 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
441 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
442 rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
443 rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
444 rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
445 rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
446 rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
447 rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
448 rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
449 rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
450 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
451
452 rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
453
454 rtl8225_rf_set_tx_power(dev, 1);
455
456 /* RX antenna default to A */
457 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
458 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
459
460 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
461 msleep(1);
462 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
463
464 /* set sensitivity */
465 rtl8225_write(dev, 0x0c, 0x50);
466 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
467 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
468 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
469 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
470 rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
471}
472
473static const u8 rtl8225z2_tx_power_cck_ch14[] = {
474 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
475};
476
477static const u8 rtl8225z2_tx_power_cck[] = {
478 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
479};
480
481static const u8 rtl8225z2_tx_power_ofdm[] = {
482 0x42, 0x00, 0x40, 0x00, 0x40
483};
484
485static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
486 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
487 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
488 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
489 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
490 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
491 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
492};
493
494static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
495{
496 struct rtl8187_priv *priv = dev->priv;
497 u8 cck_power, ofdm_power;
498 const u8 *tmp;
499 u32 reg;
500 int i;
501
502 cck_power = priv->channels[channel - 1].val & 0xF;
503 ofdm_power = priv->channels[channel - 1].val >> 4;
504
505 cck_power = min(cck_power, (u8)15);
506 cck_power += priv->txpwr_base & 0xF;
507 cck_power = min(cck_power, (u8)35);
508
509 ofdm_power = min(ofdm_power, (u8)15);
510 ofdm_power += priv->txpwr_base >> 4;
511 ofdm_power = min(ofdm_power, (u8)35);
512
513 if (channel == 14)
514 tmp = rtl8225z2_tx_power_cck_ch14;
515 else
516 tmp = rtl8225z2_tx_power_cck;
517
518 for (i = 0; i < 8; i++)
519 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
520
521 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
522 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
523 msleep(1);
524
525 /* anaparam2 on */
526 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
527 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
528 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
529 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
530 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
531 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
532
533 rtl8225_write_phy_ofdm(dev, 2, 0x42);
534 rtl8225_write_phy_ofdm(dev, 5, 0x00);
535 rtl8225_write_phy_ofdm(dev, 6, 0x40);
536 rtl8225_write_phy_ofdm(dev, 7, 0x00);
537 rtl8225_write_phy_ofdm(dev, 8, 0x40);
538
539 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
540 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
541 msleep(1);
542}
543
544static const u16 rtl8225z2_rxgain[] = {
545 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
546 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
547 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
548 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
549 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
550 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
551 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
552 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
553 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
554 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
555 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
556 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
557};
558
559static const u8 rtl8225z2_gain_bg[] = {
560 0x23, 0x15, 0xa5, /* -82-1dBm */
561 0x23, 0x15, 0xb5, /* -82-2dBm */
562 0x23, 0x15, 0xc5, /* -82-3dBm */
563 0x33, 0x15, 0xc5, /* -78dBm */
564 0x43, 0x15, 0xc5, /* -74dBm */
565 0x53, 0x15, 0xc5, /* -70dBm */
566 0x63, 0x15, 0xc5 /* -66dBm */
567};
568
569void rtl8225z2_rf_init(struct ieee80211_hw *dev)
570{
571 struct rtl8187_priv *priv = dev->priv;
572 int i;
573
574 rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
575 rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
576 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
577 rtl8225_write(dev, 0x3, 0x441); msleep(1);
578 rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
579 rtl8225_write(dev, 0x5, 0xC72); msleep(1);
580 rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
581 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
582 rtl8225_write(dev, 0x8, 0x03F); msleep(1);
583 rtl8225_write(dev, 0x9, 0x335); msleep(1);
584 rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
585 rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
586 rtl8225_write(dev, 0xc, 0x850); msleep(1);
587 rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
588 rtl8225_write(dev, 0xe, 0x02B); msleep(1);
589 rtl8225_write(dev, 0xf, 0x114); msleep(100);
590
591 rtl8225_write(dev, 0x0, 0x1B7);
592
593 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
594 rtl8225_write(dev, 0x1, i + 1);
595 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
596 }
597
598 rtl8225_write(dev, 0x3, 0x080);
599 rtl8225_write(dev, 0x5, 0x004);
600 rtl8225_write(dev, 0x0, 0x0B7);
601 rtl8225_write(dev, 0x2, 0xc4D);
602
603 msleep(200);
604 rtl8225_write(dev, 0x2, 0x44D);
605 msleep(100);
606
607 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
608 rtl8225_write(dev, 0x02, 0x0C4D);
609 msleep(200);
610 rtl8225_write(dev, 0x02, 0x044D);
611 msleep(100);
612 if (!(rtl8225_read(dev, 6) & (1 << 7)))
613 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
614 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
615 }
616
617 msleep(200);
618
619 rtl8225_write(dev, 0x0, 0x2BF);
620
621 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
622 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
623 msleep(1);
624 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
625 msleep(1);
626 }
627
628 msleep(1);
629
630 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
631 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
632 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
633 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
634 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
635 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
636 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
637 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
638 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
639 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
640 rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
641 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
642 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
643 rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
644 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
645 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
646 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
647 rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
648 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
649 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
650 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
651 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
652 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
653 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
654 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
655 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
656 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
657 rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
658 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
659 rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
660 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
661 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
662 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
663 rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
664 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
665 rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
666 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
667 rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
668 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
669 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
670
671 rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
672 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
673 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
674 rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
675
676 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
677 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
678 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
679 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
680 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
681 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
682 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
683 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
684 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
685 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
686 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
687 rtl8225_write_phy_cck(dev, 0x19, 0x00);
688 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
689 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
690 rtl8225_write_phy_cck(dev, 0x40, 0x86);
691 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
692 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
693 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
694 rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
695 rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
696 rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
697 rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
698 rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
699 rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
700 rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
701 rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
702 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
703
704 rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
705
706 rtl8225z2_rf_set_tx_power(dev, 1);
707
708 /* RX antenna default to A */
709 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
710 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
711
712 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
713 msleep(1);
714 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
715}
716
717void rtl8225_rf_stop(struct ieee80211_hw *dev)
718{
719 u8 reg;
720 struct rtl8187_priv *priv = dev->priv;
721
722 rtl8225_write(dev, 0x4, 0x1f); msleep(1);
723
724 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
725 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
726 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
727 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
728 rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
729 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
730 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
731}
732
733void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
734{
735 struct rtl8187_priv *priv = dev->priv;
736
737 if (priv->rf_init == rtl8225_rf_init)
738 rtl8225_rf_set_tx_power(dev, channel);
739 else
740 rtl8225z2_rf_set_tx_power(dev, channel);
741
742 rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
743 msleep(10);
744}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 000000000000..ed28118653c7
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,30 @@
1#ifndef RTL8187_RTL8225_H
2#define RTL8187_RTL8225_H
3
4#define RTL8225_ANAPARAM_ON 0xa0000a59
5#define RTL8225_ANAPARAM2_ON 0x860c7312
6#define RTL8225_ANAPARAM_OFF 0xa00beb59
7#define RTL8225_ANAPARAM2_OFF 0x840dec11
8
9void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
10u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
11
12void rtl8225_rf_init(struct ieee80211_hw *);
13void rtl8225z2_rf_init(struct ieee80211_hw *);
14void rtl8225_rf_stop(struct ieee80211_hw *);
15void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
16
17
18static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
19 u8 addr, u32 data)
20{
21 rtl8187_write_phy(dev, addr, data);
22}
23
24static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
25 u8 addr, u32 data)
26{
27 rtl8187_write_phy(dev, addr, data | 0x10000);
28}
29
30#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 000000000000..e4ee946e1d90
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,212 @@
1#ifndef RTL818X_H
2#define RTL818X_H
3
4struct rtl818x_csr {
5 u8 MAC[6];
6 u8 reserved_0[2];
7 __le32 MAR[2];
8 u8 RX_FIFO_COUNT;
9 u8 reserved_1;
10 u8 TX_FIFO_COUNT;
11 u8 BQREQ;
12 u8 reserved_2[4];
13 __le32 TSFT[2];
14 __le32 TLPDA;
15 __le32 TNPDA;
16 __le32 THPDA;
17 __le16 BRSR;
18 u8 BSSID[6];
19 u8 RESP_RATE;
20 u8 EIFS;
21 u8 reserved_3[1];
22 u8 CMD;
23#define RTL818X_CMD_TX_ENABLE (1 << 2)
24#define RTL818X_CMD_RX_ENABLE (1 << 3)
25#define RTL818X_CMD_RESET (1 << 4)
26 u8 reserved_4[4];
27 __le16 INT_MASK;
28 __le16 INT_STATUS;
29#define RTL818X_INT_RX_OK (1 << 0)
30#define RTL818X_INT_RX_ERR (1 << 1)
31#define RTL818X_INT_TXL_OK (1 << 2)
32#define RTL818X_INT_TXL_ERR (1 << 3)
33#define RTL818X_INT_RX_DU (1 << 4)
34#define RTL818X_INT_RX_FO (1 << 5)
35#define RTL818X_INT_TXN_OK (1 << 6)
36#define RTL818X_INT_TXN_ERR (1 << 7)
37#define RTL818X_INT_TXH_OK (1 << 8)
38#define RTL818X_INT_TXH_ERR (1 << 9)
39#define RTL818X_INT_TXB_OK (1 << 10)
40#define RTL818X_INT_TXB_ERR (1 << 11)
41#define RTL818X_INT_ATIM (1 << 12)
42#define RTL818X_INT_BEACON (1 << 13)
43#define RTL818X_INT_TIME_OUT (1 << 14)
44#define RTL818X_INT_TX_FO (1 << 15)
45 __le32 TX_CONF;
46#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
47#define RTL818X_TX_CONF_NO_ICV (1 << 19)
48#define RTL818X_TX_CONF_DISCW (1 << 20)
49#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
50#define RTL818X_TX_CONF_R8180_F (3 << 25)
51#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
52#define RTL818X_TX_CONF_R8185_D (5 << 25)
53#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
54#define RTL818X_TX_CONF_CW_MIN (1 << 31)
55 __le32 RX_CONF;
56#define RTL818X_RX_CONF_MONITOR (1 << 0)
57#define RTL818X_RX_CONF_NICMAC (1 << 1)
58#define RTL818X_RX_CONF_MULTICAST (1 << 2)
59#define RTL818X_RX_CONF_BROADCAST (1 << 3)
60#define RTL818X_RX_CONF_DATA (1 << 18)
61#define RTL818X_RX_CONF_CTRL (1 << 19)
62#define RTL818X_RX_CONF_MGMT (1 << 20)
63#define RTL818X_RX_CONF_BSSID (1 << 23)
64#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
65#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
66 __le32 INT_TIMEOUT;
67 __le32 TBDA;
68 u8 EEPROM_CMD;
69#define RTL818X_EEPROM_CMD_READ (1 << 0)
70#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
71#define RTL818X_EEPROM_CMD_CK (1 << 2)
72#define RTL818X_EEPROM_CMD_CS (1 << 3)
73#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
74#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
75#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
76#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
77 u8 CONFIG0;
78 u8 CONFIG1;
79 u8 CONFIG2;
80 __le32 ANAPARAM;
81 u8 MSR;
82#define RTL818X_MSR_NO_LINK (0 << 2)
83#define RTL818X_MSR_ADHOC (1 << 2)
84#define RTL818X_MSR_INFRA (2 << 2)
85 u8 CONFIG3;
86#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
87 u8 CONFIG4;
88#define RTL818X_CONFIG4_POWEROFF (1 << 6)
89#define RTL818X_CONFIG4_VCOOFF (1 << 7)
90 u8 TESTR;
91 u8 reserved_9[2];
92 __le16 PGSELECT;
93 __le32 ANAPARAM2;
94 u8 reserved_10[12];
95 __le16 BEACON_INTERVAL;
96 __le16 ATIM_WND;
97 __le16 BEACON_INTERVAL_TIME;
98 __le16 ATIMTR_INTERVAL;
99 u8 reserved_11[4];
100 u8 PHY[4];
101 __le16 RFPinsOutput;
102 __le16 RFPinsEnable;
103 __le16 RFPinsSelect;
104 __le16 RFPinsInput;
105 __le32 RF_PARA;
106 __le32 RF_TIMING;
107 u8 GP_ENABLE;
108 u8 GPIO;
109 u8 reserved_12[10];
110 u8 TX_AGC_CTL;
111#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
112#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
113#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
114 u8 TX_GAIN_CCK;
115 u8 TX_GAIN_OFDM;
116 u8 TX_ANTENNA;
117 u8 reserved_13[16];
118 u8 WPA_CONF;
119 u8 reserved_14[3];
120 u8 SIFS;
121 u8 DIFS;
122 u8 SLOT;
123 u8 reserved_15[5];
124 u8 CW_CONF;
125#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
126#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
127 u8 CW_VAL;
128 u8 RATE_FALLBACK;
129 u8 reserved_16[25];
130 u8 CONFIG5;
131 u8 TX_DMA_POLLING;
132 u8 reserved_17[2];
133 __le16 CWR;
134 u8 RETRY_CTR;
135 u8 reserved_18[5];
136 __le32 RDSAR;
137 u8 reserved_19[18];
138 u16 TALLY_CNT;
139 u8 TALLY_SEL;
140} __attribute__((packed));
141
142static const struct ieee80211_rate rtl818x_rates[] = {
143 { .rate = 10,
144 .val = 0,
145 .flags = IEEE80211_RATE_CCK },
146 { .rate = 20,
147 .val = 1,
148 .flags = IEEE80211_RATE_CCK },
149 { .rate = 55,
150 .val = 2,
151 .flags = IEEE80211_RATE_CCK },
152 { .rate = 110,
153 .val = 3,
154 .flags = IEEE80211_RATE_CCK },
155 { .rate = 60,
156 .val = 4,
157 .flags = IEEE80211_RATE_OFDM },
158 { .rate = 90,
159 .val = 5,
160 .flags = IEEE80211_RATE_OFDM },
161 { .rate = 120,
162 .val = 6,
163 .flags = IEEE80211_RATE_OFDM },
164 { .rate = 180,
165 .val = 7,
166 .flags = IEEE80211_RATE_OFDM },
167 { .rate = 240,
168 .val = 8,
169 .flags = IEEE80211_RATE_OFDM },
170 { .rate = 360,
171 .val = 9,
172 .flags = IEEE80211_RATE_OFDM },
173 { .rate = 480,
174 .val = 10,
175 .flags = IEEE80211_RATE_OFDM },
176 { .rate = 540,
177 .val = 11,
178 .flags = IEEE80211_RATE_OFDM },
179};
180
181static const struct ieee80211_channel rtl818x_channels[] = {
182 { .chan = 1,
183 .freq = 2412},
184 { .chan = 2,
185 .freq = 2417},
186 { .chan = 3,
187 .freq = 2422},
188 { .chan = 4,
189 .freq = 2427},
190 { .chan = 5,
191 .freq = 2432},
192 { .chan = 6,
193 .freq = 2437},
194 { .chan = 7,
195 .freq = 2442},
196 { .chan = 8,
197 .freq = 2447},
198 { .chan = 9,
199 .freq = 2452},
200 { .chan = 10,
201 .freq = 2457},
202 { .chan = 11,
203 .freq = 2462},
204 { .chan = 12,
205 .freq = 2467},
206 { .chan = 13,
207 .freq = 2472},
208 { .chan = 14,
209 .freq = 2484}
210};
211
212#endif /* RTL818X_H */