]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[karo-tx-linux.git] / drivers / net / wireless / realtek / rtl818x / rtl8180 / rtl8225se.c
1
2 /* Radio tuning for RTL8225 on RTL8187SE
3  *
4  * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
5  * Copyright 2014 Andrea Merello <andrea.merello@gmail.com>
6  *
7  * Based on the r8180 and Realtek r8187se drivers, which are:
8  * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
9  *
10  * Also based on the rtl8187 driver, which is:
11  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
12  * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18
19 #include <net/mac80211.h>
20
21 #include "rtl8180.h"
22 #include "rtl8225se.h"
23
24 #define PFX "rtl8225 (se) "
25
26 static const u32 RF_GAIN_TABLE[] = {
27         0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
28         0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
29         0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
30         0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
31         0x0183, 0x0163, 0x0143, 0x0123, 0x0103
32 };
33
34 static const u8 cck_ofdm_gain_settings[] = {
35         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
36         0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
37         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
38         0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
39         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
40         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
41 };
42
43 static const u8 rtl8225se_tx_gain_cck_ofdm[] = {
44         0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
45 };
46
47 static const u8 rtl8225se_tx_power_cck[] = {
48         0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
49         0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
50         0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
51         0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
52         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
53         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
54 };
55
56 static const u8 rtl8225se_tx_power_cck_ch14[] = {
57         0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
58         0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
59         0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
60         0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
61         0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
62         0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
63 };
64
65 static const u8 rtl8225se_tx_power_ofdm[] = {
66         0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
67 };
68
69 static const u32 rtl8225se_chan[] = {
70         0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
71         0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
72 };
73
74 static const u8 rtl8225sez2_tx_power_cck_ch14[] = {
75         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
76 };
77
78 static const u8 rtl8225sez2_tx_power_cck_B[] = {
79         0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
80 };
81
82 static const u8 rtl8225sez2_tx_power_cck_A[] = {
83         0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
84 };
85
86 static const u8 rtl8225sez2_tx_power_cck[] = {
87         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
88 };
89
90 static const u8 ZEBRA_AGC[] = {
91         0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A,
92         0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
93         0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
94         0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
95         0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27,
96         0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
97         0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00,
98         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99         0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
100         0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
101         0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b,
102         0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
103         0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21,
104         0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
105         0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
106         0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
107 };
108
109 static const u8 OFDM_CONFIG[] = {
110         0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
111         0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
112         0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
113         0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
114         0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
115         0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
116         0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
117         0xD8, 0x3C, 0x7B, 0x10, 0x10
118 };
119
120 static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data,
121                                     u8 len, bool write)
122 {
123         struct rtl8180_priv *priv = dev->priv;
124         int i;
125         u8 tmp;
126
127         do {
128                 for (i = 0; i < 5; i++) {
129                         tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
130                         if (!(tmp & 0x3))
131                                 break;
132                         udelay(10);
133                 }
134                 if (i == 5)
135                         wiphy_err(dev->wiphy, PFX
136                                 "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp);
137
138                 tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02;
139                 rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp);
140
141                 tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7;
142                 rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp);
143                 if (write) {
144                         if (len == 16) {
145                                 rtl818x_iowrite16(priv, SW_3W_DB0,
146                                   *(u16 *)data);
147                         } else if (len == 64) {
148                                 rtl818x_iowrite32(priv, SW_3W_DB0_4,
149                                   *((u32 *)data));
150                                 rtl818x_iowrite32(priv, SW_3W_DB1_4,
151                                   *((u32 *)(data + 4)));
152                         } else
153                                 wiphy_err(dev->wiphy, PFX
154                                         "Unimplemented length\n");
155                 } else {
156                         rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data);
157                 }
158                 if (write)
159                         tmp = 2;
160                 else
161                         tmp = 1;
162                 rtl818x_iowrite8(priv, SW_3W_CMD1, tmp);
163                 for (i = 0; i < 5; i++) {
164                         tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
165                         if (!(tmp & 0x3))
166                                 break;
167                         udelay(10);
168                 }
169                 rtl818x_iowrite8(priv, SW_3W_CMD1, 0);
170                 if (!write) {
171                         *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG);
172                         *((u16 *)data) &= 0x0FFF;
173                 }
174         } while (0);
175 }
176
177 static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr)
178 {
179         u32 dataread = addr & 0x0F;
180         rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0);
181         return dataread;
182 }
183
184 static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data)
185 {
186         u32 outdata = (data << 4) | (u32)(addr & 0x0F);
187         rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1);
188 }
189
190
191 static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev)
192 {
193         int i;
194
195         for (i = 0; i < 128; i++) {
196                 rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]);
197                 rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80);
198                 rtl8225se_write_phy_ofdm(dev, 0xE, 0);
199         }
200 }
201
202 static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev)
203 {
204         /* write OFDM_CONFIG table */
205         int i;
206
207         for (i = 0; i < 60; i++)
208                 rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]);
209
210 }
211
212 static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
213 {
214         struct rtl8180_priv *priv = dev->priv;
215         u8 cck_power, ofdm_power;
216
217         cck_power = priv->channels[channel - 1].hw_value & 0xFF;
218         if (cck_power > 35)
219                 cck_power = 35;
220         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
221                          cck_ofdm_gain_settings[cck_power]);
222
223         usleep_range(1000, 5000);
224         ofdm_power = priv->channels[channel - 1].hw_value >> 8;
225         if (ofdm_power > 35)
226                 ofdm_power = 35;
227
228         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
229                          cck_ofdm_gain_settings[ofdm_power]);
230         if (ofdm_power < 12) {
231                 rtl8225se_write_phy_ofdm(dev, 7, 0x5C);
232                 rtl8225se_write_phy_ofdm(dev, 9, 0x5C);
233         }
234         if (ofdm_power < 18) {
235                 rtl8225se_write_phy_ofdm(dev, 7, 0x54);
236                 rtl8225se_write_phy_ofdm(dev, 9, 0x54);
237         } else {
238                 rtl8225se_write_phy_ofdm(dev, 7, 0x50);
239                 rtl8225se_write_phy_ofdm(dev, 9, 0x50);
240         }
241
242         usleep_range(1000, 5000);
243 }
244
245 static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev)
246 {
247         int i;
248
249         for (i = 0; i <= 36; i++) {
250                 rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1);
251                 rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1);
252         }
253 }
254
255 static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev,
256                                         int init_gain)
257 {
258         switch (init_gain) {
259         default:
260                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
261                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
262                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
263                 break;
264         case 2:
265                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
266                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
267                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
268                 break;
269         case 3:
270                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
271                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
272                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
273                 break;
274         case 4:
275                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
276                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
277                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
278                 break;
279         case 5:
280                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
281                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
282                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
283                 break;
284         case 6:
285                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
286                 rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
287                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
288                 break;
289         case 7:
290                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
291                 rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1);
292                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
293                 break;
294         case 8:
295                 rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
296                 rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1);
297                 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
298                 break;
299         }
300 }
301
302 void rtl8225se_rf_init(struct ieee80211_hw *dev)
303 {
304         struct rtl8180_priv *priv = dev->priv;
305         u32 rf23, rf24;
306         u8 d_cut = 0;
307         u8 tmp;
308
309         /* Page 1 */
310         rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
311         rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1);
312         rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1);
313         if (rf23 == 0x0818 && rf24 == 0x070C)
314                 d_cut = 1;
315
316         wiphy_info(dev->wiphy, "RTL8225-SE version %s\n",
317                 d_cut ? "D" : "not-D");
318
319         /* Page 0: reg 0 - 15 */
320         rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
321         rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1);
322         rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
323         rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1);
324         rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1);
325         rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1);
326         rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1);
327         rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1);
328         rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1);
329         rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1);
330         rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1);
331         rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1);
332         rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1);
333         rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
334         rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1);
335         rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1);
336         /* page 1: reg 16-30 */
337         rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
338         rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1);
339         rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1);
340         rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1);
341         rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1);
342         rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1);
343         rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
344         rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1);
345         rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1);
346         rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1);
347         if (d_cut)
348                 rtl8187se_rf_writereg(dev, 0x0E, 0x0807);
349         else
350                 rtl8187se_rf_writereg(dev, 0x0E, 0x0806);
351         mdelay(1);
352         rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1);
353         rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1);
354         rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1);
355         rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1);
356
357         rtl8187se_write_rf_gain(dev);
358
359         rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1);
360         rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1);
361         rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
362         rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11);
363         rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11);
364         rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11);
365         rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11);
366         rtl8187se_rf_writereg(dev, 0x02, 0x088D); mdelay(221);
367         rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
368         rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1);
369         rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1);
370         rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1);
371         rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1);
372         rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1);
373         rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
374         if (priv->xtal_cal) {
375                 tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) |
376                       (1 << 11) | (1 << 9);
377                 rtl8187se_rf_writereg(dev, 0x0F, tmp);
378                 wiphy_info(dev->wiphy, "Xtal cal\n");
379                 mdelay(1);
380         } else {
381                 wiphy_info(dev->wiphy, "NO Xtal cal\n");
382                 rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC);
383                 mdelay(1);
384         }
385         /* page 0 */
386         rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1);
387         rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
388         rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
389         rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(31);
390         rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1);
391         rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1);
392
393         rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
394         rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1);
395         rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1);
396         /* power save parameters */
397         /* TODO: move to dev.c */
398         rtl818x_iowrite8(priv, REG_ADDR1(0x024E),
399                  rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F);
400         rtl8225se_write_phy_cck(dev, 0x00, 0xC8);
401         rtl8225se_write_phy_cck(dev, 0x06, 0x1C);
402         rtl8225se_write_phy_cck(dev, 0x10, 0x78);
403         rtl8225se_write_phy_cck(dev, 0x2E, 0xD0);
404         rtl8225se_write_phy_cck(dev, 0x2F, 0x06);
405         rtl8225se_write_phy_cck(dev, 0x01, 0x46);
406
407         /* power control */
408         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10);
409         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B);
410
411         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
412         rtl8225se_write_phy_ofdm(dev, 0x00, 0x12);
413
414         rtl8225se_write_zebra_agc(dev);
415
416         rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
417
418         rtl8187se_write_ofdm_config(dev);
419
420         /* turn on RF */
421         rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
422         rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
423         /* turn on RF again */
424         rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
425         rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
426         /* turn on BB */
427         rtl8225se_write_phy_ofdm(dev, 0x10, 0x40);
428         rtl8225se_write_phy_ofdm(dev, 0x12, 0x40);
429
430         rtl8187se_write_initial_gain(dev, 4);
431 }
432
433 void rtl8225se_rf_stop(struct ieee80211_hw *dev)
434 {
435         /* checked for 8187se */
436         struct rtl8180_priv *priv = dev->priv;
437
438         /* turn off BB RXIQ matrix to cut off rx signal */
439         rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
440         rtl8225se_write_phy_ofdm(dev, 0x12, 0x00);
441         /* turn off RF */
442         rtl8187se_rf_writereg(dev, 0x04, 0x0000);
443         rtl8187se_rf_writereg(dev, 0x00, 0x0000);
444
445         usleep_range(1000, 5000);
446         /* turn off A/D and D/A */
447         rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF);
448         rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF);
449 }
450
451 void rtl8225se_rf_set_channel(struct ieee80211_hw *dev,
452                                    struct ieee80211_conf *conf)
453 {
454         int chan =
455                 ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
456
457         rtl8225sez2_rf_set_tx_power(dev, chan);
458         rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
459         if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) !=
460                 rtl8225se_chan[chan - 1])
461                 rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
462         usleep_range(10000, 20000);
463 }
464
465 static const struct rtl818x_rf_ops rtl8225se_ops = {
466         .name           = "rtl8225-se",
467         .init           = rtl8225se_rf_init,
468         .stop           = rtl8225se_rf_stop,
469         .set_chan       = rtl8225se_rf_set_channel,
470 };
471
472 const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev)
473 {
474         return &rtl8225se_ops;
475 }