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