Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
 68 
 69 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
 70 {
 71         struct rtl8187_priv *priv = dev->priv;
 72         u16 reg80, reg82, reg84;
 73 
 74         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
 75         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 76         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 77 
 78         reg80 &= ~(0x3 << 2);
 79         reg84 &= ~0xF;
 80 
 81         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
 82         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
 83         udelay(10);
 84 
 85         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 86         udelay(2);
 87 
 88         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 89         udelay(10);
 90 
 91         mutex_lock(&priv->io_mutex);
 92 
 93         priv->io_dmabuf->bits16 = data;
 94         usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 95                         RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 96                         addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
 97                         HZ / 2);
 98 
 99         mutex_unlock(&priv->io_mutex);
100 
101         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
102         udelay(10);
103 
104         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
105         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
106 }
107 
108 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
109 {
110         struct rtl8187_priv *priv = dev->priv;
111 
112         if (priv->asic_rev)
113                 rtl8225_write_8051(dev, addr, cpu_to_le16(data));
114         else
115                 rtl8225_write_bitbang(dev, addr, data);
116 }
117 
118 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
119 {
120         struct rtl8187_priv *priv = dev->priv;
121         u16 reg80, reg82, reg84, out;
122         int i;
123 
124         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
125         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
126         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
127 
128         reg80 &= ~0xF;
129 
130         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
131         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
132 
133         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
134         udelay(4);
135         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
136         udelay(5);
137 
138         for (i = 4; i >= 0; i--) {
139                 u16 reg = reg80 | ((addr >> i) & 1);
140 
141                 if (!(i & 1)) {
142                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
143                         udelay(1);
144                 }
145 
146                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
147                                   reg | (1 << 1));
148                 udelay(2);
149                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
150                                   reg | (1 << 1));
151                 udelay(2);
152 
153                 if (i & 1) {
154                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
155                         udelay(1);
156                 }
157         }
158 
159         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
160                           reg80 | (1 << 3) | (1 << 1));
161         udelay(2);
162         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
163                           reg80 | (1 << 3));
164         udelay(2);
165         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
166                           reg80 | (1 << 3));
167         udelay(2);
168 
169         out = 0;
170         for (i = 11; i >= 0; i--) {
171                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
172                                   reg80 | (1 << 3));
173                 udelay(1);
174                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
175                                   reg80 | (1 << 3) | (1 << 1));
176                 udelay(2);
177                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
178                                   reg80 | (1 << 3) | (1 << 1));
179                 udelay(2);
180                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
181                                   reg80 | (1 << 3) | (1 << 1));
182                 udelay(2);
183 
184                 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
185                         out |= 1 << i;
186 
187                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
188                                   reg80 | (1 << 3));
189                 udelay(2);
190         }
191 
192         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
193                           reg80 | (1 << 3) | (1 << 2));
194         udelay(2);
195 
196         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
197         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
198         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
199 
200         return out;
201 }
202 
203 static const u16 rtl8225bcd_rxgain[] = {
204         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
205         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
206         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
207         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
208         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
209         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
210         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
211         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
212         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
213         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
214         0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
215         0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
216 };
217 
218 static const u8 rtl8225_agc[] = {
219         0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
220         0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
221         0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
222         0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
223         0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
224         0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
225         0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
226         0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
227         0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
228         0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
229         0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
230         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
231         0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
232         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
233         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
234         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
235 };
236 
237 static const u8 rtl8225_gain[] = {
238         0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
239         0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
240         0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
241         0x33, 0x80, 0x79, 0xc5, /* -78dBm */
242         0x43, 0x78, 0x76, 0xc5, /* -74dBm */
243         0x53, 0x60, 0x73, 0xc5, /* -70dBm */
244         0x63, 0x58, 0x70, 0xc5, /* -66dBm */
245 };
246 
247 static const u8 rtl8225_threshold[] = {
248         0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
249 };
250 
251 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
252         0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
253 };
254 
255 static const u8 rtl8225_tx_power_cck[] = {
256         0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
257         0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
258         0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
259         0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
260         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
261         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
262 };
263 
264 static const u8 rtl8225_tx_power_cck_ch14[] = {
265         0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
266         0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
267         0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
268         0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
269         0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
270         0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
271 };
272 
273 static const u8 rtl8225_tx_power_ofdm[] = {
274         0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
275 };
276 
277 static const u32 rtl8225_chan[] = {
278         0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
279         0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
280 };
281 
282 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
283 {
284         struct rtl8187_priv *priv = dev->priv;
285         u8 cck_power, ofdm_power;
286         const u8 *tmp;
287         u32 reg;
288         int i;
289 
290         cck_power = priv->channels[channel - 1].hw_value & 0xF;
291         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
292 
293         cck_power = min(cck_power, (u8)11);
294         if (ofdm_power > (u8)15)
295                 ofdm_power = 25;
296         else
297                 ofdm_power += 10;
298 
299         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
300                          rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
301 
302         if (channel == 14)
303                 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
304         else
305                 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
306 
307         for (i = 0; i < 8; i++)
308                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
309 
310         msleep(1); // FIXME: optional?
311 
312         /* anaparam2 on */
313         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
314         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
315         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
316                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
317         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
318                           RTL8187_RTL8225_ANAPARAM2_ON);
319         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
320                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
321         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
322 
323         rtl8225_write_phy_ofdm(dev, 2, 0x42);
324         rtl8225_write_phy_ofdm(dev, 6, 0x00);
325         rtl8225_write_phy_ofdm(dev, 8, 0x00);
326 
327         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
328                          rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
329 
330         tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
331 
332         rtl8225_write_phy_ofdm(dev, 5, *tmp);
333         rtl8225_write_phy_ofdm(dev, 7, *tmp);
334 
335         msleep(1);
336 }
337 
338 static void rtl8225_rf_init(struct ieee80211_hw *dev)
339 {
340         struct rtl8187_priv *priv = dev->priv;
341         int i;
342 
343         rtl8225_write(dev, 0x0, 0x067);
344         rtl8225_write(dev, 0x1, 0xFE0);
345         rtl8225_write(dev, 0x2, 0x44D);
346         rtl8225_write(dev, 0x3, 0x441);
347         rtl8225_write(dev, 0x4, 0x486);
348         rtl8225_write(dev, 0x5, 0xBC0);
349         rtl8225_write(dev, 0x6, 0xAE6);
350         rtl8225_write(dev, 0x7, 0x82A);
351         rtl8225_write(dev, 0x8, 0x01F);
352         rtl8225_write(dev, 0x9, 0x334);
353         rtl8225_write(dev, 0xA, 0xFD4);
354         rtl8225_write(dev, 0xB, 0x391);
355         rtl8225_write(dev, 0xC, 0x050);
356         rtl8225_write(dev, 0xD, 0x6DB);
357         rtl8225_write(dev, 0xE, 0x029);
358         rtl8225_write(dev, 0xF, 0x914); msleep(100);
359 
360         rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
361         rtl8225_write(dev, 0x2, 0x44D); msleep(200);
362 
363         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
364                 rtl8225_write(dev, 0x02, 0x0c4d);
365                 msleep(200);
366                 rtl8225_write(dev, 0x02, 0x044d);
367                 msleep(100);
368                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
369                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
370                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
371         }
372 
373         rtl8225_write(dev, 0x0, 0x127);
374 
375         for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
376                 rtl8225_write(dev, 0x1, i + 1);
377                 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
378         }
379 
380         rtl8225_write(dev, 0x0, 0x027);
381         rtl8225_write(dev, 0x0, 0x22F);
382 
383         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
384                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
385                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
386         }
387 
388         msleep(1);
389 
390         rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
391         rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
392         rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
393         rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
394         rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
395         rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
396         rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
397         rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
398         rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
399         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
400         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
401         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
402         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
403         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
404         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
405         rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
406         rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
407         rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
408         rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
409         rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
410         rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
411         rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
412         rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
413         rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
414         rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
415         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
416         rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
417         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
418         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
419         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
420         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
421         rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
422         rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
423         rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
424         rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
425         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
426         rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
427 
428         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
429         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
430         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
431         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
432 
433         rtl8225_write_phy_cck(dev, 0x00, 0x98);
434         rtl8225_write_phy_cck(dev, 0x03, 0x20);
435         rtl8225_write_phy_cck(dev, 0x04, 0x7e);
436         rtl8225_write_phy_cck(dev, 0x05, 0x12);
437         rtl8225_write_phy_cck(dev, 0x06, 0xfc);
438         rtl8225_write_phy_cck(dev, 0x07, 0x78);
439         rtl8225_write_phy_cck(dev, 0x08, 0x2e);
440         rtl8225_write_phy_cck(dev, 0x10, 0x9b);
441         rtl8225_write_phy_cck(dev, 0x11, 0x88);
442         rtl8225_write_phy_cck(dev, 0x12, 0x47);
443         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
444         rtl8225_write_phy_cck(dev, 0x19, 0x00);
445         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
446         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
447         rtl8225_write_phy_cck(dev, 0x40, 0x86);
448         rtl8225_write_phy_cck(dev, 0x41, 0x8d);
449         rtl8225_write_phy_cck(dev, 0x42, 0x15);
450         rtl8225_write_phy_cck(dev, 0x43, 0x18);
451         rtl8225_write_phy_cck(dev, 0x44, 0x1f);
452         rtl8225_write_phy_cck(dev, 0x45, 0x1e);
453         rtl8225_write_phy_cck(dev, 0x46, 0x1a);
454         rtl8225_write_phy_cck(dev, 0x47, 0x15);
455         rtl8225_write_phy_cck(dev, 0x48, 0x10);
456         rtl8225_write_phy_cck(dev, 0x49, 0x0a);
457         rtl8225_write_phy_cck(dev, 0x4a, 0x05);
458         rtl8225_write_phy_cck(dev, 0x4b, 0x02);
459         rtl8225_write_phy_cck(dev, 0x4c, 0x05);
460 
461         rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
462 
463         rtl8225_rf_set_tx_power(dev, 1);
464 
465         /* RX antenna default to A */
466         rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
467         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
468 
469         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
470         msleep(1);
471         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
472 
473         /* set sensitivity */
474         rtl8225_write(dev, 0x0c, 0x50);
475         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
476         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
477         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
478         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
479         rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
480 }
481 
482 static const u8 rtl8225z2_agc[] = {
483         0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
484         0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
485         0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
486         0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
487         0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
488         0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
489         0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
490         0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
491         0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
492         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
493         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
494 };
495 static const u8 rtl8225z2_ofdm[] = {
496         0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
497         0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
498         0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
499         0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
500         0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
501         0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
502         0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
503         0x6d, 0x3c, 0xfb, 0x07
504 };
505 
506 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
507         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
508         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
509         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
510         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
511 };
512 
513 static const u8 rtl8225z2_tx_power_cck[] = {
514         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
515         0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
516         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
517         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
518 };
519 
520 static const u8 rtl8225z2_tx_power_ofdm[] = {
521         0x42, 0x00, 0x40, 0x00, 0x40
522 };
523 
524 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
525         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
526         0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
527         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
528         0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
529         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
530         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
531 };
532 
533 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
534 {
535         struct rtl8187_priv *priv = dev->priv;
536         u8 cck_power, ofdm_power;
537         const u8 *tmp;
538         u32 reg;
539         int i;
540 
541         cck_power = priv->channels[channel - 1].hw_value & 0xF;
542         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
543 
544         cck_power = min(cck_power, (u8)15);
545         cck_power += priv->txpwr_base & 0xF;
546         cck_power = min(cck_power, (u8)35);
547 
548         if (ofdm_power > (u8)15)
549                 ofdm_power = 25;
550         else
551                 ofdm_power += 10;
552         ofdm_power += priv->txpwr_base >> 4;
553         ofdm_power = min(ofdm_power, (u8)35);
554 
555         if (channel == 14)
556                 tmp = rtl8225z2_tx_power_cck_ch14;
557         else
558                 tmp = rtl8225z2_tx_power_cck;
559 
560         for (i = 0; i < 8; i++)
561                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
562 
563         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
564                          rtl8225z2_tx_gain_cck_ofdm[cck_power]);
565         msleep(1);
566 
567         /* anaparam2 on */
568         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
569         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
570         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
571                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
572         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
573                           RTL8187_RTL8225_ANAPARAM2_ON);
574         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
575                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
576         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
577 
578         rtl8225_write_phy_ofdm(dev, 2, 0x42);
579         rtl8225_write_phy_ofdm(dev, 5, 0x00);
580         rtl8225_write_phy_ofdm(dev, 6, 0x40);
581         rtl8225_write_phy_ofdm(dev, 7, 0x00);
582         rtl8225_write_phy_ofdm(dev, 8, 0x40);
583 
584         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
585                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
586         msleep(1);
587 }
588 
589 static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
590 {
591         struct rtl8187_priv *priv = dev->priv;
592         u8 cck_power, ofdm_power;
593         const u8 *tmp;
594         int i;
595 
596         cck_power = priv->channels[channel - 1].hw_value & 0xF;
597         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
598 
599         if (cck_power > 15)
600                 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
601         else
602                 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
603         cck_power += priv->txpwr_base & 0xF;
604         cck_power = min(cck_power, (u8)35);
605 
606         if (ofdm_power > 15)
607                 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
608         else
609                 ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
610         ofdm_power += (priv->txpwr_base >> 4) & 0xF;
611         ofdm_power = min(ofdm_power, (u8)35);
612 
613         if (channel == 14)
614                 tmp = rtl8225z2_tx_power_cck_ch14;
615         else
616                 tmp = rtl8225z2_tx_power_cck;
617 
618         if (priv->hw_rev == RTL8187BvB) {
619                 if (cck_power <= 6)
620                         ; /* do nothing */
621                 else if (cck_power <= 11)
622                         tmp += 8;
623                 else
624                         tmp += 16;
625         } else {
626                 if (cck_power <= 5)
627                         ; /* do nothing */
628                 else if (cck_power <= 11)
629                         tmp += 8;
630                 else if (cck_power <= 17)
631                         tmp += 16;
632                 else
633                         tmp += 24;
634         }
635 
636         for (i = 0; i < 8; i++)
637                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
638 
639         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
640                          rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
641         msleep(1);
642 
643         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
644                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
645         if (priv->hw_rev == RTL8187BvB) {
646                 if (ofdm_power <= 11) {
647                         rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
648                         rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
649                 } else {
650                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
651                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
652                 }
653         } else {
654                 if (ofdm_power <= 11) {
655                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
656                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
657                 } else if (ofdm_power <= 17) {
658                         rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
659                         rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
660                 } else {
661                         rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
662                         rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
663                 }
664         }
665         msleep(1);
666 }
667 
668 static const u16 rtl8225z2_rxgain[] = {
669         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
670         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
671         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
672         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
673         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
674         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
675         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
676         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
677         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
678         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
679         0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
680         0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
681 };
682 
683 static const u8 rtl8225z2_gain_bg[] = {
684         0x23, 0x15, 0xa5, /* -82-1dBm */
685         0x23, 0x15, 0xb5, /* -82-2dBm */
686         0x23, 0x15, 0xc5, /* -82-3dBm */
687         0x33, 0x15, 0xc5, /* -78dBm */
688         0x43, 0x15, 0xc5, /* -74dBm */
689         0x53, 0x15, 0xc5, /* -70dBm */
690         0x63, 0x15, 0xc5  /* -66dBm */
691 };
692 
693 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
694 {
695         struct rtl8187_priv *priv = dev->priv;
696         int i;
697 
698         rtl8225_write(dev, 0x0, 0x2BF);
699         rtl8225_write(dev, 0x1, 0xEE0);
700         rtl8225_write(dev, 0x2, 0x44D);
701         rtl8225_write(dev, 0x3, 0x441);
702         rtl8225_write(dev, 0x4, 0x8C3);
703         rtl8225_write(dev, 0x5, 0xC72);
704         rtl8225_write(dev, 0x6, 0x0E6);
705         rtl8225_write(dev, 0x7, 0x82A);
706         rtl8225_write(dev, 0x8, 0x03F);
707         rtl8225_write(dev, 0x9, 0x335);
708         rtl8225_write(dev, 0xa, 0x9D4);
709         rtl8225_write(dev, 0xb, 0x7BB);
710         rtl8225_write(dev, 0xc, 0x850);
711         rtl8225_write(dev, 0xd, 0xCDF);
712         rtl8225_write(dev, 0xe, 0x02B);
713         rtl8225_write(dev, 0xf, 0x114);
714         msleep(100);
715 
716         rtl8225_write(dev, 0x0, 0x1B7);
717 
718         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
719                 rtl8225_write(dev, 0x1, i + 1);
720                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
721         }
722 
723         rtl8225_write(dev, 0x3, 0x080);
724         rtl8225_write(dev, 0x5, 0x004);
725         rtl8225_write(dev, 0x0, 0x0B7);
726         rtl8225_write(dev, 0x2, 0xc4D);
727 
728         msleep(200);
729         rtl8225_write(dev, 0x2, 0x44D);
730         msleep(100);
731 
732         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
733                 rtl8225_write(dev, 0x02, 0x0C4D);
734                 msleep(200);
735                 rtl8225_write(dev, 0x02, 0x044D);
736                 msleep(100);
737                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
738                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
739                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
740         }
741 
742         msleep(200);
743 
744         rtl8225_write(dev, 0x0, 0x2BF);
745 
746         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
747                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
748                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
749         }
750 
751         msleep(1);
752 
753         rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
754         rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
755         rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
756         rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
757         rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
758         rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
759         rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
760         rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
761         rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
762         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
763         rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
764         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
765         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
766         rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
767         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
768         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
769         rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
770         rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
771         rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
772         rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
773         rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
774         rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
775         rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
776         rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
777         rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
778         rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
779         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
780         rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
781         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
782         rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
783         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
784         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
785         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
786         rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
787         rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
788         rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
789         rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
790         rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
791         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
792         rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
793 
794         rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
795         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
796         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
797         rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
798 
799         rtl8225_write_phy_cck(dev, 0x00, 0x98);
800         rtl8225_write_phy_cck(dev, 0x03, 0x20);
801         rtl8225_write_phy_cck(dev, 0x04, 0x7e);
802         rtl8225_write_phy_cck(dev, 0x05, 0x12);
803         rtl8225_write_phy_cck(dev, 0x06, 0xfc);
804         rtl8225_write_phy_cck(dev, 0x07, 0x78);
805         rtl8225_write_phy_cck(dev, 0x08, 0x2e);
806         rtl8225_write_phy_cck(dev, 0x10, 0x9b);
807         rtl8225_write_phy_cck(dev, 0x11, 0x88);
808         rtl8225_write_phy_cck(dev, 0x12, 0x47);
809         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
810         rtl8225_write_phy_cck(dev, 0x19, 0x00);
811         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
812         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
813         rtl8225_write_phy_cck(dev, 0x40, 0x86);
814         rtl8225_write_phy_cck(dev, 0x41, 0x8d);
815         rtl8225_write_phy_cck(dev, 0x42, 0x15);
816         rtl8225_write_phy_cck(dev, 0x43, 0x18);
817         rtl8225_write_phy_cck(dev, 0x44, 0x36);
818         rtl8225_write_phy_cck(dev, 0x45, 0x35);
819         rtl8225_write_phy_cck(dev, 0x46, 0x2e);
820         rtl8225_write_phy_cck(dev, 0x47, 0x25);
821         rtl8225_write_phy_cck(dev, 0x48, 0x1c);
822         rtl8225_write_phy_cck(dev, 0x49, 0x12);
823         rtl8225_write_phy_cck(dev, 0x4a, 0x09);
824         rtl8225_write_phy_cck(dev, 0x4b, 0x04);
825         rtl8225_write_phy_cck(dev, 0x4c, 0x05);
826 
827         rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
828 
829         rtl8225z2_rf_set_tx_power(dev, 1);
830 
831         /* RX antenna default to A */
832         rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
833         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
834 
835         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
836         msleep(1);
837         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
838 }
839 
840 static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
841 {
842         struct rtl8187_priv *priv = dev->priv;
843         int i;
844 
845         rtl8225_write(dev, 0x0, 0x0B7);
846         rtl8225_write(dev, 0x1, 0xEE0);
847         rtl8225_write(dev, 0x2, 0x44D);
848         rtl8225_write(dev, 0x3, 0x441);
849         rtl8225_write(dev, 0x4, 0x8C3);
850         rtl8225_write(dev, 0x5, 0xC72);
851         rtl8225_write(dev, 0x6, 0x0E6);
852         rtl8225_write(dev, 0x7, 0x82A);
853         rtl8225_write(dev, 0x8, 0x03F);
854         rtl8225_write(dev, 0x9, 0x335);
855         rtl8225_write(dev, 0xa, 0x9D4);
856         rtl8225_write(dev, 0xb, 0x7BB);
857         rtl8225_write(dev, 0xc, 0x850);
858         rtl8225_write(dev, 0xd, 0xCDF);
859         rtl8225_write(dev, 0xe, 0x02B);
860         rtl8225_write(dev, 0xf, 0x114);
861 
862         rtl8225_write(dev, 0x0, 0x1B7);
863 
864         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
865                 rtl8225_write(dev, 0x1, i + 1);
866                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
867         }
868 
869         rtl8225_write(dev, 0x3, 0x080);
870         rtl8225_write(dev, 0x5, 0x004);
871         rtl8225_write(dev, 0x0, 0x0B7);
872 
873         rtl8225_write(dev, 0x2, 0xC4D);
874 
875         rtl8225_write(dev, 0x2, 0x44D);
876         rtl8225_write(dev, 0x0, 0x2BF);
877 
878         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
879         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
880         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
881 
882         rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
883         for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
884                 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
885                 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
886                 rtl8225_write_phy_ofdm(dev, 0xE, 0);
887         }
888         rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
889 
890         for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
891                 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
892 
893         rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
894         rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
895         rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
896         rtl8225_write_phy_cck(dev, 0xc1, 0x88);
897 }
898 
899 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
900 {
901         u8 reg;
902         struct rtl8187_priv *priv = dev->priv;
903 
904         rtl8225_write(dev, 0x4, 0x1f);
905 
906         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
907         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
908         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
909         if (!priv->is_rtl8187b) {
910                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
911                                   RTL8187_RTL8225_ANAPARAM2_OFF);
912                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
913                                   RTL8187_RTL8225_ANAPARAM_OFF);
914         } else {
915                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
916                                   RTL8187B_RTL8225_ANAPARAM2_OFF);
917                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
918                                   RTL8187B_RTL8225_ANAPARAM_OFF);
919                 rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
920                                   RTL8187B_RTL8225_ANAPARAM3_OFF);
921         }
922         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
923         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
924 }
925 
926 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
927                                    struct ieee80211_conf *conf)
928 {
929         struct rtl8187_priv *priv = dev->priv;
930         int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
931 
932         if (priv->rf->init == rtl8225_rf_init)
933                 rtl8225_rf_set_tx_power(dev, chan);
934         else if (priv->rf->init == rtl8225z2_rf_init)
935                 rtl8225z2_rf_set_tx_power(dev, chan);
936         else
937                 rtl8225z2_b_rf_set_tx_power(dev, chan);
938 
939         rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
940         msleep(10);
941 }
942 
943 static const struct rtl818x_rf_ops rtl8225_ops = {
944         .name           = "rtl8225",
945         .init           = rtl8225_rf_init,
946         .stop           = rtl8225_rf_stop,
947         .set_chan       = rtl8225_rf_set_channel
948 };
949 
950 static const struct rtl818x_rf_ops rtl8225z2_ops = {
951         .name           = "rtl8225z2",
952         .init           = rtl8225z2_rf_init,
953         .stop           = rtl8225_rf_stop,
954         .set_chan       = rtl8225_rf_set_channel
955 };
956 
957 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
958         .name           = "rtl8225z2",
959         .init           = rtl8225z2_b_rf_init,
960         .stop           = rtl8225_rf_stop,
961         .set_chan       = rtl8225_rf_set_channel
962 };
963 
964 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
965 {
966         u16 reg8, reg9;
967         struct rtl8187_priv *priv = dev->priv;
968 
969         if (!priv->is_rtl8187b) {
970                 rtl8225_write(dev, 0, 0x1B7);
971 
972                 reg8 = rtl8225_read(dev, 8);
973                 reg9 = rtl8225_read(dev, 9);
974 
975                 rtl8225_write(dev, 0, 0x0B7);
976 
977                 if (reg8 != 0x588 || reg9 != 0x700)
978                         return &rtl8225_ops;
979 
980                 return &rtl8225z2_ops;
981         } else
982                 return &rtl8225z2_b_ops;
983 }
984 
  This page was automatically generated by the LXR engine.