Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 /* Radio tuning for RTL8225 on RTL8187SE
0004  *
0005  * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
0006  * Copyright 2014 Andrea Merello <andrea.merello@gmail.com>
0007  *
0008  * Based on the r8180 and Realtek r8187se drivers, which are:
0009  * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
0010  *
0011  * Also based on the rtl8187 driver, which is:
0012  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
0013  * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
0014  */
0015 
0016 #include <net/mac80211.h>
0017 
0018 #include "rtl8180.h"
0019 #include "rtl8225se.h"
0020 
0021 #define PFX "rtl8225 (se) "
0022 
0023 static const u32 RF_GAIN_TABLE[] = {
0024     0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
0025     0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
0026     0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
0027     0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
0028     0x0183, 0x0163, 0x0143, 0x0123, 0x0103
0029 };
0030 
0031 static const u8 cck_ofdm_gain_settings[] = {
0032     0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0033     0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0034     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0035     0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0036     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0037     0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0038 };
0039 
0040 static const u32 rtl8225se_chan[] = {
0041     0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
0042     0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
0043 };
0044 
0045 static const u8 ZEBRA_AGC[] = {
0046     0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A,
0047     0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
0048     0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
0049     0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
0050     0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27,
0051     0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
0052     0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00,
0053     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0054     0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0055     0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
0056     0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b,
0057     0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
0058     0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21,
0059     0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
0060     0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0061     0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
0062 };
0063 
0064 static const u8 OFDM_CONFIG[] = {
0065     0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
0066     0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
0067     0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
0068     0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
0069     0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
0070     0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
0071     0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
0072     0xD8, 0x3C, 0x7B, 0x10, 0x10
0073 };
0074 
0075 static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data,
0076                     u8 len, bool write)
0077 {
0078     struct rtl8180_priv *priv = dev->priv;
0079     int i;
0080     u8 tmp;
0081 
0082     do {
0083         for (i = 0; i < 5; i++) {
0084             tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
0085             if (!(tmp & 0x3))
0086                 break;
0087             udelay(10);
0088         }
0089         if (i == 5)
0090             wiphy_err(dev->wiphy, PFX
0091                 "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp);
0092 
0093         tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02;
0094         rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp);
0095 
0096         tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7;
0097         rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp);
0098         if (write) {
0099             if (len == 16) {
0100                 rtl818x_iowrite16(priv, SW_3W_DB0,
0101                   *(u16 *)data);
0102             } else if (len == 64) {
0103                 rtl818x_iowrite32(priv, SW_3W_DB0_4,
0104                   *((u32 *)data));
0105                 rtl818x_iowrite32(priv, SW_3W_DB1_4,
0106                   *((u32 *)(data + 4)));
0107             } else
0108                 wiphy_err(dev->wiphy, PFX
0109                     "Unimplemented length\n");
0110         } else {
0111             rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data);
0112         }
0113         if (write)
0114             tmp = 2;
0115         else
0116             tmp = 1;
0117         rtl818x_iowrite8(priv, SW_3W_CMD1, tmp);
0118         for (i = 0; i < 5; i++) {
0119             tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
0120             if (!(tmp & 0x3))
0121                 break;
0122             udelay(10);
0123         }
0124         rtl818x_iowrite8(priv, SW_3W_CMD1, 0);
0125         if (!write) {
0126             *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG);
0127             *((u16 *)data) &= 0x0FFF;
0128         }
0129     } while (0);
0130 }
0131 
0132 static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr)
0133 {
0134     u32 dataread = addr & 0x0F;
0135     rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0);
0136     return dataread;
0137 }
0138 
0139 static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data)
0140 {
0141     u32 outdata = (data << 4) | (u32)(addr & 0x0F);
0142     rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1);
0143 }
0144 
0145 
0146 static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev)
0147 {
0148     int i;
0149 
0150     for (i = 0; i < 128; i++) {
0151         rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]);
0152         rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80);
0153         rtl8225se_write_phy_ofdm(dev, 0xE, 0);
0154     }
0155 }
0156 
0157 static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev)
0158 {
0159     /* write OFDM_CONFIG table */
0160     int i;
0161 
0162     for (i = 0; i < 60; i++)
0163         rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]);
0164 
0165 }
0166 
0167 static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
0168 {
0169     struct rtl8180_priv *priv = dev->priv;
0170     u8 cck_power, ofdm_power;
0171 
0172     cck_power = priv->channels[channel - 1].hw_value & 0xFF;
0173     if (cck_power > 35)
0174         cck_power = 35;
0175     rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
0176              cck_ofdm_gain_settings[cck_power]);
0177 
0178     usleep_range(1000, 5000);
0179     ofdm_power = priv->channels[channel - 1].hw_value >> 8;
0180     if (ofdm_power > 35)
0181         ofdm_power = 35;
0182 
0183     rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
0184              cck_ofdm_gain_settings[ofdm_power]);
0185     if (ofdm_power < 12) {
0186         rtl8225se_write_phy_ofdm(dev, 7, 0x5C);
0187         rtl8225se_write_phy_ofdm(dev, 9, 0x5C);
0188     }
0189     if (ofdm_power < 18) {
0190         rtl8225se_write_phy_ofdm(dev, 7, 0x54);
0191         rtl8225se_write_phy_ofdm(dev, 9, 0x54);
0192     } else {
0193         rtl8225se_write_phy_ofdm(dev, 7, 0x50);
0194         rtl8225se_write_phy_ofdm(dev, 9, 0x50);
0195     }
0196 
0197     usleep_range(1000, 5000);
0198 }
0199 
0200 static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev)
0201 {
0202     int i;
0203 
0204     for (i = 0; i <= 36; i++) {
0205         rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1);
0206         rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1);
0207     }
0208 }
0209 
0210 static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev,
0211                     int init_gain)
0212 {
0213     switch (init_gain) {
0214     default:
0215         rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
0216         rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0217         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
0218         break;
0219     case 2:
0220         rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
0221         rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0222         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
0223         break;
0224     case 3:
0225         rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
0226         rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0227         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0228         break;
0229     case 4:
0230         rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
0231         rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0232         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0233         break;
0234     case 5:
0235         rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
0236         rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
0237         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0238         break;
0239     case 6:
0240         rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
0241         rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
0242         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0243         break;
0244     case 7:
0245         rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
0246         rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1);
0247         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0248         break;
0249     case 8:
0250         rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
0251         rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1);
0252         rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0253         break;
0254     }
0255 }
0256 
0257 void rtl8225se_rf_init(struct ieee80211_hw *dev)
0258 {
0259     struct rtl8180_priv *priv = dev->priv;
0260     u32 rf23, rf24;
0261     u8 d_cut = 0;
0262     u8 tmp;
0263 
0264     /* Page 1 */
0265     rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
0266     rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1);
0267     rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1);
0268     if (rf23 == 0x0818 && rf24 == 0x070C)
0269         d_cut = 1;
0270 
0271     wiphy_info(dev->wiphy, "RTL8225-SE version %s\n",
0272         d_cut ? "D" : "not-D");
0273 
0274     /* Page 0: reg 0 - 15 */
0275     rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
0276     rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1);
0277     rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
0278     rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1);
0279     rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1);
0280     rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1);
0281     rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1);
0282     rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1);
0283     rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1);
0284     rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1);
0285     rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1);
0286     rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1);
0287     rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1);
0288     rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
0289     rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1);
0290     rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1);
0291     /* page 1: reg 16-30 */
0292     rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
0293     rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1);
0294     rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1);
0295     rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1);
0296     rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1);
0297     rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1);
0298     rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
0299     rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1);
0300     rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1);
0301     rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1);
0302     if (d_cut)
0303         rtl8187se_rf_writereg(dev, 0x0E, 0x0807);
0304     else
0305         rtl8187se_rf_writereg(dev, 0x0E, 0x0806);
0306     mdelay(1);
0307     rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1);
0308     rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1);
0309     rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1);
0310     rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1);
0311 
0312     rtl8187se_write_rf_gain(dev);
0313 
0314     rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1);
0315     rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1);
0316     rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
0317     rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11);
0318     rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11);
0319     rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11);
0320     rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11);
0321     rtl8187se_rf_writereg(dev, 0x02, 0x088D); msleep(221);
0322     rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
0323     rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1);
0324     rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1);
0325     rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1);
0326     rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1);
0327     rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1);
0328     rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
0329     if (priv->xtal_cal) {
0330         tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) |
0331               (1 << 11) | (1 << 9);
0332         rtl8187se_rf_writereg(dev, 0x0F, tmp);
0333         wiphy_info(dev->wiphy, "Xtal cal\n");
0334         mdelay(1);
0335     } else {
0336         wiphy_info(dev->wiphy, "NO Xtal cal\n");
0337         rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC);
0338         mdelay(1);
0339     }
0340     /* page 0 */
0341     rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1);
0342     rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
0343     rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
0344     rtl8187se_rf_writereg(dev, 0x04, 0x0975); msleep(31);
0345     rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1);
0346     rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1);
0347 
0348     rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
0349     rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1);
0350     rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1);
0351     /* power save parameters */
0352     /* TODO: move to dev.c */
0353     rtl818x_iowrite8(priv, REG_ADDR1(0x024E),
0354          rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F);
0355     rtl8225se_write_phy_cck(dev, 0x00, 0xC8);
0356     rtl8225se_write_phy_cck(dev, 0x06, 0x1C);
0357     rtl8225se_write_phy_cck(dev, 0x10, 0x78);
0358     rtl8225se_write_phy_cck(dev, 0x2E, 0xD0);
0359     rtl8225se_write_phy_cck(dev, 0x2F, 0x06);
0360     rtl8225se_write_phy_cck(dev, 0x01, 0x46);
0361 
0362     /* power control */
0363     rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10);
0364     rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B);
0365 
0366     rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
0367     rtl8225se_write_phy_ofdm(dev, 0x00, 0x12);
0368 
0369     rtl8225se_write_zebra_agc(dev);
0370 
0371     rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
0372 
0373     rtl8187se_write_ofdm_config(dev);
0374 
0375     /* turn on RF */
0376     rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
0377     rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
0378     /* turn on RF again */
0379     rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
0380     rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
0381     /* turn on BB */
0382     rtl8225se_write_phy_ofdm(dev, 0x10, 0x40);
0383     rtl8225se_write_phy_ofdm(dev, 0x12, 0x40);
0384 
0385     rtl8187se_write_initial_gain(dev, 4);
0386 }
0387 
0388 void rtl8225se_rf_stop(struct ieee80211_hw *dev)
0389 {
0390     /* checked for 8187se */
0391     struct rtl8180_priv *priv = dev->priv;
0392 
0393     /* turn off BB RXIQ matrix to cut off rx signal */
0394     rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
0395     rtl8225se_write_phy_ofdm(dev, 0x12, 0x00);
0396     /* turn off RF */
0397     rtl8187se_rf_writereg(dev, 0x04, 0x0000);
0398     rtl8187se_rf_writereg(dev, 0x00, 0x0000);
0399 
0400     usleep_range(1000, 5000);
0401     /* turn off A/D and D/A */
0402     rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF);
0403     rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF);
0404 }
0405 
0406 void rtl8225se_rf_set_channel(struct ieee80211_hw *dev,
0407                    struct ieee80211_conf *conf)
0408 {
0409     int chan =
0410         ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
0411 
0412     rtl8225sez2_rf_set_tx_power(dev, chan);
0413     rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
0414     if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) !=
0415         rtl8225se_chan[chan - 1])
0416         rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
0417     usleep_range(10000, 20000);
0418 }
0419 
0420 static const struct rtl818x_rf_ops rtl8225se_ops = {
0421     .name       = "rtl8225-se",
0422     .init       = rtl8225se_rf_init,
0423     .stop       = rtl8225se_rf_stop,
0424     .set_chan   = rtl8225se_rf_set_channel,
0425 };
0426 
0427 const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev)
0428 {
0429     return &rtl8225se_ops;
0430 }