diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 6127 | 
1 files changed, 5296 insertions, 831 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 75631614aba..c17fcf27272 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -24,9 +24,7 @@  	GNU General Public License for more details.  	You should have received a copy of the GNU General Public License -	along with this program; if not, write to the -	Free Software Foundation, Inc., -	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -80,7 +78,7 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)  	    rt2x00_rf(rt2x00dev, RF3022))  		return true; -	NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n"); +	rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");  	return false;  } @@ -221,6 +219,215 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,  	mutex_unlock(&rt2x00dev->csr_mutex);  } +static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { +	[EEPROM_CHIP_ID]		= 0x0000, +	[EEPROM_VERSION]		= 0x0001, +	[EEPROM_MAC_ADDR_0]		= 0x0002, +	[EEPROM_MAC_ADDR_1]		= 0x0003, +	[EEPROM_MAC_ADDR_2]		= 0x0004, +	[EEPROM_NIC_CONF0]		= 0x001a, +	[EEPROM_NIC_CONF1]		= 0x001b, +	[EEPROM_FREQ]			= 0x001d, +	[EEPROM_LED_AG_CONF]		= 0x001e, +	[EEPROM_LED_ACT_CONF]		= 0x001f, +	[EEPROM_LED_POLARITY]		= 0x0020, +	[EEPROM_NIC_CONF2]		= 0x0021, +	[EEPROM_LNA]			= 0x0022, +	[EEPROM_RSSI_BG]		= 0x0023, +	[EEPROM_RSSI_BG2]		= 0x0024, +	[EEPROM_TXMIXER_GAIN_BG]	= 0x0024, /* overlaps with RSSI_BG2 */ +	[EEPROM_RSSI_A]			= 0x0025, +	[EEPROM_RSSI_A2]		= 0x0026, +	[EEPROM_TXMIXER_GAIN_A]		= 0x0026, /* overlaps with RSSI_A2 */ +	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0027, +	[EEPROM_TXPOWER_DELTA]		= 0x0028, +	[EEPROM_TXPOWER_BG1]		= 0x0029, +	[EEPROM_TXPOWER_BG2]		= 0x0030, +	[EEPROM_TSSI_BOUND_BG1]		= 0x0037, +	[EEPROM_TSSI_BOUND_BG2]		= 0x0038, +	[EEPROM_TSSI_BOUND_BG3]		= 0x0039, +	[EEPROM_TSSI_BOUND_BG4]		= 0x003a, +	[EEPROM_TSSI_BOUND_BG5]		= 0x003b, +	[EEPROM_TXPOWER_A1]		= 0x003c, +	[EEPROM_TXPOWER_A2]		= 0x0053, +	[EEPROM_TSSI_BOUND_A1]		= 0x006a, +	[EEPROM_TSSI_BOUND_A2]		= 0x006b, +	[EEPROM_TSSI_BOUND_A3]		= 0x006c, +	[EEPROM_TSSI_BOUND_A4]		= 0x006d, +	[EEPROM_TSSI_BOUND_A5]		= 0x006e, +	[EEPROM_TXPOWER_BYRATE]		= 0x006f, +	[EEPROM_BBP_START]		= 0x0078, +}; + +static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { +	[EEPROM_CHIP_ID]		= 0x0000, +	[EEPROM_VERSION]		= 0x0001, +	[EEPROM_MAC_ADDR_0]		= 0x0002, +	[EEPROM_MAC_ADDR_1]		= 0x0003, +	[EEPROM_MAC_ADDR_2]		= 0x0004, +	[EEPROM_NIC_CONF0]		= 0x001a, +	[EEPROM_NIC_CONF1]		= 0x001b, +	[EEPROM_NIC_CONF2]		= 0x001c, +	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0020, +	[EEPROM_FREQ]			= 0x0022, +	[EEPROM_LED_AG_CONF]		= 0x0023, +	[EEPROM_LED_ACT_CONF]		= 0x0024, +	[EEPROM_LED_POLARITY]		= 0x0025, +	[EEPROM_LNA]			= 0x0026, +	[EEPROM_EXT_LNA2]		= 0x0027, +	[EEPROM_RSSI_BG]		= 0x0028, +	[EEPROM_RSSI_BG2]		= 0x0029, +	[EEPROM_RSSI_A]			= 0x002a, +	[EEPROM_RSSI_A2]		= 0x002b, +	[EEPROM_TXPOWER_BG1]		= 0x0030, +	[EEPROM_TXPOWER_BG2]		= 0x0037, +	[EEPROM_EXT_TXPOWER_BG3]	= 0x003e, +	[EEPROM_TSSI_BOUND_BG1]		= 0x0045, +	[EEPROM_TSSI_BOUND_BG2]		= 0x0046, +	[EEPROM_TSSI_BOUND_BG3]		= 0x0047, +	[EEPROM_TSSI_BOUND_BG4]		= 0x0048, +	[EEPROM_TSSI_BOUND_BG5]		= 0x0049, +	[EEPROM_TXPOWER_A1]		= 0x004b, +	[EEPROM_TXPOWER_A2]		= 0x0065, +	[EEPROM_EXT_TXPOWER_A3]		= 0x007f, +	[EEPROM_TSSI_BOUND_A1]		= 0x009a, +	[EEPROM_TSSI_BOUND_A2]		= 0x009b, +	[EEPROM_TSSI_BOUND_A3]		= 0x009c, +	[EEPROM_TSSI_BOUND_A4]		= 0x009d, +	[EEPROM_TSSI_BOUND_A5]		= 0x009e, +	[EEPROM_TXPOWER_BYRATE]		= 0x00a0, +}; + +static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, +					     const enum rt2800_eeprom_word word) +{ +	const unsigned int *map; +	unsigned int index; + +	if (WARN_ONCE(word >= EEPROM_WORD_COUNT, +		      "%s: invalid EEPROM word %d\n", +		      wiphy_name(rt2x00dev->hw->wiphy), word)) +		return 0; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		map = rt2800_eeprom_map_ext; +	else +		map = rt2800_eeprom_map; + +	index = map[word]; + +	/* Index 0 is valid only for EEPROM_CHIP_ID. +	 * Otherwise it means that the offset of the +	 * given word is not initialized in the map, +	 * or that the field is not usable on the +	 * actual chipset. +	 */ +	WARN_ONCE(word != EEPROM_CHIP_ID && index == 0, +		  "%s: invalid access of EEPROM word %d\n", +		  wiphy_name(rt2x00dev->hw->wiphy), word); + +	return index; +} + +static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev, +				const enum rt2800_eeprom_word word) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	return rt2x00_eeprom_addr(rt2x00dev, index); +} + +static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev, +			       const enum rt2800_eeprom_word word, u16 *data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	rt2x00_eeprom_read(rt2x00dev, index, data); +} + +static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, +				const enum rt2800_eeprom_word word, u16 data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	rt2x00_eeprom_write(rt2x00dev, index, data); +} + +static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, +					  const enum rt2800_eeprom_word array, +					  unsigned int offset, +					  u16 *data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, array); +	rt2x00_eeprom_read(rt2x00dev, index + offset, data); +} + +static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	int i, count; + +	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +	if (rt2x00_get_field32(reg, WLAN_EN)) +		return 0; + +	rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); +	rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); +	rt2x00_set_field32(®, WLAN_CLK_EN, 0); +	rt2x00_set_field32(®, WLAN_EN, 1); +	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + +	udelay(REGISTER_BUSY_DELAY); + +	count = 0; +	do { +		/* +		 * Check PLL_LD & XTAL_RDY. +		 */ +		for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +			rt2800_register_read(rt2x00dev, CMB_CTRL, ®); +			if (rt2x00_get_field32(reg, PLL_LD) && +			    rt2x00_get_field32(reg, XTAL_RDY)) +				break; +			udelay(REGISTER_BUSY_DELAY); +		} + +		if (i >= REGISTER_BUSY_COUNT) { + +			if (count >= 10) +				return -EIO; + +			rt2800_register_write(rt2x00dev, 0x58, 0x018); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x418); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x618); +			udelay(REGISTER_BUSY_DELAY); +			count++; +		} else { +			count = 0; +		} + +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); +		rt2x00_set_field32(®, WLAN_CLK_EN, 1); +		rt2x00_set_field32(®, WLAN_RESET, 1); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2x00_set_field32(®, WLAN_RESET, 0); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); +	} while (count != 0); + +	return 0; +} +  void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,  			const u8 command, const u8 token,  			const u8 arg0, const u8 arg1) @@ -267,7 +474,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)  		msleep(1);  	} -	ERROR(rt2x00dev, "Unstable hardware.\n"); +	rt2x00_err(rt2x00dev, "Unstable hardware\n");  	return -EBUSY;  }  EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready); @@ -290,11 +497,48 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)  		msleep(10);  	} -	ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); +	rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);  	return -EACCES;  }  EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); +void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); +	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +} +EXPORT_SYMBOL_GPL(rt2800_disable_wpdma); + +void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, +			       unsigned short *txwi_size, +			       unsigned short *rxwi_size) +{ +	switch (rt2x00dev->chip.rt) { +	case RT3593: +		*txwi_size = TXWI_DESC_SIZE_4WORDS; +		*rxwi_size = RXWI_DESC_SIZE_5WORDS; +		break; + +	case RT5592: +		*txwi_size = TXWI_DESC_SIZE_5WORDS; +		*rxwi_size = RXWI_DESC_SIZE_6WORDS; +		break; + +	default: +		*txwi_size = TXWI_DESC_SIZE_4WORDS; +		*rxwi_size = RXWI_DESC_SIZE_4WORDS; +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size); +  static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)  {  	u16 fw_crc; @@ -340,16 +584,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,  	 * of 4kb. Certain USB chipsets however require different firmware,  	 * which Ralink only provides attached to the original firmware  	 * file. Thus for USB devices, firmware files have a length -	 * which is a multiple of 4kb. +	 * which is a multiple of 4kb. The firmware for rt3290 chip also +	 * have a length which is a multiple of 4kb.  	 */ -	if (rt2x00_is_usb(rt2x00dev)) { +	if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))  		fw_len = 4096; -		multiple = true; -	} else { +	else  		fw_len = 8192; -		multiple = true; -	} +	multiple = true;  	/*  	 * Validate the firmware length  	 */ @@ -387,6 +630,13 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  {  	unsigned int i;  	u32 reg; +	int retval; + +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		retval = rt2800_enable_wlan_rt3290(rt2x00dev); +		if (retval) +			return -EBUSY; +	}  	/*  	 * If driver doesn't wake up firmware here, @@ -400,20 +650,20 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  	if (rt2800_wait_csr_ready(rt2x00dev))  		return -EBUSY; -	if (rt2x00_is_pci(rt2x00dev)) +	if (rt2x00_is_pci(rt2x00dev)) { +		if (rt2x00_rt(rt2x00dev, RT3290) || +		    rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT5390) || +		    rt2x00_rt(rt2x00dev, RT5392)) { +			rt2800_register_read(rt2x00dev, AUX_CTRL, ®); +			rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); +			rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +			rt2800_register_write(rt2x00dev, AUX_CTRL, reg); +		}  		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); +	} -	/* -	 * Disable DMA, will be reenabled later when enabling -	 * the radio. -	 */ -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	/*  	 * Write firmware to the device. @@ -431,15 +681,25 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  	}  	if (i == REGISTER_BUSY_COUNT) { -		ERROR(rt2x00dev, "PBF system register not ready.\n"); +		rt2x00_err(rt2x00dev, "PBF system register not ready\n");  		return -EBUSY;  	}  	/* +	 * Disable DMA, will be reenabled later when enabling +	 * the radio. +	 */ +	rt2800_disable_wpdma(rt2x00dev); + +	/*  	 * Initialize firmware.  	 */  	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);  	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	if (rt2x00_is_usb(rt2x00dev)) { +		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); +		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +	}  	msleep(1);  	return 0; @@ -451,6 +711,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,  {  	__le32 *txwi = rt2800_drv_get_txwi(entry);  	u32 word; +	int i;  	/*  	 * Initialize TX Info descriptor @@ -465,14 +726,15 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W0_AMPDU,  			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); -	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); -	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); +	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, +			   txdesc->u.ht.mpdu_density); +	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop); +	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);  	rt2x00_set_field32(&word, TXWI_W0_BW,  			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,  			   test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); +	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);  	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);  	rt2x00_desc_write(txwi, 0, word); @@ -481,10 +743,10 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W1_NSEQ,  			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); +	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);  	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,  			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? -			   txdesc->key_idx : 0xff); +			   txdesc->key_idx : txdesc->u.ht.wcid);  	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,  			   txdesc->length);  	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); @@ -492,38 +754,40 @@ void rt2800_write_tx_data(struct queue_entry *entry,  	rt2x00_desc_write(txwi, 1, word);  	/* -	 * Always write 0 to IV/EIV fields, hardware will insert the IV -	 * from the IVEIV register when TXD_W3_WIV is set to 0. +	 * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert +	 * the IV from the IVEIV register when TXD_W3_WIV is set to 0.  	 * When TXD_W3_WIV is set to 1 it will use the IV data  	 * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which  	 * crypto entry in the registers should be used to encrypt the frame. +	 * +	 * Nulify all remaining words as well, we don't know how to program them.  	 */ -	_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); -	_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); +	for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++) +		_rt2x00_desc_write(txwi, i, 0);  }  EXPORT_SYMBOL_GPL(rt2800_write_tx_data);  static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  { -	int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); -	int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); -	int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); +	s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); +	s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); +	s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);  	u16 eeprom;  	u8 offset0;  	u8 offset1;  	u8 offset2;  	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);  		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);  		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);  		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);  	} else { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);  		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);  		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);  		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);  	} @@ -543,7 +807,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  	 * which gives less energy...  	 */  	rssi0 = max(rssi0, rssi1); -	return max(rssi0, rssi2); +	return (int)max(rssi0, rssi2);  }  void rt2800_process_rxwi(struct queue_entry *entry, @@ -584,58 +848,14 @@ void rt2800_process_rxwi(struct queue_entry *entry,  	 * Convert descriptor AGC value to RSSI value.  	 */  	rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); -  	/* -	 * Remove RXWI descriptor from start of buffer. +	 * Remove RXWI descriptor from start of the buffer.  	 */ -	skb_pull(entry->skb, RXWI_DESC_SIZE); +	skb_pull(entry->skb, entry->queue->winfo_size);  }  EXPORT_SYMBOL_GPL(rt2800_process_rxwi); -static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) -{ -	__le32 *txwi; -	u32 word; -	int wcid, ack, pid; -	int tx_wcid, tx_ack, tx_pid; - -	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); -	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); -	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - -	/* -	 * This frames has returned with an IO error, -	 * so the status report is not intended for this -	 * frame. -	 */ -	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { -		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); -		return false; -	} - -	/* -	 * Validate if this TX status report is intended for -	 * this entry by comparing the WCID/ACK/PID fields. -	 */ -	txwi = rt2800_drv_get_txwi(entry); - -	rt2x00_desc_read(txwi, 1, &word); -	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); -	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); -	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); - -	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { -		WARNING(entry->queue->rt2x00dev, -			"TX status report missed for queue %d entry %d\n", -		entry->queue->qid, entry->entry_idx); -		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); -		return false; -	} - -	return true; -} - -void rt2800_txdone_entry(struct queue_entry *entry, u32 status) +void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); @@ -643,13 +863,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  	u32 word;  	u16 mcs, real_mcs;  	int aggr, ampdu; -	__le32 *txwi;  	/*  	 * Obtain the status about this packet.  	 */  	txdesc.flags = 0; -	txwi = rt2800_drv_get_txwi(entry);  	rt2x00_desc_read(txwi, 0, &word);  	mcs = rt2x00_get_field32(word, TXWI_W0_MCS); @@ -674,11 +892,14 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  	 * confuse the rate control algortihm by providing clearly wrong  	 * data.  	 */ -	if (aggr == 1 && ampdu == 0 && real_mcs != mcs) { +	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {  		skbdesc->tx_rate_idx = real_mcs;  		mcs = real_mcs;  	} +	if (aggr == 1 || ampdu == 1) +		__set_bit(TXDONE_AMPDU, &txdesc.flags); +  	/*  	 * Ralink has a retry mechanism using a global fallback  	 * table. We setup this fallback table to try the immediate @@ -714,86 +935,47 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  }  EXPORT_SYMBOL_GPL(rt2800_txdone_entry); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev) +static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, +					  unsigned int index)  { -	struct data_queue *queue; -	struct queue_entry *entry; -	u32 reg; -	u8 pid; -	int i; - -	/* -	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO -	 * at most X times and also stop processing once the TX_STA_FIFO_VALID -	 * flag is not set anymore. -	 * -	 * The legacy drivers use X=TX_RING_SIZE but state in a comment -	 * that the TX_STA_FIFO stack has a size of 16. We stick to our -	 * tx ring size for now. -	 */ -	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); -		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) -			break; - -		/* -		 * Skip this entry when it contains an invalid -		 * queue identication number. -		 */ -		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); -		if (pid >= QID_RX) -			continue; - -		queue = rt2x00queue_get_queue(rt2x00dev, pid); -		if (unlikely(!queue)) -			continue; - -		/* -		 * Inside each queue, we process each entry in a chronological -		 * order. We first check that the queue is not empty. -		 */ -		entry = NULL; -		while (!rt2x00queue_empty(queue)) { -			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (rt2800_txdone_entry_check(entry, reg)) -				break; -		} - -		if (!entry || rt2x00queue_empty(queue)) -			break; +	return HW_BEACON_BASE(index); +} -		rt2800_txdone_entry(entry, reg); -	} +static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev, +					  unsigned int index) +{ +	return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));  } -EXPORT_SYMBOL_GPL(rt2800_txdone);  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	unsigned int beacon_base; -	u32 reg; +	unsigned int padding_len; +	u32 orig_reg, reg; +	const int txwi_desc_size = entry->queue->winfo_size;  	/*  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */  	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +	orig_reg = reg;  	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0);  	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);  	/*  	 * Add space for the TXWI in front of the skb.  	 */ -	skb_push(entry->skb, TXWI_DESC_SIZE); -	memset(entry->skb, 0, TXWI_DESC_SIZE); +	memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);  	/*  	 * Register descriptor details in skb frame descriptor.  	 */  	skbdesc->flags |= SKBDESC_DESC_IN_SKB;  	skbdesc->desc = entry->skb->data; -	skbdesc->desc_len = TXWI_DESC_SIZE; +	skbdesc->desc_len = txwi_desc_size;  	/*  	 * Add the TXWI for the beacon to the skb. @@ -806,19 +988,26 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);  	/* -	 * Write entire beacon with TXWI to register. +	 * Write entire beacon with TXWI and padding to register.  	 */ -	beacon_base = HW_BEACON_OFFSET(entry->entry_idx); -	rt2800_register_multiwrite(rt2x00dev, beacon_base, -				   entry->skb->data, entry->skb->len); +	padding_len = roundup(entry->skb->len, 4) - entry->skb->len; +	if (padding_len && skb_pad(entry->skb, padding_len)) { +		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n"); +		/* skb freed by skb_pad() on failure */ +		entry->skb = NULL; +		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg); +		return; +	} + +	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + +	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, +				   entry->skb->len + padding_len);  	/* -	 * Enable beaconing again. +	 * Restore beaconing state.  	 */ -	rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); -	rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); -	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); -	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);  	/*  	 * Clean up beacon skb. @@ -828,20 +1017,50 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  }  EXPORT_SYMBOL_GPL(rt2800_write_beacon); -static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, -				       unsigned int beacon_base) +static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, +						unsigned int index)  {  	int i; +	const int txwi_desc_size = rt2x00dev->bcn->winfo_size; +	unsigned int beacon_base; + +	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);  	/*  	 * For the Beacon base registers we only need to clear  	 * the whole TXWI which (when set to 0) will invalidate  	 * the entire beacon.  	 */ -	for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32)) +	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))  		rt2800_register_write(rt2x00dev, beacon_base + i, 0);  } +void rt2800_clear_beacon(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	u32 orig_reg, reg; + +	/* +	 * Disable beaconing while we are reloading the beacon data, +	 * otherwise we might be sending out invalid data. +	 */ +	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg); +	reg = orig_reg; +	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + +	/* +	 * Clear beacon. +	 */ +	rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx); + +	/* +	 * Restore beaconing state. +	 */ +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg); +} +EXPORT_SYMBOL_GPL(rt2800_clear_beacon); +  #ifdef CONFIG_RT2X00_LIB_DEBUGFS  const struct rt2x00debug rt2800_rt2x00debug = {  	.owner	= THIS_MODULE, @@ -854,6 +1073,9 @@ const struct rt2x00debug rt2800_rt2x00debug = {  		.word_count	= CSR_REG_SIZE / sizeof(u32),  	},  	.eeprom	= { +		/* NOTE: The local EEPROM access functions can't +		 * be used here, use the generic versions instead. +		 */  		.read		= rt2x00_eeprom_read,  		.write		= rt2x00_eeprom_write,  		.word_base	= EEPROM_BASE, @@ -874,6 +1096,13 @@ const struct rt2x00debug rt2800_rt2x00debug = {  		.word_size	= sizeof(u32),  		.word_count	= RF_SIZE / sizeof(u32),  	}, +	.rfcsr	= { +		.read		= rt2800_rfcsr_read, +		.write		= rt2800_rfcsr_write, +		.word_base	= RFCSR_BASE, +		.word_size	= sizeof(u8), +		.word_count	= RFCSR_SIZE / sizeof(u8), +	},  };  EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);  #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ @@ -882,8 +1111,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); -	return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); +	} else { +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +		return rt2x00_get_field32(reg, GPIO_CTRL_VAL2); +	}  }  EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); @@ -902,41 +1136,50 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,  	unsigned int ledmode =  		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,  				   EEPROM_FREQ_LED_MODE); - -	if (led->type == LED_TYPE_RADIO) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? 0x20 : 0); -	} else if (led->type == LED_TYPE_ASSOC) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); -	} else if (led->type == LED_TYPE_QUALITY) { -		/* -		 * The brightness is divided into 6 levels (0 - 5), -		 * The specs tell us the following levels: -		 *	0, 1 ,3, 7, 15, 31 -		 * to determine the level in a simple way we can simply -		 * work with bitshifting: -		 *	(1 << level) - 1 -		 */ -		rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, -				      (1 << brightness / (LED_FULL / 6)) - 1, -				      polarity); -	} -} - -static int rt2800_blink_set(struct led_classdev *led_cdev, -			    unsigned long *delay_on, unsigned long *delay_off) -{ -	struct rt2x00_led *led = -	    container_of(led_cdev, struct rt2x00_led, led_dev);  	u32 reg; -	rt2800_register_read(led->rt2x00dev, LED_CFG, ®); -	rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); -	rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); -	rt2800_register_write(led->rt2x00dev, LED_CFG, reg); +	/* Check for SoC (SOC devices don't support MCU requests) */ +	if (rt2x00_is_soc(led->rt2x00dev)) { +		rt2800_register_read(led->rt2x00dev, LED_CFG, ®); + +		/* Set LED Polarity */ +		rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); + +		/* Set LED Mode */ +		if (led->type == LED_TYPE_RADIO) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_QUALITY) { +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, +					   enabled ? 3 : 0); +		} -	return 0; +		rt2800_register_write(led->rt2x00dev, LED_CFG, reg); + +	} else { +		if (led->type == LED_TYPE_RADIO) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? 0x20 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); +		} else if (led->type == LED_TYPE_QUALITY) { +			/* +			 * The brightness is divided into 6 levels (0 - 5), +			 * The specs tell us the following levels: +			 *	0, 1 ,3, 7, 15, 31 +			 * to determine the level in a simple way we can simply +			 * work with bitshifting: +			 *	(1 << level) - 1 +			 */ +			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, +					      (1 << brightness / (LED_FULL / 6)) - 1, +					      polarity); +		} +	}  }  static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, @@ -945,7 +1188,6 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,  	led->rt2x00dev = rt2x00dev;  	led->type = type;  	led->led_dev.brightness_set = rt2800_brightness_set; -	led->led_dev.blink_set = rt2800_blink_set;  	led->flags = LED_INITIALIZED;  }  #endif /* CONFIG_RT2X00_LIB_LEDS */ @@ -953,11 +1195,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,  /*   * Configuration handlers.   */ -static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, -				    struct rt2x00lib_crypto *crypto, -				    struct ieee80211_key_conf *key) +static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev, +			       const u8 *address, +			       int wcid)  {  	struct mac_wcid_entry wcid_entry; +	u32 offset; + +	offset = MAC_WCID_ENTRY(wcid); + +	memset(&wcid_entry, 0xff, sizeof(wcid_entry)); +	if (address) +		memcpy(wcid_entry.mac, address, ETH_ALEN); + +	rt2800_register_multiwrite(rt2x00dev, offset, +				      &wcid_entry, sizeof(wcid_entry)); +} + +static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid) +{ +	u32 offset; +	offset = MAC_WCID_ATTR_ENTRY(wcid); +	rt2800_register_write(rt2x00dev, offset, 0); +} + +static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev, +					   int wcid, u32 bssidx) +{ +	u32 offset = MAC_WCID_ATTR_ENTRY(wcid); +	u32 reg; + +	/* +	 * The BSS Idx numbers is split in a main value of 3 bits, +	 * and a extended field for adding one additional bit to the value. +	 */ +	rt2800_register_read(rt2x00dev, offset, ®); +	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); +	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, +			   (bssidx & 0x8) >> 3); +	rt2800_register_write(rt2x00dev, offset, reg); +} + +static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, +					   struct rt2x00lib_crypto *crypto, +					   struct ieee80211_key_conf *key) +{  	struct mac_iveiv_entry iveiv_entry;  	u32 offset;  	u32 reg; @@ -977,14 +1259,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,  				   (crypto->cipher & 0x7));  		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT,  				   (crypto->cipher & 0x8) >> 3); -		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, -				   (crypto->bssidx & 0x7)); -		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, -				   (crypto->bssidx & 0x8) >> 3);  		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);  		rt2800_register_write(rt2x00dev, offset, reg);  	} else { -		rt2800_register_write(rt2x00dev, offset, 0); +		/* Delete the cipher without touching the bssidx */ +		rt2800_register_read(rt2x00dev, offset, ®); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); +		rt2800_register_write(rt2x00dev, offset, reg);  	}  	offset = MAC_IVEIV_ENTRY(key->hw_key_idx); @@ -997,14 +1281,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,  	iveiv_entry.iv[3] |= key->keyidx << 6;  	rt2800_register_multiwrite(rt2x00dev, offset,  				      &iveiv_entry, sizeof(iveiv_entry)); - -	offset = MAC_WCID_ENTRY(key->hw_key_idx); - -	memset(&wcid_entry, 0, sizeof(wcid_entry)); -	if (crypto->cmd == SET_KEY) -		memcpy(&wcid_entry, crypto->address, ETH_ALEN); -	rt2800_register_multiwrite(rt2x00dev, offset, -				      &wcid_entry, sizeof(wcid_entry));  }  int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, @@ -1051,12 +1327,47 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update WCID information  	 */ -	rt2800_config_wcid_attr(rt2x00dev, crypto, key); +	rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx); +	rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx, +				       crypto->bssidx); +	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);  	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_config_shared_key); +static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev) +{ +	struct mac_wcid_entry wcid_entry; +	int idx; +	u32 offset; + +	/* +	 * Search for the first free WCID entry and return the corresponding +	 * index. +	 * +	 * Make sure the WCID starts _after_ the last possible shared key +	 * entry (>32). +	 * +	 * Since parts of the pairwise key table might be shared with +	 * the beacon frame buffers 6 & 7 we should only write into the +	 * first 222 entries. +	 */ +	for (idx = 33; idx <= 222; idx++) { +		offset = MAC_WCID_ENTRY(idx); +		rt2800_register_multiread(rt2x00dev, offset, &wcid_entry, +					  sizeof(wcid_entry)); +		if (is_broadcast_ether_addr(wcid_entry.mac)) +			return idx; +	} + +	/* +	 * Use -1 to indicate that we don't have any more space in the WCID +	 * table. +	 */ +	return -1; +} +  int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  			       struct rt2x00lib_crypto *crypto,  			       struct ieee80211_key_conf *key) @@ -1066,18 +1377,12 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  	if (crypto->cmd == SET_KEY) {  		/* -		 * 1 pairwise key is possible per AID, this means that the AID -		 * equals our hw_key_idx. Make sure the WCID starts _after_ the -		 * last possible shared key entry. -		 * -		 * Since parts of the pairwise key table might be shared with -		 * the beacon frame buffers 6 & 7 we should only write into the -		 * first 222 entries. +		 * Allow key configuration only for STAs that are +		 * known by the hw.  		 */ -		if (crypto->aid > (222 - 32)) +		if (crypto->wcid < 0)  			return -ENOSPC; - -		key->hw_key_idx = 32 + crypto->aid; +		key->hw_key_idx = crypto->wcid;  		memcpy(key_entry.key, crypto->key,  		       sizeof(key_entry.key)); @@ -1094,12 +1399,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update WCID information  	 */ -	rt2800_config_wcid_attr(rt2x00dev, crypto, key); +	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);  	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); +int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, +		   struct ieee80211_sta *sta) +{ +	int wcid; +	struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); + +	/* +	 * Find next free WCID. +	 */ +	wcid = rt2800_find_wcid(rt2x00dev); + +	/* +	 * Store selected wcid even if it is invalid so that we can +	 * later decide if the STA is uploaded into the hw. +	 */ +	sta_priv->wcid = wcid; + +	/* +	 * No space left in the device, however, we can still communicate +	 * with the STA -> No error. +	 */ +	if (wcid < 0) +		return 0; + +	/* +	 * Clean up WCID attributes and write STA address to the device. +	 */ +	rt2800_delete_wcid_attr(rt2x00dev, wcid); +	rt2800_config_wcid(rt2x00dev, sta->addr, wcid); +	rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid, +				       rt2x00lib_get_bssidx(rt2x00dev, vif)); +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_sta_add); + +int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) +{ +	/* +	 * Remove WCID entry, no need to clean the attributes as they will +	 * get renewed when the WCID is reused. +	 */ +	rt2800_config_wcid(rt2x00dev, NULL, wcid); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_sta_remove); +  void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,  			  const unsigned int filter_flags)  { @@ -1136,8 +1488,9 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,  			   !(filter_flags & FIF_CONTROL));  	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL,  			   !(filter_flags & FIF_PSPOLL)); -	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); -	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); +	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 0); +	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, +			   !(filter_flags & FIF_CONTROL));  	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL,  			   !(filter_flags & FIF_CONTROL));  	rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); @@ -1152,29 +1505,30 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,  	if (flags & CONFIG_UPDATE_TYPE) {  		/* -		 * Clear current synchronisation setup. -		 */ -		rt2800_clear_beacon(rt2x00dev, -				    HW_BEACON_OFFSET(intf->beacon->entry_idx)); -		/*  		 * Enable synchronisation.  		 */  		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); -		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, -				   (conf->sync == TSF_SYNC_ADHOC || -				    conf->sync == TSF_SYNC_AP_NONE));  		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); -		/* -		 * Enable pre tbtt interrupt for beaconing modes -		 */ -		rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); -		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, -				   (conf->sync == TSF_SYNC_AP_NONE)); -		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); - +		if (conf->sync == TSF_SYNC_AP_NONE) { +			/* +			 * Tune beacon queue transmit parameters for AP mode +			 */ +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		} else { +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		}  	}  	if (flags & CONFIG_UPDATE_MAC) { @@ -1280,7 +1634,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,  			gf20_rate = gf40_rate = 0x0003;  		}  		break; -	}; +	}  	/* check for STAs not supporting greenfield mode */  	if (any_sta_nongf) @@ -1358,38 +1712,121 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,  }  EXPORT_SYMBOL_GPL(rt2800_config_erp); +static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u16 eeprom; +	u8 led_ctrl, led_g_mode, led_r_mode; + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 1); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 1); +	} else { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 0); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 0); +	} +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_register_read(rt2x00dev, LED_CFG, ®); +	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0; +	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; +	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || +	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); +		if (led_ctrl == 0 || led_ctrl > 0x40) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode); +			rt2800_register_write(rt2x00dev, LED_CFG, reg); +		} else { +			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff, +					   (led_g_mode << 2) | led_r_mode, 1); +		} +	} +} + +static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev, +				     enum antenna ant) +{ +	u32 reg; +	u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0; +	u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1; + +	if (rt2x00_is_pci(rt2x00dev)) { +		rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +		rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, eesk_pin); +		rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); +	} else if (rt2x00_is_usb(rt2x00dev)) +		rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff, +				   eesk_pin, 0); + +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); +	rt2x00_set_field32(®, GPIO_CTRL_VAL3, gpio_bit3); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); +} +  void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  {  	u8 r1;  	u8 r3; +	u16 eeprom;  	rt2800_bbp_read(rt2x00dev, 1, &r1);  	rt2800_bbp_read(rt2x00dev, 3, &r3); +	if (rt2x00_rt(rt2x00dev, RT3572) && +	    rt2x00_has_cap_bt_coexist(rt2x00dev)) +		rt2800_config_3572bt_ant(rt2x00dev); +  	/*  	 * Configure the TX antenna.  	 */ -	switch ((int)ant->tx) { +	switch (ant->tx_chain_num) {  	case 1:  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    rt2x00_has_cap_bt_coexist(rt2x00dev)) +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); +		else +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	case 3: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); +		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	}  	/*  	 * Configure the RX antenna.  	 */ -	switch ((int)ant->rx) { +	switch (ant->rx_chain_num) {  	case 1: +		if (rt2x00_rt(rt2x00dev, RT3070) || +		    rt2x00_rt(rt2x00dev, RT3090) || +		    rt2x00_rt(rt2x00dev, RT3352) || +		    rt2x00_rt(rt2x00dev, RT3390)) { +			rt2800_eeprom_read(rt2x00dev, +					   EEPROM_NIC_CONF1, &eeprom); +			if (rt2x00_get_field16(eeprom, +						EEPROM_NIC_CONF1_ANT_DIVERSITY)) +				rt2800_set_ant_diversity(rt2x00dev, +						rt2x00dev->default_ant.rx); +		}  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    rt2x00_has_cap_bt_coexist(rt2x00dev)) { +			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, +				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); +			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B); +		} else { +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		}  		break;  	case 3:  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); @@ -1398,6 +1835,13 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  	rt2800_bbp_write(rt2x00dev, 3, r3);  	rt2800_bbp_write(rt2x00dev, 1, r1); + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		if (ant->rx_chain_num == 1) +			rt2800_bbp_write(rt2x00dev, 86, 0x00); +		else +			rt2800_bbp_write(rt2x00dev, 86, 0x46); +	}  }  EXPORT_SYMBOL_GPL(rt2800_config_ant); @@ -1408,22 +1852,73 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	short lna_gain;  	if (libconf->rf.channel <= 14) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);  		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);  	} else if (libconf->rf.channel <= 64) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);  		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);  	} else if (libconf->rf.channel <= 128) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); -		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); +		if (rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_EXT_LNA2_A1); +		} else { +			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_RSSI_BG2_LNA_A1); +		}  	} else { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); -		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); +		if (rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_EXT_LNA2_A2); +		} else { +			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_RSSI_A2_LNA_A2); +		}  	}  	rt2x00dev->lna_gain = lna_gain;  } +#define FREQ_OFFSET_BOUND	0x5f + +static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) +{ +	u8 freq_offset, prev_freq_offset; +	u8 rfcsr, prev_rfcsr; + +	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); +	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); + +	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); +	prev_rfcsr = rfcsr; + +	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); +	if (rfcsr == prev_rfcsr) +		return; + +	if (rt2x00_is_usb(rt2x00dev)) { +		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, +				   freq_offset, prev_rfcsr); +		return; +	} + +	prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); +	while (prev_freq_offset != freq_offset) { +		if (prev_freq_offset < freq_offset) +			prev_freq_offset++; +		else +			prev_freq_offset--; + +		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); +		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + +		usleep_range(1000, 1500); +	} +} +  static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,  					 struct ieee80211_conf *conf,  					 struct rf_channel *rf, @@ -1431,19 +1926,19 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,  {  	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); -	if (rt2x00dev->default_ant.tx == 1) +	if (rt2x00dev->default_ant.tx_chain_num == 1)  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); -	if (rt2x00dev->default_ant.rx == 1) { +	if (rt2x00dev->default_ant.rx_chain_num == 1) {  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); -	} else if (rt2x00dev->default_ant.rx == 2) +	} else if (rt2x00dev->default_ant.rx_chain_num == 2)  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);  	if (rf->channel > 14) {  		/*  		 * When TX power is below 0, we should increase it by 7 to -		 * make it a positive value (Minumum value is -7). +		 * make it a positive value (Minimum value is -7).  		 * However this means that values between 0 and 7 have  		 * double meaning, and we should set a 7DBm boost flag.  		 */ @@ -1494,10 +1989,14 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  					 struct rf_channel *rf,  					 struct channel_info *info)  { -	u8 rfcsr; +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr, calib_tx, calib_rx;  	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); -	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3); +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);  	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); @@ -1511,65 +2010,1229 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);  	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, +			  rt2x00dev->default_ant.rx_chain_num <= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, +			  rt2x00dev->default_ant.rx_chain_num <= 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, +			  rt2x00dev->default_ant.tx_chain_num <= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, +			  rt2x00dev->default_ant.tx_chain_num <= 2); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +  	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);  	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); -	rt2800_rfcsr_write(rt2x00dev, 24, -			      rt2x00dev->calibration[conf_is_ht40(conf)]); +	if (rt2x00_rt(rt2x00dev, RT3390)) { +		calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f; +		calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f; +	} else { +		if (conf_is_ht40(conf)) { +			calib_tx = drv_data->calibration_bw40; +			calib_rx = drv_data->calibration_bw40; +		} else { +			calib_tx = drv_data->calibration_bw20; +			calib_rx = drv_data->calibration_bw20; +		} +	} + +	rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx); +	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx); +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);  	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);  	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); +	msleep(1); +	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);  } -static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, -				  struct ieee80211_conf *conf, -				  struct rf_channel *rf, -				  struct channel_info *info) +static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info)  { +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr;  	u32 reg; -	unsigned int tx_pin; + +	if (rf->channel <= 14) { +		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); +		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); +	} else { +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		rt2800_bbp_write(rt2x00dev, 26, 0xff); +	} + +	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2); +	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				  info->default_power1); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				  info->default_power2); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); +	if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +		if (rf->channel <= 14) { +			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		} +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +			break; +		} + +		switch (rt2x00dev->default_ant.rx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +			break; +		} +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); +	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); + +	if (conf_is_ht40(conf)) { +		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40); +		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20); +		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20); +	} + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rfcsr = 0x4c; +		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, +				  drv_data->txmixer_gain_24g); +		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	} else { +		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1); +		rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0); +		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x43); +		rfcsr = 0x7a; +		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, +				  drv_data->txmixer_gain_5g); +		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		if (rf->channel <= 64) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +		} else if (rf->channel <= 128) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x74); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} else { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x72); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} +		rt2800_rfcsr_write(rt2x00dev, 26, 0x87); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); +	} + +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); +	if (rf->channel <= 14) +		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); +	else +		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 0); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +} + +static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 txrx_agc_fc; +	u8 txrx_h20m; +	u8 rfcsr;  	u8 bbp; +	const bool txbf_enabled = false; /* TODO */ + +	/* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */ +	rt2800_bbp_read(rt2x00dev, 109, &bbp); +	rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0); +	rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0); +	rt2800_bbp_write(rt2x00dev, 109, bbp); + +	rt2800_bbp_read(rt2x00dev, 110, &bbp); +	rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0); +	rt2800_bbp_write(rt2x00dev, 110, bbp);  	if (rf->channel <= 14) { -		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); -		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2); +		/* Restore BBP 25 & 26 for 2.4 GHz */ +		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); +		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);  	} else { -		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1); -		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2); +		/* Hard code BBP 25 & 26 for 5GHz */ + +		/* Enable IQ Phase correction */ +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		/* Setup IQ Phase correction value */ +		rt2800_bbp_write(rt2x00dev, 26, 0xff);  	} -	if (rt2x00_rf(rt2x00dev, RF2020) || -	    rt2x00_rf(rt2x00dev, RF3020) || -	    rt2x00_rf(rt2x00dev, RF3021) || -	    rt2x00_rf(rt2x00dev, RF3022) || -	    rt2x00_rf(rt2x00dev, RF3052) || -	    rt2x00_rf(rt2x00dev, RF3320)) -		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3)); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);  	else -		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); +		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); -	/* -	 * Change BBP settings +	rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, +				  info->default_power1 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, +				  ((info->default_power1 & 0x18) << 1) | +				  (info->default_power1 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 53, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, +				  info->default_power2 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, +				  ((info->default_power2 & 0x18) << 1) | +				  (info->default_power2 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 55, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, +				  info->default_power3 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, +				  ((info->default_power3 & 0x18) << 1) | +				  (info->default_power3 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 54, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + +	switch (rt2x00dev->default_ant.tx_chain_num) { +	case 3: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +		/* fallthrough */ +	case 2: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		/* fallthrough */ +	case 1: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		break; +	} + +	switch (rt2x00dev->default_ant.rx_chain_num) { +	case 3: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		/* fallthrough */ +	case 2: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		/* fallthrough */ +	case 1: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +		break; +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (conf_is_ht40(conf)) { +		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, +						RFCSR24_TX_AGC_FC); +		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40, +					      RFCSR24_TX_H20M); +	} else { +		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20, +						RFCSR24_TX_AGC_FC); +		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20, +					      RFCSR24_TX_H20M); +	} + +	/* NOTE: the reference driver does not writes the new value +	 * back to RFCSR 32  	 */ +	rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc); + +	if (rf->channel <= 14) +		rfcsr = 0xa0; +	else +		rfcsr = 0x80; +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	/* Band selection */ +	rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); +	rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr); +	if (rf->channel <= 14) +		rfcsr = 0x3c; +	else +		rfcsr = 0x20; +	rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) +		rfcsr = 0x1a; +	else +		rfcsr = 0x12; +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	if (rf->channel >= 1 && rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); +	else if (rf->channel >= 36 && rf->channel <= 64) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); +	else if (rf->channel >= 100 && rf->channel <= 128) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 46, 0x60); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 10, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x23); +	} + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1); +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5); +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4); +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2); +	} +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2); + +	if (txbf_enabled) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1); + +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b); +	else +		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 57, rfcsr); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 44, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x45); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x05); +	} + +	/* Initiate VCO calibration */ +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	} +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + +	if (rf->channel >= 1 && rf->channel <= 14) { +		rfcsr = 0x23; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); +	} else if (rf->channel >= 36 && rf->channel <= 64) { +		rfcsr = 0x36; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, 0x36); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xeb); +	} else if (rf->channel >= 100 && rf->channel <= 128) { +		rfcsr = 0x32; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xb3); +	} else { +		rfcsr = 0x30; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0x9b); +	} +} + +#define POWER_BOUND		0x27 +#define POWER_BOUND_5G		0x2b + +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > POWER_BOUND) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (rf->channel <= 14) { +		if (rf->channel == 6) +			rt2800_bbp_write(rt2x00dev, 68, 0x0c); +		else +			rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +		if (rf->channel >= 1 && rf->channel <= 6) +			rt2800_bbp_write(rt2x00dev, 59, 0x0f); +		else if (rf->channel >= 7 && rf->channel <= 11) +			rt2800_bbp_write(rt2x00dev, 59, 0x0e); +		else if (rf->channel >= 12 && rf->channel <= 14) +			rt2800_bbp_write(rt2x00dev, 59, 0x0d); +	} +} + +static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); + +	rt2800_rfcsr_write(rt2x00dev, 11, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x00); + +	if (info->default_power1 > POWER_BOUND) +		rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND); +	else +		rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1); + +	if (info->default_power2 > POWER_BOUND) +		rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND); +	else +		rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); + +	if ( rt2x00dev->default_ant.tx_chain_num == 2 ) +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + +	if ( rt2x00dev->default_ant.rx_chain_num == 2 ) +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 31, 80); +} + +static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > POWER_BOUND) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +		if (info->default_power2 > POWER_BOUND) +			rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND); +		else +			rt2x00_set_field8(&rfcsr, RFCSR50_TX, +					  info->default_power2); +		rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); +	} + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +	} +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (rf->channel <= 14) { +		int idx = rf->channel-1; + +		if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +				/* r55/r59 value array of channel 1~14 */ +				static const char r55_bt_rev[] = {0x83, 0x83, +					0x83, 0x73, 0x73, 0x63, 0x53, 0x53, +					0x53, 0x43, 0x43, 0x43, 0x43, 0x43}; +				static const char r59_bt_rev[] = {0x0e, 0x0e, +					0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09, +					0x07, 0x07, 0x07, 0x07, 0x07, 0x07}; + +				rt2800_rfcsr_write(rt2x00dev, 55, +						   r55_bt_rev[idx]); +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_bt_rev[idx]); +			} else { +				static const char r59_bt[] = {0x8b, 0x8b, 0x8b, +					0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89, +					0x88, 0x88, 0x86, 0x85, 0x84}; + +				rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]); +			} +		} else { +			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +				static const char r55_nonbt_rev[] = {0x23, 0x23, +					0x23, 0x23, 0x13, 0x13, 0x03, 0x03, +					0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; +				static const char r59_nonbt_rev[] = {0x07, 0x07, +					0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +					0x07, 0x07, 0x06, 0x05, 0x04, 0x04}; + +				rt2800_rfcsr_write(rt2x00dev, 55, +						   r55_nonbt_rev[idx]); +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_nonbt_rev[idx]); +			} else if (rt2x00_rt(rt2x00dev, RT5390) || +				   rt2x00_rt(rt2x00dev, RT5392)) { +				static const char r59_non_bt[] = {0x8f, 0x8f, +					0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, +					0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; + +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_non_bt[idx]); +			} +		} +	} +} + +static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr, ep_reg; +	u32 reg; +	int power_bound; + +	/* TODO */ +	const bool is_11b = false; +	const bool is_type_ep = false; + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, +			   (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	/* Order of values on rf_channel entry: N, K, mod, R */ +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff); + +	rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf); +	rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8); +	rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2); +	rt2800_rfcsr_write(rt2x00dev, 9, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1); +	rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 10, 0x90); +		/* FIXME: RF11 owerwrite ? */ +		rt2800_rfcsr_write(rt2x00dev, 11, 0x4A); +		rt2800_rfcsr_write(rt2x00dev, 12, 0x52); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 22, 0x40); +		rt2800_rfcsr_write(rt2x00dev, 24, 0x4A); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 36, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +		rt2800_rfcsr_write(rt2x00dev, 38, 0x89); +		rt2800_rfcsr_write(rt2x00dev, 39, 0x1B); +		rt2800_rfcsr_write(rt2x00dev, 40, 0x0D); +		rt2800_rfcsr_write(rt2x00dev, 41, 0x9B); +		rt2800_rfcsr_write(rt2x00dev, 42, 0xD5); +		rt2800_rfcsr_write(rt2x00dev, 43, 0x72); +		rt2800_rfcsr_write(rt2x00dev, 44, 0x0E); +		rt2800_rfcsr_write(rt2x00dev, 45, 0xA2); +		rt2800_rfcsr_write(rt2x00dev, 46, 0x6B); +		rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +		rt2800_rfcsr_write(rt2x00dev, 51, 0x3E); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x48); +		rt2800_rfcsr_write(rt2x00dev, 54, 0x38); +		rt2800_rfcsr_write(rt2x00dev, 56, 0xA1); +		rt2800_rfcsr_write(rt2x00dev, 57, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 58, 0x39); +		rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +		rt2800_rfcsr_write(rt2x00dev, 61, 0x91); +		rt2800_rfcsr_write(rt2x00dev, 62, 0x39); + +		/* TODO RF27 <- tssi */ + +		rfcsr = rf->channel <= 10 ? 0x07 : 0x06; +		rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); + +		if (is_11b) { +			/* CCK */ +			rt2800_rfcsr_write(rt2x00dev, 31, 0xF8); +			rt2800_rfcsr_write(rt2x00dev, 32, 0xC0); +			if (is_type_ep) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x06); +			else +				rt2800_rfcsr_write(rt2x00dev, 55, 0x47); +		} else { +			/* OFDM */ +			if (is_type_ep) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x03); +			else +				rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +		} + +		power_bound = POWER_BOUND; +		ep_reg = 0x2; +	} else { +		rt2800_rfcsr_write(rt2x00dev, 10, 0x97); +		/* FIMXE: RF11 overwrite */ +		rt2800_rfcsr_write(rt2x00dev, 11, 0x40); +		rt2800_rfcsr_write(rt2x00dev, 25, 0xBF); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 37, 0x04); +		rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 40, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 41, 0xBB); +		rt2800_rfcsr_write(rt2x00dev, 42, 0xD7); +		rt2800_rfcsr_write(rt2x00dev, 45, 0x41); +		rt2800_rfcsr_write(rt2x00dev, 48, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 57, 0x77); +		rt2800_rfcsr_write(rt2x00dev, 60, 0x05); +		rt2800_rfcsr_write(rt2x00dev, 61, 0x01); + +		/* TODO RF27 <- tssi */ + +		if (rf->channel >= 36 && rf->channel <= 64) { + +			rt2800_rfcsr_write(rt2x00dev, 12, 0x2E); +			rt2800_rfcsr_write(rt2x00dev, 13, 0x22); +			rt2800_rfcsr_write(rt2x00dev, 22, 0x60); +			rt2800_rfcsr_write(rt2x00dev, 23, 0x7F); +			if (rf->channel <= 50) +				rt2800_rfcsr_write(rt2x00dev, 24, 0x09); +			else if (rf->channel >= 52) +				rt2800_rfcsr_write(rt2x00dev, 24, 0x07); +			rt2800_rfcsr_write(rt2x00dev, 39, 0x1C); +			rt2800_rfcsr_write(rt2x00dev, 43, 0x5B); +			rt2800_rfcsr_write(rt2x00dev, 44, 0X40); +			rt2800_rfcsr_write(rt2x00dev, 46, 0X00); +			rt2800_rfcsr_write(rt2x00dev, 51, 0xFE); +			rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); +			rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); +			if (rf->channel <= 50) { +				rt2800_rfcsr_write(rt2x00dev, 55, 0x06), +				rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); +			} else if (rf->channel >= 52) { +				rt2800_rfcsr_write(rt2x00dev, 55, 0x04); +				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); +			} + +			rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +			rt2800_rfcsr_write(rt2x00dev, 59, 0x7F); +			rt2800_rfcsr_write(rt2x00dev, 62, 0x15); + +		} else if (rf->channel >= 100 && rf->channel <= 165) { + +			rt2800_rfcsr_write(rt2x00dev, 12, 0x0E); +			rt2800_rfcsr_write(rt2x00dev, 13, 0x42); +			rt2800_rfcsr_write(rt2x00dev, 22, 0x40); +			if (rf->channel <= 153) { +				rt2800_rfcsr_write(rt2x00dev, 23, 0x3C); +				rt2800_rfcsr_write(rt2x00dev, 24, 0x06); +			} else if (rf->channel >= 155) { +				rt2800_rfcsr_write(rt2x00dev, 23, 0x38); +				rt2800_rfcsr_write(rt2x00dev, 24, 0x05); +			} +			if (rf->channel <= 138) { +				rt2800_rfcsr_write(rt2x00dev, 39, 0x1A); +				rt2800_rfcsr_write(rt2x00dev, 43, 0x3B); +				rt2800_rfcsr_write(rt2x00dev, 44, 0x20); +				rt2800_rfcsr_write(rt2x00dev, 46, 0x18); +			} else if (rf->channel >= 140) { +				rt2800_rfcsr_write(rt2x00dev, 39, 0x18); +				rt2800_rfcsr_write(rt2x00dev, 43, 0x1B); +				rt2800_rfcsr_write(rt2x00dev, 44, 0x10); +				rt2800_rfcsr_write(rt2x00dev, 46, 0X08); +			} +			if (rf->channel <= 124) +				rt2800_rfcsr_write(rt2x00dev, 51, 0xFC); +			else if (rf->channel >= 126) +				rt2800_rfcsr_write(rt2x00dev, 51, 0xEC); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +			rt2800_rfcsr_write(rt2x00dev, 54, 0xEB); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x01); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x00); +			if (rf->channel <= 128) +				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); +			else if (rf->channel >= 130) +				rt2800_rfcsr_write(rt2x00dev, 56, 0xAB); +			if (rf->channel <= 116) +				rt2800_rfcsr_write(rt2x00dev, 58, 0x1D); +			else if (rf->channel >= 118) +				rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 59, 0x3F); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); +			if (rf->channel <= 116) +				rt2800_rfcsr_write(rt2x00dev, 62, 0x1D); +			else if (rf->channel >= 118) +				rt2800_rfcsr_write(rt2x00dev, 62, 0x15); +		} + +		power_bound = POWER_BOUND_5G; +		ep_reg = 0x3; +	} + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > power_bound) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	if (is_type_ep) +		rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	if (info->default_power2 > power_bound) +		rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); +	else +		rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); +	if (is_type_ep) +		rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, +			  rt2x00dev->default_ant.tx_chain_num >= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, +			  rt2x00dev->default_ant.tx_chain_num == 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, +			  rt2x00dev->default_ant.rx_chain_num >= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, +			  rt2x00dev->default_ant.rx_chain_num == 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xe4); + +	if (conf_is_ht40(conf)) +		rt2800_rfcsr_write(rt2x00dev, 30, 0x16); +	else +		rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + +	if (!is_11b) { +		rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	} + +	/* TODO proper frequency adjustment */ +	rt2800_adjust_freq_offset(rt2x00dev); + +	/* TODO merge with others */ +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + +	/* BBP settings */  	rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);  	rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);  	rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); -	rt2800_bbp_write(rt2x00dev, 86, 0); -	if (rf->channel <= 14) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { -			rt2800_bbp_write(rt2x00dev, 82, 0x62); -			rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18); +	rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08); +	rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38); +	rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92); + +	/* GLRT band configuration */ +	rt2800_bbp_write(rt2x00dev, 195, 128); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0); +	rt2800_bbp_write(rt2x00dev, 195, 129); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E); +	rt2800_bbp_write(rt2x00dev, 195, 130); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28); +	rt2800_bbp_write(rt2x00dev, 195, 131); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20); +	rt2800_bbp_write(rt2x00dev, 195, 133); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F); +	rt2800_bbp_write(rt2x00dev, 195, 124); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); +} + +static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, +					   const unsigned int word, +					   const u8 value) +{ +	u8 chain, reg; + +	for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) { +		rt2800_bbp_read(rt2x00dev, 27, ®); +		rt2x00_set_field8(®,  BBP27_RX_CHAIN_SEL, chain); +		rt2800_bbp_write(rt2x00dev, 27, reg); + +		rt2800_bbp_write(rt2x00dev, word, value); +	} +} + +static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) +{ +	u8 cal; + +	/* TX0 IQ Gain */ +	rt2800_bbp_write(rt2x00dev, 158, 0x2c); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX0 IQ Phase */ +	rt2800_bbp_write(rt2x00dev, 158, 0x2d); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX1 IQ Gain */ +	rt2800_bbp_write(rt2x00dev, 158, 0x4a); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX1 IQ Phase */ +	rt2800_bbp_write(rt2x00dev, 158, 0x4b); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* FIXME: possible RX0, RX1 callibration ? */ + +	/* RF IQ compensation control */ +	rt2800_bbp_write(rt2x00dev, 158, 0x04); +	cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL); +	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); + +	/* RF IQ imbalance compensation control */ +	rt2800_bbp_write(rt2x00dev, 158, 0x03); +	cal = rt2x00_eeprom_byte(rt2x00dev, +				 EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL); +	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); +} + +static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, +				  unsigned int channel, +				  char txpower) +{ +	if (rt2x00_rt(rt2x00dev, RT3593)) +		txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); + +	if (channel <= 14) +		return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return clamp_t(char, txpower, MIN_A_TXPOWER_3593, +			       MAX_A_TXPOWER_3593); +	else +		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); +} + +static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, +				  struct ieee80211_conf *conf, +				  struct rf_channel *rf, +				  struct channel_info *info) +{ +	u32 reg; +	unsigned int tx_pin; +	u8 bbp, rfcsr; + +	info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +						     info->default_power1); +	info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +						     info->default_power2); +	if (rt2x00dev->default_ant.tx_chain_num > 2) +		info->default_power3 = +			rt2800_txpower_to_dev(rt2x00dev, rf->channel, +					      info->default_power3); + +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +		break; +	case RF3052: +		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); +		break; +	case RF3053: +		rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info); +		break; +	case RF3290: +		rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); +		break; +	case RF3322: +		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); +		break; +	case RF3070: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); +		break; +	case RF5592: +		rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); +		break; +	default: +		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); +	} + +	if (rt2x00_rf(rt2x00dev, RF3070) || +	    rt2x00_rf(rt2x00dev, RF3290) || +	    rt2x00_rf(rt2x00dev, RF3322) || +	    rt2x00_rf(rt2x00dev, RF5360) || +	    rt2x00_rf(rt2x00dev, RF5370) || +	    rt2x00_rf(rt2x00dev, RF5372) || +	    rt2x00_rf(rt2x00dev, RF5390) || +	    rt2x00_rf(rt2x00dev, RF5392)) { +		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); +		rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); +		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); +	} + +	/* +	 * Change BBP settings +	 */ +	if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_bbp_write(rt2x00dev, 27, 0x0); +		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 27, 0x20); +		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); +	} else if (rt2x00_rt(rt2x00dev, RT3593)) { +		if (rf->channel > 14) { +			/* Disable CCK Packet detection on 5GHz */ +			rt2800_bbp_write(rt2x00dev, 70, 0x00);  		} else { -			rt2800_bbp_write(rt2x00dev, 82, 0x84); -			rt2800_bbp_write(rt2x00dev, 75, 0x50); +			rt2800_bbp_write(rt2x00dev, 70, 0x0a); +		} + +		if (conf_is_ht40(conf)) +			rt2800_bbp_write(rt2x00dev, 105, 0x04); +		else +			rt2800_bbp_write(rt2x00dev, 105, 0x34); + +		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 77, 0x98); +	} else { +		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 86, 0); +	} + +	if (rf->channel <= 14) { +		if (!rt2x00_rt(rt2x00dev, RT5390) && +		    !rt2x00_rt(rt2x00dev, RT5392)) { +			if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { +				rt2800_bbp_write(rt2x00dev, 82, 0x62); +				rt2800_bbp_write(rt2x00dev, 75, 0x46); +			} else { +				if (rt2x00_rt(rt2x00dev, RT3593)) +					rt2800_bbp_write(rt2x00dev, 82, 0x62); +				else +					rt2800_bbp_write(rt2x00dev, 82, 0x84); +				rt2800_bbp_write(rt2x00dev, 75, 0x50); +			} +			if (rt2x00_rt(rt2x00dev, RT3593)) +				rt2800_bbp_write(rt2x00dev, 83, 0x8a);  		} +  	} else { -		rt2800_bbp_write(rt2x00dev, 82, 0xf2); +		if (rt2x00_rt(rt2x00dev, RT3572)) +			rt2800_bbp_write(rt2x00dev, 82, 0x94); +		else if (rt2x00_rt(rt2x00dev, RT3593)) +			rt2800_bbp_write(rt2x00dev, 82, 0x82); +		else +			rt2800_bbp_write(rt2x00dev, 82, 0xf2); + +		if (rt2x00_rt(rt2x00dev, RT3593)) +			rt2800_bbp_write(rt2x00dev, 83, 0x9a); -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) +		if (rt2x00_has_cap_external_lna_a(rt2x00dev))  			rt2800_bbp_write(rt2x00dev, 75, 0x46);  		else  			rt2800_bbp_write(rt2x00dev, 75, 0x50); @@ -1581,29 +3244,127 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);  	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0); +  	tx_pin = 0; -	/* Turn on unused PA or LNA when not using 1T or 1R */ -	if (rt2x00dev->default_ant.tx != 1) { -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +	switch (rt2x00dev->default_ant.tx_chain_num) { +	case 3: +		/* Turn on tertiary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, +				   rf->channel <= 14); +		/* fall-through */ +	case 2: +		/* Turn on secondary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, +				   rf->channel <= 14); +		/* fall-through */ +	case 1: +		/* Turn on primary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, +				   rf->channel > 14); +		if (rt2x00_has_cap_bt_coexist(rt2x00dev)) +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +		else +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, +					   rf->channel <= 14); +		break;  	} -	/* Turn on unused PA or LNA when not using 1T or 1R */ -	if (rt2x00dev->default_ant.rx != 1) { +	switch (rt2x00dev->default_ant.rx_chain_num) { +	case 3: +		/* Turn on tertiary LNAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1); +		/* fall-through */ +	case 2: +		/* Turn on secondary LNAs */  		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);  		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); +		/* fall-through */ +	case 1: +		/* Turn on primary LNAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); +		break;  	} -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);  	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); +	if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_write(rt2x00dev, 8, 0x80); + +		/* AGC init */ +		if (rf->channel <= 14) +			reg = 0x1c + (2 * rt2x00dev->lna_gain); +		else +			reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); + +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); +	} + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + +		/* Band selection */ +		if (rt2x00_is_usb(rt2x00dev) || +		    rt2x00_is_pcie(rt2x00dev)) { +			/* GPIO #8 controls all paths */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); +			if (rf->channel <= 14) +				rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); +			else +				rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); +		} + +		/* LNA PE control. */ +		if (rt2x00_is_usb(rt2x00dev)) { +			/* GPIO #4 controls PE0 and PE1, +			 * GPIO #7 controls PE2 +			 */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); +			rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); + +			rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); +			rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); +		} else if (rt2x00_is_pcie(rt2x00dev)) { +			/* GPIO #4 controls PE0, PE1 and PE2 */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); +			rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); +		} + +		rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +		/* AGC init */ +		if (rf->channel <= 14) +			reg = 0x1c + 2 * rt2x00dev->lna_gain; +		else +			reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); + +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +		usleep_range(1000, 1500); +	} + +	if (rt2x00_rt(rt2x00dev, RT5592)) { +		rt2800_bbp_write(rt2x00dev, 195, 141); +		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); + +		/* AGC init */ +		reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain; +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +		rt2800_iq_calibrate(rt2x00dev, rf->channel); +	} +  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));  	rt2800_bbp_write(rt2x00dev, 4, bbp); @@ -1625,32 +3386,729 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	}  	msleep(1); + +	/* +	 * Clear channel statistic counters +	 */ +	rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); + +	/* +	 * Clear update flag +	 */ +	if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_bbp_read(rt2x00dev, 49, &bbp); +		rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); +		rt2800_bbp_write(rt2x00dev, 49, bbp); +	}  } -static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, -				  const int max_txpower) +static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) +{ +	u8 tssi_bounds[9]; +	u8 current_tssi; +	u16 eeprom; +	u8 step; +	int i; + +	/* +	 * First check if temperature compensation is supported. +	 */ +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC)) +		return 0; + +	/* +	 * Read TSSI boundaries for temperature compensation from +	 * the EEPROM. +	 * +	 * Array idx               0    1    2    3    4    5    6    7    8 +	 * Matching Delta value   -4   -3   -2   -1    0   +1   +2   +3   +4 +	 * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 +	 */ +	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); +		tssi_bounds[0] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG1_MINUS4); +		tssi_bounds[1] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG1_MINUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); +		tssi_bounds[2] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG2_MINUS2); +		tssi_bounds[3] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG2_MINUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); +		tssi_bounds[4] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG3_REF); +		tssi_bounds[5] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG3_PLUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); +		tssi_bounds[6] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG4_PLUS2); +		tssi_bounds[7] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG4_PLUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); +		tssi_bounds[8] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG5_PLUS4); + +		step = rt2x00_get_field16(eeprom, +					  EEPROM_TSSI_BOUND_BG5_AGC_STEP); +	} else { +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); +		tssi_bounds[0] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A1_MINUS4); +		tssi_bounds[1] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A1_MINUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); +		tssi_bounds[2] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A2_MINUS2); +		tssi_bounds[3] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A2_MINUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); +		tssi_bounds[4] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A3_REF); +		tssi_bounds[5] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A3_PLUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); +		tssi_bounds[6] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A4_PLUS2); +		tssi_bounds[7] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A4_PLUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); +		tssi_bounds[8] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A5_PLUS4); + +		step = rt2x00_get_field16(eeprom, +					  EEPROM_TSSI_BOUND_A5_AGC_STEP); +	} + +	/* +	 * Check if temperature compensation is supported. +	 */ +	if (tssi_bounds[4] == 0xff || step == 0xff) +		return 0; + +	/* +	 * Read current TSSI (BBP 49). +	 */ +	rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); + +	/* +	 * Compare TSSI value (BBP49) with the compensation boundaries +	 * from the EEPROM and increase or decrease tx power. +	 */ +	for (i = 0; i <= 3; i++) { +		if (current_tssi > tssi_bounds[i]) +			break; +	} + +	if (i == 4) { +		for (i = 8; i >= 5; i--) { +			if (current_tssi < tssi_bounds[i]) +				break; +		} +	} + +	return (i - 4) * step; +} + +static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, +				      enum ieee80211_band band) +{ +	u16 eeprom; +	u8 comp_en; +	u8 comp_type; +	int comp_value = 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); + +	/* +	 * HT40 compensation not required. +	 */ +	if (eeprom == 0xffff || +	    !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +		return 0; + +	if (band == IEEE80211_BAND_2GHZ) { +		comp_en = rt2x00_get_field16(eeprom, +				 EEPROM_TXPOWER_DELTA_ENABLE_2G); +		if (comp_en) { +			comp_type = rt2x00_get_field16(eeprom, +					   EEPROM_TXPOWER_DELTA_TYPE_2G); +			comp_value = rt2x00_get_field16(eeprom, +					    EEPROM_TXPOWER_DELTA_VALUE_2G); +			if (!comp_type) +				comp_value = -comp_value; +		} +	} else { +		comp_en = rt2x00_get_field16(eeprom, +				 EEPROM_TXPOWER_DELTA_ENABLE_5G); +		if (comp_en) { +			comp_type = rt2x00_get_field16(eeprom, +					   EEPROM_TXPOWER_DELTA_TYPE_5G); +			comp_value = rt2x00_get_field16(eeprom, +					    EEPROM_TXPOWER_DELTA_VALUE_5G); +			if (!comp_type) +				comp_value = -comp_value; +		} +	} + +	return comp_value; +} + +static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, +					int power_level, int max_power) +{ +	int delta; + +	if (rt2x00_has_cap_power_limit(rt2x00dev)) +		return 0; + +	/* +	 * XXX: We don't know the maximum transmit power of our hardware since +	 * the EEPROM doesn't expose it. We only know that we are calibrated +	 * to 100% tx power. +	 * +	 * Hence, we assume the regulatory limit that cfg80211 calulated for +	 * the current channel is our maximum and if we are requested to lower +	 * the value we just reduce our tx power accordingly. +	 */ +	delta = power_level - max_power; +	return min(delta, 0); +} + +static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, +				   enum ieee80211_band band, int power_level, +				   u8 txpower, int delta) +{ +	u16 eeprom; +	u8 criterion; +	u8 eirp_txpower; +	u8 eirp_txpower_criterion; +	u8 reg_limit; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return min_t(u8, txpower, 0xc); + +	if (rt2x00_has_cap_power_limit(rt2x00dev)) { +		/* +		 * Check if eirp txpower exceed txpower_limit. +		 * We use OFDM 6M as criterion and its eirp txpower +		 * is stored at EEPROM_EIRP_MAX_TX_POWER. +		 * .11b data rate need add additional 4dbm +		 * when calculating eirp txpower. +		 */ +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      1, &eeprom); +		criterion = rt2x00_get_field16(eeprom, +					       EEPROM_TXPOWER_BYRATE_RATE0); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, +				   &eeprom); + +		if (band == IEEE80211_BAND_2GHZ) +			eirp_txpower_criterion = rt2x00_get_field16(eeprom, +						 EEPROM_EIRP_MAX_TX_POWER_2GHZ); +		else +			eirp_txpower_criterion = rt2x00_get_field16(eeprom, +						 EEPROM_EIRP_MAX_TX_POWER_5GHZ); + +		eirp_txpower = eirp_txpower_criterion + (txpower - criterion) + +			       (is_rate_b ? 4 : 0) + delta; + +		reg_limit = (eirp_txpower > power_level) ? +					(eirp_txpower - power_level) : 0; +	} else +		reg_limit = 0; + +	txpower = max(0, txpower + delta - reg_limit); +	return min_t(u8, txpower, 0xc); +} + + +enum { +	TX_PWR_CFG_0_IDX, +	TX_PWR_CFG_1_IDX, +	TX_PWR_CFG_2_IDX, +	TX_PWR_CFG_3_IDX, +	TX_PWR_CFG_4_IDX, +	TX_PWR_CFG_5_IDX, +	TX_PWR_CFG_6_IDX, +	TX_PWR_CFG_7_IDX, +	TX_PWR_CFG_8_IDX, +	TX_PWR_CFG_9_IDX, +	TX_PWR_CFG_0_EXT_IDX, +	TX_PWR_CFG_1_EXT_IDX, +	TX_PWR_CFG_2_EXT_IDX, +	TX_PWR_CFG_3_EXT_IDX, +	TX_PWR_CFG_4_EXT_IDX, +	TX_PWR_CFG_IDX_COUNT, +}; + +static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_channel *chan, +					 int power_level)  {  	u8 txpower; -	u8 max_value = (u8)max_txpower;  	u16 eeprom; +	u32 regs[TX_PWR_CFG_IDX_COUNT]; +	unsigned int offset; +	enum ieee80211_band band = chan->band; +	int delta;  	int i; -	u32 reg; -	u8 r1; -	u32 offset; + +	memset(regs, '\0', sizeof(regs)); + +	/* TODO: adapt TX power reduction from the rt28xx code */ + +	/* calculate temperature compensation delta */ +	delta = rt2800_get_gain_calibration_delta(rt2x00dev); + +	if (band == IEEE80211_BAND_5GHZ) +		offset = 16; +	else +		offset = 0; + +	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +		offset += 8; + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset, &eeprom); + +	/* CCK 1MBS,2MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK1_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK1_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_CCK1_CH2, txpower); + +	/* CCK 5.5MBS,11MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK5_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK5_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_CCK5_CH2, txpower); + +	/* OFDM 6MBS,9MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM6_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM6_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower); + +	/* OFDM 12MBS,18MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM12_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM12_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 1, &eeprom); + +	/* OFDM 24MBS,36MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM24_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM24_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower); + +	/* OFDM 48MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM48_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM48_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower); + +	/* OFDM 54MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 2, &eeprom); + +	/* MCS 0,1 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS0_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS0_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_MCS0_CH2, txpower); + +	/* MCS 2,3 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS2_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS2_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_MCS2_CH2, txpower); + +	/* MCS 4,5 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS4_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS4_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS4_CH2, txpower); + +	/* MCS 6 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS6_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS6_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS6_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 3, &eeprom); + +	/* MCS 7 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH2, txpower); + +	/* MCS 8,9 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS8_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS8_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS8_CH2, txpower); + +	/* MCS 10,11 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS10_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS10_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS10_CH2, txpower); + +	/* MCS 12,13 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS12_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS12_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_MCS12_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 4, &eeprom); + +	/* MCS 14 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS14_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS14_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_MCS14_CH2, txpower); + +	/* MCS 15 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH2, txpower); + +	/* MCS 16,17 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH2, txpower); + +	/* MCS 18,19 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 5, &eeprom); + +	/* MCS 20,21 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH2, txpower); + +	/* MCS 22 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH2, txpower); + +	/* MCS 23 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 6, &eeprom); + +	/* STBC, MCS 0,1 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC0_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC0_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_STBC0_CH2, txpower); + +	/* STBC, MCS 2,3 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC2_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC2_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_STBC2_CH2, txpower); + +	/* STBC, MCS 4,5 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0, +			   txpower); + +	/* STBC, MCS 6 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2, +			   txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 7, &eeprom); + +	/* STBC, MCS 7 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH2, txpower); + +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]); + +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT, +			      regs[TX_PWR_CFG_0_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT, +			      regs[TX_PWR_CFG_1_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT, +			      regs[TX_PWR_CFG_2_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT, +			      regs[TX_PWR_CFG_3_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT, +			      regs[TX_PWR_CFG_4_EXT_IDX]); + +	for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++) +		rt2x00_dbg(rt2x00dev, +			   "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n", +			   (band == IEEE80211_BAND_5GHZ) ? '5' : '2', +			   (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ? +								'4' : '2', +			   (i > TX_PWR_CFG_9_IDX) ? +					(i - TX_PWR_CFG_9_IDX - 1) : i, +			   (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "", +			   (unsigned long) regs[i]); +} + +/* + * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and + * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, + * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power + * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm. + * Reference per rate transmit power values are located in the EEPROM at + * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to + * current conditions (i.e. band, bandwidth, temperature, user settings). + */ +static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_channel *chan, +					 int power_level) +{ +	u8 txpower, r1; +	u16 eeprom; +	u32 reg, offset; +	int i, is_rate_b, delta, power_ctrl; +	enum ieee80211_band band = chan->band;  	/* -	 * set to normal tx power mode: +/- 0dBm +	 * Calculate HT40 compensation. For 40MHz we need to add or subtract +	 * value read from EEPROM (different for 2GHz and for 5GHz).  	 */ -	rt2800_bbp_read(rt2x00dev, 1, &r1); -	rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); -	rt2800_bbp_write(rt2x00dev, 1, r1); +	delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); + +	/* +	 * Calculate temperature compensation. Depends on measurement of current +	 * TSSI (Transmitter Signal Strength Indication) we know TX power (due +	 * to temperature or maybe other factors) is smaller or bigger than +	 * expected. We adjust it, based on TSSI reference and boundaries values +	 * provided in EEPROM. +	 */ +	delta += rt2800_get_gain_calibration_delta(rt2x00dev);  	/* -	 * The eeprom contains the tx power values for each rate. These -	 * values map to 100% tx power. Each 16bit word contains four tx -	 * power values and the order is the same as used in the TX_PWR_CFG -	 * registers. +	 * Decrease power according to user settings, on devices with unknown +	 * maximum tx power. For other devices we take user power_level into +	 * consideration on rt2800_compensate_txpower().  	 */ +	delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level, +					      chan->max_power); + +	/* +	 * BBP_R1 controls TX power for all rates, it allow to set the following +	 * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively. +	 * +	 * TODO: we do not use +6 dBm option to do not increase power beyond +	 * regulatory limit, however this could be utilized for devices with +	 * CAPABILITY_POWER_LIMIT. +	 * +	 * TODO: add different temperature compensation code for RT3290 & RT5390 +	 * to allow to use BBP_R1 for those chips. +	 */ +	if (!rt2x00_rt(rt2x00dev, RT3290) && +	    !rt2x00_rt(rt2x00dev, RT5390)) { +		rt2800_bbp_read(rt2x00dev, 1, &r1); +		if (delta <= -12) { +			power_ctrl = 2; +			delta += 12; +		} else if (delta <= -6) { +			power_ctrl = 1; +			delta += 6; +		} else { +			power_ctrl = 0; +		} +		rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); +		rt2800_bbp_write(rt2x00dev, 1, r1); +	} +  	offset = TX_PWR_CFG_0;  	for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { @@ -1661,76 +4119,102 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,  		rt2800_register_read(rt2x00dev, offset, ®);  		/* read the next four txpower values */ -		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, -				   &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      i, &eeprom); -		/* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS, +		is_rate_b = i ? 0 : 1; +		/* +		 * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,  		 * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE0); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE0, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); -		/* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS, +		/* +		 * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,  		 * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE1); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE1, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); -		/* TX_PWR_CFG_0: 55MBS, TX_PWR_CFG_1: 48MBS, +		/* +		 * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,  		 * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE2); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE2, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); -		/* TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS, +		/* +		 * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,  		 * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE3); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE3, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower);  		/* read the next four txpower values */ -		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, -				   &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      i + 1, &eeprom); -		/* TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0, +		is_rate_b = 0; +		/* +		 * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,  		 * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE0); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE4, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); -		/* TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1, +		/* +		 * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,  		 * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE1); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE5, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); -		/* TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2, +		/* +		 * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,  		 * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE2); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE6, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); -		/* TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3, +		/* +		 * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,  		 * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE3); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE7, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower);  		rt2800_register_write(rt2x00dev, offset, reg); @@ -1739,6 +4223,102 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,  	}  } +static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, +				  struct ieee80211_channel *chan, +				  int power_level) +{ +	if (rt2x00_rt(rt2x00dev, RT3593)) +		rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); +	else +		rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); +} + +void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan, +			      rt2x00dev->tx_power); +} +EXPORT_SYMBOL_GPL(rt2800_gain_calibration); + +void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) +{ +	u32	tx_pin; +	u8	rfcsr; + +	/* +	 * A voltage-controlled oscillator(VCO) is an electronic oscillator +	 * designed to be controlled in oscillation frequency by a voltage +	 * input. Maybe the temperature will affect the frequency of +	 * oscillation to be shifted. The VCO calibration will be called +	 * periodically to adjust the frequency to be precision. +	*/ + +	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); +	tx_pin &= TX_PIN_CFG_PA_PE_DISABLE; +	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +	case RF3052: +		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +		break; +	case RF3053: +	case RF3070: +	case RF3290: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); +		break; +	default: +		return; +	} + +	mdelay(1); + +	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); +	if (rt2x00dev->rf_channel <= 14) { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 3: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1); +			/* fall through */ +		case 2: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +			/* fall through */ +		case 1: +		default: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +			break; +		} +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 3: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1); +			/* fall through */ +		case 2: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); +			/* fall through */ +		case 1: +		default: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1); +			break; +		} +	} +	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +} +EXPORT_SYMBOL_GPL(rt2800_vco_calibration); +  static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,  				      struct rt2x00lib_conf *libconf)  { @@ -1789,11 +4369,15 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,  	/* Always recalculate LNA gain before changing configuration */  	rt2800_config_lna_gain(rt2x00dev, libconf); -	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) +	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {  		rt2800_config_channel(rt2x00dev, libconf->conf,  				      &libconf->rf, &libconf->channel); +		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, +				      libconf->conf->power_level); +	}  	if (flags & IEEE80211_CONF_CHANGE_POWER) -		rt2800_config_txpower(rt2x00dev, libconf->conf->power_level); +		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, +				      libconf->conf->power_level);  	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)  		rt2800_config_retry_limit(rt2x00dev, libconf);  	if (flags & IEEE80211_CONF_CHANGE_PS) @@ -1818,27 +4402,53 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats);  static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)  { +	u8 vgc; +  	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {  		if (rt2x00_rt(rt2x00dev, RT3070) ||  		    rt2x00_rt(rt2x00dev, RT3071) ||  		    rt2x00_rt(rt2x00dev, RT3090) || -		    rt2x00_rt(rt2x00dev, RT3390)) -			return 0x1c + (2 * rt2x00dev->lna_gain); +		    rt2x00_rt(rt2x00dev, RT3290) || +		    rt2x00_rt(rt2x00dev, RT3390) || +		    rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT3593) || +		    rt2x00_rt(rt2x00dev, RT5390) || +		    rt2x00_rt(rt2x00dev, RT5392) || +		    rt2x00_rt(rt2x00dev, RT5592)) +			vgc = 0x1c + (2 * rt2x00dev->lna_gain);  		else -			return 0x2e + rt2x00dev->lna_gain; +			vgc = 0x2e + rt2x00dev->lna_gain; +	} else { /* 5GHZ band */ +		if (rt2x00_rt(rt2x00dev, RT3593)) +			vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; +		else if (rt2x00_rt(rt2x00dev, RT5592)) +			vgc = 0x24 + (2 * rt2x00dev->lna_gain); +		else { +			if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +				vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; +			else +				vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3; +		}  	} -	if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) -		return 0x32 + (rt2x00dev->lna_gain * 5) / 3; -	else -		return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +	return vgc;  }  static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,  				  struct link_qual *qual, u8 vgc_level)  {  	if (qual->vgc_level != vgc_level) { -		rt2800_bbp_write(rt2x00dev, 66, vgc_level); +		if (rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, +						       vgc_level); +		} else if (rt2x00_rt(rt2x00dev, RT5592)) { +			rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); +			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); +		} else { +			rt2800_bbp_write(rt2x00dev, 66, vgc_level); +		} +  		qual->vgc_level = vgc_level;  		qual->vgc_level_reg = vgc_level;  	} @@ -1853,15 +4463,41 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);  void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,  		       const u32 count)  { +	u8 vgc; +  	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))  		return; -	/* -	 * When RSSI is better then -80 increase VGC level with 0x10 +	/* When RSSI is better than a certain threshold, increase VGC +	 * with a chip specific value in order to improve the balance +	 * between sensibility and noise isolation.  	 */ -	rt2800_set_vgc(rt2x00dev, qual, -		       rt2800_get_default_vgc(rt2x00dev) + -		       ((qual->rssi > -80) * 0x10)); + +	vgc = rt2800_get_default_vgc(rt2x00dev); + +	switch (rt2x00dev->chip.rt) { +	case RT3572: +	case RT3593: +		if (qual->rssi > -65) { +			if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) +				vgc += 0x20; +			else +				vgc += 0x10; +		} +		break; + +	case RT5592: +		if (qual->rssi > -65) +			vgc += 0x20; +		break; + +	default: +		if (qual->rssi > -80) +			vgc += 0x10; +		break; +	} + +	rt2800_set_vgc(rt2x00dev, qual, vgc);  }  EXPORT_SYMBOL_GPL(rt2800_link_tuner); @@ -1875,30 +4511,32 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	unsigned int i;  	int ret; -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	ret = rt2800_drv_init_registers(rt2x00dev);  	if (ret)  		return ret;  	rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); -	rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ +	rt2x00_set_field32(®, BCN_OFFSET0_BCN0, +			   rt2800_get_beacon_offset(rt2x00dev, 0)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN1, +			   rt2800_get_beacon_offset(rt2x00dev, 1)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN2, +			   rt2800_get_beacon_offset(rt2x00dev, 2)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN3, +			   rt2800_get_beacon_offset(rt2x00dev, 3));  	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);  	rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); -	rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ +	rt2x00_set_field32(®, BCN_OFFSET1_BCN4, +			   rt2800_get_beacon_offset(rt2x00dev, 4)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN5, +			   rt2800_get_beacon_offset(rt2x00dev, 5)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN6, +			   rt2800_get_beacon_offset(rt2x00dev, 6)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN7, +			   rt2800_get_beacon_offset(rt2x00dev, 7));  	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);  	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); @@ -1922,16 +4560,61 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);  	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		if (rt2x00_get_field32(reg, WLAN_EN) == 1) { +			rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); +			rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		} + +		rt2800_register_read(rt2x00dev, CMB_CTRL, ®); +		if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { +			rt2x00_set_field32(®, LDO0_EN, 1); +			rt2x00_set_field32(®, LDO_BGSEL, 3); +			rt2800_register_write(rt2x00dev, CMB_CTRL, reg); +		} + +		rt2800_register_read(rt2x00dev, OSC_CTRL, ®); +		rt2x00_set_field32(®, OSC_ROSC_EN, 1); +		rt2x00_set_field32(®, OSC_CAL_REQ, 1); +		rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); +		rt2800_register_write(rt2x00dev, OSC_CTRL, reg); + +		rt2800_register_read(rt2x00dev, COEX_CFG0, ®); +		rt2x00_set_field32(®, COEX_CFG_ANT, 0x5e); +		rt2800_register_write(rt2x00dev, COEX_CFG0, reg); + +		rt2800_register_read(rt2x00dev, COEX_CFG2, ®); +		rt2x00_set_field32(®, BT_COEX_CFG1, 0x00); +		rt2x00_set_field32(®, BT_COEX_CFG0, 0x17); +		rt2x00_set_field32(®, WL_COEX_CFG1, 0x93); +		rt2x00_set_field32(®, WL_COEX_CFG0, 0x7f); +		rt2800_register_write(rt2x00dev, COEX_CFG2, reg); + +		rt2800_register_read(rt2x00dev, PLL_CTRL, ®); +		rt2x00_set_field32(®, PLL_CONTROL, 1); +		rt2800_register_write(rt2x00dev, PLL_CTRL, reg); +	} +  	if (rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) || +	    rt2x00_rt(rt2x00dev, RT3290) ||  	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + +		if (rt2x00_rt(rt2x00dev, RT3290)) +			rt2800_register_write(rt2x00dev, TX_SW_CFG0, +					      0x00000404); +		else +			rt2800_register_write(rt2x00dev, TX_SW_CFG0, +					      0x00000400); +  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);  		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { -			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); -			if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))  				rt2800_register_write(rt2x00dev, TX_SW_CFG2,  						      0x0000002c);  			else @@ -1953,7 +4636,37 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	} else if (rt2800_is_305x_soc(rt2x00dev)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); -		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); +	} else if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +	} else if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, +					       EEPROM_NIC_CONF1_DAC_TEST)) +				rt2800_register_write(rt2x00dev, TX_SW_CFG2, +						      0x0000001f); +			else +				rt2800_register_write(rt2x00dev, TX_SW_CFG2, +						      0x0000000f); +		} else { +			rt2800_register_write(rt2x00dev, TX_SW_CFG2, +					      0x00000000); +		} +	} else if (rt2x00_rt(rt2x00dev, RT5390) || +		   rt2x00_rt(rt2x00dev, RT5392) || +		   rt2x00_rt(rt2x00dev, RT5592)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);  	} else {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -2022,7 +4735,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®);  	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 3);  	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2035,7 +4748,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®);  	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 3);  	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2048,7 +4761,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®);  	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004);  	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2061,7 +4774,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®);  	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084);  	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2074,7 +4787,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®);  	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004);  	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2087,7 +4800,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®);  	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084);  	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2130,7 +4843,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0);  	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); -	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); +	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; +	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);  	rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®);  	rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); @@ -2166,30 +4880,25 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  					 SHARED_KEY_MODE_ENTRY(i), 0);  	for (i = 0; i < 256; i++) { -		static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; -		rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), -					      wcid, sizeof(wcid)); - -		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); +		rt2800_config_wcid(rt2x00dev, NULL, i); +		rt2800_delete_wcid_attr(rt2x00dev, i);  		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);  	}  	/*  	 * Clear all beacons  	 */ -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7); +	for (i = 0; i < 8; i++) +		rt2800_clear_beacon_register(rt2x00dev, i);  	if (rt2x00_is_usb(rt2x00dev)) {  		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®);  		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30);  		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); +	} else if (rt2x00_is_pcie(rt2x00dev)) { +		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); +		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125); +		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);  	}  	rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); @@ -2259,6 +4968,17 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);  	rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); +	/* +	 * Set up channel statistics timer +	 */ +	rt2800_register_read(rt2x00dev, CH_TIME_CFG, ®); +	rt2x00_set_field32(®, CH_TIME_CFG_EIFS_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_NAV_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_RX_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_TX_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_TMR_EN, 1); +	rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg); +  	return 0;  } @@ -2275,7 +4995,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");  	return -EACCES;  } @@ -2299,24 +5019,116 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } -static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev) +{ +	u8 value; + +	rt2800_bbp_read(rt2x00dev, 4, &value); +	rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); +	rt2800_bbp_write(rt2x00dev, 4, value); +} + +static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 142, 1); +	rt2800_bbp_write(rt2x00dev, 143, 57); +} + +static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev) +{ +	const u8 glrt_table[] = { +		0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */ +		0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */ +		0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */ +		0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */ +		0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */ +		0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */ +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */ +		0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */ +		0x2E, 0x36, 0x30, 0x6E,					    /* 208 ~ 211 */ +	}; +	int i; + +	for (i = 0; i < ARRAY_SIZE(glrt_table); i++) { +		rt2800_bbp_write(rt2x00dev, 195, 128 + i); +		rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]); +	} +}; + +static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2C); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); +	rt2800_bbp_write(rt2x00dev, 68, 0x0B); +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); +	rt2800_bbp_write(rt2x00dev, 81, 0x37); +	rt2800_bbp_write(rt2x00dev, 82, 0x62); +	rt2800_bbp_write(rt2x00dev, 83, 0x6A); +	rt2800_bbp_write(rt2x00dev, 84, 0x99); +	rt2800_bbp_write(rt2x00dev, 86, 0x00); +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +	rt2800_bbp_write(rt2x00dev, 92, 0x00); +	rt2800_bbp_write(rt2x00dev, 103, 0x00); +	rt2800_bbp_write(rt2x00dev, 105, 0x05); +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)  { -	unsigned int i;  	u16 eeprom; -	u8 reg_id;  	u8 value; -	if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || -		     rt2800_wait_bbp_ready(rt2x00dev))) -		return -EACCES; +	rt2800_bbp_read(rt2x00dev, 138, &value); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +		value |= 0x20; +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) +		value &= ~0x02; +	rt2800_bbp_write(rt2x00dev, 138, value); +} -	if (rt2800_is_305x_soc(rt2x00dev)) -		rt2800_bbp_write(rt2x00dev, 31, 0x08); +static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 78, 0x0e); +	rt2800_bbp_write(rt2x00dev, 80, 0x08); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); +	rt2800_bbp_write(rt2x00dev, 105, 0x01); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) +{  	rt2800_bbp_write(rt2x00dev, 65, 0x2c);  	rt2800_bbp_write(rt2x00dev, 66, 0x38); @@ -2330,21 +5142,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	rt2800_bbp_write(rt2x00dev, 70, 0x0a); -	if (rt2x00_rt(rt2x00dev, RT3070) || -	    rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_bbp_write(rt2x00dev, 79, 0x13); -		rt2800_bbp_write(rt2x00dev, 80, 0x05); -		rt2800_bbp_write(rt2x00dev, 81, 0x33); -	} else if (rt2800_is_305x_soc(rt2x00dev)) { -		rt2800_bbp_write(rt2x00dev, 78, 0x0e); -		rt2800_bbp_write(rt2x00dev, 80, 0x08); -	} else { -		rt2800_bbp_write(rt2x00dev, 81, 0x37); -	} +	rt2800_bbp_write(rt2x00dev, 81, 0x37);  	rt2800_bbp_write(rt2x00dev, 82, 0x62); +  	rt2800_bbp_write(rt2x00dev, 83, 0x6a);  	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) @@ -2353,41 +5154,526 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  		rt2800_bbp_write(rt2x00dev, 84, 0x99);  	rt2800_bbp_write(rt2x00dev, 86, 0x00); +  	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0x00); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +  	rt2800_bbp_write(rt2x00dev, 92, 0x00);  	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||  	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || -	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || -	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || -	    rt2800_is_305x_soc(rt2x00dev)) +	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E))  		rt2800_bbp_write(rt2x00dev, 103, 0xc0);  	else  		rt2800_bbp_write(rt2x00dev, 103, 0x00); -	if (rt2800_is_305x_soc(rt2x00dev)) -		rt2800_bbp_write(rt2x00dev, 105, 0x01); -	else -		rt2800_bbp_write(rt2x00dev, 105, 0x05); +	rt2800_bbp_write(rt2x00dev, 105, 0x05); +  	rt2800_bbp_write(rt2x00dev, 106, 0x35);  	if (rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_bbp_read(rt2x00dev, 138, &value); +	    rt2x00_rt(rt2x00dev, RT3090)) +		rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) +{ +	u8 value; + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x58); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 74, 0x0b); +	rt2800_bbp_write(rt2x00dev, 79, 0x18); +	rt2800_bbp_write(rt2x00dev, 80, 0x09); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x7a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x9a); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x1c); + +	rt2800_bbp_write(rt2x00dev, 106, 0x03); + +	rt2800_bbp_write(rt2x00dev, 128, 0x12); + +	rt2800_bbp_write(rt2x00dev, 67, 0x24); +	rt2800_bbp_write(rt2x00dev, 143, 0x04); +	rt2800_bbp_write(rt2x00dev, 142, 0x99); +	rt2800_bbp_write(rt2x00dev, 150, 0x30); +	rt2800_bbp_write(rt2x00dev, 151, 0x2e); +	rt2800_bbp_write(rt2x00dev, 152, 0x20); +	rt2800_bbp_write(rt2x00dev, 153, 0x34); +	rt2800_bbp_write(rt2x00dev, 154, 0x40); +	rt2800_bbp_write(rt2x00dev, 155, 0x3b); +	rt2800_bbp_write(rt2x00dev, 253, 0x04); + +	rt2800_bbp_read(rt2x00dev, 47, &value); +	rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1); +	rt2800_bbp_write(rt2x00dev, 47, value); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) -			value |= 0x20; -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) -			value &= ~0x02; +	/* Use 5-bit ADC for Acquisition and 8-bit ADC for data */ +	rt2800_bbp_read(rt2x00dev, 3, &value); +	rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1); +	rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1); +	rt2800_bbp_write(rt2x00dev, 3, value); +} + +static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 3, 0x00); +	rt2800_bbp_write(rt2x00dev, 4, 0x50); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 47, 0x48); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x59); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 78, 0x0e); +	rt2800_bbp_write(rt2x00dev, 80, 0x08); +	rt2800_bbp_write(rt2x00dev, 81, 0x37); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	rt2800_bbp_write(rt2x00dev, 88, 0x90); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x34); + +	rt2800_bbp_write(rt2x00dev, 106, 0x05); + +	rt2800_bbp_write(rt2x00dev, 120, 0x50); + +	rt2800_bbp_write(rt2x00dev, 137, 0x0f); + +	rt2800_bbp_write(rt2x00dev, 163, 0xbd); +	/* Set ITxBF timeout to 0x9c40=1000msec */ +	rt2800_bbp_write(rt2x00dev, 179, 0x02); +	rt2800_bbp_write(rt2x00dev, 180, 0x00); +	rt2800_bbp_write(rt2x00dev, 182, 0x40); +	rt2800_bbp_write(rt2x00dev, 180, 0x01); +	rt2800_bbp_write(rt2x00dev, 182, 0x9c); +	rt2800_bbp_write(rt2x00dev, 179, 0x00); +	/* Reprogram the inband interface to put right values in RXWI */ +	rt2800_bbp_write(rt2x00dev, 142, 0x04); +	rt2800_bbp_write(rt2x00dev, 143, 0x3b); +	rt2800_bbp_write(rt2x00dev, 142, 0x06); +	rt2800_bbp_write(rt2x00dev, 143, 0xa0); +	rt2800_bbp_write(rt2x00dev, 142, 0x07); +	rt2800_bbp_write(rt2x00dev, 143, 0xa1); +	rt2800_bbp_write(rt2x00dev, 142, 0x08); +	rt2800_bbp_write(rt2x00dev, 143, 0xa2); + +	rt2800_bbp_write(rt2x00dev, 148, 0xc8); +} + +static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +	else +		rt2800_bbp_write(rt2x00dev, 103, 0x00); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); + +	rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); + +	rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_init_bbp_early(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); +	rt2800_bbp_write(rt2x00dev, 137, 0x0f); + +	rt2800_bbp_write(rt2x00dev, 84, 0x19); + +	/* Enable DC filter */ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +} + +static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) +{ +	int ant, div_mode; +	u16 eeprom; +	u8 value; + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); -		rt2800_bbp_write(rt2x00dev, 138, value); +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x59); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x7a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x9a); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	if (rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_bbp_write(rt2x00dev, 88, 0x90); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_bbp_write(rt2x00dev, 95, 0x9a); +		rt2800_bbp_write(rt2x00dev, 98, 0x12); +	} + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x3c); + +	if (rt2x00_rt(rt2x00dev, RT5390)) +		rt2800_bbp_write(rt2x00dev, 106, 0x03); +	else if (rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_bbp_write(rt2x00dev, 106, 0x12); +	else +		WARN_ON(1); + +	rt2800_bbp_write(rt2x00dev, 128, 0x12); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_bbp_write(rt2x00dev, 134, 0xd0); +		rt2800_bbp_write(rt2x00dev, 135, 0xf6); +	} + +	rt2800_disable_unused_dac_adc(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	div_mode = rt2x00_get_field16(eeprom, +				      EEPROM_NIC_CONF1_ANT_DIVERSITY); +	ant = (div_mode == 3) ? 1 : 0; + +	/* check if this is a Bluetooth combo card */ +	if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +		u32 reg; + +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +		rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); +		rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0); +		rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0); +		rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0); +		if (ant == 0) +			rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1); +		else if (ant == 1) +			rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1); +		rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); +	} + +	/* This chip has hardware antenna diversity*/ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { +		rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */ +		rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */ +		rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */  	} +	rt2800_bbp_read(rt2x00dev, 152, &value); +	if (ant == 0) +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); +	else +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); +	rt2800_bbp_write(rt2x00dev, 152, value); + +	rt2800_init_freq_calibration(rt2x00dev); +} + +static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) +{ +	int ant, div_mode; +	u16 eeprom; +	u8 value; + +	rt2800_init_bbp_early(rt2x00dev); + +	rt2800_bbp_read(rt2x00dev, 105, &value); +	rt2x00_set_field8(&value, BBP105_MLD, +			  rt2x00dev->default_ant.rx_chain_num == 2); +	rt2800_bbp_write(rt2x00dev, 105, value); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 20, 0x06); +	rt2800_bbp_write(rt2x00dev, 31, 0x08); +	rt2800_bbp_write(rt2x00dev, 65, 0x2C); +	rt2800_bbp_write(rt2x00dev, 68, 0xDD); +	rt2800_bbp_write(rt2x00dev, 69, 0x1A); +	rt2800_bbp_write(rt2x00dev, 70, 0x05); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 74, 0x0F); +	rt2800_bbp_write(rt2x00dev, 75, 0x4F); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); +	rt2800_bbp_write(rt2x00dev, 77, 0x59); +	rt2800_bbp_write(rt2x00dev, 84, 0x9A); +	rt2800_bbp_write(rt2x00dev, 86, 0x38); +	rt2800_bbp_write(rt2x00dev, 88, 0x90); +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +	rt2800_bbp_write(rt2x00dev, 92, 0x02); +	rt2800_bbp_write(rt2x00dev, 95, 0x9a); +	rt2800_bbp_write(rt2x00dev, 98, 0x12); +	rt2800_bbp_write(rt2x00dev, 103, 0xC0); +	rt2800_bbp_write(rt2x00dev, 104, 0x92); +	/* FIXME BBP105 owerwrite */ +	rt2800_bbp_write(rt2x00dev, 105, 0x3C); +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +	rt2800_bbp_write(rt2x00dev, 128, 0x12); +	rt2800_bbp_write(rt2x00dev, 134, 0xD0); +	rt2800_bbp_write(rt2x00dev, 135, 0xF6); +	rt2800_bbp_write(rt2x00dev, 137, 0x0F); + +	/* Initialize GLRT (Generalized Likehood Radio Test) */ +	rt2800_init_bbp_5592_glrt(rt2x00dev); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); +	ant = (div_mode == 3) ? 1 : 0; +	rt2800_bbp_read(rt2x00dev, 152, &value); +	if (ant == 0) { +		/* Main antenna */ +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); +	} else { +		/* Auxiliary antenna */ +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); +	} +	rt2800_bbp_write(rt2x00dev, 152, value); + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) { +		rt2800_bbp_read(rt2x00dev, 254, &value); +		rt2x00_set_field8(&value, BBP254_BIT7, 1); +		rt2800_bbp_write(rt2x00dev, 254, value); +	} + +	rt2800_init_freq_calibration(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 84, 0x19); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +} + +static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +{ +	unsigned int i; +	u16 eeprom; +	u8 reg_id; +	u8 value; + +	if (rt2800_is_305x_soc(rt2x00dev)) +		rt2800_init_bbp_305x_soc(rt2x00dev); + +	switch (rt2x00dev->chip.rt) { +	case RT2860: +	case RT2872: +	case RT2883: +		rt2800_init_bbp_28xx(rt2x00dev); +		break; +	case RT3070: +	case RT3071: +	case RT3090: +		rt2800_init_bbp_30xx(rt2x00dev); +		break; +	case RT3290: +		rt2800_init_bbp_3290(rt2x00dev); +		break; +	case RT3352: +		rt2800_init_bbp_3352(rt2x00dev); +		break; +	case RT3390: +		rt2800_init_bbp_3390(rt2x00dev); +		break; +	case RT3572: +		rt2800_init_bbp_3572(rt2x00dev); +		break; +	case RT3593: +		rt2800_init_bbp_3593(rt2x00dev); +		return; +	case RT5390: +	case RT5392: +		rt2800_init_bbp_53xx(rt2x00dev); +		break; +	case RT5592: +		rt2800_init_bbp_5592(rt2x00dev); +		return; +	}  	for (i = 0; i < EEPROM_BBP_SIZE; i++) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i, +					      &eeprom);  		if (eeprom != 0xffff && eeprom != 0x0000) {  			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); @@ -2395,12 +5681,19 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  			rt2800_bbp_write(rt2x00dev, reg_id, value);  		}  	} +} -	return 0; +static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); +	rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); +	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);  } -static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, -				bool bw40, u8 rfcsr24, u8 filter_target) +static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40, +				u8 filter_target)  {  	unsigned int i;  	u8 bbp; @@ -2408,6 +5701,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	u8 passband;  	u8 stopband;  	u8 overtuned = 0; +	u8 rfcsr24 = (bw40) ? 0x27 : 0x07;  	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24); @@ -2415,6 +5709,10 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);  	rt2800_bbp_write(rt2x00dev, 4, bbp); +	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40); +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); +  	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);  	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); @@ -2459,167 +5757,47 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	return rfcsr24;  } -static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) +static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev, +				       const unsigned int rf_reg)  {  	u8 rfcsr; -	u8 bbp; -	u32 reg; -	u16 eeprom; -	if (!rt2x00_rt(rt2x00dev, RT3070) && -	    !rt2x00_rt(rt2x00dev, RT3071) && -	    !rt2x00_rt(rt2x00dev, RT3090) && -	    !rt2x00_rt(rt2x00dev, RT3390) && -	    !rt2800_is_305x_soc(rt2x00dev)) -		return 0; +	rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr); +	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1); +	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr); +	msleep(1); +	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0); +	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr); +} + +static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 filter_tgt_bw20; +	u8 filter_tgt_bw40; +	u8 rfcsr, bbp;  	/* -	 * Init RF calibration. +	 * TODO: sync filter_tgt values with vendor driver  	 */ -	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); -	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); -	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); -	msleep(1); -	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); -	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - -	if (rt2x00_rt(rt2x00dev, RT3070) || -	    rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090)) { -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x03); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x70); -		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x41); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x58); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x92); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xba); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x16); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); -	} else if (rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); -		rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); -		rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); -		rt2800_rfcsr_write(rt2x00dev, 3, 0x62); -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x42); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x34); -		rt2800_rfcsr_write(rt2x00dev, 8, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x61); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); -		rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x94); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); -		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 23, 0x14); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x08); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); -		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); -		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 28, 0x41); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); -		rt2800_rfcsr_write(rt2x00dev, 30, 0x20); -		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); -	} else if (rt2800_is_305x_soc(rt2x00dev)) { -		rt2800_rfcsr_write(rt2x00dev, 0, 0x50); -		rt2800_rfcsr_write(rt2x00dev, 1, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); -		rt2800_rfcsr_write(rt2x00dev, 3, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x03); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x50); -		rt2800_rfcsr_write(rt2x00dev, 8, 0x39); -		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x60); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 13, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x58); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x92); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xba); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); -		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 23, 0x31); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x08); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 26, 0x25); -		rt2800_rfcsr_write(rt2x00dev, 27, 0x23); -		rt2800_rfcsr_write(rt2x00dev, 28, 0x13); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x83); -		rt2800_rfcsr_write(rt2x00dev, 30, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 31, 0x00); -		return 0; +	if (rt2x00_rt(rt2x00dev, RT3070)) { +		filter_tgt_bw20 = 0x16; +		filter_tgt_bw40 = 0x19; +	} else { +		filter_tgt_bw20 = 0x13; +		filter_tgt_bw40 = 0x15;  	} -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { -		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); -		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); -		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); -		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); -	} else if (rt2x00_rt(rt2x00dev, RT3071) || -		   rt2x00_rt(rt2x00dev, RT3090)) { -		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); -		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); -		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); - -		rt2800_rfcsr_write(rt2x00dev, 31, 0x14); - -		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); -		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); -		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || -		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { -			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); -			if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) -				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); -			else -				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); -		} -		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); -	} else if (rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); -		rt2x00_set_field32(®, GPIO_SWITCH_5, 0); -		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); -	} +	drv_data->calibration_bw20 = +		rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20); +	drv_data->calibration_bw40 = +		rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);  	/* -	 * Set RX Filter calibration for 20MHz and 40MHz +	 * Save BBP 25 & 26 values for later use in channel switching (for 3052)  	 */ -	if (rt2x00_rt(rt2x00dev, RT3070)) { -		rt2x00dev->calibration[0] = -			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); -		rt2x00dev->calibration[1] = -			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); -	} else if (rt2x00_rt(rt2x00dev, RT3071) || -		   rt2x00_rt(rt2x00dev, RT3090) || -		   rt2x00_rt(rt2x00dev, RT3390)) { -		rt2x00dev->calibration[0] = -			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); -		rt2x00dev->calibration[1] = -			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); -	} +	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); +	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);  	/*  	 * Set back to initial state @@ -2631,52 +5809,62 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);  	/* -	 * set BBP back to BW20 +	 * Set BBP back to BW20  	 */  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);  	rt2800_bbp_write(rt2x00dev, 4, bbp); +} -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) -		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); - -	rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); -	rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); -	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); +static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 min_gain, rfcsr, bbp; +	u16 eeprom;  	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); +  	rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +	if (rt2x00_rt(rt2x00dev, RT3070) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||  	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||  	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +		if (!rt2x00_has_cap_external_lna_bg(rt2x00dev))  			rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); -	if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) + +	min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2; +	if (drv_data->txmixer_gain_24g >= min_gain) {  		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, -				  rt2x00_get_field16(eeprom, -						   EEPROM_TXMIXER_GAIN_BG_VAL)); +				  drv_data->txmixer_gain_24g); +	} +  	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);  	if (rt2x00_rt(rt2x00dev, RT3090)) { +		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */  		rt2800_bbp_read(rt2x00dev, 138, &bbp); - -		rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) +		rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)  			rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) +		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)  			rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); -  		rt2800_bbp_write(rt2x00dev, 138, bbp);  	} -	if (rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { +	if (rt2x00_rt(rt2x00dev, RT3070)) { +		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) +			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); +		else +			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); +		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); +	} else if (rt2x00_rt(rt2x00dev, RT3071) || +		   rt2x00_rt(rt2x00dev, RT3090) || +		   rt2x00_rt(rt2x00dev, RT3390)) {  		rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);  		rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);  		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); @@ -2697,21 +5885,803 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);  		rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);  	} +} -	if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) { -		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); -		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || -		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) -			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); +static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr; +	u8 tx_gain; + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g, +				    RFCSR17_TXMIXER_GAIN); +	rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain); +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	/* TODO: enable stream mode */ +} + +static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev) +{ +	u8 reg; +	u16 eeprom; + +	/*  Turn off unused DAC1 and ADC1 to reduce power consumption */ +	rt2800_bbp_read(rt2x00dev, 138, ®); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) +		rt2x00_set_field8(®, BBP138_RX_ADC1, 0); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +		rt2x00_set_field8(®, BBP138_TX_DAC1, 1); +	rt2800_bbp_write(rt2x00dev, 138, reg); + +	rt2800_rfcsr_read(rt2x00dev, 38, ®); +	rt2x00_set_field8(®, RFCSR38_RX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 38, reg); + +	rt2800_rfcsr_read(rt2x00dev, 39, ®); +	rt2x00_set_field8(®, RFCSR39_RX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 39, reg); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 30, ®); +	rt2x00_set_field8(®, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, reg); +} + +static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 8, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x58); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x92); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xba); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x31); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x25); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x13); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x83); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x00); +} + +static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; +	u16 eeprom; +	u32 reg; + +	/* XXX vendor driver do this only for 3070 */ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x41); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x58); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x92); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xba); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	} else if (rt2x00_rt(rt2x00dev, RT3071) || +		   rt2x00_rt(rt2x00dev, RT3090)) { +		rt2800_rfcsr_write(rt2x00dev, 31, 0x14); + +		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) +				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +			else +				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +		} +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +		rt2x00_set_field32(®, GPIO_SWITCH_5, 0); +		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); +	} + +	rt2800_rx_filter_calibration(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; + +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf3); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x83); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x05); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x98); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x38); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +	rt2800_rfcsr_write(rt2x00dev, 56, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 61, 0xc1); + +	rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3); +	rt2800_rfcsr_write(rt2x00dev, 29, rfcsr); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x33); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xd2); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x5a); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); +	rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x33); +	rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); +	rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); +	rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 46, 0xdd); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x14); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x52); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 56, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x52); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 62, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x00); + +	rt2800_rx_filter_calibration(rt2x00dev); +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x62); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x34); +	rt2800_rfcsr_write(rt2x00dev, 8, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x61); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); +	rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x14); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x41); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	rt2x00_set_field32(®, GPIO_SWITCH_5, 0); +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_rx_filter_calibration(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; +	u32 reg; + +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0x70); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x81); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x05); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +	rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x70); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x65); +	rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 18, 0xac); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x10); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	msleep(1); +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	rt2800_rx_filter_calibration(rt2x00dev); +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev) +{ +	u8 bbp; +	bool txbf_enabled = false; /* FIXME */ + +	rt2800_bbp_read(rt2x00dev, 105, &bbp); +	if (rt2x00dev->default_ant.rx_chain_num == 1) +		rt2x00_set_field8(&bbp, BBP105_MLD, 0); +	else +		rt2x00_set_field8(&bbp, BBP105_MLD, 1); +	rt2800_bbp_write(rt2x00dev, 105, bbp); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); +	rt2800_bbp_write(rt2x00dev, 82, 0x82); +	rt2800_bbp_write(rt2x00dev, 106, 0x05); +	rt2800_bbp_write(rt2x00dev, 104, 0x92); +	rt2800_bbp_write(rt2x00dev, 88, 0x90); +	rt2800_bbp_write(rt2x00dev, 148, 0xc8); +	rt2800_bbp_write(rt2x00dev, 47, 0x48); +	rt2800_bbp_write(rt2x00dev, 120, 0x50); + +	if (txbf_enabled) +		rt2800_bbp_write(rt2x00dev, 163, 0xbd); +	else +		rt2800_bbp_write(rt2x00dev, 163, 0x9d); + +	/* SNR mapping */ +	rt2800_bbp_write(rt2x00dev, 142, 6); +	rt2800_bbp_write(rt2x00dev, 143, 160); +	rt2800_bbp_write(rt2x00dev, 142, 7); +	rt2800_bbp_write(rt2x00dev, 143, 161); +	rt2800_bbp_write(rt2x00dev, 142, 8); +	rt2800_bbp_write(rt2x00dev, 143, 162); + +	/* ADC/DAC control */ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	/* RX AGC energy lower bound in log2 */ +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	/* FIXME: BBP 105 owerwrite? */ +	rt2800_bbp_write(rt2x00dev, 105, 0x04); + +} + +static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u32 reg; +	u8 rfcsr; + +	/* Disable GPIO #4 and #7 function for LAN PE control */ +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	rt2x00_set_field32(®, GPIO_SWITCH_4, 0); +	rt2x00_set_field32(®, GPIO_SWITCH_7, 0); +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	/* Initialize default register values */ +	rt2800_rfcsr_write(rt2x00dev, 1, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x4e); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x3b); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 35, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x86); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 44, 0xd3); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x86); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); + +	/* Initiate calibration */ +	/* TODO: use rt2800_rf_init_calibration ? */ +	rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); +	rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1); +	rt2800_rfcsr_write(rt2x00dev, 18, rfcsr); + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	usleep_range(1000, 1500); +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	/* Set initial values for RX filter calibration */ +	drv_data->calibration_bw20 = 0x1f; +	drv_data->calibration_bw40 = 0x2f; + +	/* Save BBP 25 & 26 values for later use in channel switching */ +	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); +	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3593(rt2x00dev); + +	rt3593_post_bbp_init(rt2x00dev); + +	/* TODO: enable stream mode support */ +} + +static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x88); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); +	else +		rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x00); + +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +	if (rt2x00_is_usb(rt2x00dev) && +	    rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	else +		rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); + +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); + +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	else +		rt2800_rfcsr_write(rt2x00dev, 46, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x94); + +	rt2800_rfcsr_write(rt2x00dev, 52, 0x38); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 53, 0x00); +	else +		rt2800_rfcsr_write(rt2x00dev, 53, 0x84); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x44); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 56, 0x42); +	else +		rt2800_rfcsr_write(rt2x00dev, 56, 0x22); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); + +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +		if (rt2x00_is_usb(rt2x00dev)) +			rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);  		else -			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); -		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); +			rt2800_rfcsr_write(rt2x00dev, 61, 0xd5); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); +		else +			rt2800_rfcsr_write(rt2x00dev, 61, 0xb5);  	} +	rt2800_rfcsr_write(rt2x00dev, 62, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x00); -	return 0; +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x17); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x88); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x44); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x89); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x48); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x44); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x38); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +	rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 61, 0x91); +	rt2800_rfcsr_write(rt2x00dev, 62, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4D); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x8D); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0C); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x22); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	msleep(1); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	/* Enable DC filter */ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ +	if (rt2800_is_305x_soc(rt2x00dev)) { +		rt2800_init_rfcsr_305x_soc(rt2x00dev); +		return; +	} + +	switch (rt2x00dev->chip.rt) { +	case RT3070: +	case RT3071: +	case RT3090: +		rt2800_init_rfcsr_30xx(rt2x00dev); +		break; +	case RT3290: +		rt2800_init_rfcsr_3290(rt2x00dev); +		break; +	case RT3352: +		rt2800_init_rfcsr_3352(rt2x00dev); +		break; +	case RT3390: +		rt2800_init_rfcsr_3390(rt2x00dev); +		break; +	case RT3572: +		rt2800_init_rfcsr_3572(rt2x00dev); +		break; +	case RT3593: +		rt2800_init_rfcsr_3593(rt2x00dev); +		break; +	case RT5390: +		rt2800_init_rfcsr_5390(rt2x00dev); +		break; +	case RT5392: +		rt2800_init_rfcsr_5392(rt2x00dev); +		break; +	case RT5592: +		rt2800_init_rfcsr_5592(rt2x00dev); +		break; +	}  }  int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -2720,18 +6690,39 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)  	u16 word;  	/* -	 * Initialize all registers. +	 * Initialize MAC registers.  	 */  	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || -		     rt2800_init_registers(rt2x00dev) || -		     rt2800_init_bbp(rt2x00dev) || -		     rt2800_init_rfcsr(rt2x00dev))) +		     rt2800_init_registers(rt2x00dev))) +		return -EIO; + +	/* +	 * Wait BBP/RF to wake up. +	 */ +	if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))  		return -EIO;  	/* -	 * Send signal to firmware during boot time. +	 * Send signal during boot time to initialize firmware.  	 */ +	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); +	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	if (rt2x00_is_usb(rt2x00dev)) +		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);  	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +	msleep(1); + +	/* +	 * Make sure BBP is up and running. +	 */ +	if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) +		return -EIO; + +	/* +	 * Initialize BBP/RF registers. +	 */ +	rt2800_init_bbp(rt2x00dev); +	rt2800_init_rfcsr(rt2x00dev);  	if (rt2x00_is_usb(rt2x00dev) &&  	    (rt2x00_rt(rt2x00dev, RT3070) || @@ -2767,16 +6758,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Initialize LED control  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,  			   word & 0xff, (word >> 8) & 0xff); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,  			   word & 0xff, (word >> 8) & 0xff); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,  			   word & 0xff, (word >> 8) & 0xff);  	return 0; @@ -2787,13 +6778,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	/* Wait for DMA, ignore error */  	rt2800_wait_wpdma_ready(rt2x00dev); @@ -2802,18 +6787,20 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0);  	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0);  	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); -	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);  }  EXPORT_SYMBOL_GPL(rt2800_disable_radio);  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; +	u16 efuse_ctrl_reg; -	rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®); +	if (rt2x00_rt(rt2x00dev, RT3290)) +		efuse_ctrl_reg = EFUSE_CTRL_3290; +	else +		efuse_ctrl_reg = EFUSE_CTRL; +	rt2800_register_read(rt2x00dev, efuse_ctrl_reg, ®);  	return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);  }  EXPORT_SYMBOL_GPL(rt2800_efuse_detect); @@ -2821,105 +6808,165 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect);  static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)  {  	u32 reg; - +	u16 efuse_ctrl_reg; +	u16 efuse_data0_reg; +	u16 efuse_data1_reg; +	u16 efuse_data2_reg; +	u16 efuse_data3_reg; + +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		efuse_ctrl_reg = EFUSE_CTRL_3290; +		efuse_data0_reg = EFUSE_DATA0_3290; +		efuse_data1_reg = EFUSE_DATA1_3290; +		efuse_data2_reg = EFUSE_DATA2_3290; +		efuse_data3_reg = EFUSE_DATA3_3290; +	} else { +		efuse_ctrl_reg = EFUSE_CTRL; +		efuse_data0_reg = EFUSE_DATA0; +		efuse_data1_reg = EFUSE_DATA1; +		efuse_data2_reg = EFUSE_DATA2; +		efuse_data3_reg = EFUSE_DATA3; +	}  	mutex_lock(&rt2x00dev->csr_mutex); -	rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, ®); +	rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®);  	rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);  	rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);  	rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); -	rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg); +	rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);  	/* Wait until the EEPROM has been loaded */ -	rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); - +	rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®);  	/* Apparently the data is read from end to start */ -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, -					(u32 *)&rt2x00dev->eeprom[i]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, -					(u32 *)&rt2x00dev->eeprom[i + 2]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, -					(u32 *)&rt2x00dev->eeprom[i + 4]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, -					(u32 *)&rt2x00dev->eeprom[i + 6]); +	rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, ®); +	/* The returned value is in CPU order, but eeprom is le */ +	*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);  	mutex_unlock(&rt2x00dev->csr_mutex);  } -void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) +int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)  {  	unsigned int i;  	for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)  		rt2800_efuse_read(rt2x00dev, i); + +	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); -int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)  {  	u16 word; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); +	if ((word & 0x00ff) != 0x00ff) +		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); + +	return 0; +} + +static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) +{ +	u16 word; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); +	if ((word & 0x00ff) != 0x00ff) +		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); + +	return 0; +} + +static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u16 word;  	u8 *mac;  	u8 default_lna_gain; +	int retval; + +	/* +	 * Read the EEPROM. +	 */ +	retval = rt2800_read_eeprom(rt2x00dev); +	if (retval) +		return retval;  	/*  	 * Start validation of the data that has been read.  	 */ -	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); +	mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);  	if (word == 0xffff) { -		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); -		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); -		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	} else if (rt2x00_rt(rt2x00dev, RT2860) ||  		   rt2x00_rt(rt2x00dev, RT2872)) {  		/*  		 * There is a max of 2 RX streams for RT28x0 series  		 */ -		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) -			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); +		if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) +			rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);  	if (word == 0xffff) { -		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); -	} - -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); +	} + +	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);  	if ((word & 0x00ff) == 0x00ff) {  		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); +		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);  	}  	if ((word & 0xff00) == 0xff00) {  		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,  				   LED_MODE_TXRX_ACTIVITY);  		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); -		EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); +		rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);  	}  	/* @@ -2927,127 +6974,181 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 * lna0 as correct value. Note that EEPROM_LNA  	 * is never validated.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);  	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); +	drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); -	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || -	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) -		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, -				   default_lna_gain); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); +	if (!rt2x00_rt(rt2x00dev, RT3593)) { +		if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) +			rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, +					   default_lna_gain); +	} +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); +	drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); -	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || -	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) -		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, -				   default_lna_gain); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); - -	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word); -	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff) -		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER); -	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff) -		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word); +	if (!rt2x00_rt(rt2x00dev, RT3593)) { +		if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) +			rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, +					   default_lna_gain); +	} +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word); +		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) +			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, +					   default_lna_gain); +		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff) +			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, +					   default_lna_gain); +		rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word); +	}  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); -int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  { -	u32 reg;  	u16 value;  	u16 eeprom; +	u16 rf;  	/*  	 * Read EEPROM word for configuration.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);  	/* -	 * Identify RF chipset. +	 * Identify RF chipset by EEPROM value +	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field +	 * RT53xx: defined in "EEPROM_CHIP_ID" field  	 */ -	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); -	rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - -	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), -			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); - -	if (!rt2x00_rt(rt2x00dev, RT2860) && -	    !rt2x00_rt(rt2x00dev, RT2872) && -	    !rt2x00_rt(rt2x00dev, RT2883) && -	    !rt2x00_rt(rt2x00dev, RT3070) && -	    !rt2x00_rt(rt2x00dev, RT3071) && -	    !rt2x00_rt(rt2x00dev, RT3090) && -	    !rt2x00_rt(rt2x00dev, RT3390) && -	    !rt2x00_rt(rt2x00dev, RT3572)) { -		ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); +	if (rt2x00_rt(rt2x00dev, RT3290) || +	    rt2x00_rt(rt2x00dev, RT5390) || +	    rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +	else +		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +	switch (rf) { +	case RF2820: +	case RF2850: +	case RF2720: +	case RF2750: +	case RF3020: +	case RF2020: +	case RF3021: +	case RF3022: +	case RF3052: +	case RF3053: +	case RF3070: +	case RF3290: +	case RF3320: +	case RF3322: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +	case RF5592: +		break; +	default: +		rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n", +			   rf);  		return -ENODEV;  	} -	if (!rt2x00_rf(rt2x00dev, RF2820) && -	    !rt2x00_rf(rt2x00dev, RF2850) && -	    !rt2x00_rf(rt2x00dev, RF2720) && -	    !rt2x00_rf(rt2x00dev, RF2750) && -	    !rt2x00_rf(rt2x00dev, RF3020) && -	    !rt2x00_rf(rt2x00dev, RF2020) && -	    !rt2x00_rf(rt2x00dev, RF3021) && -	    !rt2x00_rf(rt2x00dev, RF3022) && -	    !rt2x00_rf(rt2x00dev, RF3052) && -	    !rt2x00_rf(rt2x00dev, RF3320)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); -		return -ENODEV; -	} +	rt2x00_set_rf(rt2x00dev, rf);  	/*  	 * Identify default antenna configuration.  	 */ -	rt2x00dev->default_ant.tx = -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); -	rt2x00dev->default_ant.rx = -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); +	rt2x00dev->default_ant.tx_chain_num = +	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH); +	rt2x00dev->default_ant.rx_chain_num = +	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + +	if (rt2x00_rt(rt2x00dev, RT3070) || +	    rt2x00_rt(rt2x00dev, RT3090) || +	    rt2x00_rt(rt2x00dev, RT3352) || +	    rt2x00_rt(rt2x00dev, RT3390)) { +		value = rt2x00_get_field16(eeprom, +				EEPROM_NIC_CONF1_ANT_DIVERSITY); +		switch (value) { +		case 0: +		case 1: +		case 2: +			rt2x00dev->default_ant.tx = ANTENNA_A; +			rt2x00dev->default_ant.rx = ANTENNA_A; +			break; +		case 3: +			rt2x00dev->default_ant.tx = ANTENNA_A; +			rt2x00dev->default_ant.rx = ANTENNA_B; +			break; +		} +	} else { +		rt2x00dev->default_ant.tx = ANTENNA_A; +		rt2x00dev->default_ant.rx = ANTENNA_A; +	} + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { +		rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */ +		rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */ +	}  	/* -	 * Read frequency offset and RF programming sequence. +	 * Determine external LNA informations.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); -	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	/* -	 * Read external LNA informations. +	 * Detect if this device has an hardware controlled radio.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +	/* +	 * Detect if this device has Bluetooth co-existence. +	 */ +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) +		__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);  	/* -	 * Detect if this device has an hardware controlled radio. +	 * Read frequency offset and RF programming sequence.  	 */ -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);  	/*  	 * Store led settings, for correct led behaviour. @@ -3057,12 +7158,20 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); +	rt2x00dev->led_mcu_reg = eeprom;  #endif /* CONFIG_RT2X00_LIB_LEDS */ +	/* +	 * Check if support EIRP tx power limit feature. +	 */ +	rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); + +	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < +					EIRP_MAX_TX_POWER_LIMIT) +		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); +  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_init_eeprom);  /*   * RF value list for rt28xx @@ -3141,7 +7250,7 @@ static const struct rf_channel rf_vals[] = {  /*   * RF value list for rt3xxx - * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) + * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053)   */  static const struct rf_channel rf_vals_3x[] = {  	{1,  241, 2, 2 }, @@ -3205,21 +7314,152 @@ static const struct rf_channel rf_vals_3x[] = {  	{173, 0x61, 0, 9},  }; -int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) +static const struct rf_channel rf_vals_5592_xtal20[] = { +	/* Channel, N, K, mod, R */ +	{1, 482, 4, 10, 3}, +	{2, 483, 4, 10, 3}, +	{3, 484, 4, 10, 3}, +	{4, 485, 4, 10, 3}, +	{5, 486, 4, 10, 3}, +	{6, 487, 4, 10, 3}, +	{7, 488, 4, 10, 3}, +	{8, 489, 4, 10, 3}, +	{9, 490, 4, 10, 3}, +	{10, 491, 4, 10, 3}, +	{11, 492, 4, 10, 3}, +	{12, 493, 4, 10, 3}, +	{13, 494, 4, 10, 3}, +	{14, 496, 8, 10, 3}, +	{36, 172, 8, 12, 1}, +	{38, 173, 0, 12, 1}, +	{40, 173, 4, 12, 1}, +	{42, 173, 8, 12, 1}, +	{44, 174, 0, 12, 1}, +	{46, 174, 4, 12, 1}, +	{48, 174, 8, 12, 1}, +	{50, 175, 0, 12, 1}, +	{52, 175, 4, 12, 1}, +	{54, 175, 8, 12, 1}, +	{56, 176, 0, 12, 1}, +	{58, 176, 4, 12, 1}, +	{60, 176, 8, 12, 1}, +	{62, 177, 0, 12, 1}, +	{64, 177, 4, 12, 1}, +	{100, 183, 4, 12, 1}, +	{102, 183, 8, 12, 1}, +	{104, 184, 0, 12, 1}, +	{106, 184, 4, 12, 1}, +	{108, 184, 8, 12, 1}, +	{110, 185, 0, 12, 1}, +	{112, 185, 4, 12, 1}, +	{114, 185, 8, 12, 1}, +	{116, 186, 0, 12, 1}, +	{118, 186, 4, 12, 1}, +	{120, 186, 8, 12, 1}, +	{122, 187, 0, 12, 1}, +	{124, 187, 4, 12, 1}, +	{126, 187, 8, 12, 1}, +	{128, 188, 0, 12, 1}, +	{130, 188, 4, 12, 1}, +	{132, 188, 8, 12, 1}, +	{134, 189, 0, 12, 1}, +	{136, 189, 4, 12, 1}, +	{138, 189, 8, 12, 1}, +	{140, 190, 0, 12, 1}, +	{149, 191, 6, 12, 1}, +	{151, 191, 10, 12, 1}, +	{153, 192, 2, 12, 1}, +	{155, 192, 6, 12, 1}, +	{157, 192, 10, 12, 1}, +	{159, 193, 2, 12, 1}, +	{161, 193, 6, 12, 1}, +	{165, 194, 2, 12, 1}, +	{184, 164, 0, 12, 1}, +	{188, 164, 4, 12, 1}, +	{192, 165, 8, 12, 1}, +	{196, 166, 0, 12, 1}, +}; + +static const struct rf_channel rf_vals_5592_xtal40[] = { +	/* Channel, N, K, mod, R */ +	{1, 241, 2, 10, 3}, +	{2, 241, 7, 10, 3}, +	{3, 242, 2, 10, 3}, +	{4, 242, 7, 10, 3}, +	{5, 243, 2, 10, 3}, +	{6, 243, 7, 10, 3}, +	{7, 244, 2, 10, 3}, +	{8, 244, 7, 10, 3}, +	{9, 245, 2, 10, 3}, +	{10, 245, 7, 10, 3}, +	{11, 246, 2, 10, 3}, +	{12, 246, 7, 10, 3}, +	{13, 247, 2, 10, 3}, +	{14, 248, 4, 10, 3}, +	{36, 86, 4, 12, 1}, +	{38, 86, 6, 12, 1}, +	{40, 86, 8, 12, 1}, +	{42, 86, 10, 12, 1}, +	{44, 87, 0, 12, 1}, +	{46, 87, 2, 12, 1}, +	{48, 87, 4, 12, 1}, +	{50, 87, 6, 12, 1}, +	{52, 87, 8, 12, 1}, +	{54, 87, 10, 12, 1}, +	{56, 88, 0, 12, 1}, +	{58, 88, 2, 12, 1}, +	{60, 88, 4, 12, 1}, +	{62, 88, 6, 12, 1}, +	{64, 88, 8, 12, 1}, +	{100, 91, 8, 12, 1}, +	{102, 91, 10, 12, 1}, +	{104, 92, 0, 12, 1}, +	{106, 92, 2, 12, 1}, +	{108, 92, 4, 12, 1}, +	{110, 92, 6, 12, 1}, +	{112, 92, 8, 12, 1}, +	{114, 92, 10, 12, 1}, +	{116, 93, 0, 12, 1}, +	{118, 93, 2, 12, 1}, +	{120, 93, 4, 12, 1}, +	{122, 93, 6, 12, 1}, +	{124, 93, 8, 12, 1}, +	{126, 93, 10, 12, 1}, +	{128, 94, 0, 12, 1}, +	{130, 94, 2, 12, 1}, +	{132, 94, 4, 12, 1}, +	{134, 94, 6, 12, 1}, +	{136, 94, 8, 12, 1}, +	{138, 94, 10, 12, 1}, +	{140, 95, 0, 12, 1}, +	{149, 95, 9, 12, 1}, +	{151, 95, 11, 12, 1}, +	{153, 96, 1, 12, 1}, +	{155, 96, 3, 12, 1}, +	{157, 96, 5, 12, 1}, +	{159, 96, 7, 12, 1}, +	{161, 96, 9, 12, 1}, +	{165, 97, 1, 12, 1}, +	{184, 82, 0, 12, 1}, +	{188, 82, 4, 12, 1}, +	{192, 82, 8, 12, 1}, +	{196, 83, 0, 12, 1}, +}; + +static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  {  	struct hw_mode_spec *spec = &rt2x00dev->spec;  	struct channel_info *info;  	char *default_power1;  	char *default_power2; +	char *default_power3;  	unsigned int i; -	unsigned short max_power; -	u16 eeprom; +	u32 reg;  	/* -	 * Disable powersaving as default on PCI devices. +	 * Disable powersaving as default.  	 */ -	if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) -		rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; +	rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;  	/*  	 * Initialize all hw fields. @@ -3228,7 +7468,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	    IEEE80211_HW_SIGNAL_DBM |  	    IEEE80211_HW_SUPPORTS_PS |  	    IEEE80211_HW_PS_NULLFUNC_STACK | -	    IEEE80211_HW_AMPDU_AGGREGATION; +	    IEEE80211_HW_AMPDU_AGGREGATION | +	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | +	    IEEE80211_HW_SUPPORTS_HT_CCK_RATES; +  	/*  	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices  	 * unless we are capable of sending the buffered frames out after the @@ -3242,7 +7485,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);  	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, -				rt2x00_eeprom_addr(rt2x00dev, +				rt2800_eeprom_addr(rt2x00dev,  						   EEPROM_MAC_ADDR_0));  	/* @@ -3258,36 +7501,66 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	rt2x00dev->hw->max_report_rates = 7;  	rt2x00dev->hw->max_rate_tries = 1; -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -  	/*  	 * Initialize hw_mode information.  	 */ -	spec->supported_bands = SUPPORT_BAND_2GHZ;  	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; -	if (rt2x00_rf(rt2x00dev, RF2820) || -	    rt2x00_rf(rt2x00dev, RF2720)) { +	switch (rt2x00dev->chip.rf) { +	case RF2720: +	case RF2820:  		spec->num_channels = 14;  		spec->channels = rf_vals; -	} else if (rt2x00_rf(rt2x00dev, RF2850) || -		   rt2x00_rf(rt2x00dev, RF2750)) { -		spec->supported_bands |= SUPPORT_BAND_5GHZ; +		break; + +	case RF2750: +	case RF2850:  		spec->num_channels = ARRAY_SIZE(rf_vals);  		spec->channels = rf_vals; -	} else if (rt2x00_rf(rt2x00dev, RF3020) || -		   rt2x00_rf(rt2x00dev, RF2020) || -		   rt2x00_rf(rt2x00dev, RF3021) || -		   rt2x00_rf(rt2x00dev, RF3022) || -		   rt2x00_rf(rt2x00dev, RF3320)) { +		break; + +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3070: +	case RF3290: +	case RF3320: +	case RF3322: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392:  		spec->num_channels = 14;  		spec->channels = rf_vals_3x; -	} else if (rt2x00_rf(rt2x00dev, RF3052)) { -		spec->supported_bands |= SUPPORT_BAND_5GHZ; +		break; + +	case RF3052: +	case RF3053:  		spec->num_channels = ARRAY_SIZE(rf_vals_3x);  		spec->channels = rf_vals_3x; +		break; + +	case RF5592: +		rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); +		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { +			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); +			spec->channels = rf_vals_5592_xtal40; +		} else { +			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); +			spec->channels = rf_vals_5592_xtal20; +		} +		break;  	} +	if (WARN_ON_ONCE(!spec->channels)) +		return -ENODEV; + +	spec->supported_bands = SUPPORT_BAND_2GHZ; +	if (spec->num_channels > 14) +		spec->supported_bands |= SUPPORT_BAND_5GHZ; +  	/*  	 * Initialize HT information.  	 */ @@ -3302,22 +7575,21 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	    IEEE80211_HT_CAP_SGI_20 |  	    IEEE80211_HT_CAP_SGI_40; -	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) +	if (rt2x00dev->default_ant.tx_chain_num >= 2)  		spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; -	spec->ht.cap |= -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) << -		IEEE80211_HT_CAP_RX_STBC_SHIFT; +	spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num << +			IEEE80211_HT_CAP_RX_STBC_SHIFT;  	spec->ht.ampdu_factor = 3;  	spec->ht.ampdu_density = 4;  	spec->ht.mcs.tx_params =  	    IEEE80211_HT_MCS_TX_DEFINED |  	    IEEE80211_HT_MCS_TX_RX_DIFF | -	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << -		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); +	    ((rt2x00dev->default_ant.tx_chain_num - 1) << +	     IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); -	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { +	switch (rt2x00dev->default_ant.rx_chain_num) {  	case 3:  		spec->ht.mcs.rx_mask[2] = 0xff;  	case 2: @@ -3337,32 +7609,175 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	spec->channels_info = info; -	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom); -	max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ); -	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); -	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); +	default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); +	default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + +	if (rt2x00dev->default_ant.tx_chain_num > 2) +		default_power3 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_EXT_TXPOWER_BG3); +	else +		default_power3 = NULL;  	for (i = 0; i < 14; i++) { -		info[i].max_power = max_power; -		info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]); -		info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]); +		info[i].default_power1 = default_power1[i]; +		info[i].default_power2 = default_power2[i]; +		if (default_power3) +			info[i].default_power3 = default_power3[i];  	}  	if (spec->num_channels > 14) { -		max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ); -		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); -		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); +		default_power1 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_TXPOWER_A1); +		default_power2 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_TXPOWER_A2); + +		if (rt2x00dev->default_ant.tx_chain_num > 2) +			default_power3 = +				rt2800_eeprom_addr(rt2x00dev, +						   EEPROM_EXT_TXPOWER_A3); +		else +			default_power3 = NULL;  		for (i = 14; i < spec->num_channels; i++) { -			info[i].max_power = max_power; -			info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]); -			info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]); +			info[i].default_power1 = default_power1[i - 14]; +			info[i].default_power2 = default_power2[i - 14]; +			if (default_power3) +				info[i].default_power3 = default_power3[i - 14];  		}  	} +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +	case RF3052: +	case RF3053: +	case RF3070: +	case RF3290: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); +		break; +	} + +	return 0; +} + +static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u32 rt; +	u32 rev; + +	if (rt2x00_rt(rt2x00dev, RT3290)) +		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); +	else +		rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + +	rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET); +	rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION); + +	switch (rt) { +	case RT2860: +	case RT2872: +	case RT2883: +	case RT3070: +	case RT3071: +	case RT3090: +	case RT3290: +	case RT3352: +	case RT3390: +	case RT3572: +	case RT3593: +	case RT5390: +	case RT5392: +	case RT5592: +		break; +	default: +		rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n", +			   rt, rev); +		return -ENODEV; +	} + +	rt2x00_set_rt(rt2x00dev, rt, rev); +  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode); + +int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) +{ +	int retval; +	u32 reg; + +	retval = rt2800_probe_rt(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Allocate eeprom data. +	 */ +	retval = rt2800_validate_eeprom(rt2x00dev); +	if (retval) +		return retval; + +	retval = rt2800_init_eeprom(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR2, 1); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +	/* +	 * Initialize hw specifications. +	 */ +	retval = rt2800_probe_hw_mode(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Set device capabilities. +	 */ +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); +	if (!rt2x00_is_usb(rt2x00dev)) +		__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); + +	/* +	 * Set device requirements. +	 */ +	if (!rt2x00_is_soc(rt2x00dev)) +		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); +	if (!rt2800_hwcrypt_disabled(rt2x00dev)) +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); +	if (rt2x00_is_usb(rt2x00dev)) +		__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); +	else { +		__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); +	} + +	/* +	 * Set the rssi offset. +	 */ +	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_probe_hw);  /*   * IEEE80211 stack callback functions. @@ -3421,7 +7836,8 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)  }  EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); -int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +int rt2800_conf_tx(struct ieee80211_hw *hw, +		   struct ieee80211_vif *vif, u16 queue_idx,  		   const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; @@ -3437,7 +7853,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	 * we are free to update the registers based on the value  	 * in the queue parameter.  	 */ -	retval = rt2x00mac_conf_tx(hw, queue_idx, params); +	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);  	if (retval)  		return retval; @@ -3448,7 +7864,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	if (queue_idx >= 4)  		return 0; -	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); +	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);  	/* Update WMM TXOP register */  	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); @@ -3489,7 +7905,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  }  EXPORT_SYMBOL_GPL(rt2800_conf_tx); -u64 rt2800_get_tsf(struct ieee80211_hw *hw) +u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf; @@ -3506,10 +7922,22 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf);  int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			enum ieee80211_ampdu_mlme_action action, -			struct ieee80211_sta *sta, u16 tid, u16 *ssn) +			struct ieee80211_sta *sta, u16 tid, u16 *ssn, +			u8 buf_size)  { +	struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;  	int ret = 0; +	/* +	 * Don't allow aggregation for stations the hardware isn't aware +	 * of because tx status reports for frames to an unknown station +	 * always contain wcid=255 and thus we can't distinguish between +	 * multiple stations which leads to unwanted situations when the +	 * hw reorders frames due to aggregation. +	 */ +	if (sta_priv->wcid < 0) +		return 1; +  	switch (action) {  	case IEEE80211_AMPDU_RX_START:  	case IEEE80211_AMPDU_RX_STOP: @@ -3523,19 +7951,56 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	case IEEE80211_AMPDU_TX_START:  		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);  		break; -	case IEEE80211_AMPDU_TX_STOP: +	case IEEE80211_AMPDU_TX_STOP_CONT: +	case IEEE80211_AMPDU_TX_STOP_FLUSH: +	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:  		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);  		break;  	case IEEE80211_AMPDU_TX_OPERATIONAL:  		break;  	default: -		WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n"); +		rt2x00_warn((struct rt2x00_dev *)hw->priv, +			    "Unknown AMPDU action\n");  	}  	return ret;  }  EXPORT_SYMBOL_GPL(rt2800_ampdu_action); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, +		      struct survey_info *survey) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct ieee80211_conf *conf = &hw->conf; +	u32 idle, busy, busy_ext; + +	if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->chandef.chan; + +	rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); + +	if (idle || busy) { +		survey->filled = SURVEY_INFO_CHANNEL_TIME | +				 SURVEY_INFO_CHANNEL_TIME_BUSY | +				 SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; + +		survey->channel_time = (idle + busy) / 1000; +		survey->channel_time_busy = busy / 1000; +		survey->channel_time_ext_busy = busy_ext / 1000; +	} + +	if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) +		survey->filled |= SURVEY_INFO_IN_USE; + +	return 0; + +} +EXPORT_SYMBOL_GPL(rt2800_get_survey); +  MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");  MODULE_VERSION(DRV_VERSION);  MODULE_DESCRIPTION("Ralink RT2800 library");  | 
