1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Radio tuning for RTL8225 on RTL8187
4  *
5  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
6  * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
7  *
8  * Based on the r8187 driver, which is:
9  * Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
10  *
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!
14  */
15 
16 #include <linux/usb.h>
17 #include <net/mac80211.h>
18 
19 #include "rtl8187.h"
20 #include "rtl8225.h"
21 
22 u8 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 
39 u16 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 
56 u32 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 
73 void 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 
87 void 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 
101 void 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 
115 static 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);
156 }
157 
158 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
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 
180 	mutex_lock(&priv->io_mutex);
181 
182 	priv->io_dmabuf->bits16 = data;
183 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
184 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
185 			addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
186 			HZ / 2);
187 
188 	mutex_unlock(&priv->io_mutex);
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);
195 }
196 
197 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
198 {
199 	struct rtl8187_priv *priv = dev->priv;
200 
201 	if (priv->asic_rev)
202 		rtl8225_write_8051(dev, addr, cpu_to_le16(data));
203 	else
204 		rtl8225_write_bitbang(dev, addr, data);
205 }
206 
207 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
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 
292 static 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 
307 static 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 
326 static 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 
336 static const u8 rtl8225_threshold[] = {
337 	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
338 };
339 
340 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
341 	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
342 };
343 
344 static 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 
353 static 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 
362 static const u8 rtl8225_tx_power_ofdm[] = {
363 	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
364 };
365 
366 static const u32 rtl8225_chan[] = {
367 	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
368 	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
369 };
370 
371 static 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 
379 	cck_power = priv->channels[channel - 1].hw_value & 0xF;
380 	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
381 
382 	cck_power = min(cck_power, (u8)11);
383 	if (ofdm_power > (u8)15)
384 		ofdm_power = 25;
385 	else
386 		ofdm_power += 10;
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);
404 	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
405 			reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
406 	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
407 			  RTL8187_RTL8225_ANAPARAM2_ON);
408 	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
409 			reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
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 
427 static void rtl8225_rf_init(struct ieee80211_hw *dev)
428 {
429 	struct rtl8187_priv *priv = dev->priv;
430 	int i;
431 
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);
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)))
458 			wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
459 				   rtl8225_read(dev, 6));
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]);
474 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
475 	}
476 
477 	msleep(1);
478 
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);
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 
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);
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);
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);
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 */
555 	rtl8225_write_phy_cck(dev, 0x10, 0x9b);			/* B: 0xDB */
556 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);		/* B: 0x10 */
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 
571 static 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 };
584 static 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 
595 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
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
600 };
601 
602 static const u8 rtl8225z2_tx_power_cck[] = {
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
607 };
608 
609 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
610 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
611 	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
612 	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
613 	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
614 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
615 	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
616 };
617 
618 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
619 {
620 	struct rtl8187_priv *priv = dev->priv;
621 	u8 cck_power, ofdm_power;
622 	const u8 *tmp;
623 	u32 reg;
624 	int i;
625 
626 	cck_power = priv->channels[channel - 1].hw_value & 0xF;
627 	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
628 
629 	cck_power = min(cck_power, (u8)15);
630 	cck_power += priv->txpwr_base & 0xF;
631 	cck_power = min(cck_power, (u8)35);
632 
633 	if (ofdm_power > (u8)15)
634 		ofdm_power = 25;
635 	else
636 		ofdm_power += 10;
637 	ofdm_power += priv->txpwr_base >> 4;
638 	ofdm_power = min(ofdm_power, (u8)35);
639 
640 	if (channel == 14)
641 		tmp = rtl8225z2_tx_power_cck_ch14;
642 	else
643 		tmp = rtl8225z2_tx_power_cck;
644 
645 	for (i = 0; i < 8; i++)
646 		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
647 
648 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
649 			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
650 	msleep(1);
651 
652 	/* anaparam2 on */
653 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
654 	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
655 	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
656 			reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
657 	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
658 			  RTL8187_RTL8225_ANAPARAM2_ON);
659 	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
660 			reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
661 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
662 
663 	rtl8225_write_phy_ofdm(dev, 2, 0x42);
664 	rtl8225_write_phy_ofdm(dev, 5, 0x00);
665 	rtl8225_write_phy_ofdm(dev, 6, 0x40);
666 	rtl8225_write_phy_ofdm(dev, 7, 0x00);
667 	rtl8225_write_phy_ofdm(dev, 8, 0x40);
668 
669 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
670 			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
671 	msleep(1);
672 }
673 
674 static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
675 {
676 	struct rtl8187_priv *priv = dev->priv;
677 	u8 cck_power, ofdm_power;
678 	const u8 *tmp;
679 	int i;
680 
681 	cck_power = priv->channels[channel - 1].hw_value & 0xF;
682 	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
683 
684 	cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
685 	cck_power += priv->txpwr_base & 0xF;
686 	cck_power = min(cck_power, (u8)35);
687 
688 	if (ofdm_power > 15)
689 		ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
690 	else
691 		ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
692 	ofdm_power += (priv->txpwr_base >> 4) & 0xF;
693 	ofdm_power = min(ofdm_power, (u8)35);
694 
695 	if (channel == 14)
696 		tmp = rtl8225z2_tx_power_cck_ch14;
697 	else
698 		tmp = rtl8225z2_tx_power_cck;
699 
700 	if (priv->hw_rev == RTL8187BvB) {
701 		if (cck_power <= 6)
702 			; /* do nothing */
703 		else if (cck_power <= 11)
704 			tmp += 8;
705 		else
706 			tmp += 16;
707 	} else {
708 		if (cck_power <= 5)
709 			; /* do nothing */
710 		else if (cck_power <= 11)
711 			tmp += 8;
712 		else if (cck_power <= 17)
713 			tmp += 16;
714 		else
715 			tmp += 24;
716 	}
717 
718 	for (i = 0; i < 8; i++)
719 		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
720 
721 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
722 			 rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
723 	msleep(1);
724 
725 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
726 			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
727 	if (priv->hw_rev == RTL8187BvB) {
728 		if (ofdm_power <= 11) {
729 			rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
730 			rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
731 		} else {
732 			rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
733 			rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
734 		}
735 	} else {
736 		if (ofdm_power <= 11) {
737 			rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
738 			rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
739 		} else if (ofdm_power <= 17) {
740 			rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
741 			rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
742 		} else {
743 			rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
744 			rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
745 		}
746 	}
747 	msleep(1);
748 }
749 
750 static const u16 rtl8225z2_rxgain[] = {
751 	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
752 	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
753 	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
754 	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
755 	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
756 	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
757 	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
758 	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
759 	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
760 	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
761 	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
762 	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
763 };
764 
765 static const u8 rtl8225z2_gain_bg[] = {
766 	0x23, 0x15, 0xa5, /* -82-1dBm */
767 	0x23, 0x15, 0xb5, /* -82-2dBm */
768 	0x23, 0x15, 0xc5, /* -82-3dBm */
769 	0x33, 0x15, 0xc5, /* -78dBm */
770 	0x43, 0x15, 0xc5, /* -74dBm */
771 	0x53, 0x15, 0xc5, /* -70dBm */
772 	0x63, 0x15, 0xc5  /* -66dBm */
773 };
774 
775 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
776 {
777 	struct rtl8187_priv *priv = dev->priv;
778 	int i;
779 
780 	rtl8225_write(dev, 0x0, 0x2BF);
781 	rtl8225_write(dev, 0x1, 0xEE0);
782 	rtl8225_write(dev, 0x2, 0x44D);
783 	rtl8225_write(dev, 0x3, 0x441);
784 	rtl8225_write(dev, 0x4, 0x8C3);
785 	rtl8225_write(dev, 0x5, 0xC72);
786 	rtl8225_write(dev, 0x6, 0x0E6);
787 	rtl8225_write(dev, 0x7, 0x82A);
788 	rtl8225_write(dev, 0x8, 0x03F);
789 	rtl8225_write(dev, 0x9, 0x335);
790 	rtl8225_write(dev, 0xa, 0x9D4);
791 	rtl8225_write(dev, 0xb, 0x7BB);
792 	rtl8225_write(dev, 0xc, 0x850);
793 	rtl8225_write(dev, 0xd, 0xCDF);
794 	rtl8225_write(dev, 0xe, 0x02B);
795 	rtl8225_write(dev, 0xf, 0x114);
796 	msleep(100);
797 
798 	rtl8225_write(dev, 0x0, 0x1B7);
799 
800 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
801 		rtl8225_write(dev, 0x1, i + 1);
802 		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
803 	}
804 
805 	rtl8225_write(dev, 0x3, 0x080);
806 	rtl8225_write(dev, 0x5, 0x004);
807 	rtl8225_write(dev, 0x0, 0x0B7);
808 	rtl8225_write(dev, 0x2, 0xc4D);
809 
810 	msleep(200);
811 	rtl8225_write(dev, 0x2, 0x44D);
812 	msleep(100);
813 
814 	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
815 		rtl8225_write(dev, 0x02, 0x0C4D);
816 		msleep(200);
817 		rtl8225_write(dev, 0x02, 0x044D);
818 		msleep(100);
819 		if (!(rtl8225_read(dev, 6) & (1 << 7)))
820 			wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
821 				   rtl8225_read(dev, 6));
822 	}
823 
824 	msleep(200);
825 
826 	rtl8225_write(dev, 0x0, 0x2BF);
827 
828 	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
829 		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
830 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
831 	}
832 
833 	msleep(1);
834 
835 	rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
836 	rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
837 	rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
838 	rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
839 	rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
840 	rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
841 	rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
842 	rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
843 	rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
844 	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
845 	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
846 	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
847 	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
848 	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
849 	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
850 	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
851 	rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
852 	rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
853 	rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
854 	rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
855 	rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
856 	rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
857 	rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
858 	rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
859 	rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
860 	rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
861 	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
862 	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
863 	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
864 	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
865 	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
866 	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
867 	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
868 	rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
869 	rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
870 	rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
871 	rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
872 	rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
873 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
874 	rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
875 
876 	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
877 	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
878 	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
879 	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
880 
881 	rtl8225_write_phy_cck(dev, 0x00, 0x98);
882 	rtl8225_write_phy_cck(dev, 0x03, 0x20);
883 	rtl8225_write_phy_cck(dev, 0x04, 0x7e);
884 	rtl8225_write_phy_cck(dev, 0x05, 0x12);
885 	rtl8225_write_phy_cck(dev, 0x06, 0xfc);
886 	rtl8225_write_phy_cck(dev, 0x07, 0x78);
887 	rtl8225_write_phy_cck(dev, 0x08, 0x2e);
888 	rtl8225_write_phy_cck(dev, 0x10, 0x9b);
889 	rtl8225_write_phy_cck(dev, 0x11, 0x88);
890 	rtl8225_write_phy_cck(dev, 0x12, 0x47);
891 	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
892 	rtl8225_write_phy_cck(dev, 0x19, 0x00);
893 	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
894 	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
895 	rtl8225_write_phy_cck(dev, 0x40, 0x86);
896 	rtl8225_write_phy_cck(dev, 0x41, 0x8d);
897 	rtl8225_write_phy_cck(dev, 0x42, 0x15);
898 	rtl8225_write_phy_cck(dev, 0x43, 0x18);
899 	rtl8225_write_phy_cck(dev, 0x44, 0x36);
900 	rtl8225_write_phy_cck(dev, 0x45, 0x35);
901 	rtl8225_write_phy_cck(dev, 0x46, 0x2e);
902 	rtl8225_write_phy_cck(dev, 0x47, 0x25);
903 	rtl8225_write_phy_cck(dev, 0x48, 0x1c);
904 	rtl8225_write_phy_cck(dev, 0x49, 0x12);
905 	rtl8225_write_phy_cck(dev, 0x4a, 0x09);
906 	rtl8225_write_phy_cck(dev, 0x4b, 0x04);
907 	rtl8225_write_phy_cck(dev, 0x4c, 0x05);
908 
909 	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
910 
911 	rtl8225z2_rf_set_tx_power(dev, 1);
912 
913 	/* RX antenna default to A */
914 	rtl8225_write_phy_cck(dev, 0x10, 0x9b);			/* B: 0xDB */
915 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);		/* B: 0x10 */
916 
917 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
918 	msleep(1);
919 	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
920 }
921 
922 static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
923 {
924 	struct rtl8187_priv *priv = dev->priv;
925 	int i;
926 
927 	rtl8225_write(dev, 0x0, 0x0B7);
928 	rtl8225_write(dev, 0x1, 0xEE0);
929 	rtl8225_write(dev, 0x2, 0x44D);
930 	rtl8225_write(dev, 0x3, 0x441);
931 	rtl8225_write(dev, 0x4, 0x8C3);
932 	rtl8225_write(dev, 0x5, 0xC72);
933 	rtl8225_write(dev, 0x6, 0x0E6);
934 	rtl8225_write(dev, 0x7, 0x82A);
935 	rtl8225_write(dev, 0x8, 0x03F);
936 	rtl8225_write(dev, 0x9, 0x335);
937 	rtl8225_write(dev, 0xa, 0x9D4);
938 	rtl8225_write(dev, 0xb, 0x7BB);
939 	rtl8225_write(dev, 0xc, 0x850);
940 	rtl8225_write(dev, 0xd, 0xCDF);
941 	rtl8225_write(dev, 0xe, 0x02B);
942 	rtl8225_write(dev, 0xf, 0x114);
943 
944 	rtl8225_write(dev, 0x0, 0x1B7);
945 
946 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
947 		rtl8225_write(dev, 0x1, i + 1);
948 		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
949 	}
950 
951 	rtl8225_write(dev, 0x3, 0x080);
952 	rtl8225_write(dev, 0x5, 0x004);
953 	rtl8225_write(dev, 0x0, 0x0B7);
954 
955 	rtl8225_write(dev, 0x2, 0xC4D);
956 
957 	rtl8225_write(dev, 0x2, 0x44D);
958 	rtl8225_write(dev, 0x0, 0x2BF);
959 
960 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
961 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
962 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
963 
964 	rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
965 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
966 		rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
967 		rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
968 		rtl8225_write_phy_ofdm(dev, 0xE, 0);
969 	}
970 	rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
971 
972 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
973 		rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
974 
975 	rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
976 	rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
977 	rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
978 	rtl8225_write_phy_cck(dev, 0xc1, 0x88);
979 }
980 
981 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
982 {
983 	rtl8225_write(dev, 0x4, 0x1f);
984 }
985 
986 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
987 				   struct ieee80211_conf *conf)
988 {
989 	struct rtl8187_priv *priv = dev->priv;
990 	int chan =
991 		ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
992 
993 	if (priv->rf->init == rtl8225_rf_init)
994 		rtl8225_rf_set_tx_power(dev, chan);
995 	else if (priv->rf->init == rtl8225z2_rf_init)
996 		rtl8225z2_rf_set_tx_power(dev, chan);
997 	else
998 		rtl8225z2_b_rf_set_tx_power(dev, chan);
999 
1000 	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
1001 	msleep(10);
1002 }
1003 
1004 static const struct rtl818x_rf_ops rtl8225_ops = {
1005 	.name		= "rtl8225",
1006 	.init		= rtl8225_rf_init,
1007 	.stop		= rtl8225_rf_stop,
1008 	.set_chan	= rtl8225_rf_set_channel
1009 };
1010 
1011 static const struct rtl818x_rf_ops rtl8225z2_ops = {
1012 	.name		= "rtl8225z2",
1013 	.init		= rtl8225z2_rf_init,
1014 	.stop		= rtl8225_rf_stop,
1015 	.set_chan	= rtl8225_rf_set_channel
1016 };
1017 
1018 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
1019 	.name		= "rtl8225z2",
1020 	.init		= rtl8225z2_b_rf_init,
1021 	.stop		= rtl8225_rf_stop,
1022 	.set_chan	= rtl8225_rf_set_channel
1023 };
1024 
1025 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
1026 {
1027 	u16 reg8, reg9;
1028 	struct rtl8187_priv *priv = dev->priv;
1029 
1030 	if (!priv->is_rtl8187b) {
1031 		rtl8225_write(dev, 0, 0x1B7);
1032 
1033 		reg8 = rtl8225_read(dev, 8);
1034 		reg9 = rtl8225_read(dev, 9);
1035 
1036 		rtl8225_write(dev, 0, 0x0B7);
1037 
1038 		if (reg8 != 0x588 || reg9 != 0x700)
1039 			return &rtl8225_ops;
1040 
1041 		return &rtl8225z2_ops;
1042 	} else
1043 		return &rtl8225z2_b_ops;
1044 }
1045