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