iwlwifi: remove the statistics work
[linux-2.6] / drivers / net / wireless / rtl8187_rtl8225.c
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
26 static 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
70 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 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
104 static void 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, cpu_to_le16(data));
110         else
111                 rtl8225_write_bitbang(dev, addr, data);
112 }
113
114 static u16 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
199 static 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
214 static 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
233 static 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
243 static const u8 rtl8225_threshold[] = {
244         0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
245 };
246
247 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
248         0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
249 };
250
251 static 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
260 static 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
269 static const u8 rtl8225_tx_power_ofdm[] = {
270         0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
271 };
272
273 static const u32 rtl8225_chan[] = {
274         0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
275         0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
276 };
277
278 static 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].hw_value & 0xF;
287         ofdm_power = priv->channels[channel - 1].hw_value >> 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
328 static void 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
474 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
475         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
476 };
477
478 static const u8 rtl8225z2_tx_power_cck[] = {
479         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
480 };
481
482 static const u8 rtl8225z2_tx_power_ofdm[] = {
483         0x42, 0x00, 0x40, 0x00, 0x40
484 };
485
486 static 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
495 static 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].hw_value & 0xF;
504         ofdm_power = priv->channels[channel - 1].hw_value >> 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
545 static 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
560 static 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
570 static void 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
718 static void 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
734 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
735                                    struct ieee80211_conf *conf)
736 {
737         struct rtl8187_priv *priv = dev->priv;
738         int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
739
740         if (priv->rf->init == rtl8225_rf_init)
741                 rtl8225_rf_set_tx_power(dev, chan);
742         else
743                 rtl8225z2_rf_set_tx_power(dev, chan);
744
745         rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
746         msleep(10);
747 }
748
749 static const struct rtl818x_rf_ops rtl8225_ops = {
750         .name           = "rtl8225",
751         .init           = rtl8225_rf_init,
752         .stop           = rtl8225_rf_stop,
753         .set_chan       = rtl8225_rf_set_channel
754 };
755
756 static const struct rtl818x_rf_ops rtl8225z2_ops = {
757         .name           = "rtl8225z2",
758         .init           = rtl8225z2_rf_init,
759         .stop           = rtl8225_rf_stop,
760         .set_chan       = rtl8225_rf_set_channel
761 };
762
763 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
764 {
765         u16 reg8, reg9;
766
767         rtl8225_write(dev, 0, 0x1B7);
768
769         reg8 = rtl8225_read(dev, 8);
770         reg9 = rtl8225_read(dev, 9);
771
772         rtl8225_write(dev, 0, 0x0B7);
773
774         if (reg8 != 0x588 || reg9 != 0x700)
775                 return &rtl8225_ops;
776
777         return &rtl8225z2_ops;
778 }