cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtl8225.c (32342B)


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