1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * Radio tuning for RTL8225 on RTL8180
5  *
6  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
7  * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
8  *
9  * Based on the r8180 driver, which is:
10  * Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
11  *
12  * Thanks to Realtek for their support!
13  */
14 
15 #include <linux/pci.h>
16 #include <linux/delay.h>
17 #include <net/mac80211.h>
18 
19 #include "rtl8180.h"
20 #include "rtl8225.h"
21 
22 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
23 {
24 	struct rtl8180_priv *priv = dev->priv;
25 	u16 reg80, reg84, reg82;
26 	u32 bangdata;
27 	int i;
28 
29 	bangdata = (data << 4) | (addr & 0xf);
30 
31 	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
32 	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
33 
34 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
35 
36 	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
37 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
38 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
39 	udelay(10);
40 
41 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
42 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
43 	udelay(2);
44 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
45 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
46 	udelay(10);
47 
48 	for (i = 15; i >= 0; i--) {
49 		u16 reg = reg80;
50 
51 		if (bangdata & (1 << i))
52 			reg |= 1;
53 
54 		if (i & 1)
55 			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
56 
57 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
58 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
59 
60 		if (!(i & 1))
61 			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
62 	}
63 
64 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
65 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
66 	udelay(10);
67 
68 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
69 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
70 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
71 }
72 
73 static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
74 {
75 	struct rtl8180_priv *priv = dev->priv;
76 	u16 reg80, reg82, reg84, out;
77 	int i;
78 
79 	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
80 	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
81 	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
82 
83 	reg80 &= ~0xF;
84 
85 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
86 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
87 
88 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
89 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
90 	udelay(4);
91 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
92 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
93 	udelay(5);
94 
95 	for (i = 4; i >= 0; i--) {
96 		u16 reg = reg80 | ((addr >> i) & 1);
97 
98 		if (!(i & 1)) {
99 			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
100 			rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
101 			udelay(1);
102 		}
103 
104 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
105 				  reg | (1 << 1));
106 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
107 		udelay(2);
108 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
109 				  reg | (1 << 1));
110 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
111 		udelay(2);
112 
113 		if (i & 1) {
114 			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
115 			rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
116 			udelay(1);
117 		}
118 	}
119 
120 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
121 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
122 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
123 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
124 			  reg80 | (1 << 3) | (1 << 1));
125 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
126 	udelay(2);
127 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
128 			  reg80 | (1 << 3));
129 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
130 	udelay(2);
131 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
132 			  reg80 | (1 << 3));
133 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
134 	udelay(2);
135 
136 	out = 0;
137 	for (i = 11; i >= 0; i--) {
138 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
139 				  reg80 | (1 << 3));
140 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
141 		udelay(1);
142 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
143 				  reg80 | (1 << 3) | (1 << 1));
144 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
145 		udelay(2);
146 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
147 				  reg80 | (1 << 3) | (1 << 1));
148 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
149 		udelay(2);
150 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
151 				  reg80 | (1 << 3) | (1 << 1));
152 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
153 		udelay(2);
154 
155 		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
156 			out |= 1 << i;
157 
158 		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
159 				  reg80 | (1 << 3));
160 		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
161 		udelay(2);
162 	}
163 
164 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
165 			  reg80 | (1 << 3) | (1 << 2));
166 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
167 	udelay(2);
168 
169 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
170 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
171 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
172 
173 	return out;
174 }
175 
176 static const u16 rtl8225bcd_rxgain[] = {
177 	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
178 	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
179 	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
180 	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
181 	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
182 	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
183 	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
184 	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
185 	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
186 	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
187 	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
188 	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
189 };
190 
191 static const u8 rtl8225_agc[] = {
192 	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
193 	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
194 	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
195 	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
196 	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
197 	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
198 	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
199 	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
200 	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
201 	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
202 	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
203 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
204 	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
205 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
206 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
207 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
208 };
209 
210 static const u8 rtl8225_gain[] = {
211 	0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
212 	0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
213 	0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
214 	0x33, 0x80, 0x79, 0xc5, /* -78dbm */
215 	0x43, 0x78, 0x76, 0xc5, /* -74dbm */
216 	0x53, 0x60, 0x73, 0xc5, /* -70dbm */
217 	0x63, 0x58, 0x70, 0xc5, /* -66dbm */
218 };
219 
220 static const u8 rtl8225_threshold[] = {
221 	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
222 };
223 
224 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
225 	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
226 };
227 
228 static const u8 rtl8225_tx_power_cck[] = {
229 	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
230 	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
231 	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
232 	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
233 	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
234 	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
235 };
236 
237 static const u8 rtl8225_tx_power_cck_ch14[] = {
238 	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
239 	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
240 	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
241 	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
242 	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
243 	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
244 };
245 
246 static const u8 rtl8225_tx_power_ofdm[] = {
247 	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
248 };
249 
250 static const u32 rtl8225_chan[] = {
251 	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
252 	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
253 };
254 
255 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
256 {
257 	struct rtl8180_priv *priv = dev->priv;
258 	u8 cck_power, ofdm_power;
259 	const u8 *tmp;
260 	u32 reg;
261 	int i;
262 
263 	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
264 	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
265 
266 	cck_power = min(cck_power, (u8)35);
267 	ofdm_power = min(ofdm_power, (u8)35);
268 
269 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
270 			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
271 
272 	if (channel == 14)
273 		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
274 	else
275 		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
276 
277 	for (i = 0; i < 8; i++)
278 		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
279 
280 	msleep(1); /* FIXME: optional? */
281 
282 	/* TODO: use set_anaparam2 dev.c_func*/
283 	/* anaparam2 on */
284 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
285 	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
286 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
287 	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
288 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
289 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
290 
291 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
292 			 rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
293 
294 	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
295 
296 	rtl8225_write_phy_ofdm(dev, 5, *tmp);
297 	rtl8225_write_phy_ofdm(dev, 7, *tmp);
298 
299 	msleep(1);
300 }
301 
302 static void rtl8225_rf_init(struct ieee80211_hw *dev)
303 {
304 	struct rtl8180_priv *priv = dev->priv;
305 	int i;
306 
307 	rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
308 
309 	/* host_pci_init */
310 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
311 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
312 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
313 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
314 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
315 	msleep(200);	/* FIXME: ehh?? */
316 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
317 
318 	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
319 
320 	/* TODO: check if we need really to change BRSR to do RF config */
321 	rtl818x_ioread16(priv, &priv->map->BRSR);
322 	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
323 	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
324 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
325 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
326 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
327 
328 	rtl8225_write(dev, 0x0, 0x067);
329 	rtl8225_write(dev, 0x1, 0xFE0);
330 	rtl8225_write(dev, 0x2, 0x44D);
331 	rtl8225_write(dev, 0x3, 0x441);
332 	rtl8225_write(dev, 0x4, 0x8BE);
333 	rtl8225_write(dev, 0x5, 0xBF0);		/* TODO: minipci */
334 	rtl8225_write(dev, 0x6, 0xAE6);
335 	rtl8225_write(dev, 0x7, rtl8225_chan[0]);
336 	rtl8225_write(dev, 0x8, 0x01F);
337 	rtl8225_write(dev, 0x9, 0x334);
338 	rtl8225_write(dev, 0xA, 0xFD4);
339 	rtl8225_write(dev, 0xB, 0x391);
340 	rtl8225_write(dev, 0xC, 0x050);
341 	rtl8225_write(dev, 0xD, 0x6DB);
342 	rtl8225_write(dev, 0xE, 0x029);
343 	rtl8225_write(dev, 0xF, 0x914); msleep(1);
344 
345 	rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
346 
347 	rtl8225_write(dev, 0x0, 0x127);
348 
349 	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
350 		rtl8225_write(dev, 0x1, i + 1);
351 		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
352 	}
353 
354 	rtl8225_write(dev, 0x0, 0x027);
355 	rtl8225_write(dev, 0x0, 0x22F);
356 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
357 
358 	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
359 		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
360 		msleep(1);
361 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
362 		msleep(1);
363 	}
364 
365 	msleep(1);
366 
367 	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
368 	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
369 	rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
370 	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
371 	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
372 	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
373 	rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
374 	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
375 	rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
376 	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
377 	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
378 	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
379 	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
380 	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
381 	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
382 	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
383 	rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
384 	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
385 	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
386 	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
387 	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
388 	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
389 	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
390 	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
391 	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
392 	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
393 	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
394 	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
395 	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
396 	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
397 	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
398 	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
399 	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
400 	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
401 	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
402 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
403 	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
404 
405 	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
406 	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
407 	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
408 	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
409 	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
410 	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
411 	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
412 	rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
413 	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
414 	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
415 	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
416 	rtl8225_write_phy_cck(dev, 0x19, 0x00);
417 	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
418 	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
419 	rtl8225_write_phy_cck(dev, 0x40, 0x86);
420 	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
421 	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
422 	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
423 	rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
424 	rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
425 	rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
426 	rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
427 	rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
428 	rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
429 	rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
430 	rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
431 	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
432 
433 	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
434 
435 	rtl8225_rf_set_tx_power(dev, 1);
436 
437 	/* RX antenna default to A */
438 	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
439 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
440 
441 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
442 	msleep(1);
443 	rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
444 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
445 
446 	rtl8225_write(dev, 0x0c, 0x50);
447 	/* set OFDM initial gain */
448 	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
449 	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
450 	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
451 	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
452 	/* set CCK threshold */
453 	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
454 }
455 
456 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
457 	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
458 };
459 
460 static const u8 rtl8225z2_tx_power_cck_B[] = {
461 	0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
462 };
463 
464 static const u8 rtl8225z2_tx_power_cck_A[] = {
465 	0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
466 };
467 
468 static const u8 rtl8225z2_tx_power_cck[] = {
469 	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
470 };
471 
472 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
473 {
474 	struct rtl8180_priv *priv = dev->priv;
475 	u8 cck_power, ofdm_power;
476 	const u8 *tmp;
477 	int i;
478 
479 	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
480 	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
481 
482 	if (channel == 14)
483 		tmp = rtl8225z2_tx_power_cck_ch14;
484 	else if (cck_power == 12)
485 		tmp = rtl8225z2_tx_power_cck_B;
486 	else if (cck_power == 13)
487 		tmp = rtl8225z2_tx_power_cck_A;
488 	else
489 		tmp = rtl8225z2_tx_power_cck;
490 
491 	for (i = 0; i < 8; i++)
492 		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
493 
494 	cck_power = min(cck_power, (u8)35);
495 	if (cck_power == 13 || cck_power == 14)
496 		cck_power = 12;
497 	if (cck_power >= 15)
498 		cck_power -= 2;
499 
500 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
501 	rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
502 	msleep(1);
503 
504 	ofdm_power = min(ofdm_power, (u8)35);
505 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
506 
507 	rtl8225_write_phy_ofdm(dev, 2, 0x62);
508 	rtl8225_write_phy_ofdm(dev, 5, 0x00);
509 	rtl8225_write_phy_ofdm(dev, 6, 0x40);
510 	rtl8225_write_phy_ofdm(dev, 7, 0x00);
511 	rtl8225_write_phy_ofdm(dev, 8, 0x40);
512 
513 	msleep(1);
514 }
515 
516 static const u16 rtl8225z2_rxgain[] = {
517 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
518 	0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
519 	0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
520 	0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
521 	0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
522 	0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
523 	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
524 	0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
525 	0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
526 	0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
527 	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
528 	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
529 };
530 
531 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
532 {
533 	struct rtl8180_priv *priv = dev->priv;
534 	int i;
535 
536 	rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
537 
538 	/* host_pci_init */
539 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
540 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
541 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
542 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
543 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
544 	msleep(200);	/* FIXME: ehh?? */
545 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
546 
547 	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
548 
549 	/* TODO: check if we need really to change BRSR to do RF config */
550 	rtl818x_ioread16(priv, &priv->map->BRSR);
551 	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
552 	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
553 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
554 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
555 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
556 
557 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
558 
559 	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
560 	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
561 	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
562 	rtl8225_write(dev, 0x3, 0x441); msleep(1);
563 	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
564 	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
565 	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
566 	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
567 	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
568 	rtl8225_write(dev, 0x9, 0x335); msleep(1);
569 	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
570 	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
571 	rtl8225_write(dev, 0xc, 0x850); msleep(1);
572 	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
573 	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
574 	rtl8225_write(dev, 0xf, 0x114); msleep(100);
575 
576 	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
577 		rtl8225_write(dev, 0x02, 0x0C4D);
578 		msleep(200);
579 		rtl8225_write(dev, 0x02, 0x044D);
580 		msleep(100);
581 		/* TODO: readd calibration failure message when the calibration
582 		   check works */
583 	}
584 
585 	rtl8225_write(dev, 0x0, 0x1B7);
586 	rtl8225_write(dev, 0x3, 0x002);
587 	rtl8225_write(dev, 0x5, 0x004);
588 
589 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
590 		rtl8225_write(dev, 0x1, i + 1);
591 		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
592 	}
593 
594 	rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
595 	rtl8225_write(dev, 0x2, 0xC4D);
596 
597 	msleep(200);
598 	rtl8225_write(dev, 0x2, 0x44D);
599 	msleep(100);
600 
601 	rtl8225_write(dev, 0x00, 0x2BF);
602 	rtl8225_write(dev, 0xFF, 0xFFFF);
603 
604 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
605 
606 	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
607 		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
608 		msleep(1);
609 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
610 		msleep(1);
611 	}
612 
613 	msleep(1);
614 
615 	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
616 	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
617 	rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
618 	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
619 	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
620 	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
621 	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
622 	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
623 	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
624 	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
625 	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
626 	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
627 	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
628 	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
629 	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
630 	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
631 	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
632 	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
633 	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
634 	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
635 	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
636 	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
637 	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
638 	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
639 	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
640 	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
641 	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
642 	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
643 	rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
644 	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
645 	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
646 	rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
647 	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
648 	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
649 	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
650 	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
651 	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
652 	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
653 	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
654 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
655 	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
656 
657 	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
658 	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
659 	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
660 	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
661 	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
662 	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
663 	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
664 	rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
665 	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
666 	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
667 	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
668 	rtl8225_write_phy_cck(dev, 0x19, 0x00);
669 	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
670 	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
671 	rtl8225_write_phy_cck(dev, 0x40, 0x86);
672 	rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
673 	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
674 	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
675 	rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
676 	rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
677 	rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
678 	rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
679 	rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
680 	rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
681 	rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
682 	rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
683 	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
684 
685 	rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
686 
687 	rtl8225z2_rf_set_tx_power(dev, 1);
688 
689 	/* RX antenna default to A */
690 	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
691 	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
692 
693 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
694 	msleep(1);
695 	rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
696 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
697 }
698 
699 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
700 {
701 	struct rtl8180_priv *priv = dev->priv;
702 	u8 reg;
703 
704 	rtl8225_write(dev, 0x4, 0x1f); msleep(1);
705 
706 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
707 	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
708 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
709 	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
710 	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
711 	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
712 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
713 }
714 
715 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
716 				   struct ieee80211_conf *conf)
717 {
718 	struct rtl8180_priv *priv = dev->priv;
719 	int chan =
720 		ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
721 
722 	if (priv->rf->init == rtl8225_rf_init)
723 		rtl8225_rf_set_tx_power(dev, chan);
724 	else
725 		rtl8225z2_rf_set_tx_power(dev, chan);
726 
727 	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
728 	msleep(10);
729 }
730 
731 static const struct rtl818x_rf_ops rtl8225_ops = {
732 	.name		= "rtl8225",
733 	.init		= rtl8225_rf_init,
734 	.stop		= rtl8225_rf_stop,
735 	.set_chan	= rtl8225_rf_set_channel,
736 };
737 
738 static const struct rtl818x_rf_ops rtl8225z2_ops = {
739 	.name		= "rtl8225z2",
740 	.init		= rtl8225z2_rf_init,
741 	.stop		= rtl8225_rf_stop,
742 	.set_chan	= rtl8225_rf_set_channel,
743 };
744 
745 const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
746 {
747 	struct rtl8180_priv *priv = dev->priv;
748 	u16 reg8, reg9;
749 
750 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
751 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
752 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
753 	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
754 	msleep(100);
755 
756 	rtl8225_write(dev, 0, 0x1B7);
757 
758 	reg8 = rtl8225_read(dev, 8);
759 	reg9 = rtl8225_read(dev, 9);
760 
761 	rtl8225_write(dev, 0, 0x0B7);
762 
763 	if (reg8 != 0x588 || reg9 != 0x700)
764 		return &rtl8225_ops;
765 
766 	return &rtl8225z2_ops;
767 }
768