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        cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
 692        cck_power += priv->txpwr_base & 0xF;
 693        cck_power = min(cck_power, (u8)35);
 694
 695        if (ofdm_power > 15)
 696                ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
 697        else
 698                ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
 699        ofdm_power += (priv->txpwr_base >> 4) & 0xF;
 700        ofdm_power = min(ofdm_power, (u8)35);
 701
 702        if (channel == 14)
 703                tmp = rtl8225z2_tx_power_cck_ch14;
 704        else
 705                tmp = rtl8225z2_tx_power_cck;
 706
 707        if (priv->hw_rev == RTL8187BvB) {
 708                if (cck_power <= 6)
 709                        ; /* do nothing */
 710                else if (cck_power <= 11)
 711                        tmp += 8;
 712                else
 713                        tmp += 16;
 714        } else {
 715                if (cck_power <= 5)
 716                        ; /* do nothing */
 717                else if (cck_power <= 11)
 718                        tmp += 8;
 719                else if (cck_power <= 17)
 720                        tmp += 16;
 721                else
 722                        tmp += 24;
 723        }
 724
 725        for (i = 0; i < 8; i++)
 726                rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 727
 728        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 729                         rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
 730        msleep(1);
 731
 732        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 733                         rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
 734        if (priv->hw_rev == RTL8187BvB) {
 735                if (ofdm_power <= 11) {
 736                        rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
 737                        rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
 738                } else {
 739                        rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
 740                        rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
 741                }
 742        } else {
 743                if (ofdm_power <= 11) {
 744                        rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
 745                        rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
 746                } else if (ofdm_power <= 17) {
 747                        rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
 748                        rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
 749                } else {
 750                        rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
 751                        rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
 752                }
 753        }
 754        msleep(1);
 755}
 756
 757static const u16 rtl8225z2_rxgain[] = {
 758        0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
 759        0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
 760        0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
 761        0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
 762        0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
 763        0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
 764        0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
 765        0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
 766        0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
 767        0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
 768        0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
 769        0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
 770};
 771
 772static const u8 rtl8225z2_gain_bg[] = {
 773        0x23, 0x15, 0xa5, /* -82-1dBm */
 774        0x23, 0x15, 0xb5, /* -82-2dBm */
 775        0x23, 0x15, 0xc5, /* -82-3dBm */
 776        0x33, 0x15, 0xc5, /* -78dBm */
 777        0x43, 0x15, 0xc5, /* -74dBm */
 778        0x53, 0x15, 0xc5, /* -70dBm */
 779        0x63, 0x15, 0xc5  /* -66dBm */
 780};
 781
 782static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
 783{
 784        struct rtl8187_priv *priv = dev->priv;
 785        int i;
 786
 787        rtl8225_write(dev, 0x0, 0x2BF);
 788        rtl8225_write(dev, 0x1, 0xEE0);
 789        rtl8225_write(dev, 0x2, 0x44D);
 790        rtl8225_write(dev, 0x3, 0x441);
 791        rtl8225_write(dev, 0x4, 0x8C3);
 792        rtl8225_write(dev, 0x5, 0xC72);
 793        rtl8225_write(dev, 0x6, 0x0E6);
 794        rtl8225_write(dev, 0x7, 0x82A);
 795        rtl8225_write(dev, 0x8, 0x03F);
 796        rtl8225_write(dev, 0x9, 0x335);
 797        rtl8225_write(dev, 0xa, 0x9D4);
 798        rtl8225_write(dev, 0xb, 0x7BB);
 799        rtl8225_write(dev, 0xc, 0x850);
 800        rtl8225_write(dev, 0xd, 0xCDF);
 801        rtl8225_write(dev, 0xe, 0x02B);
 802        rtl8225_write(dev, 0xf, 0x114);
 803        msleep(100);
 804
 805        rtl8225_write(dev, 0x0, 0x1B7);
 806
 807        for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
 808                rtl8225_write(dev, 0x1, i + 1);
 809                rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 810        }
 811
 812        rtl8225_write(dev, 0x3, 0x080);
 813        rtl8225_write(dev, 0x5, 0x004);
 814        rtl8225_write(dev, 0x0, 0x0B7);
 815        rtl8225_write(dev, 0x2, 0xc4D);
 816
 817        msleep(200);
 818        rtl8225_write(dev, 0x2, 0x44D);
 819        msleep(100);
 820
 821        if (!(rtl8225_read(dev, 6) & (1 << 7))) {
 822                rtl8225_write(dev, 0x02, 0x0C4D);
 823                msleep(200);
 824                rtl8225_write(dev, 0x02, 0x044D);
 825                msleep(100);
 826                if (!(rtl8225_read(dev, 6) & (1 << 7)))
 827                        wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
 828                                   rtl8225_read(dev, 6));
 829        }
 830
 831        msleep(200);
 832
 833        rtl8225_write(dev, 0x0, 0x2BF);
 834
 835        for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 836                rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
 837                rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
 838        }
 839
 840        msleep(1);
 841
 842        rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
 843        rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
 844        rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
 845        rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
 846        rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
 847        rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
 848        rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
 849        rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
 850        rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
 851        rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
 852        rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
 853        rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
 854        rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
 855        rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
 856        rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
 857        rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
 858        rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
 859        rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
 860        rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
 861        rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
 862        rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
 863        rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
 864        rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
 865        rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
 866        rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
 867        rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
 868        rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
 869        rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
 870        rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
 871        rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
 872        rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
 873        rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
 874        rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
 875        rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
 876        rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
 877        rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
 878        rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
 879        rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
 880        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
 881        rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
 882
 883        rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
 884        rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
 885        rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
 886        rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
 887
 888        rtl8225_write_phy_cck(dev, 0x00, 0x98);
 889        rtl8225_write_phy_cck(dev, 0x03, 0x20);
 890        rtl8225_write_phy_cck(dev, 0x04, 0x7e);
 891        rtl8225_write_phy_cck(dev, 0x05, 0x12);
 892        rtl8225_write_phy_cck(dev, 0x06, 0xfc);
 893        rtl8225_write_phy_cck(dev, 0x07, 0x78);
 894        rtl8225_write_phy_cck(dev, 0x08, 0x2e);
 895        rtl8225_write_phy_cck(dev, 0x10, 0x9b);
 896        rtl8225_write_phy_cck(dev, 0x11, 0x88);
 897        rtl8225_write_phy_cck(dev, 0x12, 0x47);
 898        rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 899        rtl8225_write_phy_cck(dev, 0x19, 0x00);
 900        rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 901        rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 902        rtl8225_write_phy_cck(dev, 0x40, 0x86);
 903        rtl8225_write_phy_cck(dev, 0x41, 0x8d);
 904        rtl8225_write_phy_cck(dev, 0x42, 0x15);
 905        rtl8225_write_phy_cck(dev, 0x43, 0x18);
 906        rtl8225_write_phy_cck(dev, 0x44, 0x36);
 907        rtl8225_write_phy_cck(dev, 0x45, 0x35);
 908        rtl8225_write_phy_cck(dev, 0x46, 0x2e);
 909        rtl8225_write_phy_cck(dev, 0x47, 0x25);
 910        rtl8225_write_phy_cck(dev, 0x48, 0x1c);
 911        rtl8225_write_phy_cck(dev, 0x49, 0x12);
 912        rtl8225_write_phy_cck(dev, 0x4a, 0x09);
 913        rtl8225_write_phy_cck(dev, 0x4b, 0x04);
 914        rtl8225_write_phy_cck(dev, 0x4c, 0x05);
 915
 916        rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
 917
 918        rtl8225z2_rf_set_tx_power(dev, 1);
 919
 920        /* RX antenna default to A */
 921        rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
 922        rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
 923
 924        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
 925        msleep(1);
 926        rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
 927}
 928
 929static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
 930{
 931        struct rtl8187_priv *priv = dev->priv;
 932        int i;
 933
 934        rtl8225_write(dev, 0x0, 0x0B7);
 935        rtl8225_write(dev, 0x1, 0xEE0);
 936        rtl8225_write(dev, 0x2, 0x44D);
 937        rtl8225_write(dev, 0x3, 0x441);
 938        rtl8225_write(dev, 0x4, 0x8C3);
 939        rtl8225_write(dev, 0x5, 0xC72);
 940        rtl8225_write(dev, 0x6, 0x0E6);
 941        rtl8225_write(dev, 0x7, 0x82A);
 942        rtl8225_write(dev, 0x8, 0x03F);
 943        rtl8225_write(dev, 0x9, 0x335);
 944        rtl8225_write(dev, 0xa, 0x9D4);
 945        rtl8225_write(dev, 0xb, 0x7BB);
 946        rtl8225_write(dev, 0xc, 0x850);
 947        rtl8225_write(dev, 0xd, 0xCDF);
 948        rtl8225_write(dev, 0xe, 0x02B);
 949        rtl8225_write(dev, 0xf, 0x114);
 950
 951        rtl8225_write(dev, 0x0, 0x1B7);
 952
 953        for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
 954                rtl8225_write(dev, 0x1, i + 1);
 955                rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 956        }
 957
 958        rtl8225_write(dev, 0x3, 0x080);
 959        rtl8225_write(dev, 0x5, 0x004);
 960        rtl8225_write(dev, 0x0, 0x0B7);
 961
 962        rtl8225_write(dev, 0x2, 0xC4D);
 963
 964        rtl8225_write(dev, 0x2, 0x44D);
 965        rtl8225_write(dev, 0x0, 0x2BF);
 966
 967        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
 968        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
 969        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
 970
 971        rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
 972        for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
 973                rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
 974                rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
 975                rtl8225_write_phy_ofdm(dev, 0xE, 0);
 976        }
 977        rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
 978
 979        for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
 980                rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
 981
 982        rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
 983        rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
 984        rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
 985        rtl8225_write_phy_cck(dev, 0xc1, 0x88);
 986}
 987
 988static void rtl8225_rf_stop(struct ieee80211_hw *dev)
 989{
 990        rtl8225_write(dev, 0x4, 0x1f);
 991}
 992
 993static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
 994                                   struct ieee80211_conf *conf)
 995{
 996        struct rtl8187_priv *priv = dev->priv;
 997        int chan =
 998                ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
 999
1000        if (priv->rf->init == rtl8225_rf_init)
1001                rtl8225_rf_set_tx_power(dev, chan);
1002        else if (priv->rf->init == rtl8225z2_rf_init)
1003                rtl8225z2_rf_set_tx_power(dev, chan);
1004        else
1005                rtl8225z2_b_rf_set_tx_power(dev, chan);
1006
1007        rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
1008        msleep(10);
1009}
1010
1011static const struct rtl818x_rf_ops rtl8225_ops = {
1012        .name           = "rtl8225",
1013        .init           = rtl8225_rf_init,
1014        .stop           = rtl8225_rf_stop,
1015        .set_chan       = rtl8225_rf_set_channel
1016};
1017
1018static const struct rtl818x_rf_ops rtl8225z2_ops = {
1019        .name           = "rtl8225z2",
1020        .init           = rtl8225z2_rf_init,
1021        .stop           = rtl8225_rf_stop,
1022        .set_chan       = rtl8225_rf_set_channel
1023};
1024
1025static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
1026        .name           = "rtl8225z2",
1027        .init           = rtl8225z2_b_rf_init,
1028        .stop           = rtl8225_rf_stop,
1029        .set_chan       = rtl8225_rf_set_channel
1030};
1031
1032const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
1033{
1034        u16 reg8, reg9;
1035        struct rtl8187_priv *priv = dev->priv;
1036
1037        if (!priv->is_rtl8187b) {
1038                rtl8225_write(dev, 0, 0x1B7);
1039
1040                reg8 = rtl8225_read(dev, 8);
1041                reg9 = rtl8225_read(dev, 9);
1042
1043                rtl8225_write(dev, 0, 0x0B7);
1044
1045                if (reg8 != 0x588 || reg9 != 0x700)
1046                        return &rtl8225_ops;
1047
1048                return &rtl8225z2_ops;
1049        } else
1050                return &rtl8225z2_b_ops;
1051}
1052