2 * Radio tuning for RTL8225 on RTL8187
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
10 * Magic delays, register offsets, and phy value tables below are
11 * taken from the original r8187 driver sources. Thanks to Realtek
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.
19 #include <linux/init.h>
20 #include <linux/usb.h>
21 #include <net/mac80211.h>
24 #include "rtl8187_rtl8225.h"
26 static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
28 struct rtl8187_priv *priv = dev->priv;
29 u16 reg80, reg84, reg82;
33 bangdata = (data << 4) | (addr & 0xf);
35 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
36 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
38 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
40 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
41 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
44 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
46 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
49 for (i = 15; i >= 0; i--) {
50 u16 reg = reg80 | (bangdata & (1 << i)) >> i;
53 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
55 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
56 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
59 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
62 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
65 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
66 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
70 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
72 struct rtl8187_priv *priv = dev->priv;
73 u16 reg80, reg82, reg84;
75 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
76 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
77 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
82 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
83 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
86 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
89 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
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);
96 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
99 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
100 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
104 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
106 struct rtl8187_priv *priv = dev->priv;
109 rtl8225_write_8051(dev, addr, cpu_to_le16(data));
111 rtl8225_write_bitbang(dev, addr, data);
114 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
116 struct rtl8187_priv *priv = dev->priv;
117 u16 reg80, reg82, reg84, out;
120 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
121 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
122 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
126 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
127 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
129 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
131 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
134 for (i = 4; i >= 0; i--) {
135 u16 reg = reg80 | ((addr >> i) & 1);
138 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
142 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
145 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
150 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
155 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
156 reg80 | (1 << 3) | (1 << 1));
158 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
161 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
166 for (i = 11; i >= 0; i--) {
167 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
170 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
171 reg80 | (1 << 3) | (1 << 1));
173 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
174 reg80 | (1 << 3) | (1 << 1));
176 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
177 reg80 | (1 << 3) | (1 << 1));
180 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
183 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
188 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
189 reg80 | (1 << 3) | (1 << 2));
192 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
193 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
194 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
199 static 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
214 static 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
233 static 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 */
243 static const u8 rtl8225_threshold[] = {
244 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
247 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
248 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
251 static 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
260 static 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
269 static const u8 rtl8225_tx_power_ofdm[] = {
270 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
273 static const u32 rtl8225_chan[] = {
274 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
275 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
278 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
280 struct rtl8187_priv *priv = dev->priv;
281 u8 cck_power, ofdm_power;
286 cck_power = priv->channels[channel - 1].hw_value & 0xF;
287 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
289 cck_power = min(cck_power, (u8)11);
290 ofdm_power = min(ofdm_power, (u8)35);
292 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
293 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
296 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
298 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
300 for (i = 0; i < 8; i++)
301 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
303 msleep(1); // FIXME: optional?
306 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
307 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
308 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
309 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
310 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
311 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
312 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
313 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
315 rtl8225_write_phy_ofdm(dev, 2, 0x42);
316 rtl8225_write_phy_ofdm(dev, 6, 0x00);
317 rtl8225_write_phy_ofdm(dev, 8, 0x00);
319 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
320 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
322 tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
324 rtl8225_write_phy_ofdm(dev, 5, *tmp);
325 rtl8225_write_phy_ofdm(dev, 7, *tmp);
330 static void rtl8225_rf_init(struct ieee80211_hw *dev)
332 struct rtl8187_priv *priv = dev->priv;
335 rtl8225_write(dev, 0x0, 0x067); msleep(1);
336 rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
337 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
338 rtl8225_write(dev, 0x3, 0x441); msleep(1);
339 rtl8225_write(dev, 0x4, 0x486); msleep(1);
340 rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
341 rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
342 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
343 rtl8225_write(dev, 0x8, 0x01F); msleep(1);
344 rtl8225_write(dev, 0x9, 0x334); msleep(1);
345 rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
346 rtl8225_write(dev, 0xB, 0x391); msleep(1);
347 rtl8225_write(dev, 0xC, 0x050); msleep(1);
348 rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
349 rtl8225_write(dev, 0xE, 0x029); msleep(1);
350 rtl8225_write(dev, 0xF, 0x914); msleep(100);
352 rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
353 rtl8225_write(dev, 0x2, 0x44D); msleep(200);
355 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
356 rtl8225_write(dev, 0x02, 0x0c4d);
358 rtl8225_write(dev, 0x02, 0x044d);
360 if (!(rtl8225_read(dev, 6) & (1 << 7)))
361 printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
362 wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
365 rtl8225_write(dev, 0x0, 0x127);
367 for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
368 rtl8225_write(dev, 0x1, i + 1);
369 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
372 rtl8225_write(dev, 0x0, 0x027);
373 rtl8225_write(dev, 0x0, 0x22F);
375 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
376 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
378 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
384 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
385 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
386 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
387 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
388 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
389 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
390 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
391 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
392 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
393 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
394 rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
395 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
396 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
397 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
398 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
399 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
400 rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
401 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
402 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
403 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
404 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
405 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
406 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
407 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
408 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
409 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
410 rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
411 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
412 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
413 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
414 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
415 rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
416 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
417 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
418 rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
419 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
420 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
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]);
427 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
428 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
429 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
430 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
431 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
432 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
433 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
434 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
435 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
436 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
437 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);
442 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
443 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
444 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
445 rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
446 rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
447 rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
448 rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
449 rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
450 rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
451 rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
452 rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
453 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
455 rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
457 rtl8225_rf_set_tx_power(dev, 1);
459 /* RX antenna default to A */
460 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
461 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
463 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
465 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
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]);
476 static 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
489 static 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
500 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
501 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
507 static const u8 rtl8225z2_tx_power_cck[] = {
508 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
514 static const u8 rtl8225z2_tx_power_ofdm[] = {
515 0x42, 0x00, 0x40, 0x00, 0x40
518 static 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
527 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
529 struct rtl8187_priv *priv = dev->priv;
530 u8 cck_power, ofdm_power;
535 cck_power = priv->channels[channel - 1].hw_value & 0xF;
536 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
538 cck_power = min(cck_power, (u8)15);
539 cck_power += priv->txpwr_base & 0xF;
540 cck_power = min(cck_power, (u8)35);
542 ofdm_power = min(ofdm_power, (u8)15);
543 ofdm_power += priv->txpwr_base >> 4;
544 ofdm_power = min(ofdm_power, (u8)35);
547 tmp = rtl8225z2_tx_power_cck_ch14;
549 tmp = rtl8225z2_tx_power_cck;
551 for (i = 0; i < 8; i++)
552 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
554 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
555 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
559 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
560 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
561 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
562 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
563 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
564 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
565 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
566 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
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);
574 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
575 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
579 static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
581 struct rtl8187_priv *priv = dev->priv;
582 u8 cck_power, ofdm_power;
586 cck_power = priv->channels[channel - 1].hw_value & 0xF;
587 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
590 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
592 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
593 cck_power += priv->txpwr_base & 0xF;
594 cck_power = min(cck_power, (u8)35);
597 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
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);
604 tmp = rtl8225z2_tx_power_cck_ch14;
606 tmp = rtl8225z2_tx_power_cck;
608 if (priv->hw_rev == RTL8187BvB) {
611 else if (cck_power <= 11)
618 else if (cck_power <= 11)
620 else if (cck_power <= 17)
626 for (i = 0; i < 8; i++)
627 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
629 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
630 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
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);
640 rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
641 rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
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);
651 rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
652 rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
658 static 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
673 static 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 */
683 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
685 struct rtl8187_priv *priv = dev->priv;
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);
705 rtl8225_write(dev, 0x0, 0x1B7);
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]);
712 rtl8225_write(dev, 0x3, 0x080);
713 rtl8225_write(dev, 0x5, 0x004);
714 rtl8225_write(dev, 0x0, 0x0B7);
715 rtl8225_write(dev, 0x2, 0xc4D);
718 rtl8225_write(dev, 0x2, 0x44D);
721 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
722 rtl8225_write(dev, 0x02, 0x0C4D);
724 rtl8225_write(dev, 0x02, 0x044D);
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));
733 rtl8225_write(dev, 0x0, 0x2BF);
735 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
736 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
738 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
744 rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
745 rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
746 rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
747 rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
748 rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
749 rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
750 rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
751 rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
752 rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
753 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
754 rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
755 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
756 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
757 rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
758 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
759 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
760 rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
761 rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
762 rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
763 rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
764 rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
765 rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
766 rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
767 rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
768 rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
769 rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
770 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
771 rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
772 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
773 rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
774 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
775 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
776 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
777 rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
778 rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
779 rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
780 rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
781 rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
782 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
783 rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
785 rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
786 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
787 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
788 rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
790 rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
791 rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
792 rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
793 rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
794 rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
795 rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
796 rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
797 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
798 rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
799 rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
800 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
801 rtl8225_write_phy_cck(dev, 0x19, 0x00);
802 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
803 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
804 rtl8225_write_phy_cck(dev, 0x40, 0x86);
805 rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
806 rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
807 rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
808 rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
809 rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
810 rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
811 rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
812 rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
813 rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
814 rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
815 rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
816 rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
818 rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
820 rtl8225z2_rf_set_tx_power(dev, 1);
822 /* RX antenna default to A */
823 rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
824 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
826 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
828 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
831 static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
833 struct rtl8187_priv *priv = dev->priv;
836 rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
837 rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
838 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
839 rtl8225_write(dev, 0x3, 0x441); msleep(1);
840 rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
841 rtl8225_write(dev, 0x5, 0xC72); msleep(1);
842 rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
843 rtl8225_write(dev, 0x7, 0x82A); msleep(1);
844 rtl8225_write(dev, 0x8, 0x03F); msleep(1);
845 rtl8225_write(dev, 0x9, 0x335); msleep(1);
846 rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
847 rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
848 rtl8225_write(dev, 0xc, 0x850); msleep(1);
849 rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
850 rtl8225_write(dev, 0xe, 0x02B); msleep(1);
851 rtl8225_write(dev, 0xf, 0x114); msleep(1);
853 rtl8225_write(dev, 0x0, 0x1B7); msleep(1);
855 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
856 rtl8225_write(dev, 0x1, i + 1); msleep(1);
857 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
860 rtl8225_write(dev, 0x3, 0x080); msleep(1);
861 rtl8225_write(dev, 0x5, 0x004); msleep(1);
862 rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
865 rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
868 rtl8225_write(dev, 0x2, 0x44D); msleep(1);
869 rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
871 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
872 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
873 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
875 rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
876 for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
877 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
878 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
879 rtl8225_write_phy_ofdm(dev, 0xE, 0);
881 rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
883 for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
884 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
886 rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
887 rtl818x_iowrite8(priv, &priv->map->SLOT, 9);
888 rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28);
889 rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28);
890 rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28);
891 rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28);
892 rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B);
893 rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B);
894 rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
895 rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
896 rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
897 rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
898 rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
900 rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1);
901 rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1);
902 rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1);
903 rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1);
906 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
909 struct rtl8187_priv *priv = dev->priv;
911 rtl8225_write(dev, 0x4, 0x1f); msleep(1);
913 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
914 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
915 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
916 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
917 rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
918 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
919 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
922 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
923 struct ieee80211_conf *conf)
925 struct rtl8187_priv *priv = dev->priv;
926 int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
928 if (priv->rf->init == rtl8225_rf_init)
929 rtl8225_rf_set_tx_power(dev, chan);
930 else if (priv->rf->init == rtl8225z2_rf_init)
931 rtl8225z2_rf_set_tx_power(dev, chan);
933 rtl8225z2_b_rf_set_tx_power(dev, chan);
935 rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
939 static const struct rtl818x_rf_ops rtl8225_ops = {
941 .init = rtl8225_rf_init,
942 .stop = rtl8225_rf_stop,
943 .set_chan = rtl8225_rf_set_channel
946 static const struct rtl818x_rf_ops rtl8225z2_ops = {
948 .init = rtl8225z2_rf_init,
949 .stop = rtl8225_rf_stop,
950 .set_chan = rtl8225_rf_set_channel
953 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
955 .init = rtl8225z2_b_rf_init,
956 .stop = rtl8225_rf_stop,
957 .set_chan = rtl8225_rf_set_channel
960 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
963 struct rtl8187_priv *priv = dev->priv;
965 if (!priv->is_rtl8187b) {
966 rtl8225_write(dev, 0, 0x1B7);
968 reg8 = rtl8225_read(dev, 8);
969 reg9 = rtl8225_read(dev, 9);
971 rtl8225_write(dev, 0, 0x0B7);
973 if (reg8 != 0x588 || reg9 != 0x700)
976 return &rtl8225z2_ops;
978 return &rtl8225z2_b_ops;