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
22u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
23				u8 *addr, u8 idx)
24{
25	u8 val;
26
27	mutex_lock(&priv->io_mutex);
28	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
29			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
30			(unsigned long)addr, idx & 0x03,
31			&priv->io_dmabuf->bits8, sizeof(val), 500);
32
33	val = priv->io_dmabuf->bits8;
34	mutex_unlock(&priv->io_mutex);
35
36	return val;
37}
38
39u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
40				__le16 *addr, u8 idx)
41{
42	__le16 val;
43
44	mutex_lock(&priv->io_mutex);
45	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
46			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
47			(unsigned long)addr, idx & 0x03,
48			&priv->io_dmabuf->bits16, sizeof(val), 500);
49
50	val = priv->io_dmabuf->bits16;
51	mutex_unlock(&priv->io_mutex);
52
53	return le16_to_cpu(val);
54}
55
56u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
57				__le32 *addr, u8 idx)
58{
59	__le32 val;
60
61	mutex_lock(&priv->io_mutex);
62	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
63			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
64			(unsigned long)addr, idx & 0x03,
65			&priv->io_dmabuf->bits32, sizeof(val), 500);
66
67	val = priv->io_dmabuf->bits32;
68	mutex_unlock(&priv->io_mutex);
69
70	return le32_to_cpu(val);
71}
72
73void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
74				u8 *addr, u8 val, u8 idx)
75{
76	mutex_lock(&priv->io_mutex);
77
78	priv->io_dmabuf->bits8 = val;
79	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
80			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
81			(unsigned long)addr, idx & 0x03,
82			&priv->io_dmabuf->bits8, sizeof(val), 500);
83
84	mutex_unlock(&priv->io_mutex);
85}
86
87void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
88				__le16 *addr, u16 val, u8 idx)
89{
90	mutex_lock(&priv->io_mutex);
91
92	priv->io_dmabuf->bits16 = cpu_to_le16(val);
93	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
94			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
95			(unsigned long)addr, idx & 0x03,
96			&priv->io_dmabuf->bits16, sizeof(val), 500);
97
98	mutex_unlock(&priv->io_mutex);
99}
100
101void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
102				__le32 *addr, u32 val, u8 idx)
103{
104	mutex_lock(&priv->io_mutex);
105
106	priv->io_dmabuf->bits32 = cpu_to_le32(val);
107	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
108			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
109			(unsigned long)addr, idx & 0x03,
110			&priv->io_dmabuf->bits32, sizeof(val), 500);
111
112	mutex_unlock(&priv->io_mutex);
113}
114
115static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
116{
117	struct rtl8187_priv *priv = dev->priv;
118	u16 reg80, reg84, reg82;
119	u32 bangdata;
120	int i;
121
122	bangdata = (data << 4) | (addr & 0xf);
123
124	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
125	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
126
127	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
128
129	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
130	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
131	udelay(10);
132
133	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
134	udelay(2);
135	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
136	udelay(10);
137
138	for (i = 15; i >= 0; i--) {
139		u16 reg = reg80 | (bangdata & (1 << i)) >> i;
140
141		if (i & 1)
142			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
143
144		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
145		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
146
147		if (!(i & 1))
148			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
149	}
150
151	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
152	udelay(10);
153
154	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
155	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
156}
157
158static 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			500);
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
197static 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
207static 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
292static const u16 rtl8225bcd_rxgain[] = {
293	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
294	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
295	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
296	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
297	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
298	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
299	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
300	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
301	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
302	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
303	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
304	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
305};
306
307static const u8 rtl8225_agc[] = {
308	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
309	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
310	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
311	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
312	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
313	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
314	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
315	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
316	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
317	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
318	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
319	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
320	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
321	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
322	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
323	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
324};
325
326static const u8 rtl8225_gain[] = {
327	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
328	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
329	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
330	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
331	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
332	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
333	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
334};
335
336static const u8 rtl8225_threshold[] = {
337	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
338};
339
340static const u8 rtl8225_tx_gain_cck_ofdm[] = {
341	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
342};
343
344static const u8 rtl8225_tx_power_cck[] = {
345	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
346	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
347	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
348	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
349	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
350	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
351};
352
353static const u8 rtl8225_tx_power_cck_ch14[] = {
354	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
355	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
356	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
357	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
358	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
359	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
360};
361
362static const u8 rtl8225_tx_power_ofdm[] = {
363	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
364};
365
366static const u32 rtl8225_chan[] = {
367	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
368	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
369};
370
371static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
372{
373	struct rtl8187_priv *priv = dev->priv;
374	u8 cck_power, ofdm_power;
375	const u8 *tmp;
376	u32 reg;
377	int i;
378
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
427static 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
571static const u8 rtl8225z2_agc[] = {
572	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
573	0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
574	0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
575	0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
576	0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
577	0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
578	0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
579	0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
580	0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
581	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
582	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
583};
584static const u8 rtl8225z2_ofdm[] = {
585	0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
586	0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
587	0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
588	0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
589	0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
590	0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
591	0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
592	0x6d, 0x3c, 0xfb, 0x07
593};
594
595static 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
602static 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
609static 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
618static 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
674static 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
750static 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
765static 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
775static 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
922static 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
981static void rtl8225_rf_stop(struct ieee80211_hw *dev)
982{
983	rtl8225_write(dev, 0x4, 0x1f);
984}
985
986static 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
1004static 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
1011static 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
1018static 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
1025const 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