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 /*
3  * Radio tuning for RTL8225 on RTL8180
4  *
5  * Copyright 2007 Michael Wu <[email protected]>
6  * Copyright 2007 Andrea Merello <[email protected]>
7  *
8  * Based on the r8180 driver, which is:
9  * Copyright 2005 Andrea Merello <[email protected]>, et al.
10  *
11  * Thanks to Realtek for their support!
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  */
17 
18 #include <linux/init.h>
19 #include <linux/pci.h>
20 #include <linux/delay.h>
21 #include <net/mac80211.h>
22 
23 #include "rtl8180.h"
24 #include "rtl8225.h"
25 
26 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
27 {
28  struct rtl8180_priv *priv = dev->priv;
29  u16 reg80, reg84, reg82;
30  u32 bangdata;
31  int i;
32 
33  bangdata = (data << 4) | (addr & 0xf);
34 
35  reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
36  reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
37 
38  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
39 
40  reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
41  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
42  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
43  udelay(10);
44 
45  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
46  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
47  udelay(2);
48  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
49  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
50  udelay(10);
51 
52  for (i = 15; i >= 0; i--) {
53  u16 reg = reg80;
54 
55  if (bangdata & (1 << i))
56  reg |= 1;
57 
58  if (i & 1)
59  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
60 
61  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
62  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
63 
64  if (!(i & 1))
65  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
66  }
67 
68  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
69  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
70  udelay(10);
71 
72  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
73  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
74  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
75 }
76 
77 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
78 {
79  struct rtl8180_priv *priv = dev->priv;
80  u16 reg80, reg82, reg84, out;
81  int i;
82 
83  reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
84  reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
85  reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
86 
87  reg80 &= ~0xF;
88 
89  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
90  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
91 
92  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
93  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
94  udelay(4);
95  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
96  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
97  udelay(5);
98 
99  for (i = 4; i >= 0; i--) {
100  u16 reg = reg80 | ((addr >> i) & 1);
101 
102  if (!(i & 1)) {
103  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
104  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
105  udelay(1);
106  }
107 
108  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
109  reg | (1 << 1));
110  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
111  udelay(2);
112  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
113  reg | (1 << 1));
114  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
115  udelay(2);
116 
117  if (i & 1) {
118  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
119  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
120  udelay(1);
121  }
122  }
123 
124  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
125  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
126  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
127  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
128  reg80 | (1 << 3) | (1 << 1));
129  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
130  udelay(2);
131  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
132  reg80 | (1 << 3));
133  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
134  udelay(2);
135  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
136  reg80 | (1 << 3));
137  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
138  udelay(2);
139 
140  out = 0;
141  for (i = 11; i >= 0; i--) {
142  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
143  reg80 | (1 << 3));
144  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
145  udelay(1);
146  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
147  reg80 | (1 << 3) | (1 << 1));
148  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
149  udelay(2);
150  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
151  reg80 | (1 << 3) | (1 << 1));
152  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
153  udelay(2);
154  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
155  reg80 | (1 << 3) | (1 << 1));
156  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
157  udelay(2);
158 
159  if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
160  out |= 1 << i;
161 
162  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
163  reg80 | (1 << 3));
164  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
165  udelay(2);
166  }
167 
168  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
169  reg80 | (1 << 3) | (1 << 2));
170  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
171  udelay(2);
172 
173  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
174  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
175  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
176 
177  return out;
178 }
179 
180 static const u16 rtl8225bcd_rxgain[] = {
181  0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
182  0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
183  0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
184  0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
185  0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
186  0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
187  0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
188  0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
189  0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
190  0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
191  0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
192  0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
193 };
194 
195 static const u8 rtl8225_agc[] = {
196  0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
197  0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
198  0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
199  0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
200  0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
201  0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
202  0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
203  0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
204  0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
205  0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
206  0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
207  0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
208  0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
209  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
210  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
211  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
212 };
213 
214 static const u8 rtl8225_gain[] = {
215  0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
216  0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
217  0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
218  0x33, 0x80, 0x79, 0xc5, /* -78dbm */
219  0x43, 0x78, 0x76, 0xc5, /* -74dbm */
220  0x53, 0x60, 0x73, 0xc5, /* -70dbm */
221  0x63, 0x58, 0x70, 0xc5, /* -66dbm */
222 };
223 
224 static const u8 rtl8225_threshold[] = {
225  0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
226 };
227 
228 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
229  0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
230 };
231 
232 static const u8 rtl8225_tx_power_cck[] = {
233  0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
234  0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
235  0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
236  0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
237  0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
238  0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
239 };
240 
241 static const u8 rtl8225_tx_power_cck_ch14[] = {
242  0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
243  0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
244  0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
245  0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
246  0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
247  0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
248 };
249 
250 static const u8 rtl8225_tx_power_ofdm[] = {
251  0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
252 };
253 
254 static const u32 rtl8225_chan[] = {
255  0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
256  0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
257 };
258 
259 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
260 {
261  struct rtl8180_priv *priv = dev->priv;
262  u8 cck_power, ofdm_power;
263  const u8 *tmp;
264  u32 reg;
265  int i;
266 
267  cck_power = priv->channels[channel - 1].hw_value & 0xFF;
268  ofdm_power = priv->channels[channel - 1].hw_value >> 8;
269 
270  cck_power = min(cck_power, (u8)35);
271  ofdm_power = min(ofdm_power, (u8)35);
272 
273  rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
274  rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
275 
276  if (channel == 14)
277  tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
278  else
279  tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
280 
281  for (i = 0; i < 8; i++)
282  rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
283 
284  msleep(1); /* FIXME: optional? */
285 
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 
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 
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 = ieee80211_frequency_to_channel(conf->channel->center_freq);
723 
724  if (priv->rf->init == rtl8225_rf_init)
725  rtl8225_rf_set_tx_power(dev, chan);
726  else
727  rtl8225z2_rf_set_tx_power(dev, chan);
728 
729  rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
730  msleep(10);
731 }
732 
733 static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
734  struct ieee80211_bss_conf *info)
735 {
736  struct rtl8180_priv *priv = dev->priv;
737 
738  if (info->use_short_slot) {
739  rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
740  rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
741  rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
742  rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
743  rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
744  } else {
745  rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
746  rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
747  rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
748  rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
749  rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
750  }
751 }
752 
753 static const struct rtl818x_rf_ops rtl8225_ops = {
754  .name = "rtl8225",
755  .init = rtl8225_rf_init,
756  .stop = rtl8225_rf_stop,
757  .set_chan = rtl8225_rf_set_channel,
758  .conf_erp = rtl8225_rf_conf_erp,
759 };
760 
761 static const struct rtl818x_rf_ops rtl8225z2_ops = {
762  .name = "rtl8225z2",
763  .init = rtl8225z2_rf_init,
764  .stop = rtl8225_rf_stop,
765  .set_chan = rtl8225_rf_set_channel,
766  .conf_erp = rtl8225_rf_conf_erp,
767 };
768 
769 const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
770 {
771  struct rtl8180_priv *priv = dev->priv;
772  u16 reg8, reg9;
773 
774  rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
775  rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
776  rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
777  rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
778  msleep(100);
779 
780  rtl8225_write(dev, 0, 0x1B7);
781 
782  reg8 = rtl8225_read(dev, 8);
783  reg9 = rtl8225_read(dev, 9);
784 
785  rtl8225_write(dev, 0, 0x0B7);
786 
787  if (reg8 != 0x588 || reg9 != 0x700)
788  return &rtl8225_ops;
789 
790  return &rtl8225z2_ops;
791 }