Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl8225.c
Go to the documentation of this file.
1 /*
2  * Radio tuning for RTL8225 on RTL8187
3  *
4  * Copyright 2007 Michael Wu <[email protected]>
5  * Copyright 2007 Andrea Merello <[email protected]>
6  *
7  * Based on the r8187 driver, which is:
8  * Copyright 2005 Andrea Merello <[email protected]>, 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 "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),
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,
317  rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
319  rtl818x_iowrite8(priv, &priv->map->CONFIG3,
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  wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
370  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,
572  rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
574  rtl818x_iowrite8(priv, &priv->map->CONFIG3,
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  wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
739  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  rtl8225_write(dev, 0x4, 0x1f);
902 }
903 
904 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
905  struct ieee80211_conf *conf)
906 {
907  struct rtl8187_priv *priv = dev->priv;
908  int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
909 
910  if (priv->rf->init == rtl8225_rf_init)
911  rtl8225_rf_set_tx_power(dev, chan);
912  else if (priv->rf->init == rtl8225z2_rf_init)
913  rtl8225z2_rf_set_tx_power(dev, chan);
914  else
915  rtl8225z2_b_rf_set_tx_power(dev, chan);
916 
917  rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
918  msleep(10);
919 }
920 
921 static const struct rtl818x_rf_ops rtl8225_ops = {
922  .name = "rtl8225",
923  .init = rtl8225_rf_init,
924  .stop = rtl8225_rf_stop,
925  .set_chan = rtl8225_rf_set_channel
926 };
927 
928 static const struct rtl818x_rf_ops rtl8225z2_ops = {
929  .name = "rtl8225z2",
930  .init = rtl8225z2_rf_init,
931  .stop = rtl8225_rf_stop,
932  .set_chan = rtl8225_rf_set_channel
933 };
934 
935 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
936  .name = "rtl8225z2",
937  .init = rtl8225z2_b_rf_init,
938  .stop = rtl8225_rf_stop,
939  .set_chan = rtl8225_rf_set_channel
940 };
941 
942 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
943 {
944  u16 reg8, reg9;
945  struct rtl8187_priv *priv = dev->priv;
946 
947  if (!priv->is_rtl8187b) {
948  rtl8225_write(dev, 0, 0x1B7);
949 
950  reg8 = rtl8225_read(dev, 8);
951  reg9 = rtl8225_read(dev, 9);
952 
953  rtl8225_write(dev, 0, 0x0B7);
954 
955  if (reg8 != 0x588 || reg9 != 0x700)
956  return &rtl8225_ops;
957 
958  return &rtl8225z2_ops;
959  } else
960  return &rtl8225z2_b_ops;
961 }