linux/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Radio tuning for RTL8225 on RTL8187
   4 *
   5 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
   6 * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
   7 *
   8 * Based on the r8187 driver, which is:
   9 * Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
  10 *
  11 * Magic delays, register offsets, and phy value tables below are
  12 * taken from the original r8187 driver sources.  Thanks to Realtek
  13 * for their support!
  14 */
  15
  16#include <linux/usb.h>
  17#include <net/mac80211.h>
  18
  19#include "rtl8187.h"
  20#include "rtl8225.h"
  21
  22u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
  23                                u8 *addr, u8 idx)
  24{
  25        u8 val;
  26
  27        mutex_lock(&priv->io_mutex);
  28        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  29                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  30                        (unsigned long)addr, idx & 0x03,
  31                        &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
  32
  33        val = priv->io_dmabuf->bits8;
  34        mutex_unlock(&priv->io_mutex);
  35
  36        return val;
  37}
  38
  39u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
  40                                __le16 *addr, u8 idx)
  41{
  42        __le16 val;
  43
  44        mutex_lock(&priv->io_mutex);
  45        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  46                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  47                        (unsigned long)addr, idx & 0x03,
  48                        &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
  49
  50        val = priv->io_dmabuf->bits16;
  51        mutex_unlock(&priv->io_mutex);
  52
  53        return le16_to_cpu(val);
  54}
  55
  56u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
  57                                __le32 *addr, u8 idx)
  58{
  59        __le32 val;
  60
  61        mutex_lock(&priv->io_mutex);
  62        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  63                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  64                        (unsigned long)addr, idx & 0x03,
  65                        &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
  66
  67        val = priv->io_dmabuf->bits32;
  68        mutex_unlock(&priv->io_mutex);
  69
  70        return le32_to_cpu(val);
  71}
  72
  73void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
  74                                u8 *addr, u8 val, u8 idx)
  75{
  76        mutex_lock(&priv->io_mutex);
  77
  78        priv->io_dmabuf->bits8 = val;
  79        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  80                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  81                        (unsigned long)addr, idx & 0x03,
  82                        &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
  83
  84        mutex_unlock(&priv->io_mutex);
  85}
  86
  87void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
  88                                __le16 *addr, u16 val, u8 idx)
  89{
  90        mutex_lock(&priv->io_mutex);
  91
  92        priv->io_dmabuf->bits16 = cpu_to_le16(val);
  93        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  94                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  95                        (unsigned long)addr, idx & 0x03,
  96                        &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
  97
  98        mutex_unlock(&priv->io_mutex);
  99}
 100
 101void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
 102                                __le32 *addr, u32 val, u8 idx)
 103{
 104        mutex_lock(&priv->io_mutex);
 105
 106        priv->io_dmabuf->bits32 = cpu_to_le32(val);
 107        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 108                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 109                        (unsigned long)addr, idx & 0x03,
 110                        &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
 111
 112        mutex_unlock(&priv->io_mutex);
 113}
 114
 115static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
 116{
 117        struct rtl8187_priv *priv = dev->priv;
 118        u16 reg80, reg84, reg82;
 119        u32 bangdata;
 120        int i;
 121
 122        bangdata = (data << 4) | (addr & 0xf);
 123
 124        reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
 125        reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 126
 127        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
 128
 129        reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 130        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
 131        udelay(10);
 132
 133        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 134        udelay(2);
 135        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 136        udelay(10);
 137
 138        for (i = 15; i >= 0; i--) {
 139                u16 reg = reg80 | (bangdata & (1 << i)) >> i;
 140
 141                if (i & 1)
 142                        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 143
 144                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
 145                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
 146
 147                if (!(i & 1))
 148                        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 149        }
 150
 151        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 152        udelay(10);
 153
 154        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 155        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 156}
 157
 158static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
 159{
 160        struct rtl8187_priv *priv = dev->priv;
 161        u16 reg80, reg82, reg84;
 162
 163        reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
 164        reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 165        reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 166
 167        reg80 &= ~(0x3 << 2);
 168        reg84 &= ~0xF;
 169
 170        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
 171        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
 172        udelay(10);
 173
 174        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 175        udelay(2);
 176
 177        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 178        udelay(10);
 179
 180        mutex_lock(&priv->io_mutex);
 181
 182        priv->io_dmabuf->bits16 = data;
 183        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 184                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 185                        addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
 186                        HZ / 2);
 187
 188        mutex_unlock(&priv->io_mutex);
 189
 190        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 191        udelay(10);
 192
 193        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 194        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 195}
 196
 197static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
 198{
 199        struct rtl8187_priv *priv = dev->priv;
 200
 201        if (priv->asic_rev)
 202                rtl8225_write_8051(dev, addr, cpu_to_le16(data));
 203        else
 204                rtl8225_write_bitbang(dev, addr, data);
 205}
 206
 207static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
 208{
 209        struct rtl8187_priv *priv = dev->priv;
 210        u16 reg80, reg82, reg84, out;
 211        int i;
 212
 213        reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
 214        reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 215        reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 216
 217        reg80 &= ~0xF;
 218
 219        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
 220        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
 221
 222        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 223        udelay(4);
 224        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 225        udelay(5);
 226
 227        for (i = 4; i >= 0; i--) {
 228                u16 reg = reg80 | ((addr >> i) & 1);
 229
 230                if (!(i & 1)) {
 231                        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 232                        udelay(1);
 233                }
 234
 235                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 236                                  reg | (1 << 1));
 237                udelay(2);
 238                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 239                                  reg | (1 << 1));
 240                udelay(2);
 241
 242                if (i & 1) {
 243                        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 244                        udelay(1);
 245                }
 246        }
 247
 248        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 249                          reg80 | (1 << 3) | (1 << 1));
 250        udelay(2);
 251        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 252                          reg80 | (1 << 3));
 253        udelay(2);
 254        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 255                          reg80 | (1 << 3));
 256        udelay(2);
 257
 258        out = 0;
 259        for (i = 11; i >= 0; i--) {
 260                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 261                                  reg80 | (1 << 3));
 262                udelay(1);
 263                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 264                                  reg80 | (1 << 3) | (1 << 1));
 265                udelay(2);
 266                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 267                                  reg80 | (1 << 3) | (1 << 1));
 268                udelay(2);
 269                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 270                                  reg80 | (1 << 3) | (1 << 1));
 271                udelay(2);
 272
 273                if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
 274                        out |= 1 << i;
 275
 276                rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 277                                  reg80 | (1 << 3));
 278                udelay(2);
 279        }
 280
 281        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 282                          reg80 | (1 << 3) | (1 << 2));
 283        udelay(2);
 284
 285        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
 286        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 287        rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
 288
 289        return out;
 290}
 291
 292static const u16 rtl8225bcd_rxgain[] = {
 293        0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
 294        0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
 295        0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
 296        0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
 297        0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
 298        0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
 299        0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
 300        0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
 301        0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
 302        0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
 303        0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
 304        0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
 305};
 306
 307static const u8 rtl8225_agc[] = {
 308        0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
 309        0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
 310        0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
 311        0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
 312        0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
 313        0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
 314        0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
 315        0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
 316        0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
 317        0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
 318        0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
 319        0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
 320        0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
 321        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
 322        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
 323        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
 324};
 325
 326static const u8 rtl8225_gain[] = {
 327        0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
 328        0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
 329        0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
 330        0x33, 0x80, 0x79, 0xc5, /* -78dBm */
 331        0x43, 0x78, 0x76, 0xc5, /* -74dBm */
 332        0x53, 0x60, 0x73, 0xc5, /* -70dBm */
 333        0x63, 0x58, 0x70, 0xc5, /* -66dBm */
 334};
 335
 336static const u8 rtl8225_threshold[] = {
 337        0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
 338};
 339
 340static const u8 rtl8225_tx_gain_cck_ofdm[] = {
 341        0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
 342};
 343
 344static const u8 rtl8225_tx_power_cck[] = {
 345        0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
 346        0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
 347        0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
 348        0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
 349        0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
 350        0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
 351};
 352
 353static const u8 rtl8225_tx_power_cck_ch14[] = {
 354        0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
 355        0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
 356        0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
 357        0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
 358        0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
 359        0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
 360};
 361
 362static const u8 rtl8225_tx_power_ofdm[] = {
 363        0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
 364};
 365
 366static const u32 rtl8225_chan[] = {
 367        0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
 368        0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
 369};
 370
 371static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 372{
 373        struct rtl8187_priv *priv = dev->priv;
 374        u8 cck_power, ofdm_power;
 375        const u8 *tmp;
 376        u32 reg;
 377        int i;
 378
 379        cck_power = priv->channels[channel - 1].hw_value & 0xF;
 380        ofdm_power = priv->channels[channel - 1].hw_value >> 4;
 381
 382        cck_power = min(cck_power, (u8)11);
 383        if (ofdm_power > (u8)15)
 384                ofdm_power = 25;
 385        else
 386                ofdm_power += 10;
 387
 388        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 389                         rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
 390
 391        if (channel == 14)
 392                tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
 393        else
 394                tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
 395
 396        for (i = 0; i < 8; i++)
 397                rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 398
 399        msleep(1); // FIXME: optional?
 400
 401        /* anaparam2 on */
 402        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 403        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
 404        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
 405                        reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
 406        rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
 407                          RTL8187_RTL8225_ANAPARAM2_ON);
 408        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
 409                        reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
 410        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 411
 412        rtl8225_write_phy_ofdm(dev, 2, 0x42);
 413        rtl8225_write_phy_ofdm(dev, 6, 0x00);
 414        rtl8225_write_phy_ofdm(dev, 8, 0x00);
 415
 416        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 417                         rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
 418
 419        tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
 420
 421        rtl8225_write_phy_ofdm(dev, 5, *tmp);
 422        rtl8225_write_phy_ofdm(dev, 7, *tmp);
 423
 424        msleep(1);
 425}
 426
 427static void rtl8225_rf_init(struct ieee80211_hw *dev)
 428{
 429        struct rtl8187_priv *priv = dev->priv;
 430        int i;
 431
 432        rtl8225_write(dev, 0x0, 0x067);
 433        rtl8225_write(dev, 0x1, 0xFE0);
 434        rtl8225_write(dev, 0x2, 0x44D);
 435        rtl8225_write(dev, 0x3, 0x441);
 436        rtl8225_write(dev, 0x4, 0x486);
 437        rtl8225_write(dev, 0x5, 0xBC0);
 438        rtl8225_write(dev, 0x6, 0xAE6);
 439        rtl8225_write(dev, 0x7, 0x82A);
 440        rtl8225_write(dev, 0x8, 0x01F);
 441        rtl8225_write(dev, 0x9, 0x334);
 442        rtl8225_write(dev, 0xA, 0xFD4);
 443        rtl8225_write(dev, 0xB, 0x391);
 444        rtl8225_write(dev, 0xC, 0x050);
 445        rtl8225_write(dev, 0xD, 0x6DB);
 446        rtl8225_write(dev, 0xE, 0x029);
 447        rtl8225_write(dev, 0xF, 0x914); msleep(100);
 448
 449        rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
 450        rtl8225_write(dev, 0x2, 0x44D); msleep(200);
 451
 452        if (!(rtl8225_read(dev, 6) & (1 << 7))) {
 453                rtl8225_write(dev, 0x02, 0x0c4d);
 454                msleep(200);
 455                rtl8225_write(dev, 0x02, 0x044d);
 456                msleep(100);
 457                if (!(rtl8225_read(dev, 6) & (1 << 7)))
 458                        wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
 459                                   rtl8225_read(dev, 6));
 460        }
 461
 462        rtl8225_write(dev, 0x0, 0x127);
 463
 464        for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
 465                rtl8225_write(dev, 0x1, i + 1);
 466                rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
 467        }
 468
 469        rtl8225_write(dev, 0x0, 0x027);
 470        rtl8225_write(dev, 0x0, 0x22F);
 471
 472        for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 473                rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
 474                rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
 475        }
 476
 477        msleep(1);
 478
 479        rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
 480        rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
 481        rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
 482        rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
 483        rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
 484        rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
 485        rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
 486        rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
 487        rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
 488        rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
 489        rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
 490        rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
 491        rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
 492        rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
 493        rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
 494        rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
 495        rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
 496        rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
 497        rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
 498        rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
 499        rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
 500        rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
 501        rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
 502        rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
 503        rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
 504        rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
 505        rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
 506        rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
 507        rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
 508        rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
 509        rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
 510        rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
 511        rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
 512        rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
 513        rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
 514        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
 515        rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
 516
 517        rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
 518        rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
 519        rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
 520        rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
 521
 522        rtl8225_write_phy_cck(dev, 0x00, 0x98);
 523        rtl8225_write_phy_cck(dev, 0x03, 0x20);
 524        rtl8225_write_phy_cck(dev, 0x04, 0x7e);
 525        rtl8225_write_phy_cck(dev, 0x05, 0x12);
 526        rtl8225_write_phy_cck(dev, 0x06, 0xfc);
 527        rtl8225_write_phy_cck(dev, 0x07, 0x78);
 528        rtl8225_write_phy_cck(dev, 0x08, 0x2e);
 529        rtl8225_write_phy_cck(dev, 0x10, 0x9b);
 530        rtl8225_write_phy_cck(dev, 0x11, 0x88);
 531        rtl8225_write_phy_cck(dev, 0x12, 0x47);
 532        rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 533        rtl8225_write_phy_cck(dev, 0x19, 0x00);
 534        rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 535        rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 536        rtl8225_write_phy_cck(dev, 0x40, 0x86);
 537        rtl8225_write_phy_cck(dev, 0x41, 0x8d);
 538        rtl8225_write_phy_cck(dev, 0x42, 0x15);
 539        rtl8225_write_phy_cck(dev, 0x43, 0x18);
 540        rtl8225_write_phy_cck(dev, 0x44, 0x1f);
 541        rtl8225_write_phy_cck(dev, 0x45, 0x1e);
 542        rtl8225_write_phy_cck(dev, 0x46, 0x1a);
 543        rtl8225_write_phy_cck(dev, 0x47, 0x15);
 544        rtl8225_write_phy_cck(dev, 0x48, 0x10);
 545        rtl8225_write_phy_cck(dev, 0x49, 0x0a);
 546        rtl8225_write_phy_cck(dev, 0x4a, 0x05);
 547        rtl8225_write_phy_cck(dev, 0x4b, 0x02);
 548        rtl8225_write_phy_cck(dev, 0x4c, 0x05);
 549
 550        rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
 551
 552        rtl8225_rf_set_tx_power(dev, 1);
 553
 554        /* RX antenna default to A */
 555        rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
 556        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
 557
 558        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
 559        msleep(1);
 560        rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
 561
 562        /* set sensitivity */
 563        rtl8225_write(dev, 0x0c, 0x50);
 564        rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
 565        rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
 566        rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
 567        rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
 568        rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
 569}
 570
 571static const u8 rtl8225z2_agc[] = {
 572        0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
 573        0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
 574        0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
 575        0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
 576        0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
 577        0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
 578        0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
 579        0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
 580        0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
 581        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
 582        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
 583};
 584static const u8 rtl8225z2_ofdm[] = {
 585        0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
 586        0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
 587        0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
 588        0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
 589        0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
 590        0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
 591        0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
 592        0x6d, 0x3c, 0xfb, 0x07
 593};
 594
 595static const u8 rtl8225z2_tx_power_cck_ch14[] = {
 596        0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
 597        0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
 598        0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
 599        0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
 600};
 601
 602static const u8 rtl8225z2_tx_power_cck[] = {
 603        0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
 604        0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
 605        0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
 606        0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
 607};
 608
 609static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
 610        0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
 611        0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
 612        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
 613        0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
 614        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
 615        0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
 616};
 617
 618static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 619{
 620        struct rtl8187_priv *priv = dev->priv;
 621        u8 cck_power, ofdm_power;
 622        const u8 *tmp;
 623        u32 reg;
 624        int i;
 625
 626        cck_power = priv->channels[channel - 1].hw_value & 0xF;
 627        ofdm_power = priv->channels[channel - 1].hw_value >> 4;
 628
 629        cck_power = min(cck_power, (u8)15);
 630        cck_power += priv->txpwr_base & 0xF;
 631        cck_power = min(cck_power, (u8)35);
 632
 633        if (ofdm_power > (u8)15)
 634                ofdm_power = 25;
 635        else
 636                ofdm_power += 10;
 637        ofdm_power += priv->txpwr_base >> 4;
 638        ofdm_power = min(ofdm_power, (u8)35);
 639
 640        if (channel == 14)
 641                tmp = rtl8225z2_tx_power_cck_ch14;
 642        else
 643                tmp = rtl8225z2_tx_power_cck;
 644
 645        for (i = 0; i < 8; i++)
 646                rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 647
 648        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 649                         rtl8225z2_tx_gain_cck_ofdm[cck_power]);
 650        msleep(1);
 651
 652        /* anaparam2 on */
 653        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 654        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
 655        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
 656                        reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
 657        rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
 658                          RTL8187_RTL8225_ANAPARAM2_ON);
 659        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
 660                        reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
 661        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 662
 663        rtl8225_write_phy_ofdm(dev, 2, 0x42);
 664        rtl8225_write_phy_ofdm(dev, 5, 0x00);
 665        rtl8225_write_phy_ofdm(dev, 6, 0x40);
 666        rtl8225_write_phy_ofdm(dev, 7, 0x00);
 667        rtl8225_write_phy_ofdm(dev, 8, 0x40);
 668
 669        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 670                         rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
 671        msleep(1);
 672}
 673
 674static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 675{
 676        struct rtl8187_priv *priv = dev->priv;
 677        u8 cck_power, ofdm_power;
 678        const u8 *tmp;
 679        int i;
 680
 681        cck_power = priv->channels[channel - 1].hw_value & 0xF;
 682        ofdm_power = priv->channels[channel - 1].hw_value >> 4;
 683
 684        cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
 685        cck_power += priv->txpwr_base & 0xF;
 686        cck_power = min(cck_power, (u8)35);
 687
 688        if (ofdm_power > 15)
 689                ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
 690        else
 691                ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
 692        ofdm_power += (priv->txpwr_base >> 4) & 0xF;
 693        ofdm_power = min(ofdm_power, (u8)35);
 694
 695        if (channel == 14)
 696                tmp = rtl8225z2_tx_power_cck_ch14;
 697        else
 698                tmp = rtl8225z2_tx_power_cck;
 699
 700        if (priv->hw_rev == RTL8187BvB) {
 701                if (cck_power <= 6)
 702                        ; /* do nothing */
 703                else if (cck_power <= 11)
 704                        tmp += 8;
 705                else
 706                        tmp += 16;
 707        } else {
 708                if (cck_power <= 5)
 709                        ; /* do nothing */
 710                else if (cck_power <= 11)
 711                        tmp += 8;
 712                else if (cck_power <= 17)
 713                        tmp += 16;
 714                else
 715                        tmp += 24;
 716        }
 717
 718        for (i = 0; i < 8; i++)
 719                rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 720
 721        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 722                         rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
 723        msleep(1);
 724
 725        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 726                         rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
 727        if (priv->hw_rev == RTL8187BvB) {
 728                if (ofdm_power <= 11) {
 729                        rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
 730                        rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
 731                } else {
 732                        rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
 733                        rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
 734                }
 735        } else {
 736                if (ofdm_power <= 11) {
 737                        rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
 738                        rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
 739                } else if (ofdm_power <= 17) {
 740                        rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
 741                        rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
 742                } else {
 743                        rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
 744                        rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
 745                }
 746        }
 747        msleep(1);
 748}
 749
 750static const u16 rtl8225z2_rxgain[] = {
 751        0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
 752        0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
 753        0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
 754        0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
 755        0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
 756        0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
 757        0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
 758        0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
 759        0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
 760        0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
 761        0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
 762        0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
 763};
 764
 765static const u8 rtl8225z2_gain_bg[] = {
 766        0x23, 0x15, 0xa5, /* -82-1dBm */
 767        0x23, 0x15, 0xb5, /* -82-2dBm */
 768        0x23, 0x15, 0xc5, /* -82-3dBm */
 769        0x33, 0x15, 0xc5, /* -78dBm */
 770        0x43, 0x15, 0xc5, /* -74dBm */
 771        0x53, 0x15, 0xc5, /* -70dBm */
 772        0x63, 0x15, 0xc5  /* -66dBm */
 773};
 774
 775static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
 776{
 777        struct rtl8187_priv *priv = dev->priv;
 778        int i;
 779
 780        rtl8225_write(dev, 0x0, 0x2BF);
 781        rtl8225_write(dev, 0x1, 0xEE0);
 782        rtl8225_write(dev, 0x2, 0x44D);
 783        rtl8225_write(dev, 0x3, 0x441);
 784        rtl8225_write(dev, 0x4, 0x8C3);
 785        rtl8225_write(dev, 0x5, 0xC72);
 786        rtl8225_write(dev, 0x6, 0x0E6);
 787        rtl8225_write(dev, 0x7, 0x82A);
 788        rtl8225_write(dev, 0x8, 0x03F);
 789        rtl8225_write(dev, 0x9, 0x335);
 790        rtl8225_write(dev, 0xa, 0x9D4);
 791        rtl8225_write(dev, 0xb, 0x7BB);
 792        rtl8225_write(dev, 0xc, 0x850);
 793        rtl8225_write(dev, 0xd, 0xCDF);
 794        rtl8225_write(dev, 0xe, 0x02B);
 795        rtl8225_write(dev, 0xf, 0x114);
 796        msleep(100);
 797
 798        rtl8225_write(dev, 0x0, 0x1B7);
 799
 800        for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
 801                rtl8225_write(dev, 0x1, i + 1);
 802                rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 803        }
 804
 805        rtl8225_write(dev, 0x3, 0x080);
 806        rtl8225_write(dev, 0x5, 0x004);
 807        rtl8225_write(dev, 0x0, 0x0B7);
 808        rtl8225_write(dev, 0x2, 0xc4D);
 809
 810        msleep(200);
 811        rtl8225_write(dev, 0x2, 0x44D);
 812        msleep(100);
 813
 814        if (!(rtl8225_read(dev, 6) & (1 << 7))) {
 815                rtl8225_write(dev, 0x02, 0x0C4D);
 816                msleep(200);
 817                rtl8225_write(dev, 0x02, 0x044D);
 818                msleep(100);
 819                if (!(rtl8225_read(dev, 6) & (1 << 7)))
 820                        wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
 821                                   rtl8225_read(dev, 6));
 822        }
 823
 824        msleep(200);
 825
 826        rtl8225_write(dev, 0x0, 0x2BF);
 827
 828        for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 829                rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
 830                rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
 831        }
 832
 833        msleep(1);
 834
 835        rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
 836        rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
 837        rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
 838        rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
 839        rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
 840        rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
 841        rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
 842        rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
 843        rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
 844        rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
 845        rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
 846        rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
 847        rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
 848        rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
 849        rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
 850        rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
 851        rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
 852        rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
 853        rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
 854        rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
 855        rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
 856        rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
 857        rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
 858        rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
 859        rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
 860        rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
 861        rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
 862        rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
 863        rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
 864        rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
 865        rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
 866        rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
 867        rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
 868        rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
 869        rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
 870        rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
 871        rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
 872        rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
 873        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
 874        rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
 875
 876        rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
 877        rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
 878        rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
 879        rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
 880
 881        rtl8225_write_phy_cck(dev, 0x00, 0x98);
 882        rtl8225_write_phy_cck(dev, 0x03, 0x20);
 883        rtl8225_write_phy_cck(dev, 0x04, 0x7e);
 884        rtl8225_write_phy_cck(dev, 0x05, 0x12);
 885        rtl8225_write_phy_cck(dev, 0x06, 0xfc);
 886        rtl8225_write_phy_cck(dev, 0x07, 0x78);
 887        rtl8225_write_phy_cck(dev, 0x08, 0x2e);
 888        rtl8225_write_phy_cck(dev, 0x10, 0x9b);
 889        rtl8225_write_phy_cck(dev, 0x11, 0x88);
 890        rtl8225_write_phy_cck(dev, 0x12, 0x47);
 891        rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 892        rtl8225_write_phy_cck(dev, 0x19, 0x00);
 893        rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 894        rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 895        rtl8225_write_phy_cck(dev, 0x40, 0x86);
 896        rtl8225_write_phy_cck(dev, 0x41, 0x8d);
 897        rtl8225_write_phy_cck(dev, 0x42, 0x15);
 898        rtl8225_write_phy_cck(dev, 0x43, 0x18);
 899        rtl8225_write_phy_cck(dev, 0x44, 0x36);
 900        rtl8225_write_phy_cck(dev, 0x45, 0x35);
 901        rtl8225_write_phy_cck(dev, 0x46, 0x2e);
 902        rtl8225_write_phy_cck(dev, 0x47, 0x25);
 903        rtl8225_write_phy_cck(dev, 0x48, 0x1c);
 904        rtl8225_write_phy_cck(dev, 0x49, 0x12);
 905        rtl8225_write_phy_cck(dev, 0x4a, 0x09);
 906        rtl8225_write_phy_cck(dev, 0x4b, 0x04);
 907        rtl8225_write_phy_cck(dev, 0x4c, 0x05);
 908
 909        rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
 910
 911        rtl8225z2_rf_set_tx_power(dev, 1);
 912
 913        /* RX antenna default to A */
 914        rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
 915        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
 916
 917        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
 918        msleep(1);
 919        rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
 920}
 921
 922static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
 923{
 924        struct rtl8187_priv *priv = dev->priv;
 925        int i;
 926
 927        rtl8225_write(dev, 0x0, 0x0B7);
 928        rtl8225_write(dev, 0x1, 0xEE0);
 929        rtl8225_write(dev, 0x2, 0x44D);
 930        rtl8225_write(dev, 0x3, 0x441);
 931        rtl8225_write(dev, 0x4, 0x8C3);
 932        rtl8225_write(dev, 0x5, 0xC72);
 933        rtl8225_write(dev, 0x6, 0x0E6);
 934        rtl8225_write(dev, 0x7, 0x82A);
 935        rtl8225_write(dev, 0x8, 0x03F);
 936        rtl8225_write(dev, 0x9, 0x335);
 937        rtl8225_write(dev, 0xa, 0x9D4);
 938        rtl8225_write(dev, 0xb, 0x7BB);
 939        rtl8225_write(dev, 0xc, 0x850);
 940        rtl8225_write(dev, 0xd, 0xCDF);
 941        rtl8225_write(dev, 0xe, 0x02B);
 942        rtl8225_write(dev, 0xf, 0x114);
 943
 944        rtl8225_write(dev, 0x0, 0x1B7);
 945
 946        for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
 947                rtl8225_write(dev, 0x1, i + 1);
 948                rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 949        }
 950
 951        rtl8225_write(dev, 0x3, 0x080);
 952        rtl8225_write(dev, 0x5, 0x004);
 953        rtl8225_write(dev, 0x0, 0x0B7);
 954
 955        rtl8225_write(dev, 0x2, 0xC4D);
 956
 957        rtl8225_write(dev, 0x2, 0x44D);
 958        rtl8225_write(dev, 0x0, 0x2BF);
 959
 960        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
 961        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
 962        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
 963
 964        rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
 965        for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
 966                rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
 967                rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
 968                rtl8225_write_phy_ofdm(dev, 0xE, 0);
 969        }
 970        rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
 971
 972        for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
 973                rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
 974
 975        rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
 976        rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
 977        rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
 978        rtl8225_write_phy_cck(dev, 0xc1, 0x88);
 979}
 980
 981static void rtl8225_rf_stop(struct ieee80211_hw *dev)
 982{
 983        rtl8225_write(dev, 0x4, 0x1f);
 984}
 985
 986static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
 987                                   struct ieee80211_conf *conf)
 988{
 989        struct rtl8187_priv *priv = dev->priv;
 990        int chan =
 991                ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
 992
 993        if (priv->rf->init == rtl8225_rf_init)
 994                rtl8225_rf_set_tx_power(dev, chan);
 995        else if (priv->rf->init == rtl8225z2_rf_init)
 996                rtl8225z2_rf_set_tx_power(dev, chan);
 997        else
 998                rtl8225z2_b_rf_set_tx_power(dev, chan);
 999
1000        rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
1001        msleep(10);
1002}
1003
1004static const struct rtl818x_rf_ops rtl8225_ops = {
1005        .name           = "rtl8225",
1006        .init           = rtl8225_rf_init,
1007        .stop           = rtl8225_rf_stop,
1008        .set_chan       = rtl8225_rf_set_channel
1009};
1010
1011static const struct rtl818x_rf_ops rtl8225z2_ops = {
1012        .name           = "rtl8225z2",
1013        .init           = rtl8225z2_rf_init,
1014        .stop           = rtl8225_rf_stop,
1015        .set_chan       = rtl8225_rf_set_channel
1016};
1017
1018static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
1019        .name           = "rtl8225z2",
1020        .init           = rtl8225z2_b_rf_init,
1021        .stop           = rtl8225_rf_stop,
1022        .set_chan       = rtl8225_rf_set_channel
1023};
1024
1025const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
1026{
1027        u16 reg8, reg9;
1028        struct rtl8187_priv *priv = dev->priv;
1029
1030        if (!priv->is_rtl8187b) {
1031                rtl8225_write(dev, 0, 0x1B7);
1032
1033                reg8 = rtl8225_read(dev, 8);
1034                reg9 = rtl8225_read(dev, 9);
1035
1036                rtl8225_write(dev, 0, 0x0B7);
1037
1038                if (reg8 != 0x588 || reg9 != 0x700)
1039                        return &rtl8225_ops;
1040
1041                return &rtl8225z2_ops;
1042        } else
1043                return &rtl8225z2_b_ops;
1044}
1045