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