blob: 78df281b297a4604fd2e10e8b3bf67d3f9c1990a [file] [log] [blame]
Michael Wu605bebe2007-05-14 01:41:02 -04001/*
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 *
John W. Linville0aec00a2007-06-12 22:11:42 -040010 * 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!
Michael Wu605bebe2007-05-14 01:41:02 -040013 *
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
26static 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);
Michael Wu605bebe2007-05-14 01:41:02 -040067}
68
Michael Wu899413d2007-06-14 00:33:48 -070069static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
Michael Wu605bebe2007-05-14 01:41:02 -040070{
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 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
92 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
93 addr, 0x8225, &data, sizeof(data), HZ / 2);
94
95 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
96 udelay(10);
97
98 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
99 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
Michael Wu605bebe2007-05-14 01:41:02 -0400100}
101
Michael Wuf6532112007-10-14 14:43:16 -0400102static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
Michael Wu605bebe2007-05-14 01:41:02 -0400103{
104 struct rtl8187_priv *priv = dev->priv;
105
106 if (priv->asic_rev)
Michael Wu899413d2007-06-14 00:33:48 -0700107 rtl8225_write_8051(dev, addr, cpu_to_le16(data));
Michael Wu605bebe2007-05-14 01:41:02 -0400108 else
109 rtl8225_write_bitbang(dev, addr, data);
110}
111
Michael Wuf6532112007-10-14 14:43:16 -0400112static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
Michael Wu605bebe2007-05-14 01:41:02 -0400113{
114 struct rtl8187_priv *priv = dev->priv;
115 u16 reg80, reg82, reg84, out;
116 int i;
117
118 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
119 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
120 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
121
122 reg80 &= ~0xF;
123
124 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
125 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
126
127 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
128 udelay(4);
129 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
130 udelay(5);
131
132 for (i = 4; i >= 0; i--) {
133 u16 reg = reg80 | ((addr >> i) & 1);
134
135 if (!(i & 1)) {
136 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
137 udelay(1);
138 }
139
140 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
141 reg | (1 << 1));
142 udelay(2);
143 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
144 reg | (1 << 1));
145 udelay(2);
146
147 if (i & 1) {
148 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
149 udelay(1);
150 }
151 }
152
153 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
154 reg80 | (1 << 3) | (1 << 1));
155 udelay(2);
156 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
157 reg80 | (1 << 3));
158 udelay(2);
159 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
160 reg80 | (1 << 3));
161 udelay(2);
162
163 out = 0;
164 for (i = 11; i >= 0; i--) {
165 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
166 reg80 | (1 << 3));
167 udelay(1);
168 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
169 reg80 | (1 << 3) | (1 << 1));
170 udelay(2);
171 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
172 reg80 | (1 << 3) | (1 << 1));
173 udelay(2);
174 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
175 reg80 | (1 << 3) | (1 << 1));
176 udelay(2);
177
178 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
179 out |= 1 << i;
180
181 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
182 reg80 | (1 << 3));
183 udelay(2);
184 }
185
186 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
187 reg80 | (1 << 3) | (1 << 2));
188 udelay(2);
189
190 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
191 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
192 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
193
194 return out;
195}
196
197static const u16 rtl8225bcd_rxgain[] = {
198 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
199 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
200 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
201 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
202 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
203 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
204 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
205 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
206 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
207 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
208 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
209 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
210};
211
212static const u8 rtl8225_agc[] = {
213 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
214 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
215 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
216 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
217 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
218 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
219 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
220 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
221 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
222 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
223 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
224 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
225 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
226 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
227 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
228 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
229};
230
231static const u8 rtl8225_gain[] = {
232 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
233 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
234 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
235 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
236 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
237 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
238 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
239};
240
241static const u8 rtl8225_threshold[] = {
242 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
243};
244
245static const u8 rtl8225_tx_gain_cck_ofdm[] = {
246 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
247};
248
249static const u8 rtl8225_tx_power_cck[] = {
250 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
251 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
252 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
253 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
254 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
255 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
256};
257
258static const u8 rtl8225_tx_power_cck_ch14[] = {
259 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
260 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
261 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
262 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
263 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
264 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
265};
266
267static const u8 rtl8225_tx_power_ofdm[] = {
268 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
269};
270
271static const u32 rtl8225_chan[] = {
272 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
273 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
274};
275
276static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
277{
278 struct rtl8187_priv *priv = dev->priv;
279 u8 cck_power, ofdm_power;
280 const u8 *tmp;
281 u32 reg;
282 int i;
283
Johannes Berg8318d782008-01-24 19:38:38 +0100284 cck_power = priv->channels[channel - 1].hw_value & 0xF;
285 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
Michael Wu605bebe2007-05-14 01:41:02 -0400286
287 cck_power = min(cck_power, (u8)11);
Larry Fingereb83bbf2009-01-27 12:31:23 -0600288 if (ofdm_power > (u8)15)
289 ofdm_power = 25;
290 else
291 ofdm_power += 10;
Michael Wu605bebe2007-05-14 01:41:02 -0400292
293 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
294 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
295
296 if (channel == 14)
297 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
298 else
299 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
300
301 for (i = 0; i < 8; i++)
302 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
303
304 msleep(1); // FIXME: optional?
305
306 /* anaparam2 on */
307 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
308 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100309 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
310 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
Herton Ronaldo Krzesinski4ece16a2008-07-10 18:55:23 -0300311 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
312 RTL8187_RTL8225_ANAPARAM2_ON);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100313 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
314 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
Michael Wu605bebe2007-05-14 01:41:02 -0400315 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
316
317 rtl8225_write_phy_ofdm(dev, 2, 0x42);
318 rtl8225_write_phy_ofdm(dev, 6, 0x00);
319 rtl8225_write_phy_ofdm(dev, 8, 0x00);
320
321 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
322 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
323
324 tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
325
326 rtl8225_write_phy_ofdm(dev, 5, *tmp);
327 rtl8225_write_phy_ofdm(dev, 7, *tmp);
328
329 msleep(1);
330}
331
Michael Wuf6532112007-10-14 14:43:16 -0400332static void rtl8225_rf_init(struct ieee80211_hw *dev)
Michael Wu605bebe2007-05-14 01:41:02 -0400333{
334 struct rtl8187_priv *priv = dev->priv;
335 int i;
336
Larry Finger946d1c22008-10-31 09:54:13 -0700337 rtl8225_write(dev, 0x0, 0x067);
338 rtl8225_write(dev, 0x1, 0xFE0);
339 rtl8225_write(dev, 0x2, 0x44D);
340 rtl8225_write(dev, 0x3, 0x441);
341 rtl8225_write(dev, 0x4, 0x486);
342 rtl8225_write(dev, 0x5, 0xBC0);
343 rtl8225_write(dev, 0x6, 0xAE6);
344 rtl8225_write(dev, 0x7, 0x82A);
345 rtl8225_write(dev, 0x8, 0x01F);
346 rtl8225_write(dev, 0x9, 0x334);
347 rtl8225_write(dev, 0xA, 0xFD4);
348 rtl8225_write(dev, 0xB, 0x391);
349 rtl8225_write(dev, 0xC, 0x050);
350 rtl8225_write(dev, 0xD, 0x6DB);
351 rtl8225_write(dev, 0xE, 0x029);
Michael Wu605bebe2007-05-14 01:41:02 -0400352 rtl8225_write(dev, 0xF, 0x914); msleep(100);
353
354 rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
355 rtl8225_write(dev, 0x2, 0x44D); msleep(200);
356
357 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
358 rtl8225_write(dev, 0x02, 0x0c4d);
359 msleep(200);
360 rtl8225_write(dev, 0x02, 0x044d);
361 msleep(100);
362 if (!(rtl8225_read(dev, 6) & (1 << 7)))
363 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
364 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
365 }
366
367 rtl8225_write(dev, 0x0, 0x127);
368
369 for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
370 rtl8225_write(dev, 0x1, i + 1);
371 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
372 }
373
374 rtl8225_write(dev, 0x0, 0x027);
375 rtl8225_write(dev, 0x0, 0x22F);
376
377 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
378 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
Michael Wu605bebe2007-05-14 01:41:02 -0400379 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
Michael Wu605bebe2007-05-14 01:41:02 -0400380 }
381
382 msleep(1);
383
Larry Finger35cc9882008-10-31 09:52:39 -0700384 rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
385 rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
386 rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
387 rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
388 rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
389 rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
390 rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
391 rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
392 rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
393 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
394 rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
395 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
396 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
397 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
398 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
399 rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
400 rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
401 rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
402 rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
403 rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
404 rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
405 rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
406 rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
407 rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
408 rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
409 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
410 rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
411 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
412 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
413 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
414 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
415 rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
416 rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
417 rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
418 rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
419 rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
420 rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
Michael Wu605bebe2007-05-14 01:41:02 -0400421
422 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
423 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
424 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
425 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
426
Larry Fingera3d67bc2008-10-31 09:52:58 -0700427 rtl8225_write_phy_cck(dev, 0x00, 0x98);
428 rtl8225_write_phy_cck(dev, 0x03, 0x20);
429 rtl8225_write_phy_cck(dev, 0x04, 0x7e);
430 rtl8225_write_phy_cck(dev, 0x05, 0x12);
431 rtl8225_write_phy_cck(dev, 0x06, 0xfc);
432 rtl8225_write_phy_cck(dev, 0x07, 0x78);
433 rtl8225_write_phy_cck(dev, 0x08, 0x2e);
434 rtl8225_write_phy_cck(dev, 0x10, 0x9b);
435 rtl8225_write_phy_cck(dev, 0x11, 0x88);
436 rtl8225_write_phy_cck(dev, 0x12, 0x47);
Michael Wu605bebe2007-05-14 01:41:02 -0400437 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
438 rtl8225_write_phy_cck(dev, 0x19, 0x00);
439 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
440 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
441 rtl8225_write_phy_cck(dev, 0x40, 0x86);
Larry Fingera3d67bc2008-10-31 09:52:58 -0700442 rtl8225_write_phy_cck(dev, 0x41, 0x8d);
443 rtl8225_write_phy_cck(dev, 0x42, 0x15);
444 rtl8225_write_phy_cck(dev, 0x43, 0x18);
445 rtl8225_write_phy_cck(dev, 0x44, 0x1f);
446 rtl8225_write_phy_cck(dev, 0x45, 0x1e);
447 rtl8225_write_phy_cck(dev, 0x46, 0x1a);
448 rtl8225_write_phy_cck(dev, 0x47, 0x15);
449 rtl8225_write_phy_cck(dev, 0x48, 0x10);
450 rtl8225_write_phy_cck(dev, 0x49, 0x0a);
451 rtl8225_write_phy_cck(dev, 0x4a, 0x05);
452 rtl8225_write_phy_cck(dev, 0x4b, 0x02);
453 rtl8225_write_phy_cck(dev, 0x4c, 0x05);
Michael Wu605bebe2007-05-14 01:41:02 -0400454
455 rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
456
457 rtl8225_rf_set_tx_power(dev, 1);
458
459 /* RX antenna default to A */
Larry Fingera3d67bc2008-10-31 09:52:58 -0700460 rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
Larry Finger35cc9882008-10-31 09:52:39 -0700461 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
Michael Wu605bebe2007-05-14 01:41:02 -0400462
463 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
464 msleep(1);
465 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
466
467 /* set sensitivity */
468 rtl8225_write(dev, 0x0c, 0x50);
469 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
470 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
471 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
472 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
473 rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
474}
475
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100476static const u8 rtl8225z2_agc[] = {
477 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
478 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
479 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
480 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
481 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
482 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
483 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
484 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
485 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
486 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
487 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
488};
489static const u8 rtl8225z2_ofdm[] = {
490 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
491 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
492 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
493 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
494 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
495 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
496 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
497 0x6d, 0x3c, 0xfb, 0x07
498};
499
Michael Wu605bebe2007-05-14 01:41:02 -0400500static const u8 rtl8225z2_tx_power_cck_ch14[] = {
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100501 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
502 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
503 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
504 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
Michael Wu605bebe2007-05-14 01:41:02 -0400505};
506
507static const u8 rtl8225z2_tx_power_cck[] = {
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100508 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
509 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
510 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
511 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
Michael Wu605bebe2007-05-14 01:41:02 -0400512};
513
514static const u8 rtl8225z2_tx_power_ofdm[] = {
515 0x42, 0x00, 0x40, 0x00, 0x40
516};
517
518static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
519 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
520 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
521 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
522 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
523 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
524 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
525};
526
527static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
528{
529 struct rtl8187_priv *priv = dev->priv;
530 u8 cck_power, ofdm_power;
531 const u8 *tmp;
532 u32 reg;
533 int i;
534
Johannes Berg8318d782008-01-24 19:38:38 +0100535 cck_power = priv->channels[channel - 1].hw_value & 0xF;
536 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
Michael Wu605bebe2007-05-14 01:41:02 -0400537
538 cck_power = min(cck_power, (u8)15);
539 cck_power += priv->txpwr_base & 0xF;
540 cck_power = min(cck_power, (u8)35);
541
Larry Fingereb83bbf2009-01-27 12:31:23 -0600542 if (ofdm_power > (u8)15)
543 ofdm_power = 25;
544 else
545 ofdm_power += 10;
Michael Wu605bebe2007-05-14 01:41:02 -0400546 ofdm_power += priv->txpwr_base >> 4;
547 ofdm_power = min(ofdm_power, (u8)35);
548
549 if (channel == 14)
550 tmp = rtl8225z2_tx_power_cck_ch14;
551 else
552 tmp = rtl8225z2_tx_power_cck;
553
554 for (i = 0; i < 8; i++)
555 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
556
557 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
558 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
559 msleep(1);
560
561 /* anaparam2 on */
562 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
563 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100564 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
565 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
Herton Ronaldo Krzesinski4ece16a2008-07-10 18:55:23 -0300566 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
567 RTL8187_RTL8225_ANAPARAM2_ON);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100568 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
569 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
Michael Wu605bebe2007-05-14 01:41:02 -0400570 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
571
572 rtl8225_write_phy_ofdm(dev, 2, 0x42);
573 rtl8225_write_phy_ofdm(dev, 5, 0x00);
574 rtl8225_write_phy_ofdm(dev, 6, 0x40);
575 rtl8225_write_phy_ofdm(dev, 7, 0x00);
576 rtl8225_write_phy_ofdm(dev, 8, 0x40);
577
578 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
579 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
580 msleep(1);
581}
582
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100583static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
584{
585 struct rtl8187_priv *priv = dev->priv;
586 u8 cck_power, ofdm_power;
587 const u8 *tmp;
588 int i;
589
590 cck_power = priv->channels[channel - 1].hw_value & 0xF;
591 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
592
593 if (cck_power > 15)
594 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
595 else
596 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
597 cck_power += priv->txpwr_base & 0xF;
598 cck_power = min(cck_power, (u8)35);
599
600 if (ofdm_power > 15)
601 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
602 else
603 ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
604 ofdm_power += (priv->txpwr_base >> 4) & 0xF;
605 ofdm_power = min(ofdm_power, (u8)35);
606
607 if (channel == 14)
608 tmp = rtl8225z2_tx_power_cck_ch14;
609 else
610 tmp = rtl8225z2_tx_power_cck;
611
612 if (priv->hw_rev == RTL8187BvB) {
613 if (cck_power <= 6)
614 ; /* do nothing */
615 else if (cck_power <= 11)
616 tmp += 8;
617 else
618 tmp += 16;
619 } else {
620 if (cck_power <= 5)
621 ; /* do nothing */
622 else if (cck_power <= 11)
623 tmp += 8;
624 else if (cck_power <= 17)
625 tmp += 16;
626 else
627 tmp += 24;
628 }
629
630 for (i = 0; i < 8; i++)
631 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
632
633 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
Larry Fingerc4832462008-10-31 09:40:44 -0700634 rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100635 msleep(1);
636
637 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
638 rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
639 if (priv->hw_rev == RTL8187BvB) {
640 if (ofdm_power <= 11) {
641 rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
642 rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
643 } else {
644 rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
645 rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
646 }
647 } else {
648 if (ofdm_power <= 11) {
649 rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
650 rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
651 } else if (ofdm_power <= 17) {
652 rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
653 rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
654 } else {
655 rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
656 rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
657 }
658 }
659 msleep(1);
660}
661
Michael Wu605bebe2007-05-14 01:41:02 -0400662static const u16 rtl8225z2_rxgain[] = {
663 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
664 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
665 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
666 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
667 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
668 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
669 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
670 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
671 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
672 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
673 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
674 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
675};
676
677static const u8 rtl8225z2_gain_bg[] = {
678 0x23, 0x15, 0xa5, /* -82-1dBm */
679 0x23, 0x15, 0xb5, /* -82-2dBm */
680 0x23, 0x15, 0xc5, /* -82-3dBm */
681 0x33, 0x15, 0xc5, /* -78dBm */
682 0x43, 0x15, 0xc5, /* -74dBm */
683 0x53, 0x15, 0xc5, /* -70dBm */
684 0x63, 0x15, 0xc5 /* -66dBm */
685};
686
Michael Wuf6532112007-10-14 14:43:16 -0400687static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
Michael Wu605bebe2007-05-14 01:41:02 -0400688{
689 struct rtl8187_priv *priv = dev->priv;
690 int i;
691
Larry Finger946d1c22008-10-31 09:54:13 -0700692 rtl8225_write(dev, 0x0, 0x2BF);
693 rtl8225_write(dev, 0x1, 0xEE0);
694 rtl8225_write(dev, 0x2, 0x44D);
695 rtl8225_write(dev, 0x3, 0x441);
696 rtl8225_write(dev, 0x4, 0x8C3);
697 rtl8225_write(dev, 0x5, 0xC72);
698 rtl8225_write(dev, 0x6, 0x0E6);
699 rtl8225_write(dev, 0x7, 0x82A);
700 rtl8225_write(dev, 0x8, 0x03F);
701 rtl8225_write(dev, 0x9, 0x335);
702 rtl8225_write(dev, 0xa, 0x9D4);
703 rtl8225_write(dev, 0xb, 0x7BB);
704 rtl8225_write(dev, 0xc, 0x850);
705 rtl8225_write(dev, 0xd, 0xCDF);
706 rtl8225_write(dev, 0xe, 0x02B);
707 rtl8225_write(dev, 0xf, 0x114);
708 msleep(100);
Michael Wu605bebe2007-05-14 01:41:02 -0400709
710 rtl8225_write(dev, 0x0, 0x1B7);
711
712 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
713 rtl8225_write(dev, 0x1, i + 1);
714 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
715 }
716
717 rtl8225_write(dev, 0x3, 0x080);
718 rtl8225_write(dev, 0x5, 0x004);
719 rtl8225_write(dev, 0x0, 0x0B7);
720 rtl8225_write(dev, 0x2, 0xc4D);
721
722 msleep(200);
723 rtl8225_write(dev, 0x2, 0x44D);
724 msleep(100);
725
726 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
727 rtl8225_write(dev, 0x02, 0x0C4D);
728 msleep(200);
729 rtl8225_write(dev, 0x02, 0x044D);
730 msleep(100);
731 if (!(rtl8225_read(dev, 6) & (1 << 7)))
732 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
733 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
734 }
735
736 msleep(200);
737
738 rtl8225_write(dev, 0x0, 0x2BF);
739
740 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
741 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
Michael Wu605bebe2007-05-14 01:41:02 -0400742 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
Michael Wu605bebe2007-05-14 01:41:02 -0400743 }
744
745 msleep(1);
746
Larry Finger35cc9882008-10-31 09:52:39 -0700747 rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
748 rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
749 rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
750 rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
751 rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
752 rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
753 rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
754 rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
755 rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
756 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
757 rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
758 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
759 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
Michael Wu605bebe2007-05-14 01:41:02 -0400760 rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
Larry Finger35cc9882008-10-31 09:52:39 -0700761 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
762 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
763 rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
764 rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
765 rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
766 rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
767 rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
768 rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
769 rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
770 rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
771 rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
772 rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
773 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
774 rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
775 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
776 rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
777 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
778 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
779 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
780 rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
781 rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
782 rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
783 rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
784 rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
785 rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
786 rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
Michael Wu605bebe2007-05-14 01:41:02 -0400787
788 rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
789 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
790 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
791 rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
792
Larry Fingera3d67bc2008-10-31 09:52:58 -0700793 rtl8225_write_phy_cck(dev, 0x00, 0x98);
794 rtl8225_write_phy_cck(dev, 0x03, 0x20);
795 rtl8225_write_phy_cck(dev, 0x04, 0x7e);
796 rtl8225_write_phy_cck(dev, 0x05, 0x12);
797 rtl8225_write_phy_cck(dev, 0x06, 0xfc);
798 rtl8225_write_phy_cck(dev, 0x07, 0x78);
799 rtl8225_write_phy_cck(dev, 0x08, 0x2e);
800 rtl8225_write_phy_cck(dev, 0x10, 0x9b);
801 rtl8225_write_phy_cck(dev, 0x11, 0x88);
802 rtl8225_write_phy_cck(dev, 0x12, 0x47);
Michael Wu605bebe2007-05-14 01:41:02 -0400803 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
804 rtl8225_write_phy_cck(dev, 0x19, 0x00);
805 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
806 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
807 rtl8225_write_phy_cck(dev, 0x40, 0x86);
Larry Fingera3d67bc2008-10-31 09:52:58 -0700808 rtl8225_write_phy_cck(dev, 0x41, 0x8d);
809 rtl8225_write_phy_cck(dev, 0x42, 0x15);
810 rtl8225_write_phy_cck(dev, 0x43, 0x18);
811 rtl8225_write_phy_cck(dev, 0x44, 0x36);
812 rtl8225_write_phy_cck(dev, 0x45, 0x35);
813 rtl8225_write_phy_cck(dev, 0x46, 0x2e);
814 rtl8225_write_phy_cck(dev, 0x47, 0x25);
815 rtl8225_write_phy_cck(dev, 0x48, 0x1c);
816 rtl8225_write_phy_cck(dev, 0x49, 0x12);
817 rtl8225_write_phy_cck(dev, 0x4a, 0x09);
818 rtl8225_write_phy_cck(dev, 0x4b, 0x04);
819 rtl8225_write_phy_cck(dev, 0x4c, 0x05);
Michael Wu605bebe2007-05-14 01:41:02 -0400820
821 rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
822
823 rtl8225z2_rf_set_tx_power(dev, 1);
824
825 /* RX antenna default to A */
Larry Fingera3d67bc2008-10-31 09:52:58 -0700826 rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
Larry Finger35cc9882008-10-31 09:52:39 -0700827 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
Michael Wu605bebe2007-05-14 01:41:02 -0400828
829 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
830 msleep(1);
831 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
832}
833
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100834static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
835{
836 struct rtl8187_priv *priv = dev->priv;
837 int i;
838
Larry Finger946d1c22008-10-31 09:54:13 -0700839 rtl8225_write(dev, 0x0, 0x0B7);
840 rtl8225_write(dev, 0x1, 0xEE0);
841 rtl8225_write(dev, 0x2, 0x44D);
842 rtl8225_write(dev, 0x3, 0x441);
843 rtl8225_write(dev, 0x4, 0x8C3);
844 rtl8225_write(dev, 0x5, 0xC72);
845 rtl8225_write(dev, 0x6, 0x0E6);
846 rtl8225_write(dev, 0x7, 0x82A);
847 rtl8225_write(dev, 0x8, 0x03F);
848 rtl8225_write(dev, 0x9, 0x335);
849 rtl8225_write(dev, 0xa, 0x9D4);
850 rtl8225_write(dev, 0xb, 0x7BB);
851 rtl8225_write(dev, 0xc, 0x850);
852 rtl8225_write(dev, 0xd, 0xCDF);
853 rtl8225_write(dev, 0xe, 0x02B);
854 rtl8225_write(dev, 0xf, 0x114);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100855
Larry Finger946d1c22008-10-31 09:54:13 -0700856 rtl8225_write(dev, 0x0, 0x1B7);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100857
858 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
Larry Finger946d1c22008-10-31 09:54:13 -0700859 rtl8225_write(dev, 0x1, i + 1);
860 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100861 }
862
Larry Finger946d1c22008-10-31 09:54:13 -0700863 rtl8225_write(dev, 0x3, 0x080);
864 rtl8225_write(dev, 0x5, 0x004);
865 rtl8225_write(dev, 0x0, 0x0B7);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100866
Larry Finger946d1c22008-10-31 09:54:13 -0700867 rtl8225_write(dev, 0x2, 0xC4D);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100868
Larry Finger946d1c22008-10-31 09:54:13 -0700869 rtl8225_write(dev, 0x2, 0x44D);
870 rtl8225_write(dev, 0x0, 0x2BF);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100871
872 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
873 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
874 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
875
876 rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
877 for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
878 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
879 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
880 rtl8225_write_phy_ofdm(dev, 0xE, 0);
881 }
882 rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
883
884 for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
885 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
886
Larry Finger35cc9882008-10-31 09:52:39 -0700887 rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
888 rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
889 rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
890 rtl8225_write_phy_cck(dev, 0xc1, 0x88);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100891}
892
Michael Wuf6532112007-10-14 14:43:16 -0400893static void rtl8225_rf_stop(struct ieee80211_hw *dev)
Michael Wu605bebe2007-05-14 01:41:02 -0400894{
895 u8 reg;
896 struct rtl8187_priv *priv = dev->priv;
897
Larry Finger946d1c22008-10-31 09:54:13 -0700898 rtl8225_write(dev, 0x4, 0x1f);
Michael Wu605bebe2007-05-14 01:41:02 -0400899
900 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
901 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
902 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
Herton Ronaldo Krzesinski4ece16a2008-07-10 18:55:23 -0300903 if (!priv->is_rtl8187b) {
904 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
905 RTL8187_RTL8225_ANAPARAM2_OFF);
906 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
907 RTL8187_RTL8225_ANAPARAM_OFF);
908 } else {
909 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
910 RTL8187B_RTL8225_ANAPARAM2_OFF);
911 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
912 RTL8187B_RTL8225_ANAPARAM_OFF);
913 rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
914 RTL8187B_RTL8225_ANAPARAM3_OFF);
915 }
Michael Wu605bebe2007-05-14 01:41:02 -0400916 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
917 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
918}
919
Michael Wuf6532112007-10-14 14:43:16 -0400920static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
921 struct ieee80211_conf *conf)
Michael Wu605bebe2007-05-14 01:41:02 -0400922{
923 struct rtl8187_priv *priv = dev->priv;
Johannes Berg8318d782008-01-24 19:38:38 +0100924 int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
Michael Wu605bebe2007-05-14 01:41:02 -0400925
Michael Wuf6532112007-10-14 14:43:16 -0400926 if (priv->rf->init == rtl8225_rf_init)
Johannes Berg8318d782008-01-24 19:38:38 +0100927 rtl8225_rf_set_tx_power(dev, chan);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100928 else if (priv->rf->init == rtl8225z2_rf_init)
Johannes Berg8318d782008-01-24 19:38:38 +0100929 rtl8225z2_rf_set_tx_power(dev, chan);
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100930 else
931 rtl8225z2_b_rf_set_tx_power(dev, chan);
Michael Wu605bebe2007-05-14 01:41:02 -0400932
Johannes Berg8318d782008-01-24 19:38:38 +0100933 rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
Michael Wu605bebe2007-05-14 01:41:02 -0400934 msleep(10);
935}
Michael Wuf6532112007-10-14 14:43:16 -0400936
937static const struct rtl818x_rf_ops rtl8225_ops = {
938 .name = "rtl8225",
939 .init = rtl8225_rf_init,
940 .stop = rtl8225_rf_stop,
941 .set_chan = rtl8225_rf_set_channel
942};
943
944static const struct rtl818x_rf_ops rtl8225z2_ops = {
945 .name = "rtl8225z2",
946 .init = rtl8225z2_rf_init,
947 .stop = rtl8225_rf_stop,
948 .set_chan = rtl8225_rf_set_channel
949};
950
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100951static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
952 .name = "rtl8225z2",
953 .init = rtl8225z2_b_rf_init,
954 .stop = rtl8225_rf_stop,
955 .set_chan = rtl8225_rf_set_channel
956};
957
Michael Wuf6532112007-10-14 14:43:16 -0400958const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
959{
960 u16 reg8, reg9;
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100961 struct rtl8187_priv *priv = dev->priv;
Michael Wuf6532112007-10-14 14:43:16 -0400962
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100963 if (!priv->is_rtl8187b) {
964 rtl8225_write(dev, 0, 0x1B7);
Michael Wuf6532112007-10-14 14:43:16 -0400965
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100966 reg8 = rtl8225_read(dev, 8);
967 reg9 = rtl8225_read(dev, 9);
Michael Wuf6532112007-10-14 14:43:16 -0400968
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100969 rtl8225_write(dev, 0, 0x0B7);
Michael Wuf6532112007-10-14 14:43:16 -0400970
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100971 if (reg8 != 0x588 || reg9 != 0x700)
972 return &rtl8225_ops;
Michael Wuf6532112007-10-14 14:43:16 -0400973
Hin-Tak Leunge7d414f2008-07-08 12:31:57 +0100974 return &rtl8225z2_ops;
975 } else
976 return &rtl8225z2_b_ops;
Michael Wuf6532112007-10-14 14:43:16 -0400977}