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