wl1251: Add support for idle mode
[pandora-wifi.git] / drivers / net / wireless / rtl818x / rtl8180_rtl8225.c
1
2 /*
3  * Radio tuning for RTL8225 on RTL8180
4  *
5  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
6  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
7  *
8  * Based on the r8180 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/pci.h>
20 #include <linux/delay.h>
21 #include <net/mac80211.h>
22
23 #include "rtl8180.h"
24 #include "rtl8180_rtl8225.h"
25
26 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
27 {
28         struct rtl8180_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 | 0x400);
42         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
43         udelay(10);
44
45         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
46         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
47         udelay(2);
48         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
49         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
50         udelay(10);
51
52         for (i = 15; i >= 0; i--) {
53                 u16 reg = reg80 | !!(bangdata & (1 << i));
54
55                 if (i & 1)
56                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
57
58                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
59                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
60
61                 if (!(i & 1))
62                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
63         }
64
65         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
66         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
67         udelay(10);
68
69         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
70         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
71         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
72 }
73
74 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
75 {
76         struct rtl8180_priv *priv = dev->priv;
77         u16 reg80, reg82, reg84, out;
78         int i;
79
80         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
81         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
82         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
83
84         reg80 &= ~0xF;
85
86         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
87         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
88
89         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
90         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
91         udelay(4);
92         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
93         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
94         udelay(5);
95
96         for (i = 4; i >= 0; i--) {
97                 u16 reg = reg80 | ((addr >> i) & 1);
98
99                 if (!(i & 1)) {
100                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
101                         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
102                         udelay(1);
103                 }
104
105                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
106                                   reg | (1 << 1));
107                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
108                 udelay(2);
109                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
110                                   reg | (1 << 1));
111                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
112                 udelay(2);
113
114                 if (i & 1) {
115                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
116                         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
117                         udelay(1);
118                 }
119         }
120
121         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
122         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
123         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
124         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
125                           reg80 | (1 << 3) | (1 << 1));
126         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
127         udelay(2);
128         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
129                           reg80 | (1 << 3));
130         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
131         udelay(2);
132         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
133                           reg80 | (1 << 3));
134         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
135         udelay(2);
136
137         out = 0;
138         for (i = 11; i >= 0; i--) {
139                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
140                                   reg80 | (1 << 3));
141                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
142                 udelay(1);
143                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
144                                   reg80 | (1 << 3) | (1 << 1));
145                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
146                 udelay(2);
147                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
148                                   reg80 | (1 << 3) | (1 << 1));
149                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
150                 udelay(2);
151                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
152                                   reg80 | (1 << 3) | (1 << 1));
153                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
154                 udelay(2);
155
156                 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
157                         out |= 1 << i;
158
159                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
160                                   reg80 | (1 << 3));
161                 rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
162                 udelay(2);
163         }
164
165         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
166                           reg80 | (1 << 3) | (1 << 2));
167         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
168         udelay(2);
169
170         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
171         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
172         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
173
174         return out;
175 }
176
177 static const u16 rtl8225bcd_rxgain[] = {
178         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
179         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
180         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
181         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
182         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
183         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
184         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
185         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
186         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
187         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
188         0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
189         0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
190 };
191
192 static const u8 rtl8225_agc[] = {
193         0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
194         0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
195         0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
196         0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
197         0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
198         0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
199         0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
200         0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
201         0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
202         0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
203         0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
204         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
205         0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
206         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
207         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
208         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
209 };
210
211 static const u8 rtl8225_gain[] = {
212         0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
213         0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
214         0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
215         0x33, 0x80, 0x79, 0xc5, /* -78dbm */
216         0x43, 0x78, 0x76, 0xc5, /* -74dbm */
217         0x53, 0x60, 0x73, 0xc5, /* -70dbm */
218         0x63, 0x58, 0x70, 0xc5, /* -66dbm */
219 };
220
221 static const u8 rtl8225_threshold[] = {
222         0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
223 };
224
225 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
226         0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
227 };
228
229 static const u8 rtl8225_tx_power_cck[] = {
230         0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
231         0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
232         0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
233         0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
234         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
235         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
236 };
237
238 static const u8 rtl8225_tx_power_cck_ch14[] = {
239         0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
240         0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
241         0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
242         0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
243         0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
244         0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
245 };
246
247 static const u8 rtl8225_tx_power_ofdm[] = {
248         0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
249 };
250
251 static const u32 rtl8225_chan[] = {
252         0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
253         0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
254 };
255
256 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
257 {
258         struct rtl8180_priv *priv = dev->priv;
259         u8 cck_power, ofdm_power;
260         const u8 *tmp;
261         u32 reg;
262         int i;
263
264         cck_power = priv->channels[channel - 1].hw_value & 0xFF;
265         ofdm_power = priv->channels[channel - 1].hw_value >> 8;
266
267         cck_power = min(cck_power, (u8)35);
268         ofdm_power = min(ofdm_power, (u8)35);
269
270         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
271                          rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
272
273         if (channel == 14)
274                 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
275         else
276                 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
277
278         for (i = 0; i < 8; i++)
279                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
280
281         msleep(1); /* FIXME: optional? */
282
283         /* anaparam2 on */
284         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
285         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
286         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
287         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
288         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
289         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
290
291         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
292                          rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
293
294         tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
295
296         rtl8225_write_phy_ofdm(dev, 5, *tmp);
297         rtl8225_write_phy_ofdm(dev, 7, *tmp);
298
299         msleep(1);
300 }
301
302 static void rtl8225_rf_init(struct ieee80211_hw *dev)
303 {
304         struct rtl8180_priv *priv = dev->priv;
305         int i;
306
307         rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
308
309         /* host_pci_init */
310         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
311         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
312         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
313         rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
314         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
315         msleep(200);    /* FIXME: ehh?? */
316         rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
317
318         rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
319
320         /* TODO: check if we need really to change BRSR to do RF config */
321         rtl818x_ioread16(priv, &priv->map->BRSR);
322         rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
323         rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
324         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
325         rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
326         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
327
328         rtl8225_write(dev, 0x0, 0x067);
329         rtl8225_write(dev, 0x1, 0xFE0);
330         rtl8225_write(dev, 0x2, 0x44D);
331         rtl8225_write(dev, 0x3, 0x441);
332         rtl8225_write(dev, 0x4, 0x8BE);
333         rtl8225_write(dev, 0x5, 0xBF0);         /* TODO: minipci */
334         rtl8225_write(dev, 0x6, 0xAE6);
335         rtl8225_write(dev, 0x7, rtl8225_chan[0]);
336         rtl8225_write(dev, 0x8, 0x01F);
337         rtl8225_write(dev, 0x9, 0x334);
338         rtl8225_write(dev, 0xA, 0xFD4);
339         rtl8225_write(dev, 0xB, 0x391);
340         rtl8225_write(dev, 0xC, 0x050);
341         rtl8225_write(dev, 0xD, 0x6DB);
342         rtl8225_write(dev, 0xE, 0x029);
343         rtl8225_write(dev, 0xF, 0x914); msleep(1);
344
345         rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
346
347         rtl8225_write(dev, 0x0, 0x127);
348
349         for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
350                 rtl8225_write(dev, 0x1, i + 1);
351                 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
352         }
353
354         rtl8225_write(dev, 0x0, 0x027);
355         rtl8225_write(dev, 0x0, 0x22F);
356         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
357
358         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
359                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
360                 msleep(1);
361                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
362                 msleep(1);
363         }
364
365         msleep(1);
366
367         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
368         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
369         rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
370         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
371         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
372         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
373         rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
374         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
375         rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
376         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
377         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
378         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
379         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
380         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
381         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
382         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
383         rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
384         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
385         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
386         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
387         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
388         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
389         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
390         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
391         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
392         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
393         rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
394         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
395         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
396         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
397         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
398         rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
399         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
400         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
401         rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
402         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
403         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
404
405         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
406         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
407         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
408         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
409         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
410         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
411         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
412         rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
413         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
414         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
415         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
416         rtl8225_write_phy_cck(dev, 0x19, 0x00);
417         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
418         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
419         rtl8225_write_phy_cck(dev, 0x40, 0x86);
420         rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
421         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
422         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
423         rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
424         rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
425         rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
426         rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
427         rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
428         rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
429         rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
430         rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
431         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
432
433         rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
434
435         rtl8225_rf_set_tx_power(dev, 1);
436
437         /* RX antenna default to A */
438         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
439         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
440
441         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
442         msleep(1);
443         rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
444         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
445
446         rtl8225_write(dev, 0x0c, 0x50);
447         /* set OFDM initial gain */
448         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
449         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
450         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
451         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
452         /* set CCK threshold */
453         rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
454 }
455
456 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
457         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
458 };
459
460 static const u8 rtl8225z2_tx_power_cck_B[] = {
461         0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
462 };
463
464 static const u8 rtl8225z2_tx_power_cck_A[] = {
465         0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
466 };
467
468 static const u8 rtl8225z2_tx_power_cck[] = {
469         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
470 };
471
472 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
473 {
474         struct rtl8180_priv *priv = dev->priv;
475         u8 cck_power, ofdm_power;
476         const u8 *tmp;
477         int i;
478
479         cck_power = priv->channels[channel - 1].hw_value & 0xFF;
480         ofdm_power = priv->channels[channel - 1].hw_value >> 8;
481
482         if (channel == 14)
483                 tmp = rtl8225z2_tx_power_cck_ch14;
484         else if (cck_power == 12)
485                 tmp = rtl8225z2_tx_power_cck_B;
486         else if (cck_power == 13)
487                 tmp = rtl8225z2_tx_power_cck_A;
488         else
489                 tmp = rtl8225z2_tx_power_cck;
490
491         for (i = 0; i < 8; i++)
492                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
493
494         cck_power = min(cck_power, (u8)35);
495         if (cck_power == 13 || cck_power == 14)
496                 cck_power = 12;
497         if (cck_power >= 15)
498                 cck_power -= 2;
499
500         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
501         rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
502         msleep(1);
503
504         ofdm_power = min(ofdm_power, (u8)35);
505         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
506
507         rtl8225_write_phy_ofdm(dev, 2, 0x62);
508         rtl8225_write_phy_ofdm(dev, 5, 0x00);
509         rtl8225_write_phy_ofdm(dev, 6, 0x40);
510         rtl8225_write_phy_ofdm(dev, 7, 0x00);
511         rtl8225_write_phy_ofdm(dev, 8, 0x40);
512
513         msleep(1);
514 }
515
516 static const u16 rtl8225z2_rxgain[] = {
517         0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
518         0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
519         0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
520         0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
521         0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
522         0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
523         0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
524         0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
525         0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
526         0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
527         0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
528         0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
529 };
530
531 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
532 {
533         struct rtl8180_priv *priv = dev->priv;
534         int i;
535
536         rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
537
538         /* host_pci_init */
539         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
540         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
541         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
542         rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
543         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
544         msleep(200);    /* FIXME: ehh?? */
545         rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
546
547         rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
548
549         /* TODO: check if we need really to change BRSR to do RF config */
550         rtl818x_ioread16(priv, &priv->map->BRSR);
551         rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
552         rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
553         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
554         rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
555         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
556
557         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
558
559         rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
560         rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
561         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
562         rtl8225_write(dev, 0x3, 0x441); msleep(1);
563         rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
564         rtl8225_write(dev, 0x5, 0xC72); msleep(1);
565         rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
566         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
567         rtl8225_write(dev, 0x8, 0x03F); msleep(1);
568         rtl8225_write(dev, 0x9, 0x335); msleep(1);
569         rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
570         rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
571         rtl8225_write(dev, 0xc, 0x850); msleep(1);
572         rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
573         rtl8225_write(dev, 0xe, 0x02B); msleep(1);
574         rtl8225_write(dev, 0xf, 0x114); msleep(100);
575
576         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
577                 rtl8225_write(dev, 0x02, 0x0C4D);
578                 msleep(200);
579                 rtl8225_write(dev, 0x02, 0x044D);
580                 msleep(100);
581                 /* TODO: readd calibration failure message when the calibration
582                    check works */
583         }
584
585         rtl8225_write(dev, 0x0, 0x1B7);
586         rtl8225_write(dev, 0x3, 0x002);
587         rtl8225_write(dev, 0x5, 0x004);
588
589         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
590                 rtl8225_write(dev, 0x1, i + 1);
591                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
592         }
593
594         rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
595         rtl8225_write(dev, 0x2, 0xC4D);
596
597         msleep(200);
598         rtl8225_write(dev, 0x2, 0x44D);
599         msleep(100);
600
601         rtl8225_write(dev, 0x00, 0x2BF);
602         rtl8225_write(dev, 0xFF, 0xFFFF);
603
604         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
605
606         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
607                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
608                 msleep(1);
609                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
610                 msleep(1);
611         }
612
613         msleep(1);
614
615         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
616         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
617         rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
618         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
619         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
620         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
621         rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
622         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
623         rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
624         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
625         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
626         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
627         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
628         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
629         rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
630         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
631         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
632         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
633         rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
634         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
635         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
636         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
637         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
638         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
639         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
640         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
641         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
642         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
643         rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
644         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
645         rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
646         rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
647         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
648         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
649         rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
650         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
651         rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
652         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
653         rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
654         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
655         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
656
657         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
658         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
659         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
660         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
661         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
662         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
663         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
664         rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
665         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
666         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
667         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
668         rtl8225_write_phy_cck(dev, 0x19, 0x00);
669         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
670         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
671         rtl8225_write_phy_cck(dev, 0x40, 0x86);
672         rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
673         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
674         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
675         rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
676         rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
677         rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
678         rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
679         rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
680         rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
681         rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
682         rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
683         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
684
685         rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
686
687         rtl8225z2_rf_set_tx_power(dev, 1);
688
689         /* RX antenna default to A */
690         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
691         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
692
693         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
694         msleep(1);
695         rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
696         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
697 }
698
699 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
700 {
701         struct rtl8180_priv *priv = dev->priv;
702         u8 reg;
703
704         rtl8225_write(dev, 0x4, 0x1f); msleep(1);
705
706         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
707         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
708         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
709         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
710         rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
711         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
712         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
713 }
714
715 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
716                                    struct ieee80211_conf *conf)
717 {
718         struct rtl8180_priv *priv = dev->priv;
719         int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
720
721         if (priv->rf->init == rtl8225_rf_init)
722                 rtl8225_rf_set_tx_power(dev, chan);
723         else
724                 rtl8225z2_rf_set_tx_power(dev, chan);
725
726         rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
727         msleep(10);
728 }
729
730 static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
731                                 struct ieee80211_bss_conf *info)
732 {
733         struct rtl8180_priv *priv = dev->priv;
734
735         if (info->use_short_slot) {
736                 rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
737                 rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
738                 rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
739                 rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
740                 rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
741         } else {
742                 rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
743                 rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
744                 rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
745                 rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
746                 rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
747         }
748 }
749
750 static const struct rtl818x_rf_ops rtl8225_ops = {
751         .name           = "rtl8225",
752         .init           = rtl8225_rf_init,
753         .stop           = rtl8225_rf_stop,
754         .set_chan       = rtl8225_rf_set_channel,
755         .conf_erp       = rtl8225_rf_conf_erp,
756 };
757
758 static const struct rtl818x_rf_ops rtl8225z2_ops = {
759         .name           = "rtl8225z2",
760         .init           = rtl8225z2_rf_init,
761         .stop           = rtl8225_rf_stop,
762         .set_chan       = rtl8225_rf_set_channel,
763         .conf_erp       = rtl8225_rf_conf_erp,
764 };
765
766 const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
767 {
768         struct rtl8180_priv *priv = dev->priv;
769         u16 reg8, reg9;
770
771         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
772         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
773         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
774         rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
775         msleep(100);
776
777         rtl8225_write(dev, 0, 0x1B7);
778
779         reg8 = rtl8225_read(dev, 8);
780         reg9 = rtl8225_read(dev, 9);
781
782         rtl8225_write(dev, 0, 0x0B7);
783
784         if (reg8 != 0x588 || reg9 != 0x700)
785                 return &rtl8225_ops;
786
787         return &rtl8225z2_ops;
788 }