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 (27233B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2
      3/*
      4 * Radio tuning for RTL8225 on RTL8180
      5 *
      6 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
      7 * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
      8 *
      9 * Based on the r8180 driver, which is:
     10 * Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
     11 *
     12 * Thanks to Realtek for their support!
     13 */
     14
     15#include <linux/pci.h>
     16#include <linux/delay.h>
     17#include <net/mac80211.h>
     18
     19#include "rtl8180.h"
     20#include "rtl8225.h"
     21
     22static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
     23{
     24	struct rtl8180_priv *priv = dev->priv;
     25	u16 reg80, reg84, reg82;
     26	u32 bangdata;
     27	int i;
     28
     29	bangdata = (data << 4) | (addr & 0xf);
     30
     31	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
     32	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
     33
     34	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
     35
     36	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
     37	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
     38	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     39	udelay(10);
     40
     41	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
     42	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     43	udelay(2);
     44	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
     45	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     46	udelay(10);
     47
     48	for (i = 15; i >= 0; i--) {
     49		u16 reg = reg80;
     50
     51		if (bangdata & (1 << i))
     52			reg |= 1;
     53
     54		if (i & 1)
     55			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
     56
     57		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
     58		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
     59
     60		if (!(i & 1))
     61			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
     62	}
     63
     64	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
     65	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     66	udelay(10);
     67
     68	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
     69	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
     70	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
     71}
     72
     73static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
     74{
     75	struct rtl8180_priv *priv = dev->priv;
     76	u16 reg80, reg82, reg84, out;
     77	int i;
     78
     79	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
     80	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
     81	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
     82
     83	reg80 &= ~0xF;
     84
     85	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
     86	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
     87
     88	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
     89	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     90	udelay(4);
     91	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
     92	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
     93	udelay(5);
     94
     95	for (i = 4; i >= 0; i--) {
     96		u16 reg = reg80 | ((addr >> i) & 1);
     97
     98		if (!(i & 1)) {
     99			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
    100			rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    101			udelay(1);
    102		}
    103
    104		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    105				  reg | (1 << 1));
    106		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    107		udelay(2);
    108		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    109				  reg | (1 << 1));
    110		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    111		udelay(2);
    112
    113		if (i & 1) {
    114			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
    115			rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    116			udelay(1);
    117		}
    118	}
    119
    120	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
    121	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
    122	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    123	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    124			  reg80 | (1 << 3) | (1 << 1));
    125	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    126	udelay(2);
    127	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    128			  reg80 | (1 << 3));
    129	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    130	udelay(2);
    131	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    132			  reg80 | (1 << 3));
    133	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    134	udelay(2);
    135
    136	out = 0;
    137	for (i = 11; i >= 0; i--) {
    138		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    139				  reg80 | (1 << 3));
    140		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    141		udelay(1);
    142		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    143				  reg80 | (1 << 3) | (1 << 1));
    144		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    145		udelay(2);
    146		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    147				  reg80 | (1 << 3) | (1 << 1));
    148		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    149		udelay(2);
    150		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    151				  reg80 | (1 << 3) | (1 << 1));
    152		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    153		udelay(2);
    154
    155		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
    156			out |= 1 << i;
    157
    158		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    159				  reg80 | (1 << 3));
    160		rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    161		udelay(2);
    162	}
    163
    164	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
    165			  reg80 | (1 << 3) | (1 << 2));
    166	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    167	udelay(2);
    168
    169	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
    170	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
    171	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
    172
    173	return out;
    174}
    175
    176static const u16 rtl8225bcd_rxgain[] = {
    177	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
    178	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
    179	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
    180	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
    181	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
    182	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
    183	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
    184	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
    185	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
    186	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
    187	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
    188	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
    189};
    190
    191static const u8 rtl8225_agc[] = {
    192	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
    193	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
    194	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
    195	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
    196	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
    197	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
    198	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
    199	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
    200	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
    201	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
    202	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
    203	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
    204	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
    205	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    206	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    207	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    208};
    209
    210static const u8 rtl8225_gain[] = {
    211	0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
    212	0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
    213	0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
    214	0x33, 0x80, 0x79, 0xc5, /* -78dbm */
    215	0x43, 0x78, 0x76, 0xc5, /* -74dbm */
    216	0x53, 0x60, 0x73, 0xc5, /* -70dbm */
    217	0x63, 0x58, 0x70, 0xc5, /* -66dbm */
    218};
    219
    220static const u8 rtl8225_threshold[] = {
    221	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
    222};
    223
    224static const u8 rtl8225_tx_gain_cck_ofdm[] = {
    225	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
    226};
    227
    228static const u8 rtl8225_tx_power_cck[] = {
    229	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
    230	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
    231	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
    232	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
    233	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
    234	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
    235};
    236
    237static const u8 rtl8225_tx_power_cck_ch14[] = {
    238	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
    239	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
    240	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
    241	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
    242	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
    243	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
    244};
    245
    246static const u8 rtl8225_tx_power_ofdm[] = {
    247	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
    248};
    249
    250static const u32 rtl8225_chan[] = {
    251	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
    252	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
    253};
    254
    255static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
    256{
    257	struct rtl8180_priv *priv = dev->priv;
    258	u8 cck_power, ofdm_power;
    259	const u8 *tmp;
    260	u32 reg;
    261	int i;
    262
    263	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
    264	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
    265
    266	cck_power = min(cck_power, (u8)35);
    267	ofdm_power = min(ofdm_power, (u8)35);
    268
    269	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
    270			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
    271
    272	if (channel == 14)
    273		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
    274	else
    275		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
    276
    277	for (i = 0; i < 8; i++)
    278		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
    279
    280	msleep(1); /* FIXME: optional? */
    281
    282	/* TODO: use set_anaparam2 dev.c_func*/
    283	/* anaparam2 on */
    284	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
    285	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
    286	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
    287	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
    288	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
    289	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
    290
    291	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
    292			 rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
    293
    294	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
    295
    296	rtl8225_write_phy_ofdm(dev, 5, *tmp);
    297	rtl8225_write_phy_ofdm(dev, 7, *tmp);
    298
    299	msleep(1);
    300}
    301
    302static void rtl8225_rf_init(struct ieee80211_hw *dev)
    303{
    304	struct rtl8180_priv *priv = dev->priv;
    305	int i;
    306
    307	rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
    308
    309	/* host_pci_init */
    310	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
    311	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    312	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
    313	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
    314	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    315	msleep(200);	/* FIXME: ehh?? */
    316	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
    317
    318	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
    319
    320	/* TODO: check if we need really to change BRSR to do RF config */
    321	rtl818x_ioread16(priv, &priv->map->BRSR);
    322	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
    323	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
    324	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
    325	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
    326	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
    327
    328	rtl8225_write(dev, 0x0, 0x067);
    329	rtl8225_write(dev, 0x1, 0xFE0);
    330	rtl8225_write(dev, 0x2, 0x44D);
    331	rtl8225_write(dev, 0x3, 0x441);
    332	rtl8225_write(dev, 0x4, 0x8BE);
    333	rtl8225_write(dev, 0x5, 0xBF0);		/* TODO: minipci */
    334	rtl8225_write(dev, 0x6, 0xAE6);
    335	rtl8225_write(dev, 0x7, rtl8225_chan[0]);
    336	rtl8225_write(dev, 0x8, 0x01F);
    337	rtl8225_write(dev, 0x9, 0x334);
    338	rtl8225_write(dev, 0xA, 0xFD4);
    339	rtl8225_write(dev, 0xB, 0x391);
    340	rtl8225_write(dev, 0xC, 0x050);
    341	rtl8225_write(dev, 0xD, 0x6DB);
    342	rtl8225_write(dev, 0xE, 0x029);
    343	rtl8225_write(dev, 0xF, 0x914); msleep(1);
    344
    345	rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
    346
    347	rtl8225_write(dev, 0x0, 0x127);
    348
    349	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
    350		rtl8225_write(dev, 0x1, i + 1);
    351		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
    352	}
    353
    354	rtl8225_write(dev, 0x0, 0x027);
    355	rtl8225_write(dev, 0x0, 0x22F);
    356	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    357
    358	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
    359		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
    360		msleep(1);
    361		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
    362		msleep(1);
    363	}
    364
    365	msleep(1);
    366
    367	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
    368	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
    369	rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
    370	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
    371	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
    372	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
    373	rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
    374	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
    375	rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
    376	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
    377	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
    378	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
    379	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
    380	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
    381	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
    382	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
    383	rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
    384	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
    385	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
    386	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
    387	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
    388	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
    389	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
    390	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
    391	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
    392	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
    393	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
    394	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
    395	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
    396	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
    397	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
    398	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
    399	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
    400	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
    401	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
    402	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
    403	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
    404
    405	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
    406	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
    407	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
    408	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
    409	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
    410	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
    411	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
    412	rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
    413	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
    414	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
    415	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
    416	rtl8225_write_phy_cck(dev, 0x19, 0x00);
    417	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
    418	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
    419	rtl8225_write_phy_cck(dev, 0x40, 0x86);
    420	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
    421	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
    422	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
    423	rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
    424	rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
    425	rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
    426	rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
    427	rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
    428	rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
    429	rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
    430	rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
    431	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
    432
    433	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
    434
    435	rtl8225_rf_set_tx_power(dev, 1);
    436
    437	/* RX antenna default to A */
    438	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
    439	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
    440
    441	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
    442	msleep(1);
    443	rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
    444	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    445
    446	rtl8225_write(dev, 0x0c, 0x50);
    447	/* set OFDM initial gain */
    448	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
    449	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
    450	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
    451	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
    452	/* set CCK threshold */
    453	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
    454}
    455
    456static const u8 rtl8225z2_tx_power_cck_ch14[] = {
    457	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
    458};
    459
    460static const u8 rtl8225z2_tx_power_cck_B[] = {
    461	0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
    462};
    463
    464static const u8 rtl8225z2_tx_power_cck_A[] = {
    465	0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
    466};
    467
    468static const u8 rtl8225z2_tx_power_cck[] = {
    469	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
    470};
    471
    472static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
    473{
    474	struct rtl8180_priv *priv = dev->priv;
    475	u8 cck_power, ofdm_power;
    476	const u8 *tmp;
    477	int i;
    478
    479	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
    480	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
    481
    482	if (channel == 14)
    483		tmp = rtl8225z2_tx_power_cck_ch14;
    484	else if (cck_power == 12)
    485		tmp = rtl8225z2_tx_power_cck_B;
    486	else if (cck_power == 13)
    487		tmp = rtl8225z2_tx_power_cck_A;
    488	else
    489		tmp = rtl8225z2_tx_power_cck;
    490
    491	for (i = 0; i < 8; i++)
    492		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
    493
    494	cck_power = min(cck_power, (u8)35);
    495	if (cck_power == 13 || cck_power == 14)
    496		cck_power = 12;
    497	if (cck_power >= 15)
    498		cck_power -= 2;
    499
    500	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
    501	rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
    502	msleep(1);
    503
    504	ofdm_power = min(ofdm_power, (u8)35);
    505	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
    506
    507	rtl8225_write_phy_ofdm(dev, 2, 0x62);
    508	rtl8225_write_phy_ofdm(dev, 5, 0x00);
    509	rtl8225_write_phy_ofdm(dev, 6, 0x40);
    510	rtl8225_write_phy_ofdm(dev, 7, 0x00);
    511	rtl8225_write_phy_ofdm(dev, 8, 0x40);
    512
    513	msleep(1);
    514}
    515
    516static const u16 rtl8225z2_rxgain[] = {
    517	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
    518	0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
    519	0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
    520	0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
    521	0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
    522	0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
    523	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
    524	0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
    525	0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
    526	0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
    527	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
    528	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
    529};
    530
    531static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
    532{
    533	struct rtl8180_priv *priv = dev->priv;
    534	int i;
    535
    536	rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
    537
    538	/* host_pci_init */
    539	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
    540	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    541	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
    542	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
    543	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    544	msleep(200);	/* FIXME: ehh?? */
    545	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
    546
    547	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
    548
    549	/* TODO: check if we need really to change BRSR to do RF config */
    550	rtl818x_ioread16(priv, &priv->map->BRSR);
    551	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
    552	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
    553	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
    554	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
    555	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
    556
    557	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    558
    559	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
    560	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
    561	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
    562	rtl8225_write(dev, 0x3, 0x441); msleep(1);
    563	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
    564	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
    565	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
    566	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
    567	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
    568	rtl8225_write(dev, 0x9, 0x335); msleep(1);
    569	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
    570	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
    571	rtl8225_write(dev, 0xc, 0x850); msleep(1);
    572	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
    573	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
    574	rtl8225_write(dev, 0xf, 0x114); msleep(100);
    575
    576	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
    577		rtl8225_write(dev, 0x02, 0x0C4D);
    578		msleep(200);
    579		rtl8225_write(dev, 0x02, 0x044D);
    580		msleep(100);
    581		/* TODO: readd calibration failure message when the calibration
    582		   check works */
    583	}
    584
    585	rtl8225_write(dev, 0x0, 0x1B7);
    586	rtl8225_write(dev, 0x3, 0x002);
    587	rtl8225_write(dev, 0x5, 0x004);
    588
    589	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
    590		rtl8225_write(dev, 0x1, i + 1);
    591		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
    592	}
    593
    594	rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
    595	rtl8225_write(dev, 0x2, 0xC4D);
    596
    597	msleep(200);
    598	rtl8225_write(dev, 0x2, 0x44D);
    599	msleep(100);
    600
    601	rtl8225_write(dev, 0x00, 0x2BF);
    602	rtl8225_write(dev, 0xFF, 0xFFFF);
    603
    604	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    605
    606	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
    607		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
    608		msleep(1);
    609		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
    610		msleep(1);
    611	}
    612
    613	msleep(1);
    614
    615	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
    616	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
    617	rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
    618	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
    619	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
    620	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
    621	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
    622	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
    623	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
    624	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
    625	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
    626	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
    627	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
    628	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
    629	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
    630	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
    631	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
    632	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
    633	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
    634	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
    635	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
    636	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
    637	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
    638	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
    639	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
    640	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
    641	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
    642	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
    643	rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
    644	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
    645	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
    646	rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
    647	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
    648	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
    649	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
    650	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
    651	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
    652	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
    653	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
    654	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
    655	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
    656
    657	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
    658	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
    659	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
    660	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
    661	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
    662	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
    663	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
    664	rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
    665	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
    666	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
    667	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
    668	rtl8225_write_phy_cck(dev, 0x19, 0x00);
    669	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
    670	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
    671	rtl8225_write_phy_cck(dev, 0x40, 0x86);
    672	rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
    673	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
    674	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
    675	rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
    676	rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
    677	rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
    678	rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
    679	rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
    680	rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
    681	rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
    682	rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
    683	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
    684
    685	rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
    686
    687	rtl8225z2_rf_set_tx_power(dev, 1);
    688
    689	/* RX antenna default to A */
    690	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
    691	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
    692
    693	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
    694	msleep(1);
    695	rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
    696	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    697}
    698
    699static void rtl8225_rf_stop(struct ieee80211_hw *dev)
    700{
    701	struct rtl8180_priv *priv = dev->priv;
    702	u8 reg;
    703
    704	rtl8225_write(dev, 0x4, 0x1f); msleep(1);
    705
    706	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
    707	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
    708	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
    709	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
    710	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
    711	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
    712	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
    713}
    714
    715static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
    716				   struct ieee80211_conf *conf)
    717{
    718	struct rtl8180_priv *priv = dev->priv;
    719	int chan =
    720		ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
    721
    722	if (priv->rf->init == rtl8225_rf_init)
    723		rtl8225_rf_set_tx_power(dev, chan);
    724	else
    725		rtl8225z2_rf_set_tx_power(dev, chan);
    726
    727	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
    728	msleep(10);
    729}
    730
    731static const struct rtl818x_rf_ops rtl8225_ops = {
    732	.name		= "rtl8225",
    733	.init		= rtl8225_rf_init,
    734	.stop		= rtl8225_rf_stop,
    735	.set_chan	= rtl8225_rf_set_channel,
    736};
    737
    738static const struct rtl818x_rf_ops rtl8225z2_ops = {
    739	.name		= "rtl8225z2",
    740	.init		= rtl8225z2_rf_init,
    741	.stop		= rtl8225_rf_stop,
    742	.set_chan	= rtl8225_rf_set_channel,
    743};
    744
    745const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
    746{
    747	struct rtl8180_priv *priv = dev->priv;
    748	u16 reg8, reg9;
    749
    750	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
    751	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
    752	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
    753	rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
    754	msleep(100);
    755
    756	rtl8225_write(dev, 0, 0x1B7);
    757
    758	reg8 = rtl8225_read(dev, 8);
    759	reg9 = rtl8225_read(dev, 9);
    760
    761	rtl8225_write(dev, 0, 0x0B7);
    762
    763	if (reg8 != 0x588 || reg9 != 0x700)
    764		return &rtl8225_ops;
    765
    766	return &rtl8225z2_ops;
    767}