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