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