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 } 476