2  * Radio tuning for RTL8225 on RTL8187
 
   4  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
 
   5  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
 
   7  * Based on the r8187 driver, which is:
 
   8  * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
 
  10  * Magic delays, register offsets, and phy value tables below are
 
  11  * taken from the original r8187 driver sources.  Thanks to Realtek
 
  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.
 
  19 #include <linux/init.h>
 
  20 #include <linux/usb.h>
 
  21 #include <net/mac80211.h>
 
  24 #include "rtl8187_rtl8225.h"
 
  26 static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
 
  28         struct rtl8187_priv *priv = dev->priv;
 
  29         u16 reg80, reg84, reg82;
 
  33         bangdata = (data << 4) | (addr & 0xf);
 
  35         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
 
  36         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 
  38         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
 
  40         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 
  41         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
 
  44         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
  46         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 
  49         for (i = 15; i >= 0; i--) {
 
  50                 u16 reg = reg80 | (bangdata & (1 << i)) >> i;
 
  53                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 
  55                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
 
  56                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
 
  59                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 
  62         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
  65         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
  66         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 
  70 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
 
  72         struct rtl8187_priv *priv = dev->priv;
 
  73         u16 reg80, reg82, reg84;
 
  75         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
 
  76         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 
  77         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 
  82         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
 
  83         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
 
  86         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
  89         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 
  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);
 
  96         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
  99         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
 100         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 
 104 void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
 
 106         struct rtl8187_priv *priv = dev->priv;
 
 109                 rtl8225_write_8051(dev, addr, cpu_to_le16(data));
 
 111                 rtl8225_write_bitbang(dev, addr, data);
 
 114 u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
 
 116         struct rtl8187_priv *priv = dev->priv;
 
 117         u16 reg80, reg82, reg84, out;
 
 120         reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
 
 121         reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
 
 122         reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
 
 126         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
 
 127         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
 
 129         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 
 131         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
 
 134         for (i = 4; i >= 0; i--) {
 
 135                 u16 reg = reg80 | ((addr >> i) & 1);
 
 138                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 
 142                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 145                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 150                         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
 
 155         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 156                           reg80 | (1 << 3) | (1 << 1));
 
 158         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 161         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 166         for (i = 11; i >= 0; i--) {
 
 167                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 170                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 171                                   reg80 | (1 << 3) | (1 << 1));
 
 173                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 174                                   reg80 | (1 << 3) | (1 << 1));
 
 176                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 177                                   reg80 | (1 << 3) | (1 << 1));
 
 180                 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
 
 183                 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 188         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
 
 189                           reg80 | (1 << 3) | (1 << 2));
 
 192         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
 
 193         rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
 
 194         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
 
 199 static 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
 
 214 static 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
 
 233 static 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 */
 
 243 static const u8 rtl8225_threshold[] = {
 
 244         0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
 
 247 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
 
 248         0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
 
 251 static 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
 
 260 static 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
 
 269 static const u8 rtl8225_tx_power_ofdm[] = {
 
 270         0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
 
 273 static const u32 rtl8225_chan[] = {
 
 274         0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
 
 275         0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
 
 278 static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 
 280         struct rtl8187_priv *priv = dev->priv;
 
 281         u8 cck_power, ofdm_power;
 
 286         cck_power = priv->channels[channel - 1].val & 0xF;
 
 287         ofdm_power = priv->channels[channel - 1].val >> 4;
 
 289         cck_power = min(cck_power, (u8)11);
 
 290         ofdm_power = min(ofdm_power, (u8)35);
 
 292         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 
 293                          rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
 
 296                 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
 
 298                 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
 
 300         for (i = 0; i < 8; i++)
 
 301                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 
 303         msleep(1); // FIXME: optional?
 
 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, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 309         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
 
 310         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 311         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
 313         rtl8225_write_phy_ofdm(dev, 2, 0x42);
 
 314         rtl8225_write_phy_ofdm(dev, 6, 0x00);
 
 315         rtl8225_write_phy_ofdm(dev, 8, 0x00);
 
 317         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 
 318                          rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
 
 320         tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
 
 322         rtl8225_write_phy_ofdm(dev, 5, *tmp);
 
 323         rtl8225_write_phy_ofdm(dev, 7, *tmp);
 
 328 void rtl8225_rf_init(struct ieee80211_hw *dev)
 
 330         struct rtl8187_priv *priv = dev->priv;
 
 333         rtl8225_write(dev, 0x0, 0x067); msleep(1);
 
 334         rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
 
 335         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
 
 336         rtl8225_write(dev, 0x3, 0x441); msleep(1);
 
 337         rtl8225_write(dev, 0x4, 0x486); msleep(1);
 
 338         rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
 
 339         rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
 
 340         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
 
 341         rtl8225_write(dev, 0x8, 0x01F); msleep(1);
 
 342         rtl8225_write(dev, 0x9, 0x334); msleep(1);
 
 343         rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
 
 344         rtl8225_write(dev, 0xB, 0x391); msleep(1);
 
 345         rtl8225_write(dev, 0xC, 0x050); msleep(1);
 
 346         rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
 
 347         rtl8225_write(dev, 0xE, 0x029); msleep(1);
 
 348         rtl8225_write(dev, 0xF, 0x914); msleep(100);
 
 350         rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
 
 351         rtl8225_write(dev, 0x2, 0x44D); msleep(200);
 
 353         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
 
 354                 rtl8225_write(dev, 0x02, 0x0c4d);
 
 356                 rtl8225_write(dev, 0x02, 0x044d);
 
 358                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
 
 359                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
 
 360                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
 
 363         rtl8225_write(dev, 0x0, 0x127);
 
 365         for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
 
 366                 rtl8225_write(dev, 0x1, i + 1);
 
 367                 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
 
 370         rtl8225_write(dev, 0x0, 0x027);
 
 371         rtl8225_write(dev, 0x0, 0x22F);
 
 373         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 
 374                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
 
 376                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
 
 382         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
 
 383         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
 
 384         rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
 
 385         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
 
 386         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
 
 387         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
 
 388         rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
 
 389         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
 
 390         rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
 
 391         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
 
 392         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
 
 393         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
 
 394         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
 
 395         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
 
 396         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
 
 397         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
 
 398         rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
 
 399         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
 
 400         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
 
 401         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
 
 402         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
 
 403         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
 
 404         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
 
 405         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
 
 406         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
 
 407         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
 
 408         rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
 
 409         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
 
 410         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
 
 411         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
 
 412         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
 
 413         rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
 
 414         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
 
 415         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
 
 416         rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
 
 417         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
 
 418         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
 
 420         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
 
 421         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
 
 422         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
 
 423         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
 
 425         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
 
 426         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
 
 427         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
 
 428         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
 
 429         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
 
 430         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
 
 431         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
 
 432         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
 
 433         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
 
 434         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
 
 435         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 
 436         rtl8225_write_phy_cck(dev, 0x19, 0x00);
 
 437         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 
 438         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 
 439         rtl8225_write_phy_cck(dev, 0x40, 0x86);
 
 440         rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
 
 441         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
 
 442         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
 
 443         rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
 
 444         rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
 
 445         rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
 
 446         rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
 
 447         rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
 
 448         rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
 
 449         rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
 
 450         rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
 
 451         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
 
 453         rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
 
 455         rtl8225_rf_set_tx_power(dev, 1);
 
 457         /* RX antenna default to A */
 
 458         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
 
 459         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
 
 461         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
 
 463         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
 
 465         /* set sensitivity */
 
 466         rtl8225_write(dev, 0x0c, 0x50);
 
 467         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
 
 468         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
 
 469         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
 
 470         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
 
 471         rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
 
 474 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
 
 475         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
 
 478 static const u8 rtl8225z2_tx_power_cck[] = {
 
 479         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
 
 482 static const u8 rtl8225z2_tx_power_ofdm[] = {
 
 483         0x42, 0x00, 0x40, 0x00, 0x40
 
 486 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
 
 487         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
 
 488         0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
 
 489         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
 
 490         0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
 
 491         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
 
 492         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
 
 495 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 
 497         struct rtl8187_priv *priv = dev->priv;
 
 498         u8 cck_power, ofdm_power;
 
 503         cck_power = priv->channels[channel - 1].val & 0xF;
 
 504         ofdm_power = priv->channels[channel - 1].val >> 4;
 
 506         cck_power = min(cck_power, (u8)15);
 
 507         cck_power += priv->txpwr_base & 0xF;
 
 508         cck_power = min(cck_power, (u8)35);
 
 510         ofdm_power = min(ofdm_power, (u8)15);
 
 511         ofdm_power += priv->txpwr_base >> 4;
 
 512         ofdm_power = min(ofdm_power, (u8)35);
 
 515                 tmp = rtl8225z2_tx_power_cck_ch14;
 
 517                 tmp = rtl8225z2_tx_power_cck;
 
 519         for (i = 0; i < 8; i++)
 
 520                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 
 522         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
 
 523                          rtl8225z2_tx_gain_cck_ofdm[cck_power]);
 
 527         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 
 528         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
 
 529         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 530         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
 
 531         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 532         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
 534         rtl8225_write_phy_ofdm(dev, 2, 0x42);
 
 535         rtl8225_write_phy_ofdm(dev, 5, 0x00);
 
 536         rtl8225_write_phy_ofdm(dev, 6, 0x40);
 
 537         rtl8225_write_phy_ofdm(dev, 7, 0x00);
 
 538         rtl8225_write_phy_ofdm(dev, 8, 0x40);
 
 540         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
 
 541                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
 
 545 static const u16 rtl8225z2_rxgain[] = {
 
 546         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
 
 547         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
 
 548         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
 
 549         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
 
 550         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
 
 551         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
 
 552         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
 
 553         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
 
 554         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
 
 555         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
 
 556         0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
 
 557         0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
 
 560 static const u8 rtl8225z2_gain_bg[] = {
 
 561         0x23, 0x15, 0xa5, /* -82-1dBm */
 
 562         0x23, 0x15, 0xb5, /* -82-2dBm */
 
 563         0x23, 0x15, 0xc5, /* -82-3dBm */
 
 564         0x33, 0x15, 0xc5, /* -78dBm */
 
 565         0x43, 0x15, 0xc5, /* -74dBm */
 
 566         0x53, 0x15, 0xc5, /* -70dBm */
 
 567         0x63, 0x15, 0xc5  /* -66dBm */
 
 570 void rtl8225z2_rf_init(struct ieee80211_hw *dev)
 
 572         struct rtl8187_priv *priv = dev->priv;
 
 575         rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
 
 576         rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
 
 577         rtl8225_write(dev, 0x2, 0x44D); msleep(1);
 
 578         rtl8225_write(dev, 0x3, 0x441); msleep(1);
 
 579         rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
 
 580         rtl8225_write(dev, 0x5, 0xC72); msleep(1);
 
 581         rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
 
 582         rtl8225_write(dev, 0x7, 0x82A); msleep(1);
 
 583         rtl8225_write(dev, 0x8, 0x03F); msleep(1);
 
 584         rtl8225_write(dev, 0x9, 0x335); msleep(1);
 
 585         rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
 
 586         rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
 
 587         rtl8225_write(dev, 0xc, 0x850); msleep(1);
 
 588         rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
 
 589         rtl8225_write(dev, 0xe, 0x02B); msleep(1);
 
 590         rtl8225_write(dev, 0xf, 0x114); msleep(100);
 
 592         rtl8225_write(dev, 0x0, 0x1B7);
 
 594         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
 
 595                 rtl8225_write(dev, 0x1, i + 1);
 
 596                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 
 599         rtl8225_write(dev, 0x3, 0x080);
 
 600         rtl8225_write(dev, 0x5, 0x004);
 
 601         rtl8225_write(dev, 0x0, 0x0B7);
 
 602         rtl8225_write(dev, 0x2, 0xc4D);
 
 605         rtl8225_write(dev, 0x2, 0x44D);
 
 608         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
 
 609                 rtl8225_write(dev, 0x02, 0x0C4D);
 
 611                 rtl8225_write(dev, 0x02, 0x044D);
 
 613                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
 
 614                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
 
 615                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
 
 620         rtl8225_write(dev, 0x0, 0x2BF);
 
 622         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 
 623                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
 
 625                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
 
 631         rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
 
 632         rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
 
 633         rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
 
 634         rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
 
 635         rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
 
 636         rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
 
 637         rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
 
 638         rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
 
 639         rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
 
 640         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
 
 641         rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
 
 642         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
 
 643         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
 
 644         rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
 
 645         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
 
 646         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
 
 647         rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
 
 648         rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
 
 649         rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
 
 650         rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
 
 651         rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
 
 652         rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
 
 653         rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
 
 654         rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
 
 655         rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
 
 656         rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
 
 657         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
 
 658         rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
 
 659         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
 
 660         rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
 
 661         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
 
 662         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
 
 663         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
 
 664         rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
 
 665         rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
 
 666         rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
 
 667         rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
 
 668         rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
 
 669         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
 
 670         rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
 
 672         rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
 
 673         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
 
 674         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
 
 675         rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
 
 677         rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
 
 678         rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
 
 679         rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
 
 680         rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
 
 681         rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
 
 682         rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
 
 683         rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
 
 684         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
 
 685         rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
 
 686         rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
 
 687         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 
 688         rtl8225_write_phy_cck(dev, 0x19, 0x00);
 
 689         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 
 690         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 
 691         rtl8225_write_phy_cck(dev, 0x40, 0x86);
 
 692         rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
 
 693         rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
 
 694         rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
 
 695         rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
 
 696         rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
 
 697         rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
 
 698         rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
 
 699         rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
 
 700         rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
 
 701         rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
 
 702         rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
 
 703         rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
 
 705         rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
 
 707         rtl8225z2_rf_set_tx_power(dev, 1);
 
 709         /* RX antenna default to A */
 
 710         rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
 
 711         rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
 
 713         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
 
 715         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
 
 718 void rtl8225_rf_stop(struct ieee80211_hw *dev)
 
 721         struct rtl8187_priv *priv = dev->priv;
 
 723         rtl8225_write(dev, 0x4, 0x1f); msleep(1);
 
 725         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 
 726         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
 
 727         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 728         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
 
 729         rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
 
 730         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
 
 731         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
 734 void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
 
 736         struct rtl8187_priv *priv = dev->priv;
 
 738         if (priv->rf_init == rtl8225_rf_init)
 
 739                 rtl8225_rf_set_tx_power(dev, channel);
 
 741                 rtl8225z2_rf_set_tx_power(dev, channel);
 
 743         rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);