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