linux/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c
<<
>>
Prefs
   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
  26static 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
  34static 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
  43static const u8 rtl8225se_tx_gain_cck_ofdm[] = {
  44        0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
  45};
  46
  47static 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
  56static 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
  65static const u8 rtl8225se_tx_power_ofdm[] = {
  66        0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
  67};
  68
  69static const u32 rtl8225se_chan[] = {
  70        0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
  71        0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
  72};
  73
  74static const u8 rtl8225sez2_tx_power_cck_ch14[] = {
  75        0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
  76};
  77
  78static const u8 rtl8225sez2_tx_power_cck_B[] = {
  79        0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
  80};
  81
  82static const u8 rtl8225sez2_tx_power_cck_A[] = {
  83        0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
  84};
  85
  86static const u8 rtl8225sez2_tx_power_cck[] = {
  87        0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
  88};
  89
  90static 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
 109static 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
 120static 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
 177static 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
 184static 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
 191static 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
 202static 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
 212static 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
 245static 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
 255static 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
 302void 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
 433void 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
 451void 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
 465static 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
 472const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev)
 473{
 474        return &rtl8225se_ops;
 475}
 476