Merge branch 'for-rmk' of git://git.marvell.com/orion
[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,
309                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
310         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
311                           RTL8187_RTL8225_ANAPARAM2_ON);
312         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
313                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
314         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
315
316         rtl8225_write_phy_ofdm(dev, 2, 0x42);
317         rtl8225_write_phy_ofdm(dev, 6, 0x00);
318         rtl8225_write_phy_ofdm(dev, 8, 0x00);
319
320         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
321                          rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
322
323         tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
324
325         rtl8225_write_phy_ofdm(dev, 5, *tmp);
326         rtl8225_write_phy_ofdm(dev, 7, *tmp);
327
328         msleep(1);
329 }
330
331 static void rtl8225_rf_init(struct ieee80211_hw *dev)
332 {
333         struct rtl8187_priv *priv = dev->priv;
334         int i;
335
336         rtl8225_write(dev, 0x0, 0x067); msleep(1);
337         rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
338         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
339         rtl8225_write(dev, 0x3, 0x441); msleep(1);
340         rtl8225_write(dev, 0x4, 0x486); msleep(1);
341         rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
342         rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
343         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
344         rtl8225_write(dev, 0x8, 0x01F); msleep(1);
345         rtl8225_write(dev, 0x9, 0x334); msleep(1);
346         rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
347         rtl8225_write(dev, 0xB, 0x391); msleep(1);
348         rtl8225_write(dev, 0xC, 0x050); msleep(1);
349         rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
350         rtl8225_write(dev, 0xE, 0x029); msleep(1);
351         rtl8225_write(dev, 0xF, 0x914); msleep(100);
352
353         rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
354         rtl8225_write(dev, 0x2, 0x44D); msleep(200);
355
356         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
357                 rtl8225_write(dev, 0x02, 0x0c4d);
358                 msleep(200);
359                 rtl8225_write(dev, 0x02, 0x044d);
360                 msleep(100);
361                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
362                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
363                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
364         }
365
366         rtl8225_write(dev, 0x0, 0x127);
367
368         for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
369                 rtl8225_write(dev, 0x1, i + 1);
370                 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
371         }
372
373         rtl8225_write(dev, 0x0, 0x027);
374         rtl8225_write(dev, 0x0, 0x22F);
375
376         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
377                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
378                 msleep(1);
379                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
380                 msleep(1);
381         }
382
383         msleep(1);
384
385         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
386         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
387         rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
388         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
389         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
390         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
391         rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
392         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
393         rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
394         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
395         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
396         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
397         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
398         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
399         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
400         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
401         rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
402         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
403         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
404         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
405         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
406         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
407         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
408         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
409         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
410         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
411         rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
412         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
413         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
414         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
415         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
416         rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
417         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
418         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
419         rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
420         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
421         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
422
423         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
424         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
425         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
426         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
427
428         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
429         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
430         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
431         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
432         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
433         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
434         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
435         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
436         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
437         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
438         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
439         rtl8225_write_phy_cck(dev, 0x19, 0x00);
440         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
441         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
442         rtl8225_write_phy_cck(dev, 0x40, 0x86);
443         rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
444         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
445         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
446         rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
447         rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
448         rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
449         rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
450         rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
451         rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
452         rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
453         rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
454         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
455
456         rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
457
458         rtl8225_rf_set_tx_power(dev, 1);
459
460         /* RX antenna default to A */
461         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
462         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
463
464         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
465         msleep(1);
466         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
467
468         /* set sensitivity */
469         rtl8225_write(dev, 0x0c, 0x50);
470         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
471         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
472         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
473         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
474         rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
475 }
476
477 static const u8 rtl8225z2_agc[] = {
478         0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
479         0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
480         0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
481         0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
482         0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
483         0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
484         0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
485         0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
486         0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
487         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
488         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
489 };
490 static const u8 rtl8225z2_ofdm[] = {
491         0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
492         0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
493         0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
494         0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
495         0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
496         0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
497         0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
498         0x6d, 0x3c, 0xfb, 0x07
499 };
500
501 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
502         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
503         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
504         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
505         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
506 };
507
508 static const u8 rtl8225z2_tx_power_cck[] = {
509         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
510         0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
511         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
512         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
513 };
514
515 static const u8 rtl8225z2_tx_power_ofdm[] = {
516         0x42, 0x00, 0x40, 0x00, 0x40
517 };
518
519 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
520         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
521         0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
522         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
523         0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
524         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
525         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
526 };
527
528 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
529 {
530         struct rtl8187_priv *priv = dev->priv;
531         u8 cck_power, ofdm_power;
532         const u8 *tmp;
533         u32 reg;
534         int i;
535
536         cck_power = priv->channels[channel - 1].hw_value & 0xF;
537         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
538
539         cck_power = min(cck_power, (u8)15);
540         cck_power += priv->txpwr_base & 0xF;
541         cck_power = min(cck_power, (u8)35);
542
543         ofdm_power = min(ofdm_power, (u8)15);
544         ofdm_power += priv->txpwr_base >> 4;
545         ofdm_power = min(ofdm_power, (u8)35);
546
547         if (channel == 14)
548                 tmp = rtl8225z2_tx_power_cck_ch14;
549         else
550                 tmp = rtl8225z2_tx_power_cck;
551
552         for (i = 0; i < 8; i++)
553                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
554
555         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
556                          rtl8225z2_tx_gain_cck_ofdm[cck_power]);
557         msleep(1);
558
559         /* anaparam2 on */
560         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
561         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
562         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
563                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
564         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
565                           RTL8187_RTL8225_ANAPARAM2_ON);
566         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
567                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
568         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
569
570         rtl8225_write_phy_ofdm(dev, 2, 0x42);
571         rtl8225_write_phy_ofdm(dev, 5, 0x00);
572         rtl8225_write_phy_ofdm(dev, 6, 0x40);
573         rtl8225_write_phy_ofdm(dev, 7, 0x00);
574         rtl8225_write_phy_ofdm(dev, 8, 0x40);
575
576         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
577                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
578         msleep(1);
579 }
580
581 static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
582 {
583         struct rtl8187_priv *priv = dev->priv;
584         u8 cck_power, ofdm_power;
585         const u8 *tmp;
586         int i;
587
588         cck_power = priv->channels[channel - 1].hw_value & 0xF;
589         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
590
591         if (cck_power > 15)
592                 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
593         else
594                 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
595         cck_power += priv->txpwr_base & 0xF;
596         cck_power = min(cck_power, (u8)35);
597
598         if (ofdm_power > 15)
599                 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
600         else
601                 ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
602         ofdm_power += (priv->txpwr_base >> 4) & 0xF;
603         ofdm_power = min(ofdm_power, (u8)35);
604
605         if (channel == 14)
606                 tmp = rtl8225z2_tx_power_cck_ch14;
607         else
608                 tmp = rtl8225z2_tx_power_cck;
609
610         if (priv->hw_rev == RTL8187BvB) {
611                 if (cck_power <= 6)
612                         ; /* do nothing */
613                 else if (cck_power <= 11)
614                         tmp += 8;
615                 else
616                         tmp += 16;
617         } else {
618                 if (cck_power <= 5)
619                         ; /* do nothing */
620                 else if (cck_power <= 11)
621                         tmp += 8;
622                 else if (cck_power <= 17)
623                         tmp += 16;
624                 else
625                         tmp += 24;
626         }
627
628         for (i = 0; i < 8; i++)
629                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
630
631         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
632                          rtl8225z2_tx_gain_cck_ofdm[cck_power]);
633         msleep(1);
634
635         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
636                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
637         if (priv->hw_rev == RTL8187BvB) {
638                 if (ofdm_power <= 11) {
639                         rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
640                         rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
641                 } else {
642                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
643                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
644                 }
645         } else {
646                 if (ofdm_power <= 11) {
647                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
648                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
649                 } else if (ofdm_power <= 17) {
650                         rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
651                         rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
652                 } else {
653                         rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
654                         rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
655                 }
656         }
657         msleep(1);
658 }
659
660 static const u16 rtl8225z2_rxgain[] = {
661         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
662         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
663         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
664         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
665         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
666         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
667         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
668         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
669         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
670         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
671         0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
672         0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
673 };
674
675 static const u8 rtl8225z2_gain_bg[] = {
676         0x23, 0x15, 0xa5, /* -82-1dBm */
677         0x23, 0x15, 0xb5, /* -82-2dBm */
678         0x23, 0x15, 0xc5, /* -82-3dBm */
679         0x33, 0x15, 0xc5, /* -78dBm */
680         0x43, 0x15, 0xc5, /* -74dBm */
681         0x53, 0x15, 0xc5, /* -70dBm */
682         0x63, 0x15, 0xc5  /* -66dBm */
683 };
684
685 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
686 {
687         struct rtl8187_priv *priv = dev->priv;
688         int i;
689
690         rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
691         rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
692         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
693         rtl8225_write(dev, 0x3, 0x441); msleep(1);
694         rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
695         rtl8225_write(dev, 0x5, 0xC72); msleep(1);
696         rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
697         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
698         rtl8225_write(dev, 0x8, 0x03F); msleep(1);
699         rtl8225_write(dev, 0x9, 0x335); msleep(1);
700         rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
701         rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
702         rtl8225_write(dev, 0xc, 0x850); msleep(1);
703         rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
704         rtl8225_write(dev, 0xe, 0x02B); msleep(1);
705         rtl8225_write(dev, 0xf, 0x114); msleep(100);
706
707         rtl8225_write(dev, 0x0, 0x1B7);
708
709         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
710                 rtl8225_write(dev, 0x1, i + 1);
711                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
712         }
713
714         rtl8225_write(dev, 0x3, 0x080);
715         rtl8225_write(dev, 0x5, 0x004);
716         rtl8225_write(dev, 0x0, 0x0B7);
717         rtl8225_write(dev, 0x2, 0xc4D);
718
719         msleep(200);
720         rtl8225_write(dev, 0x2, 0x44D);
721         msleep(100);
722
723         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
724                 rtl8225_write(dev, 0x02, 0x0C4D);
725                 msleep(200);
726                 rtl8225_write(dev, 0x02, 0x044D);
727                 msleep(100);
728                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
729                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
730                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
731         }
732
733         msleep(200);
734
735         rtl8225_write(dev, 0x0, 0x2BF);
736
737         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
738                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
739                 msleep(1);
740                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
741                 msleep(1);
742         }
743
744         msleep(1);
745
746         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
747         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
748         rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
749         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
750         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
751         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
752         rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
753         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
754         rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
755         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
756         rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
757         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
758         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
759         rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
760         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
761         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
762         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
763         rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
764         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
765         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
766         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
767         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
768         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
769         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
770         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
771         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
772         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
773         rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
774         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
775         rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
776         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
777         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
778         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
779         rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
780         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
781         rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
782         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
783         rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
784         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
785         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
786
787         rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
788         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
789         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
790         rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
791
792         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
793         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
794         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
795         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
796         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
797         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
798         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
799         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
800         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
801         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
802         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
803         rtl8225_write_phy_cck(dev, 0x19, 0x00);
804         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
805         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
806         rtl8225_write_phy_cck(dev, 0x40, 0x86);
807         rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
808         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
809         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
810         rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
811         rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
812         rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
813         rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
814         rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
815         rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
816         rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
817         rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
818         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
819
820         rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
821
822         rtl8225z2_rf_set_tx_power(dev, 1);
823
824         /* RX antenna default to A */
825         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
826         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
827
828         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
829         msleep(1);
830         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
831 }
832
833 static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
834 {
835         struct rtl8187_priv *priv = dev->priv;
836         int i;
837
838         rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
839         rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
840         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
841         rtl8225_write(dev, 0x3, 0x441); msleep(1);
842         rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
843         rtl8225_write(dev, 0x5, 0xC72); msleep(1);
844         rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
845         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
846         rtl8225_write(dev, 0x8, 0x03F); msleep(1);
847         rtl8225_write(dev, 0x9, 0x335); msleep(1);
848         rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
849         rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
850         rtl8225_write(dev, 0xc, 0x850); msleep(1);
851         rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
852         rtl8225_write(dev, 0xe, 0x02B); msleep(1);
853         rtl8225_write(dev, 0xf, 0x114); msleep(1);
854
855         rtl8225_write(dev, 0x0, 0x1B7); msleep(1);
856
857         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
858                 rtl8225_write(dev, 0x1, i + 1); msleep(1);
859                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
860         }
861
862         rtl8225_write(dev, 0x3, 0x080); msleep(1);
863         rtl8225_write(dev, 0x5, 0x004); msleep(1);
864         rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
865         msleep(3000);
866
867         rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
868         msleep(2000);
869
870         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
871         rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
872
873         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
874         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
875         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
876
877         rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
878         for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
879                 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
880                 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
881                 rtl8225_write_phy_ofdm(dev, 0xE, 0);
882         }
883         rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
884
885         for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
886                 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
887
888         rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
889         rtl818x_iowrite8(priv, &priv->map->SLOT, 9);
890         rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28);
891         rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28);
892         rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28);
893         rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28);
894         rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B);
895         rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B);
896         rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
897         rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
898         rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
899         rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
900         rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
901
902         rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1);
903         rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1);
904         rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1);
905         rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1);
906 }
907
908 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
909 {
910         u8 reg;
911         struct rtl8187_priv *priv = dev->priv;
912
913         rtl8225_write(dev, 0x4, 0x1f); msleep(1);
914
915         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
916         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
917         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
918         if (!priv->is_rtl8187b) {
919                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
920                                   RTL8187_RTL8225_ANAPARAM2_OFF);
921                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
922                                   RTL8187_RTL8225_ANAPARAM_OFF);
923         } else {
924                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
925                                   RTL8187B_RTL8225_ANAPARAM2_OFF);
926                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
927                                   RTL8187B_RTL8225_ANAPARAM_OFF);
928                 rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
929                                   RTL8187B_RTL8225_ANAPARAM3_OFF);
930         }
931         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
932         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
933 }
934
935 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
936                                    struct ieee80211_conf *conf)
937 {
938         struct rtl8187_priv *priv = dev->priv;
939         int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
940
941         if (priv->rf->init == rtl8225_rf_init)
942                 rtl8225_rf_set_tx_power(dev, chan);
943         else if (priv->rf->init == rtl8225z2_rf_init)
944                 rtl8225z2_rf_set_tx_power(dev, chan);
945         else
946                 rtl8225z2_b_rf_set_tx_power(dev, chan);
947
948         rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
949         msleep(10);
950 }
951
952 static const struct rtl818x_rf_ops rtl8225_ops = {
953         .name           = "rtl8225",
954         .init           = rtl8225_rf_init,
955         .stop           = rtl8225_rf_stop,
956         .set_chan       = rtl8225_rf_set_channel
957 };
958
959 static const struct rtl818x_rf_ops rtl8225z2_ops = {
960         .name           = "rtl8225z2",
961         .init           = rtl8225z2_rf_init,
962         .stop           = rtl8225_rf_stop,
963         .set_chan       = rtl8225_rf_set_channel
964 };
965
966 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
967         .name           = "rtl8225z2",
968         .init           = rtl8225z2_b_rf_init,
969         .stop           = rtl8225_rf_stop,
970         .set_chan       = rtl8225_rf_set_channel
971 };
972
973 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
974 {
975         u16 reg8, reg9;
976         struct rtl8187_priv *priv = dev->priv;
977
978         if (!priv->is_rtl8187b) {
979                 rtl8225_write(dev, 0, 0x1B7);
980
981                 reg8 = rtl8225_read(dev, 8);
982                 reg9 = rtl8225_read(dev, 9);
983
984                 rtl8225_write(dev, 0, 0x0B7);
985
986                 if (reg8 != 0x588 || reg9 != 0x700)
987                         return &rtl8225_ops;
988
989                 return &rtl8225z2_ops;
990         } else
991                 return &rtl8225z2_b_ops;
992 }