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