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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
991 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
992 {
993 	rtl8225_write(dev, 0x4, 0x1f);
994 }
995 
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 
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