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