18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
48c2ecf20Sopenharmony_ci	<http://rt2x00.serialmonkey.com>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci	Module: rt73usb
108c2ecf20Sopenharmony_ci	Abstract: rt73usb device specific routines.
118c2ecf20Sopenharmony_ci	Supported chipsets: rt2571W & rt2671.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/crc-itu-t.h>
158c2ecf20Sopenharmony_ci#include <linux/delay.h>
168c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
178c2ecf20Sopenharmony_ci#include <linux/kernel.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/slab.h>
208c2ecf20Sopenharmony_ci#include <linux/usb.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "rt2x00.h"
238c2ecf20Sopenharmony_ci#include "rt2x00usb.h"
248c2ecf20Sopenharmony_ci#include "rt73usb.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * Allow hardware encryption to be disabled.
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_cistatic bool modparam_nohwcrypt;
308c2ecf20Sopenharmony_cimodule_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/*
348c2ecf20Sopenharmony_ci * Register access.
358c2ecf20Sopenharmony_ci * All access to the CSR registers will go through the methods
368c2ecf20Sopenharmony_ci * rt2x00usb_register_read and rt2x00usb_register_write.
378c2ecf20Sopenharmony_ci * BBP and RF register require indirect register access,
388c2ecf20Sopenharmony_ci * and use the CSR registers BBPCSR and RFCSR to achieve this.
398c2ecf20Sopenharmony_ci * These indirect registers work with busy bits,
408c2ecf20Sopenharmony_ci * and we will try maximal REGISTER_BUSY_COUNT times to access
418c2ecf20Sopenharmony_ci * the register while taking a REGISTER_BUSY_DELAY us delay
428c2ecf20Sopenharmony_ci * between each attampt. When the busy bit is still set at that time,
438c2ecf20Sopenharmony_ci * the access attempt is considered to have failed,
448c2ecf20Sopenharmony_ci * and we will print an error.
458c2ecf20Sopenharmony_ci * The _lock versions must be used if you already hold the csr_mutex
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_ci#define WAIT_FOR_BBP(__dev, __reg) \
488c2ecf20Sopenharmony_ci	rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
498c2ecf20Sopenharmony_ci#define WAIT_FOR_RF(__dev, __reg) \
508c2ecf20Sopenharmony_ci	rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
538c2ecf20Sopenharmony_ci			      const unsigned int word, const u8 value)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	u32 reg;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	/*
608c2ecf20Sopenharmony_ci	 * Wait until the BBP becomes available, afterwards we
618c2ecf20Sopenharmony_ci	 * can safely write the new data into the register.
628c2ecf20Sopenharmony_ci	 */
638c2ecf20Sopenharmony_ci	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
648c2ecf20Sopenharmony_ci		reg = 0;
658c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
668c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
678c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
688c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic u8 rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
778c2ecf20Sopenharmony_ci			   const unsigned int word)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	u32 reg;
808c2ecf20Sopenharmony_ci	u8 value;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	/*
858c2ecf20Sopenharmony_ci	 * Wait until the BBP becomes available, afterwards we
868c2ecf20Sopenharmony_ci	 * can safely write the read request into the register.
878c2ecf20Sopenharmony_ci	 * After the data has been written, we wait until hardware
888c2ecf20Sopenharmony_ci	 * returns the correct value, if at any time the register
898c2ecf20Sopenharmony_ci	 * doesn't become available in time, reg will be 0xffffffff
908c2ecf20Sopenharmony_ci	 * which means we return 0xff to the caller.
918c2ecf20Sopenharmony_ci	 */
928c2ecf20Sopenharmony_ci	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
938c2ecf20Sopenharmony_ci		reg = 0;
948c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
958c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
968c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci		WAIT_FOR_BBP(rt2x00dev, &reg);
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	return value;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
1118c2ecf20Sopenharmony_ci			     const unsigned int word, const u32 value)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	u32 reg;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/*
1188c2ecf20Sopenharmony_ci	 * Wait until the RF becomes available, afterwards we
1198c2ecf20Sopenharmony_ci	 * can safely write the new data into the register.
1208c2ecf20Sopenharmony_ci	 */
1218c2ecf20Sopenharmony_ci	if (WAIT_FOR_RF(rt2x00dev, &reg)) {
1228c2ecf20Sopenharmony_ci		reg = 0;
1238c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
1248c2ecf20Sopenharmony_ci		/*
1258c2ecf20Sopenharmony_ci		 * RF5225 and RF2527 contain 21 bits per RF register value,
1268c2ecf20Sopenharmony_ci		 * all others contain 20 bits.
1278c2ecf20Sopenharmony_ci		 */
1288c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
1298c2ecf20Sopenharmony_ci				   20 + (rt2x00_rf(rt2x00dev, RF5225) ||
1308c2ecf20Sopenharmony_ci					 rt2x00_rf(rt2x00dev, RF2527)));
1318c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
1328c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci		rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
1358c2ecf20Sopenharmony_ci		rt2x00_rf_write(rt2x00dev, word, value);
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS
1428c2ecf20Sopenharmony_cistatic const struct rt2x00debug rt73usb_rt2x00debug = {
1438c2ecf20Sopenharmony_ci	.owner	= THIS_MODULE,
1448c2ecf20Sopenharmony_ci	.csr	= {
1458c2ecf20Sopenharmony_ci		.read		= rt2x00usb_register_read,
1468c2ecf20Sopenharmony_ci		.write		= rt2x00usb_register_write,
1478c2ecf20Sopenharmony_ci		.flags		= RT2X00DEBUGFS_OFFSET,
1488c2ecf20Sopenharmony_ci		.word_base	= CSR_REG_BASE,
1498c2ecf20Sopenharmony_ci		.word_size	= sizeof(u32),
1508c2ecf20Sopenharmony_ci		.word_count	= CSR_REG_SIZE / sizeof(u32),
1518c2ecf20Sopenharmony_ci	},
1528c2ecf20Sopenharmony_ci	.eeprom	= {
1538c2ecf20Sopenharmony_ci		.read		= rt2x00_eeprom_read,
1548c2ecf20Sopenharmony_ci		.write		= rt2x00_eeprom_write,
1558c2ecf20Sopenharmony_ci		.word_base	= EEPROM_BASE,
1568c2ecf20Sopenharmony_ci		.word_size	= sizeof(u16),
1578c2ecf20Sopenharmony_ci		.word_count	= EEPROM_SIZE / sizeof(u16),
1588c2ecf20Sopenharmony_ci	},
1598c2ecf20Sopenharmony_ci	.bbp	= {
1608c2ecf20Sopenharmony_ci		.read		= rt73usb_bbp_read,
1618c2ecf20Sopenharmony_ci		.write		= rt73usb_bbp_write,
1628c2ecf20Sopenharmony_ci		.word_base	= BBP_BASE,
1638c2ecf20Sopenharmony_ci		.word_size	= sizeof(u8),
1648c2ecf20Sopenharmony_ci		.word_count	= BBP_SIZE / sizeof(u8),
1658c2ecf20Sopenharmony_ci	},
1668c2ecf20Sopenharmony_ci	.rf	= {
1678c2ecf20Sopenharmony_ci		.read		= rt2x00_rf_read,
1688c2ecf20Sopenharmony_ci		.write		= rt73usb_rf_write,
1698c2ecf20Sopenharmony_ci		.word_base	= RF_BASE,
1708c2ecf20Sopenharmony_ci		.word_size	= sizeof(u32),
1718c2ecf20Sopenharmony_ci		.word_count	= RF_SIZE / sizeof(u32),
1728c2ecf20Sopenharmony_ci	},
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	u32 reg;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
1818c2ecf20Sopenharmony_ci	return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS
1858c2ecf20Sopenharmony_cistatic void rt73usb_brightness_set(struct led_classdev *led_cdev,
1868c2ecf20Sopenharmony_ci				   enum led_brightness brightness)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	struct rt2x00_led *led =
1898c2ecf20Sopenharmony_ci	   container_of(led_cdev, struct rt2x00_led, led_dev);
1908c2ecf20Sopenharmony_ci	unsigned int enabled = brightness != LED_OFF;
1918c2ecf20Sopenharmony_ci	unsigned int a_mode =
1928c2ecf20Sopenharmony_ci	    (enabled && led->rt2x00dev->curr_band == NL80211_BAND_5GHZ);
1938c2ecf20Sopenharmony_ci	unsigned int bg_mode =
1948c2ecf20Sopenharmony_ci	    (enabled && led->rt2x00dev->curr_band == NL80211_BAND_2GHZ);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (led->type == LED_TYPE_RADIO) {
1978c2ecf20Sopenharmony_ci		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
1988c2ecf20Sopenharmony_ci				   MCU_LEDCS_RADIO_STATUS, enabled);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
2018c2ecf20Sopenharmony_ci					    0, led->rt2x00dev->led_mcu_reg,
2028c2ecf20Sopenharmony_ci					    REGISTER_TIMEOUT);
2038c2ecf20Sopenharmony_ci	} else if (led->type == LED_TYPE_ASSOC) {
2048c2ecf20Sopenharmony_ci		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
2058c2ecf20Sopenharmony_ci				   MCU_LEDCS_LINK_BG_STATUS, bg_mode);
2068c2ecf20Sopenharmony_ci		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
2078c2ecf20Sopenharmony_ci				   MCU_LEDCS_LINK_A_STATUS, a_mode);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
2108c2ecf20Sopenharmony_ci					    0, led->rt2x00dev->led_mcu_reg,
2118c2ecf20Sopenharmony_ci					    REGISTER_TIMEOUT);
2128c2ecf20Sopenharmony_ci	} else if (led->type == LED_TYPE_QUALITY) {
2138c2ecf20Sopenharmony_ci		/*
2148c2ecf20Sopenharmony_ci		 * The brightness is divided into 6 levels (0 - 5),
2158c2ecf20Sopenharmony_ci		 * this means we need to convert the brightness
2168c2ecf20Sopenharmony_ci		 * argument into the matching level within that range.
2178c2ecf20Sopenharmony_ci		 */
2188c2ecf20Sopenharmony_ci		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
2198c2ecf20Sopenharmony_ci					    brightness / (LED_FULL / 6),
2208c2ecf20Sopenharmony_ci					    led->rt2x00dev->led_mcu_reg,
2218c2ecf20Sopenharmony_ci					    REGISTER_TIMEOUT);
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic int rt73usb_blink_set(struct led_classdev *led_cdev,
2268c2ecf20Sopenharmony_ci			     unsigned long *delay_on,
2278c2ecf20Sopenharmony_ci			     unsigned long *delay_off)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	struct rt2x00_led *led =
2308c2ecf20Sopenharmony_ci	    container_of(led_cdev, struct rt2x00_led, led_dev);
2318c2ecf20Sopenharmony_ci	u32 reg;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14);
2348c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
2358c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
2368c2ecf20Sopenharmony_ci	rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	return 0;
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
2428c2ecf20Sopenharmony_ci			     struct rt2x00_led *led,
2438c2ecf20Sopenharmony_ci			     enum led_type type)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	led->rt2x00dev = rt2x00dev;
2468c2ecf20Sopenharmony_ci	led->type = type;
2478c2ecf20Sopenharmony_ci	led->led_dev.brightness_set = rt73usb_brightness_set;
2488c2ecf20Sopenharmony_ci	led->led_dev.blink_set = rt73usb_blink_set;
2498c2ecf20Sopenharmony_ci	led->flags = LED_INITIALIZED;
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci/*
2548c2ecf20Sopenharmony_ci * Configuration handlers.
2558c2ecf20Sopenharmony_ci */
2568c2ecf20Sopenharmony_cistatic int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
2578c2ecf20Sopenharmony_ci				     struct rt2x00lib_crypto *crypto,
2588c2ecf20Sopenharmony_ci				     struct ieee80211_key_conf *key)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	struct hw_key_entry key_entry;
2618c2ecf20Sopenharmony_ci	struct rt2x00_field32 field;
2628c2ecf20Sopenharmony_ci	u32 mask;
2638c2ecf20Sopenharmony_ci	u32 reg;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (crypto->cmd == SET_KEY) {
2668c2ecf20Sopenharmony_ci		/*
2678c2ecf20Sopenharmony_ci		 * rt2x00lib can't determine the correct free
2688c2ecf20Sopenharmony_ci		 * key_idx for shared keys. We have 1 register
2698c2ecf20Sopenharmony_ci		 * with key valid bits. The goal is simple, read
2708c2ecf20Sopenharmony_ci		 * the register, if that is full we have no slots
2718c2ecf20Sopenharmony_ci		 * left.
2728c2ecf20Sopenharmony_ci		 * Note that each BSS is allowed to have up to 4
2738c2ecf20Sopenharmony_ci		 * shared keys, so put a mask over the allowed
2748c2ecf20Sopenharmony_ci		 * entries.
2758c2ecf20Sopenharmony_ci		 */
2768c2ecf20Sopenharmony_ci		mask = (0xf << crypto->bssidx);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
2798c2ecf20Sopenharmony_ci		reg &= mask;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		if (reg && reg == mask)
2828c2ecf20Sopenharmony_ci			return -ENOSPC;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		key->hw_key_idx += reg ? ffz(reg) : 0;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci		/*
2878c2ecf20Sopenharmony_ci		 * Upload key to hardware
2888c2ecf20Sopenharmony_ci		 */
2898c2ecf20Sopenharmony_ci		memcpy(key_entry.key, crypto->key,
2908c2ecf20Sopenharmony_ci		       sizeof(key_entry.key));
2918c2ecf20Sopenharmony_ci		memcpy(key_entry.tx_mic, crypto->tx_mic,
2928c2ecf20Sopenharmony_ci		       sizeof(key_entry.tx_mic));
2938c2ecf20Sopenharmony_ci		memcpy(key_entry.rx_mic, crypto->rx_mic,
2948c2ecf20Sopenharmony_ci		       sizeof(key_entry.rx_mic));
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci		reg = SHARED_KEY_ENTRY(key->hw_key_idx);
2978c2ecf20Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, reg,
2988c2ecf20Sopenharmony_ci					      &key_entry, sizeof(key_entry));
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		/*
3018c2ecf20Sopenharmony_ci		 * The cipher types are stored over 2 registers.
3028c2ecf20Sopenharmony_ci		 * bssidx 0 and 1 keys are stored in SEC_CSR1 and
3038c2ecf20Sopenharmony_ci		 * bssidx 1 and 2 keys are stored in SEC_CSR5.
3048c2ecf20Sopenharmony_ci		 * Using the correct defines correctly will cause overhead,
3058c2ecf20Sopenharmony_ci		 * so just calculate the correct offset.
3068c2ecf20Sopenharmony_ci		 */
3078c2ecf20Sopenharmony_ci		if (key->hw_key_idx < 8) {
3088c2ecf20Sopenharmony_ci			field.bit_offset = (3 * key->hw_key_idx);
3098c2ecf20Sopenharmony_ci			field.bit_mask = 0x7 << field.bit_offset;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci			reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR1);
3128c2ecf20Sopenharmony_ci			rt2x00_set_field32(&reg, field, crypto->cipher);
3138c2ecf20Sopenharmony_ci			rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
3148c2ecf20Sopenharmony_ci		} else {
3158c2ecf20Sopenharmony_ci			field.bit_offset = (3 * (key->hw_key_idx - 8));
3168c2ecf20Sopenharmony_ci			field.bit_mask = 0x7 << field.bit_offset;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci			reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR5);
3198c2ecf20Sopenharmony_ci			rt2x00_set_field32(&reg, field, crypto->cipher);
3208c2ecf20Sopenharmony_ci			rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
3218c2ecf20Sopenharmony_ci		}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		/*
3248c2ecf20Sopenharmony_ci		 * The driver does not support the IV/EIV generation
3258c2ecf20Sopenharmony_ci		 * in hardware. However it doesn't support the IV/EIV
3268c2ecf20Sopenharmony_ci		 * inside the ieee80211 frame either, but requires it
3278c2ecf20Sopenharmony_ci		 * to be provided separately for the descriptor.
3288c2ecf20Sopenharmony_ci		 * rt2x00lib will cut the IV/EIV data out of all frames
3298c2ecf20Sopenharmony_ci		 * given to us by mac80211, but we must tell mac80211
3308c2ecf20Sopenharmony_ci		 * to generate the IV/EIV data.
3318c2ecf20Sopenharmony_ci		 */
3328c2ecf20Sopenharmony_ci		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3338c2ecf20Sopenharmony_ci	}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	/*
3368c2ecf20Sopenharmony_ci	 * SEC_CSR0 contains only single-bit fields to indicate
3378c2ecf20Sopenharmony_ci	 * a particular key is valid. Because using the FIELD32()
3388c2ecf20Sopenharmony_ci	 * defines directly will cause a lot of overhead we use
3398c2ecf20Sopenharmony_ci	 * a calculation to determine the correct bit directly.
3408c2ecf20Sopenharmony_ci	 */
3418c2ecf20Sopenharmony_ci	mask = 1 << key->hw_key_idx;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
3448c2ecf20Sopenharmony_ci	if (crypto->cmd == SET_KEY)
3458c2ecf20Sopenharmony_ci		reg |= mask;
3468c2ecf20Sopenharmony_ci	else if (crypto->cmd == DISABLE_KEY)
3478c2ecf20Sopenharmony_ci		reg &= ~mask;
3488c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	return 0;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
3548c2ecf20Sopenharmony_ci				       struct rt2x00lib_crypto *crypto,
3558c2ecf20Sopenharmony_ci				       struct ieee80211_key_conf *key)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	struct hw_pairwise_ta_entry addr_entry;
3588c2ecf20Sopenharmony_ci	struct hw_key_entry key_entry;
3598c2ecf20Sopenharmony_ci	u32 mask;
3608c2ecf20Sopenharmony_ci	u32 reg;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (crypto->cmd == SET_KEY) {
3638c2ecf20Sopenharmony_ci		/*
3648c2ecf20Sopenharmony_ci		 * rt2x00lib can't determine the correct free
3658c2ecf20Sopenharmony_ci		 * key_idx for pairwise keys. We have 2 registers
3668c2ecf20Sopenharmony_ci		 * with key valid bits. The goal is simple, read
3678c2ecf20Sopenharmony_ci		 * the first register, if that is full move to
3688c2ecf20Sopenharmony_ci		 * the next register.
3698c2ecf20Sopenharmony_ci		 * When both registers are full, we drop the key,
3708c2ecf20Sopenharmony_ci		 * otherwise we use the first invalid entry.
3718c2ecf20Sopenharmony_ci		 */
3728c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
3738c2ecf20Sopenharmony_ci		if (reg && reg == ~0) {
3748c2ecf20Sopenharmony_ci			key->hw_key_idx = 32;
3758c2ecf20Sopenharmony_ci			reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
3768c2ecf20Sopenharmony_ci			if (reg && reg == ~0)
3778c2ecf20Sopenharmony_ci				return -ENOSPC;
3788c2ecf20Sopenharmony_ci		}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci		key->hw_key_idx += reg ? ffz(reg) : 0;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci		/*
3838c2ecf20Sopenharmony_ci		 * Upload key to hardware
3848c2ecf20Sopenharmony_ci		 */
3858c2ecf20Sopenharmony_ci		memcpy(key_entry.key, crypto->key,
3868c2ecf20Sopenharmony_ci		       sizeof(key_entry.key));
3878c2ecf20Sopenharmony_ci		memcpy(key_entry.tx_mic, crypto->tx_mic,
3888c2ecf20Sopenharmony_ci		       sizeof(key_entry.tx_mic));
3898c2ecf20Sopenharmony_ci		memcpy(key_entry.rx_mic, crypto->rx_mic,
3908c2ecf20Sopenharmony_ci		       sizeof(key_entry.rx_mic));
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci		reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
3938c2ecf20Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, reg,
3948c2ecf20Sopenharmony_ci					      &key_entry, sizeof(key_entry));
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		/*
3978c2ecf20Sopenharmony_ci		 * Send the address and cipher type to the hardware register.
3988c2ecf20Sopenharmony_ci		 */
3998c2ecf20Sopenharmony_ci		memset(&addr_entry, 0, sizeof(addr_entry));
4008c2ecf20Sopenharmony_ci		memcpy(&addr_entry, crypto->address, ETH_ALEN);
4018c2ecf20Sopenharmony_ci		addr_entry.cipher = crypto->cipher;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci		reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
4048c2ecf20Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, reg,
4058c2ecf20Sopenharmony_ci					    &addr_entry, sizeof(addr_entry));
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci		/*
4088c2ecf20Sopenharmony_ci		 * Enable pairwise lookup table for given BSS idx,
4098c2ecf20Sopenharmony_ci		 * without this received frames will not be decrypted
4108c2ecf20Sopenharmony_ci		 * by the hardware.
4118c2ecf20Sopenharmony_ci		 */
4128c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR4);
4138c2ecf20Sopenharmony_ci		reg |= (1 << crypto->bssidx);
4148c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		/*
4178c2ecf20Sopenharmony_ci		 * The driver does not support the IV/EIV generation
4188c2ecf20Sopenharmony_ci		 * in hardware. However it doesn't support the IV/EIV
4198c2ecf20Sopenharmony_ci		 * inside the ieee80211 frame either, but requires it
4208c2ecf20Sopenharmony_ci		 * to be provided separately for the descriptor.
4218c2ecf20Sopenharmony_ci		 * rt2x00lib will cut the IV/EIV data out of all frames
4228c2ecf20Sopenharmony_ci		 * given to us by mac80211, but we must tell mac80211
4238c2ecf20Sopenharmony_ci		 * to generate the IV/EIV data.
4248c2ecf20Sopenharmony_ci		 */
4258c2ecf20Sopenharmony_ci		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/*
4298c2ecf20Sopenharmony_ci	 * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
4308c2ecf20Sopenharmony_ci	 * a particular key is valid. Because using the FIELD32()
4318c2ecf20Sopenharmony_ci	 * defines directly will cause a lot of overhead we use
4328c2ecf20Sopenharmony_ci	 * a calculation to determine the correct bit directly.
4338c2ecf20Sopenharmony_ci	 */
4348c2ecf20Sopenharmony_ci	if (key->hw_key_idx < 32) {
4358c2ecf20Sopenharmony_ci		mask = 1 << key->hw_key_idx;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
4388c2ecf20Sopenharmony_ci		if (crypto->cmd == SET_KEY)
4398c2ecf20Sopenharmony_ci			reg |= mask;
4408c2ecf20Sopenharmony_ci		else if (crypto->cmd == DISABLE_KEY)
4418c2ecf20Sopenharmony_ci			reg &= ~mask;
4428c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
4438c2ecf20Sopenharmony_ci	} else {
4448c2ecf20Sopenharmony_ci		mask = 1 << (key->hw_key_idx - 32);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
4478c2ecf20Sopenharmony_ci		if (crypto->cmd == SET_KEY)
4488c2ecf20Sopenharmony_ci			reg |= mask;
4498c2ecf20Sopenharmony_ci		else if (crypto->cmd == DISABLE_KEY)
4508c2ecf20Sopenharmony_ci			reg &= ~mask;
4518c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return 0;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
4588c2ecf20Sopenharmony_ci				  const unsigned int filter_flags)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	u32 reg;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/*
4638c2ecf20Sopenharmony_ci	 * Start configuration steps.
4648c2ecf20Sopenharmony_ci	 * Note that the version error will always be dropped
4658c2ecf20Sopenharmony_ci	 * and broadcast frames will always be accepted since
4668c2ecf20Sopenharmony_ci	 * there is no filter for it at this time.
4678c2ecf20Sopenharmony_ci	 */
4688c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
4698c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
4708c2ecf20Sopenharmony_ci			   !(filter_flags & FIF_FCSFAIL));
4718c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
4728c2ecf20Sopenharmony_ci			   !(filter_flags & FIF_PLCPFAIL));
4738c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
4748c2ecf20Sopenharmony_ci			   !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
4758c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
4768c2ecf20Sopenharmony_ci			   !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
4778c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
4788c2ecf20Sopenharmony_ci			   !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
4798c2ecf20Sopenharmony_ci			   !rt2x00dev->intf_ap_count);
4808c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
4818c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
4828c2ecf20Sopenharmony_ci			   !(filter_flags & FIF_ALLMULTI));
4838c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
4848c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
4858c2ecf20Sopenharmony_ci			   !(filter_flags & FIF_CONTROL));
4868c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
4908c2ecf20Sopenharmony_ci				struct rt2x00_intf *intf,
4918c2ecf20Sopenharmony_ci				struct rt2x00intf_conf *conf,
4928c2ecf20Sopenharmony_ci				const unsigned int flags)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	u32 reg;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	if (flags & CONFIG_UPDATE_TYPE) {
4978c2ecf20Sopenharmony_ci		/*
4988c2ecf20Sopenharmony_ci		 * Enable synchronisation.
4998c2ecf20Sopenharmony_ci		 */
5008c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
5018c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
5028c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (flags & CONFIG_UPDATE_MAC) {
5068c2ecf20Sopenharmony_ci		reg = le32_to_cpu(conf->mac[1]);
5078c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
5088c2ecf20Sopenharmony_ci		conf->mac[1] = cpu_to_le32(reg);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
5118c2ecf20Sopenharmony_ci					    conf->mac, sizeof(conf->mac));
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	if (flags & CONFIG_UPDATE_BSSID) {
5158c2ecf20Sopenharmony_ci		reg = le32_to_cpu(conf->bssid[1]);
5168c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
5178c2ecf20Sopenharmony_ci		conf->bssid[1] = cpu_to_le32(reg);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
5208c2ecf20Sopenharmony_ci					    conf->bssid, sizeof(conf->bssid));
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_cistatic void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
5258c2ecf20Sopenharmony_ci			       struct rt2x00lib_erp *erp,
5268c2ecf20Sopenharmony_ci			       u32 changed)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	u32 reg;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
5318c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
5328c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
5338c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
5368c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
5378c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
5388c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
5398c2ecf20Sopenharmony_ci				   !!erp->short_preamble);
5408c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (changed & BSS_CHANGED_BASIC_RATES)
5448c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
5458c2ecf20Sopenharmony_ci					 erp->basic_rates);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	if (changed & BSS_CHANGED_BEACON_INT) {
5488c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
5498c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
5508c2ecf20Sopenharmony_ci				   erp->beacon_int * 16);
5518c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	if (changed & BSS_CHANGED_ERP_SLOT) {
5558c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
5568c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
5578c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR8);
5608c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
5618c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
5628c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
5638c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
5688c2ecf20Sopenharmony_ci				      struct antenna_setup *ant)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	u8 r3;
5718c2ecf20Sopenharmony_ci	u8 r4;
5728c2ecf20Sopenharmony_ci	u8 r77;
5738c2ecf20Sopenharmony_ci	u8 temp;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	r3 = rt73usb_bbp_read(rt2x00dev, 3);
5768c2ecf20Sopenharmony_ci	r4 = rt73usb_bbp_read(rt2x00dev, 4);
5778c2ecf20Sopenharmony_ci	r77 = rt73usb_bbp_read(rt2x00dev, 77);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	/*
5828c2ecf20Sopenharmony_ci	 * Configure the RX antenna.
5838c2ecf20Sopenharmony_ci	 */
5848c2ecf20Sopenharmony_ci	switch (ant->rx) {
5858c2ecf20Sopenharmony_ci	case ANTENNA_HW_DIVERSITY:
5868c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
5878c2ecf20Sopenharmony_ci		temp = !rt2x00_has_cap_frame_type(rt2x00dev) &&
5888c2ecf20Sopenharmony_ci		       (rt2x00dev->curr_band != NL80211_BAND_5GHZ);
5898c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
5908c2ecf20Sopenharmony_ci		break;
5918c2ecf20Sopenharmony_ci	case ANTENNA_A:
5928c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
5938c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
5948c2ecf20Sopenharmony_ci		if (rt2x00dev->curr_band == NL80211_BAND_5GHZ)
5958c2ecf20Sopenharmony_ci			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
5968c2ecf20Sopenharmony_ci		else
5978c2ecf20Sopenharmony_ci			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
5988c2ecf20Sopenharmony_ci		break;
5998c2ecf20Sopenharmony_ci	case ANTENNA_B:
6008c2ecf20Sopenharmony_ci	default:
6018c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
6028c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
6038c2ecf20Sopenharmony_ci		if (rt2x00dev->curr_band == NL80211_BAND_5GHZ)
6048c2ecf20Sopenharmony_ci			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
6058c2ecf20Sopenharmony_ci		else
6068c2ecf20Sopenharmony_ci			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 77, r77);
6118c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 3, r3);
6128c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 4, r4);
6138c2ecf20Sopenharmony_ci}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_cistatic void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
6168c2ecf20Sopenharmony_ci				      struct antenna_setup *ant)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	u8 r3;
6198c2ecf20Sopenharmony_ci	u8 r4;
6208c2ecf20Sopenharmony_ci	u8 r77;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	r3 = rt73usb_bbp_read(rt2x00dev, 3);
6238c2ecf20Sopenharmony_ci	r4 = rt73usb_bbp_read(rt2x00dev, 4);
6248c2ecf20Sopenharmony_ci	r77 = rt73usb_bbp_read(rt2x00dev, 77);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
6278c2ecf20Sopenharmony_ci	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
6288c2ecf20Sopenharmony_ci			  !rt2x00_has_cap_frame_type(rt2x00dev));
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	/*
6318c2ecf20Sopenharmony_ci	 * Configure the RX antenna.
6328c2ecf20Sopenharmony_ci	 */
6338c2ecf20Sopenharmony_ci	switch (ant->rx) {
6348c2ecf20Sopenharmony_ci	case ANTENNA_HW_DIVERSITY:
6358c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
6368c2ecf20Sopenharmony_ci		break;
6378c2ecf20Sopenharmony_ci	case ANTENNA_A:
6388c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
6398c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
6408c2ecf20Sopenharmony_ci		break;
6418c2ecf20Sopenharmony_ci	case ANTENNA_B:
6428c2ecf20Sopenharmony_ci	default:
6438c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
6448c2ecf20Sopenharmony_ci		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
6458c2ecf20Sopenharmony_ci		break;
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 77, r77);
6498c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 3, r3);
6508c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 4, r4);
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistruct antenna_sel {
6548c2ecf20Sopenharmony_ci	u8 word;
6558c2ecf20Sopenharmony_ci	/*
6568c2ecf20Sopenharmony_ci	 * value[0] -> non-LNA
6578c2ecf20Sopenharmony_ci	 * value[1] -> LNA
6588c2ecf20Sopenharmony_ci	 */
6598c2ecf20Sopenharmony_ci	u8 value[2];
6608c2ecf20Sopenharmony_ci};
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_cistatic const struct antenna_sel antenna_sel_a[] = {
6638c2ecf20Sopenharmony_ci	{ 96,  { 0x58, 0x78 } },
6648c2ecf20Sopenharmony_ci	{ 104, { 0x38, 0x48 } },
6658c2ecf20Sopenharmony_ci	{ 75,  { 0xfe, 0x80 } },
6668c2ecf20Sopenharmony_ci	{ 86,  { 0xfe, 0x80 } },
6678c2ecf20Sopenharmony_ci	{ 88,  { 0xfe, 0x80 } },
6688c2ecf20Sopenharmony_ci	{ 35,  { 0x60, 0x60 } },
6698c2ecf20Sopenharmony_ci	{ 97,  { 0x58, 0x58 } },
6708c2ecf20Sopenharmony_ci	{ 98,  { 0x58, 0x58 } },
6718c2ecf20Sopenharmony_ci};
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic const struct antenna_sel antenna_sel_bg[] = {
6748c2ecf20Sopenharmony_ci	{ 96,  { 0x48, 0x68 } },
6758c2ecf20Sopenharmony_ci	{ 104, { 0x2c, 0x3c } },
6768c2ecf20Sopenharmony_ci	{ 75,  { 0xfe, 0x80 } },
6778c2ecf20Sopenharmony_ci	{ 86,  { 0xfe, 0x80 } },
6788c2ecf20Sopenharmony_ci	{ 88,  { 0xfe, 0x80 } },
6798c2ecf20Sopenharmony_ci	{ 35,  { 0x50, 0x50 } },
6808c2ecf20Sopenharmony_ci	{ 97,  { 0x48, 0x48 } },
6818c2ecf20Sopenharmony_ci	{ 98,  { 0x48, 0x48 } },
6828c2ecf20Sopenharmony_ci};
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_cistatic void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
6858c2ecf20Sopenharmony_ci			       struct antenna_setup *ant)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	const struct antenna_sel *sel;
6888c2ecf20Sopenharmony_ci	unsigned int lna;
6898c2ecf20Sopenharmony_ci	unsigned int i;
6908c2ecf20Sopenharmony_ci	u32 reg;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	/*
6938c2ecf20Sopenharmony_ci	 * We should never come here because rt2x00lib is supposed
6948c2ecf20Sopenharmony_ci	 * to catch this and send us the correct antenna explicitely.
6958c2ecf20Sopenharmony_ci	 */
6968c2ecf20Sopenharmony_ci	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
6978c2ecf20Sopenharmony_ci	       ant->tx == ANTENNA_SW_DIVERSITY);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
7008c2ecf20Sopenharmony_ci		sel = antenna_sel_a;
7018c2ecf20Sopenharmony_ci		lna = rt2x00_has_cap_external_lna_a(rt2x00dev);
7028c2ecf20Sopenharmony_ci	} else {
7038c2ecf20Sopenharmony_ci		sel = antenna_sel_bg;
7048c2ecf20Sopenharmony_ci		lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);
7058c2ecf20Sopenharmony_ci	}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
7088c2ecf20Sopenharmony_ci		rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, PHY_CSR0);
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
7138c2ecf20Sopenharmony_ci			   (rt2x00dev->curr_band == NL80211_BAND_2GHZ));
7148c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
7158c2ecf20Sopenharmony_ci			   (rt2x00dev->curr_band == NL80211_BAND_5GHZ));
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
7208c2ecf20Sopenharmony_ci		rt73usb_config_antenna_5x(rt2x00dev, ant);
7218c2ecf20Sopenharmony_ci	else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
7228c2ecf20Sopenharmony_ci		rt73usb_config_antenna_2x(rt2x00dev, ant);
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cistatic void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
7268c2ecf20Sopenharmony_ci				    struct rt2x00lib_conf *libconf)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	u16 eeprom;
7298c2ecf20Sopenharmony_ci	short lna_gain = 0;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (libconf->conf->chandef.chan->band == NL80211_BAND_2GHZ) {
7328c2ecf20Sopenharmony_ci		if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
7338c2ecf20Sopenharmony_ci			lna_gain += 14;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci		eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
7368c2ecf20Sopenharmony_ci		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
7378c2ecf20Sopenharmony_ci	} else {
7388c2ecf20Sopenharmony_ci		eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
7398c2ecf20Sopenharmony_ci		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
7408c2ecf20Sopenharmony_ci	}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	rt2x00dev->lna_gain = lna_gain;
7438c2ecf20Sopenharmony_ci}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_cistatic void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
7468c2ecf20Sopenharmony_ci				   struct rf_channel *rf, const int txpower)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	u8 r3;
7498c2ecf20Sopenharmony_ci	u8 r94;
7508c2ecf20Sopenharmony_ci	u8 smart;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
7538c2ecf20Sopenharmony_ci	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	r3 = rt73usb_bbp_read(rt2x00dev, 3);
7588c2ecf20Sopenharmony_ci	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
7598c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 3, r3);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	r94 = 6;
7628c2ecf20Sopenharmony_ci	if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
7638c2ecf20Sopenharmony_ci		r94 += txpower - MAX_TXPOWER;
7648c2ecf20Sopenharmony_ci	else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
7658c2ecf20Sopenharmony_ci		r94 += txpower;
7668c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 94, r94);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
7698c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
7708c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
7718c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
7748c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
7758c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
7768c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
7798c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
7808c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
7818c2ecf20Sopenharmony_ci	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	udelay(10);
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
7878c2ecf20Sopenharmony_ci				   const int txpower)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	struct rf_channel rf;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	rf.rf1 = rt2x00_rf_read(rt2x00dev, 1);
7928c2ecf20Sopenharmony_ci	rf.rf2 = rt2x00_rf_read(rt2x00dev, 2);
7938c2ecf20Sopenharmony_ci	rf.rf3 = rt2x00_rf_read(rt2x00dev, 3);
7948c2ecf20Sopenharmony_ci	rf.rf4 = rt2x00_rf_read(rt2x00dev, 4);
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	rt73usb_config_channel(rt2x00dev, &rf, txpower);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_cistatic void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
8008c2ecf20Sopenharmony_ci				       struct rt2x00lib_conf *libconf)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	u32 reg;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
8058c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
8068c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
8078c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
8088c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
8098c2ecf20Sopenharmony_ci			   libconf->conf->long_frame_max_tx_count);
8108c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
8118c2ecf20Sopenharmony_ci			   libconf->conf->short_frame_max_tx_count);
8128c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
8138c2ecf20Sopenharmony_ci}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_cistatic void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
8168c2ecf20Sopenharmony_ci				struct rt2x00lib_conf *libconf)
8178c2ecf20Sopenharmony_ci{
8188c2ecf20Sopenharmony_ci	enum dev_state state =
8198c2ecf20Sopenharmony_ci	    (libconf->conf->flags & IEEE80211_CONF_PS) ?
8208c2ecf20Sopenharmony_ci		STATE_SLEEP : STATE_AWAKE;
8218c2ecf20Sopenharmony_ci	u32 reg;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	if (state == STATE_SLEEP) {
8248c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
8258c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
8268c2ecf20Sopenharmony_ci				   rt2x00dev->beacon_int - 10);
8278c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
8288c2ecf20Sopenharmony_ci				   libconf->conf->listen_interval - 1);
8298c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci		/* We must first disable autowake before it can be enabled */
8328c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
8338c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
8368c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci		rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
8398c2ecf20Sopenharmony_ci					    USB_MODE_SLEEP, REGISTER_TIMEOUT);
8408c2ecf20Sopenharmony_ci	} else {
8418c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
8428c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
8438c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
8448c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
8458c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
8468c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
8498c2ecf20Sopenharmony_ci					    USB_MODE_WAKEUP, REGISTER_TIMEOUT);
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_cistatic void rt73usb_config(struct rt2x00_dev *rt2x00dev,
8548c2ecf20Sopenharmony_ci			   struct rt2x00lib_conf *libconf,
8558c2ecf20Sopenharmony_ci			   const unsigned int flags)
8568c2ecf20Sopenharmony_ci{
8578c2ecf20Sopenharmony_ci	/* Always recalculate LNA gain before changing configuration */
8588c2ecf20Sopenharmony_ci	rt73usb_config_lna_gain(rt2x00dev, libconf);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
8618c2ecf20Sopenharmony_ci		rt73usb_config_channel(rt2x00dev, &libconf->rf,
8628c2ecf20Sopenharmony_ci				       libconf->conf->power_level);
8638c2ecf20Sopenharmony_ci	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
8648c2ecf20Sopenharmony_ci	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
8658c2ecf20Sopenharmony_ci		rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
8668c2ecf20Sopenharmony_ci	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
8678c2ecf20Sopenharmony_ci		rt73usb_config_retry_limit(rt2x00dev, libconf);
8688c2ecf20Sopenharmony_ci	if (flags & IEEE80211_CONF_CHANGE_PS)
8698c2ecf20Sopenharmony_ci		rt73usb_config_ps(rt2x00dev, libconf);
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci/*
8738c2ecf20Sopenharmony_ci * Link tuning
8748c2ecf20Sopenharmony_ci */
8758c2ecf20Sopenharmony_cistatic void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
8768c2ecf20Sopenharmony_ci			       struct link_qual *qual)
8778c2ecf20Sopenharmony_ci{
8788c2ecf20Sopenharmony_ci	u32 reg;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	/*
8818c2ecf20Sopenharmony_ci	 * Update FCS error count from register.
8828c2ecf20Sopenharmony_ci	 */
8838c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
8848c2ecf20Sopenharmony_ci	qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	/*
8878c2ecf20Sopenharmony_ci	 * Update False CCA count from register.
8888c2ecf20Sopenharmony_ci	 */
8898c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
8908c2ecf20Sopenharmony_ci	qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
8918c2ecf20Sopenharmony_ci}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_cistatic inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev,
8948c2ecf20Sopenharmony_ci				   struct link_qual *qual, u8 vgc_level)
8958c2ecf20Sopenharmony_ci{
8968c2ecf20Sopenharmony_ci	if (qual->vgc_level != vgc_level) {
8978c2ecf20Sopenharmony_ci		rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
8988c2ecf20Sopenharmony_ci		qual->vgc_level = vgc_level;
8998c2ecf20Sopenharmony_ci		qual->vgc_level_reg = vgc_level;
9008c2ecf20Sopenharmony_ci	}
9018c2ecf20Sopenharmony_ci}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_cistatic void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
9048c2ecf20Sopenharmony_ci				struct link_qual *qual)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	rt73usb_set_vgc(rt2x00dev, qual, 0x20);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
9108c2ecf20Sopenharmony_ci			       struct link_qual *qual, const u32 count)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci	u8 up_bound;
9138c2ecf20Sopenharmony_ci	u8 low_bound;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	/*
9168c2ecf20Sopenharmony_ci	 * Determine r17 bounds.
9178c2ecf20Sopenharmony_ci	 */
9188c2ecf20Sopenharmony_ci	if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
9198c2ecf20Sopenharmony_ci		low_bound = 0x28;
9208c2ecf20Sopenharmony_ci		up_bound = 0x48;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
9238c2ecf20Sopenharmony_ci			low_bound += 0x10;
9248c2ecf20Sopenharmony_ci			up_bound += 0x10;
9258c2ecf20Sopenharmony_ci		}
9268c2ecf20Sopenharmony_ci	} else {
9278c2ecf20Sopenharmony_ci		if (qual->rssi > -82) {
9288c2ecf20Sopenharmony_ci			low_bound = 0x1c;
9298c2ecf20Sopenharmony_ci			up_bound = 0x40;
9308c2ecf20Sopenharmony_ci		} else if (qual->rssi > -84) {
9318c2ecf20Sopenharmony_ci			low_bound = 0x1c;
9328c2ecf20Sopenharmony_ci			up_bound = 0x20;
9338c2ecf20Sopenharmony_ci		} else {
9348c2ecf20Sopenharmony_ci			low_bound = 0x1c;
9358c2ecf20Sopenharmony_ci			up_bound = 0x1c;
9368c2ecf20Sopenharmony_ci		}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
9398c2ecf20Sopenharmony_ci			low_bound += 0x14;
9408c2ecf20Sopenharmony_ci			up_bound += 0x10;
9418c2ecf20Sopenharmony_ci		}
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	/*
9458c2ecf20Sopenharmony_ci	 * If we are not associated, we should go straight to the
9468c2ecf20Sopenharmony_ci	 * dynamic CCA tuning.
9478c2ecf20Sopenharmony_ci	 */
9488c2ecf20Sopenharmony_ci	if (!rt2x00dev->intf_associated)
9498c2ecf20Sopenharmony_ci		goto dynamic_cca_tune;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	/*
9528c2ecf20Sopenharmony_ci	 * Special big-R17 for very short distance
9538c2ecf20Sopenharmony_ci	 */
9548c2ecf20Sopenharmony_ci	if (qual->rssi > -35) {
9558c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual, 0x60);
9568c2ecf20Sopenharmony_ci		return;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	/*
9608c2ecf20Sopenharmony_ci	 * Special big-R17 for short distance
9618c2ecf20Sopenharmony_ci	 */
9628c2ecf20Sopenharmony_ci	if (qual->rssi >= -58) {
9638c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual, up_bound);
9648c2ecf20Sopenharmony_ci		return;
9658c2ecf20Sopenharmony_ci	}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	/*
9688c2ecf20Sopenharmony_ci	 * Special big-R17 for middle-short distance
9698c2ecf20Sopenharmony_ci	 */
9708c2ecf20Sopenharmony_ci	if (qual->rssi >= -66) {
9718c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
9728c2ecf20Sopenharmony_ci		return;
9738c2ecf20Sopenharmony_ci	}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	/*
9768c2ecf20Sopenharmony_ci	 * Special mid-R17 for middle distance
9778c2ecf20Sopenharmony_ci	 */
9788c2ecf20Sopenharmony_ci	if (qual->rssi >= -74) {
9798c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
9808c2ecf20Sopenharmony_ci		return;
9818c2ecf20Sopenharmony_ci	}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	/*
9848c2ecf20Sopenharmony_ci	 * Special case: Change up_bound based on the rssi.
9858c2ecf20Sopenharmony_ci	 * Lower up_bound when rssi is weaker then -74 dBm.
9868c2ecf20Sopenharmony_ci	 */
9878c2ecf20Sopenharmony_ci	up_bound -= 2 * (-74 - qual->rssi);
9888c2ecf20Sopenharmony_ci	if (low_bound > up_bound)
9898c2ecf20Sopenharmony_ci		up_bound = low_bound;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	if (qual->vgc_level > up_bound) {
9928c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual, up_bound);
9938c2ecf20Sopenharmony_ci		return;
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_cidynamic_cca_tune:
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	/*
9998c2ecf20Sopenharmony_ci	 * r17 does not yet exceed upper limit, continue and base
10008c2ecf20Sopenharmony_ci	 * the r17 tuning on the false CCA count.
10018c2ecf20Sopenharmony_ci	 */
10028c2ecf20Sopenharmony_ci	if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
10038c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual,
10048c2ecf20Sopenharmony_ci				min_t(u8, qual->vgc_level + 4, up_bound));
10058c2ecf20Sopenharmony_ci	else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
10068c2ecf20Sopenharmony_ci		rt73usb_set_vgc(rt2x00dev, qual,
10078c2ecf20Sopenharmony_ci				max_t(u8, qual->vgc_level - 4, low_bound));
10088c2ecf20Sopenharmony_ci}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci/*
10118c2ecf20Sopenharmony_ci * Queue handlers.
10128c2ecf20Sopenharmony_ci */
10138c2ecf20Sopenharmony_cistatic void rt73usb_start_queue(struct data_queue *queue)
10148c2ecf20Sopenharmony_ci{
10158c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
10168c2ecf20Sopenharmony_ci	u32 reg;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	switch (queue->qid) {
10198c2ecf20Sopenharmony_ci	case QID_RX:
10208c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
10218c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
10228c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
10238c2ecf20Sopenharmony_ci		break;
10248c2ecf20Sopenharmony_ci	case QID_BEACON:
10258c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
10268c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
10278c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
10288c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
10298c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
10308c2ecf20Sopenharmony_ci		break;
10318c2ecf20Sopenharmony_ci	default:
10328c2ecf20Sopenharmony_ci		break;
10338c2ecf20Sopenharmony_ci	}
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_cistatic void rt73usb_stop_queue(struct data_queue *queue)
10378c2ecf20Sopenharmony_ci{
10388c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
10398c2ecf20Sopenharmony_ci	u32 reg;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	switch (queue->qid) {
10428c2ecf20Sopenharmony_ci	case QID_RX:
10438c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
10448c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
10458c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
10468c2ecf20Sopenharmony_ci		break;
10478c2ecf20Sopenharmony_ci	case QID_BEACON:
10488c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
10498c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
10508c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
10518c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
10528c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
10538c2ecf20Sopenharmony_ci		break;
10548c2ecf20Sopenharmony_ci	default:
10558c2ecf20Sopenharmony_ci		break;
10568c2ecf20Sopenharmony_ci	}
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci/*
10608c2ecf20Sopenharmony_ci * Firmware functions
10618c2ecf20Sopenharmony_ci */
10628c2ecf20Sopenharmony_cistatic char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	return FIRMWARE_RT2571;
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev,
10688c2ecf20Sopenharmony_ci				  const u8 *data, const size_t len)
10698c2ecf20Sopenharmony_ci{
10708c2ecf20Sopenharmony_ci	u16 fw_crc;
10718c2ecf20Sopenharmony_ci	u16 crc;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	/*
10748c2ecf20Sopenharmony_ci	 * Only support 2kb firmware files.
10758c2ecf20Sopenharmony_ci	 */
10768c2ecf20Sopenharmony_ci	if (len != 2048)
10778c2ecf20Sopenharmony_ci		return FW_BAD_LENGTH;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	/*
10808c2ecf20Sopenharmony_ci	 * The last 2 bytes in the firmware array are the crc checksum itself,
10818c2ecf20Sopenharmony_ci	 * this means that we should never pass those 2 bytes to the crc
10828c2ecf20Sopenharmony_ci	 * algorithm.
10838c2ecf20Sopenharmony_ci	 */
10848c2ecf20Sopenharmony_ci	fw_crc = (data[len - 2] << 8 | data[len - 1]);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	/*
10878c2ecf20Sopenharmony_ci	 * Use the crc itu-t algorithm.
10888c2ecf20Sopenharmony_ci	 */
10898c2ecf20Sopenharmony_ci	crc = crc_itu_t(0, data, len - 2);
10908c2ecf20Sopenharmony_ci	crc = crc_itu_t_byte(crc, 0);
10918c2ecf20Sopenharmony_ci	crc = crc_itu_t_byte(crc, 0);
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
10948c2ecf20Sopenharmony_ci}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_cistatic int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
10978c2ecf20Sopenharmony_ci				 const u8 *data, const size_t len)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	unsigned int i;
11008c2ecf20Sopenharmony_ci	int status;
11018c2ecf20Sopenharmony_ci	u32 reg;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	/*
11048c2ecf20Sopenharmony_ci	 * Wait for stable hardware.
11058c2ecf20Sopenharmony_ci	 */
11068c2ecf20Sopenharmony_ci	for (i = 0; i < 100; i++) {
11078c2ecf20Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
11088c2ecf20Sopenharmony_ci		if (reg)
11098c2ecf20Sopenharmony_ci			break;
11108c2ecf20Sopenharmony_ci		msleep(1);
11118c2ecf20Sopenharmony_ci	}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	if (!reg) {
11148c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Unstable hardware\n");
11158c2ecf20Sopenharmony_ci		return -EBUSY;
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	/*
11198c2ecf20Sopenharmony_ci	 * Write firmware to device.
11208c2ecf20Sopenharmony_ci	 */
11218c2ecf20Sopenharmony_ci	rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	/*
11248c2ecf20Sopenharmony_ci	 * Send firmware request to device to load firmware,
11258c2ecf20Sopenharmony_ci	 * we need to specify a long timeout time.
11268c2ecf20Sopenharmony_ci	 */
11278c2ecf20Sopenharmony_ci	status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
11288c2ecf20Sopenharmony_ci					     0, USB_MODE_FIRMWARE,
11298c2ecf20Sopenharmony_ci					     REGISTER_TIMEOUT_FIRMWARE);
11308c2ecf20Sopenharmony_ci	if (status < 0) {
11318c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
11328c2ecf20Sopenharmony_ci		return status;
11338c2ecf20Sopenharmony_ci	}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	return 0;
11368c2ecf20Sopenharmony_ci}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci/*
11398c2ecf20Sopenharmony_ci * Initialization functions.
11408c2ecf20Sopenharmony_ci */
11418c2ecf20Sopenharmony_cistatic int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
11428c2ecf20Sopenharmony_ci{
11438c2ecf20Sopenharmony_ci	u32 reg;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
11468c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
11478c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
11488c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
11498c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR1);
11528c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
11538c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
11548c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
11558c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1_VALID, 1);
11568c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */
11578c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
11588c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
11598c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
11608c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	/*
11638c2ecf20Sopenharmony_ci	 * CCK TXD BBP registers
11648c2ecf20Sopenharmony_ci	 */
11658c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR2);
11668c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
11678c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
11688c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
11698c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1_VALID, 1);
11708c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2, 11);
11718c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
11728c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
11738c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
11748c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	/*
11778c2ecf20Sopenharmony_ci	 * OFDM TXD BBP registers
11788c2ecf20Sopenharmony_ci	 */
11798c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR3);
11808c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
11818c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
11828c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
11838c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
11848c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
11858c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
11868c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR7);
11898c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
11908c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
11918c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
11928c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
11938c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR8);
11968c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
11978c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
11988c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
11998c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
12008c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
12038c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
12048c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
12058c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
12068c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
12078c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
12088c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
12098c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR6);
12148c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
12158c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
12208c2ecf20Sopenharmony_ci		return -EBUSY;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	/*
12258c2ecf20Sopenharmony_ci	 * Invalidate all Shared Keys (SEC_CSR0),
12268c2ecf20Sopenharmony_ci	 * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
12278c2ecf20Sopenharmony_ci	 */
12288c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
12298c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
12308c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	reg = 0x000023b0;
12338c2ecf20Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
12348c2ecf20Sopenharmony_ci		rt2x00_set_field32(&reg, PHY_CSR1_RF_RPI, 1);
12358c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
12388c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
12398c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
12428c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
12438c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	/*
12468c2ecf20Sopenharmony_ci	 * Clear all beacons
12478c2ecf20Sopenharmony_ci	 * For the Beacon base registers we only need to clear
12488c2ecf20Sopenharmony_ci	 * the first byte since that byte contains the VALID and OWNER
12498c2ecf20Sopenharmony_ci	 * bits which (when set to 0) will invalidate the entire beacon.
12508c2ecf20Sopenharmony_ci	 */
12518c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
12528c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
12538c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
12548c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	/*
12578c2ecf20Sopenharmony_ci	 * We must clear the error counters.
12588c2ecf20Sopenharmony_ci	 * These registers are cleared on read,
12598c2ecf20Sopenharmony_ci	 * so we may pass a useless variable to store the value.
12608c2ecf20Sopenharmony_ci	 */
12618c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
12628c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
12638c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, STA_CSR2);
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	/*
12668c2ecf20Sopenharmony_ci	 * Reset MAC and BBP registers.
12678c2ecf20Sopenharmony_ci	 */
12688c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
12698c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
12708c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
12718c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
12748c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
12758c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
12768c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
12798c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
12808c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	return 0;
12838c2ecf20Sopenharmony_ci}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_cistatic int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
12868c2ecf20Sopenharmony_ci{
12878c2ecf20Sopenharmony_ci	unsigned int i;
12888c2ecf20Sopenharmony_ci	u8 value;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
12918c2ecf20Sopenharmony_ci		value = rt73usb_bbp_read(rt2x00dev, 0);
12928c2ecf20Sopenharmony_ci		if ((value != 0xff) && (value != 0x00))
12938c2ecf20Sopenharmony_ci			return 0;
12948c2ecf20Sopenharmony_ci		udelay(REGISTER_BUSY_DELAY);
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
12988c2ecf20Sopenharmony_ci	return -EACCES;
12998c2ecf20Sopenharmony_ci}
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_cistatic int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
13028c2ecf20Sopenharmony_ci{
13038c2ecf20Sopenharmony_ci	unsigned int i;
13048c2ecf20Sopenharmony_ci	u16 eeprom;
13058c2ecf20Sopenharmony_ci	u8 reg_id;
13068c2ecf20Sopenharmony_ci	u8 value;
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev)))
13098c2ecf20Sopenharmony_ci		return -EACCES;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 3, 0x80);
13128c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 15, 0x30);
13138c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
13148c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 22, 0x38);
13158c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 23, 0x06);
13168c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 24, 0xfe);
13178c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 25, 0x0a);
13188c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 26, 0x0d);
13198c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 32, 0x0b);
13208c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 34, 0x12);
13218c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 37, 0x07);
13228c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 39, 0xf8);
13238c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 41, 0x60);
13248c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 53, 0x10);
13258c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 54, 0x18);
13268c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 60, 0x10);
13278c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 61, 0x04);
13288c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 62, 0x04);
13298c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 75, 0xfe);
13308c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 86, 0xfe);
13318c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 88, 0xfe);
13328c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 90, 0x0f);
13338c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 99, 0x00);
13348c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 102, 0x16);
13358c2ecf20Sopenharmony_ci	rt73usb_bbp_write(rt2x00dev, 107, 0x04);
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
13388c2ecf20Sopenharmony_ci		eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci		if (eeprom != 0xffff && eeprom != 0x0000) {
13418c2ecf20Sopenharmony_ci			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
13428c2ecf20Sopenharmony_ci			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
13438c2ecf20Sopenharmony_ci			rt73usb_bbp_write(rt2x00dev, reg_id, value);
13448c2ecf20Sopenharmony_ci		}
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	return 0;
13488c2ecf20Sopenharmony_ci}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci/*
13518c2ecf20Sopenharmony_ci * Device state switch handlers.
13528c2ecf20Sopenharmony_ci */
13538c2ecf20Sopenharmony_cistatic int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
13548c2ecf20Sopenharmony_ci{
13558c2ecf20Sopenharmony_ci	/*
13568c2ecf20Sopenharmony_ci	 * Initialize all registers.
13578c2ecf20Sopenharmony_ci	 */
13588c2ecf20Sopenharmony_ci	if (unlikely(rt73usb_init_registers(rt2x00dev) ||
13598c2ecf20Sopenharmony_ci		     rt73usb_init_bbp(rt2x00dev)))
13608c2ecf20Sopenharmony_ci		return -EIO;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	return 0;
13638c2ecf20Sopenharmony_ci}
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_cistatic void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
13668c2ecf20Sopenharmony_ci{
13678c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	/*
13708c2ecf20Sopenharmony_ci	 * Disable synchronisation.
13718c2ecf20Sopenharmony_ci	 */
13728c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	rt2x00usb_disable_radio(rt2x00dev);
13758c2ecf20Sopenharmony_ci}
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_cistatic int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
13788c2ecf20Sopenharmony_ci{
13798c2ecf20Sopenharmony_ci	u32 reg, reg2;
13808c2ecf20Sopenharmony_ci	unsigned int i;
13818c2ecf20Sopenharmony_ci	char put_to_sleep;
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	put_to_sleep = (state != STATE_AWAKE);
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
13868c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
13878c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
13888c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	/*
13918c2ecf20Sopenharmony_ci	 * Device is not guaranteed to be in the requested state yet.
13928c2ecf20Sopenharmony_ci	 * We must wait until the register indicates that the
13938c2ecf20Sopenharmony_ci	 * device has entered the correct state.
13948c2ecf20Sopenharmony_ci	 */
13958c2ecf20Sopenharmony_ci	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
13968c2ecf20Sopenharmony_ci		reg2 = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
13978c2ecf20Sopenharmony_ci		state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
13988c2ecf20Sopenharmony_ci		if (state == !put_to_sleep)
13998c2ecf20Sopenharmony_ci			return 0;
14008c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
14018c2ecf20Sopenharmony_ci		msleep(10);
14028c2ecf20Sopenharmony_ci	}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	return -EBUSY;
14058c2ecf20Sopenharmony_ci}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_cistatic int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
14088c2ecf20Sopenharmony_ci				    enum dev_state state)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	int retval = 0;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	switch (state) {
14138c2ecf20Sopenharmony_ci	case STATE_RADIO_ON:
14148c2ecf20Sopenharmony_ci		retval = rt73usb_enable_radio(rt2x00dev);
14158c2ecf20Sopenharmony_ci		break;
14168c2ecf20Sopenharmony_ci	case STATE_RADIO_OFF:
14178c2ecf20Sopenharmony_ci		rt73usb_disable_radio(rt2x00dev);
14188c2ecf20Sopenharmony_ci		break;
14198c2ecf20Sopenharmony_ci	case STATE_RADIO_IRQ_ON:
14208c2ecf20Sopenharmony_ci	case STATE_RADIO_IRQ_OFF:
14218c2ecf20Sopenharmony_ci		/* No support, but no error either */
14228c2ecf20Sopenharmony_ci		break;
14238c2ecf20Sopenharmony_ci	case STATE_DEEP_SLEEP:
14248c2ecf20Sopenharmony_ci	case STATE_SLEEP:
14258c2ecf20Sopenharmony_ci	case STATE_STANDBY:
14268c2ecf20Sopenharmony_ci	case STATE_AWAKE:
14278c2ecf20Sopenharmony_ci		retval = rt73usb_set_state(rt2x00dev, state);
14288c2ecf20Sopenharmony_ci		break;
14298c2ecf20Sopenharmony_ci	default:
14308c2ecf20Sopenharmony_ci		retval = -ENOTSUPP;
14318c2ecf20Sopenharmony_ci		break;
14328c2ecf20Sopenharmony_ci	}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	if (unlikely(retval))
14358c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
14368c2ecf20Sopenharmony_ci			   state, retval);
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	return retval;
14398c2ecf20Sopenharmony_ci}
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci/*
14428c2ecf20Sopenharmony_ci * TX descriptor initialization
14438c2ecf20Sopenharmony_ci */
14448c2ecf20Sopenharmony_cistatic void rt73usb_write_tx_desc(struct queue_entry *entry,
14458c2ecf20Sopenharmony_ci				  struct txentry_desc *txdesc)
14468c2ecf20Sopenharmony_ci{
14478c2ecf20Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
14488c2ecf20Sopenharmony_ci	__le32 *txd = (__le32 *) entry->skb->data;
14498c2ecf20Sopenharmony_ci	u32 word;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci	/*
14528c2ecf20Sopenharmony_ci	 * Start writing the descriptor words.
14538c2ecf20Sopenharmony_ci	 */
14548c2ecf20Sopenharmony_ci	word = rt2x00_desc_read(txd, 0);
14558c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_BURST,
14568c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
14578c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
14588c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
14598c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
14608c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_ACK,
14618c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
14628c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
14638c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
14648c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_OFDM,
14658c2ecf20Sopenharmony_ci			   (txdesc->rate_mode == RATE_MODE_OFDM));
14668c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
14678c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
14688c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
14698c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
14708c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
14718c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
14728c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
14738c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
14748c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
14758c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_BURST2,
14768c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
14778c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
14788c2ecf20Sopenharmony_ci	rt2x00_desc_write(txd, 0, word);
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	word = rt2x00_desc_read(txd, 1);
14818c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
14828c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
14838c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
14848c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
14858c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
14868c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
14878c2ecf20Sopenharmony_ci			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
14888c2ecf20Sopenharmony_ci	rt2x00_desc_write(txd, 1, word);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	word = rt2x00_desc_read(txd, 2);
14918c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
14928c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
14938c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
14948c2ecf20Sopenharmony_ci			   txdesc->u.plcp.length_low);
14958c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
14968c2ecf20Sopenharmony_ci			   txdesc->u.plcp.length_high);
14978c2ecf20Sopenharmony_ci	rt2x00_desc_write(txd, 2, word);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
15008c2ecf20Sopenharmony_ci		_rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
15018c2ecf20Sopenharmony_ci		_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
15028c2ecf20Sopenharmony_ci	}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	word = rt2x00_desc_read(txd, 5);
15058c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
15068c2ecf20Sopenharmony_ci			   TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
15078c2ecf20Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
15088c2ecf20Sopenharmony_ci	rt2x00_desc_write(txd, 5, word);
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	/*
15118c2ecf20Sopenharmony_ci	 * Register descriptor details in skb frame descriptor.
15128c2ecf20Sopenharmony_ci	 */
15138c2ecf20Sopenharmony_ci	skbdesc->flags |= SKBDESC_DESC_IN_SKB;
15148c2ecf20Sopenharmony_ci	skbdesc->desc = txd;
15158c2ecf20Sopenharmony_ci	skbdesc->desc_len = TXD_DESC_SIZE;
15168c2ecf20Sopenharmony_ci}
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci/*
15198c2ecf20Sopenharmony_ci * TX data initialization
15208c2ecf20Sopenharmony_ci */
15218c2ecf20Sopenharmony_cistatic void rt73usb_write_beacon(struct queue_entry *entry,
15228c2ecf20Sopenharmony_ci				 struct txentry_desc *txdesc)
15238c2ecf20Sopenharmony_ci{
15248c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
15258c2ecf20Sopenharmony_ci	unsigned int beacon_base;
15268c2ecf20Sopenharmony_ci	unsigned int padding_len;
15278c2ecf20Sopenharmony_ci	u32 orig_reg, reg;
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	/*
15308c2ecf20Sopenharmony_ci	 * Disable beaconing while we are reloading the beacon data,
15318c2ecf20Sopenharmony_ci	 * otherwise we might be sending out invalid data.
15328c2ecf20Sopenharmony_ci	 */
15338c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
15348c2ecf20Sopenharmony_ci	orig_reg = reg;
15358c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
15368c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	/*
15398c2ecf20Sopenharmony_ci	 * Add space for the descriptor in front of the skb.
15408c2ecf20Sopenharmony_ci	 */
15418c2ecf20Sopenharmony_ci	skb_push(entry->skb, TXD_DESC_SIZE);
15428c2ecf20Sopenharmony_ci	memset(entry->skb->data, 0, TXD_DESC_SIZE);
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	/*
15458c2ecf20Sopenharmony_ci	 * Write the TX descriptor for the beacon.
15468c2ecf20Sopenharmony_ci	 */
15478c2ecf20Sopenharmony_ci	rt73usb_write_tx_desc(entry, txdesc);
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	/*
15508c2ecf20Sopenharmony_ci	 * Dump beacon to userspace through debugfs.
15518c2ecf20Sopenharmony_ci	 */
15528c2ecf20Sopenharmony_ci	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/*
15558c2ecf20Sopenharmony_ci	 * Write entire beacon with descriptor and padding to register.
15568c2ecf20Sopenharmony_ci	 */
15578c2ecf20Sopenharmony_ci	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
15588c2ecf20Sopenharmony_ci	if (padding_len && skb_pad(entry->skb, padding_len)) {
15598c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
15608c2ecf20Sopenharmony_ci		/* skb freed by skb_pad() on failure */
15618c2ecf20Sopenharmony_ci		entry->skb = NULL;
15628c2ecf20Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
15638c2ecf20Sopenharmony_ci		return;
15648c2ecf20Sopenharmony_ci	}
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
15678c2ecf20Sopenharmony_ci	rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
15688c2ecf20Sopenharmony_ci				      entry->skb->len + padding_len);
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	/*
15718c2ecf20Sopenharmony_ci	 * Enable beaconing again.
15728c2ecf20Sopenharmony_ci	 *
15738c2ecf20Sopenharmony_ci	 * For Wi-Fi faily generated beacons between participating stations.
15748c2ecf20Sopenharmony_ci	 * Set TBTT phase adaptive adjustment step to 8us (default 16us)
15758c2ecf20Sopenharmony_ci	 */
15768c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
15798c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	/*
15828c2ecf20Sopenharmony_ci	 * Clean up the beacon skb.
15838c2ecf20Sopenharmony_ci	 */
15848c2ecf20Sopenharmony_ci	dev_kfree_skb(entry->skb);
15858c2ecf20Sopenharmony_ci	entry->skb = NULL;
15868c2ecf20Sopenharmony_ci}
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_cistatic void rt73usb_clear_beacon(struct queue_entry *entry)
15898c2ecf20Sopenharmony_ci{
15908c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
15918c2ecf20Sopenharmony_ci	unsigned int beacon_base;
15928c2ecf20Sopenharmony_ci	u32 orig_reg, reg;
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	/*
15958c2ecf20Sopenharmony_ci	 * Disable beaconing while we are reloading the beacon data,
15968c2ecf20Sopenharmony_ci	 * otherwise we might be sending out invalid data.
15978c2ecf20Sopenharmony_ci	 */
15988c2ecf20Sopenharmony_ci	orig_reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
15998c2ecf20Sopenharmony_ci	reg = orig_reg;
16008c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
16018c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	/*
16048c2ecf20Sopenharmony_ci	 * Clear beacon.
16058c2ecf20Sopenharmony_ci	 */
16068c2ecf20Sopenharmony_ci	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
16078c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	/*
16108c2ecf20Sopenharmony_ci	 * Restore beaconing state.
16118c2ecf20Sopenharmony_ci	 */
16128c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
16138c2ecf20Sopenharmony_ci}
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_cistatic int rt73usb_get_tx_data_len(struct queue_entry *entry)
16168c2ecf20Sopenharmony_ci{
16178c2ecf20Sopenharmony_ci	int length;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	/*
16208c2ecf20Sopenharmony_ci	 * The length _must_ be a multiple of 4,
16218c2ecf20Sopenharmony_ci	 * but it must _not_ be a multiple of the USB packet size.
16228c2ecf20Sopenharmony_ci	 */
16238c2ecf20Sopenharmony_ci	length = roundup(entry->skb->len, 4);
16248c2ecf20Sopenharmony_ci	length += (4 * !(length % entry->queue->usb_maxpacket));
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	return length;
16278c2ecf20Sopenharmony_ci}
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci/*
16308c2ecf20Sopenharmony_ci * RX control handlers
16318c2ecf20Sopenharmony_ci */
16328c2ecf20Sopenharmony_cistatic int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
16338c2ecf20Sopenharmony_ci{
16348c2ecf20Sopenharmony_ci	u8 offset = rt2x00dev->lna_gain;
16358c2ecf20Sopenharmony_ci	u8 lna;
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
16388c2ecf20Sopenharmony_ci	switch (lna) {
16398c2ecf20Sopenharmony_ci	case 3:
16408c2ecf20Sopenharmony_ci		offset += 90;
16418c2ecf20Sopenharmony_ci		break;
16428c2ecf20Sopenharmony_ci	case 2:
16438c2ecf20Sopenharmony_ci		offset += 74;
16448c2ecf20Sopenharmony_ci		break;
16458c2ecf20Sopenharmony_ci	case 1:
16468c2ecf20Sopenharmony_ci		offset += 64;
16478c2ecf20Sopenharmony_ci		break;
16488c2ecf20Sopenharmony_ci	default:
16498c2ecf20Sopenharmony_ci		return 0;
16508c2ecf20Sopenharmony_ci	}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
16538c2ecf20Sopenharmony_ci		if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
16548c2ecf20Sopenharmony_ci			if (lna == 3 || lna == 2)
16558c2ecf20Sopenharmony_ci				offset += 10;
16568c2ecf20Sopenharmony_ci		} else {
16578c2ecf20Sopenharmony_ci			if (lna == 3)
16588c2ecf20Sopenharmony_ci				offset += 6;
16598c2ecf20Sopenharmony_ci			else if (lna == 2)
16608c2ecf20Sopenharmony_ci				offset += 8;
16618c2ecf20Sopenharmony_ci		}
16628c2ecf20Sopenharmony_ci	}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
16658c2ecf20Sopenharmony_ci}
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_cistatic void rt73usb_fill_rxdone(struct queue_entry *entry,
16688c2ecf20Sopenharmony_ci				struct rxdone_entry_desc *rxdesc)
16698c2ecf20Sopenharmony_ci{
16708c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
16718c2ecf20Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
16728c2ecf20Sopenharmony_ci	__le32 *rxd = (__le32 *)entry->skb->data;
16738c2ecf20Sopenharmony_ci	u32 word0;
16748c2ecf20Sopenharmony_ci	u32 word1;
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	/*
16778c2ecf20Sopenharmony_ci	 * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
16788c2ecf20Sopenharmony_ci	 * frame data in rt2x00usb.
16798c2ecf20Sopenharmony_ci	 */
16808c2ecf20Sopenharmony_ci	memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
16818c2ecf20Sopenharmony_ci	rxd = (__le32 *)skbdesc->desc;
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	/*
16848c2ecf20Sopenharmony_ci	 * It is now safe to read the descriptor on all architectures.
16858c2ecf20Sopenharmony_ci	 */
16868c2ecf20Sopenharmony_ci	word0 = rt2x00_desc_read(rxd, 0);
16878c2ecf20Sopenharmony_ci	word1 = rt2x00_desc_read(rxd, 1);
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
16908c2ecf20Sopenharmony_ci		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
16938c2ecf20Sopenharmony_ci	rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	if (rxdesc->cipher != CIPHER_NONE) {
16968c2ecf20Sopenharmony_ci		rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
16978c2ecf20Sopenharmony_ci		rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
16988c2ecf20Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci		rxdesc->icv = _rt2x00_desc_read(rxd, 4);
17018c2ecf20Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci		/*
17048c2ecf20Sopenharmony_ci		 * Hardware has stripped IV/EIV data from 802.11 frame during
17058c2ecf20Sopenharmony_ci		 * decryption. It has provided the data separately but rt2x00lib
17068c2ecf20Sopenharmony_ci		 * should decide if it should be reinserted.
17078c2ecf20Sopenharmony_ci		 */
17088c2ecf20Sopenharmony_ci		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci		/*
17118c2ecf20Sopenharmony_ci		 * The hardware has already checked the Michael Mic and has
17128c2ecf20Sopenharmony_ci		 * stripped it from the frame. Signal this to mac80211.
17138c2ecf20Sopenharmony_ci		 */
17148c2ecf20Sopenharmony_ci		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
17178c2ecf20Sopenharmony_ci			rxdesc->flags |= RX_FLAG_DECRYPTED;
17188c2ecf20Sopenharmony_ci		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
17198c2ecf20Sopenharmony_ci			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
17208c2ecf20Sopenharmony_ci	}
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	/*
17238c2ecf20Sopenharmony_ci	 * Obtain the status about this packet.
17248c2ecf20Sopenharmony_ci	 * When frame was received with an OFDM bitrate,
17258c2ecf20Sopenharmony_ci	 * the signal is the PLCP value. If it was received with
17268c2ecf20Sopenharmony_ci	 * a CCK bitrate the signal is the rate in 100kbit/s.
17278c2ecf20Sopenharmony_ci	 */
17288c2ecf20Sopenharmony_ci	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
17298c2ecf20Sopenharmony_ci	rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
17308c2ecf20Sopenharmony_ci	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
17338c2ecf20Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
17348c2ecf20Sopenharmony_ci	else
17358c2ecf20Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
17368c2ecf20Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
17378c2ecf20Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_MY_BSS;
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	/*
17408c2ecf20Sopenharmony_ci	 * Set skb pointers, and update frame information.
17418c2ecf20Sopenharmony_ci	 */
17428c2ecf20Sopenharmony_ci	skb_pull(entry->skb, entry->queue->desc_size);
17438c2ecf20Sopenharmony_ci	skb_trim(entry->skb, rxdesc->size);
17448c2ecf20Sopenharmony_ci}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci/*
17478c2ecf20Sopenharmony_ci * Device probe functions.
17488c2ecf20Sopenharmony_ci */
17498c2ecf20Sopenharmony_cistatic int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
17508c2ecf20Sopenharmony_ci{
17518c2ecf20Sopenharmony_ci	u16 word;
17528c2ecf20Sopenharmony_ci	u8 *mac;
17538c2ecf20Sopenharmony_ci	s8 value;
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	/*
17588c2ecf20Sopenharmony_ci	 * Start validation of the data that has been read.
17598c2ecf20Sopenharmony_ci	 */
17608c2ecf20Sopenharmony_ci	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
17618c2ecf20Sopenharmony_ci	rt2x00lib_set_mac_address(rt2x00dev, mac);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
17648c2ecf20Sopenharmony_ci	if (word == 0xffff) {
17658c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
17668c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
17678c2ecf20Sopenharmony_ci				   ANTENNA_B);
17688c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
17698c2ecf20Sopenharmony_ci				   ANTENNA_B);
17708c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
17718c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
17728c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
17738c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);
17748c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
17758c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
17768c2ecf20Sopenharmony_ci	}
17778c2ecf20Sopenharmony_ci
17788c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
17798c2ecf20Sopenharmony_ci	if (word == 0xffff) {
17808c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
17818c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
17828c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
17868c2ecf20Sopenharmony_ci	if (word == 0xffff) {
17878c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0);
17888c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0);
17898c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_ACT, 0);
17908c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_0, 0);
17918c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_1, 0);
17928c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_2, 0);
17938c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_3, 0);
17948c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_4, 0);
17958c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
17968c2ecf20Sopenharmony_ci				   LED_MODE_DEFAULT);
17978c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
17988c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
17998c2ecf20Sopenharmony_ci	}
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
18028c2ecf20Sopenharmony_ci	if (word == 0xffff) {
18038c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
18048c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
18058c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
18068c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
18078c2ecf20Sopenharmony_ci	}
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
18108c2ecf20Sopenharmony_ci	if (word == 0xffff) {
18118c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
18128c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
18138c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
18148c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
18158c2ecf20Sopenharmony_ci	} else {
18168c2ecf20Sopenharmony_ci		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
18178c2ecf20Sopenharmony_ci		if (value < -10 || value > 10)
18188c2ecf20Sopenharmony_ci			rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
18198c2ecf20Sopenharmony_ci		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
18208c2ecf20Sopenharmony_ci		if (value < -10 || value > 10)
18218c2ecf20Sopenharmony_ci			rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
18228c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
18238c2ecf20Sopenharmony_ci	}
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
18268c2ecf20Sopenharmony_ci	if (word == 0xffff) {
18278c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
18288c2ecf20Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
18298c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
18308c2ecf20Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
18318c2ecf20Sopenharmony_ci	} else {
18328c2ecf20Sopenharmony_ci		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
18338c2ecf20Sopenharmony_ci		if (value < -10 || value > 10)
18348c2ecf20Sopenharmony_ci			rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
18358c2ecf20Sopenharmony_ci		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
18368c2ecf20Sopenharmony_ci		if (value < -10 || value > 10)
18378c2ecf20Sopenharmony_ci			rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
18388c2ecf20Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
18398c2ecf20Sopenharmony_ci	}
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	return 0;
18428c2ecf20Sopenharmony_ci}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_cistatic int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
18458c2ecf20Sopenharmony_ci{
18468c2ecf20Sopenharmony_ci	u32 reg;
18478c2ecf20Sopenharmony_ci	u16 value;
18488c2ecf20Sopenharmony_ci	u16 eeprom;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	/*
18518c2ecf20Sopenharmony_ci	 * Read EEPROM word for configuration.
18528c2ecf20Sopenharmony_ci	 */
18538c2ecf20Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci	/*
18568c2ecf20Sopenharmony_ci	 * Identify RF chipset.
18578c2ecf20Sopenharmony_ci	 */
18588c2ecf20Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
18598c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
18608c2ecf20Sopenharmony_ci	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
18618c2ecf20Sopenharmony_ci			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci	if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
18648c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
18658c2ecf20Sopenharmony_ci		return -ENODEV;
18668c2ecf20Sopenharmony_ci	}
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	if (!rt2x00_rf(rt2x00dev, RF5226) &&
18698c2ecf20Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2528) &&
18708c2ecf20Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF5225) &&
18718c2ecf20Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2527)) {
18728c2ecf20Sopenharmony_ci		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
18738c2ecf20Sopenharmony_ci		return -ENODEV;
18748c2ecf20Sopenharmony_ci	}
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_ci	/*
18778c2ecf20Sopenharmony_ci	 * Identify default antenna configuration.
18788c2ecf20Sopenharmony_ci	 */
18798c2ecf20Sopenharmony_ci	rt2x00dev->default_ant.tx =
18808c2ecf20Sopenharmony_ci	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
18818c2ecf20Sopenharmony_ci	rt2x00dev->default_ant.rx =
18828c2ecf20Sopenharmony_ci	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	/*
18858c2ecf20Sopenharmony_ci	 * Read the Frame type.
18868c2ecf20Sopenharmony_ci	 */
18878c2ecf20Sopenharmony_ci	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
18888c2ecf20Sopenharmony_ci		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	/*
18918c2ecf20Sopenharmony_ci	 * Detect if this device has an hardware controlled radio.
18928c2ecf20Sopenharmony_ci	 */
18938c2ecf20Sopenharmony_ci	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
18948c2ecf20Sopenharmony_ci		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci	/*
18978c2ecf20Sopenharmony_ci	 * Read frequency offset.
18988c2ecf20Sopenharmony_ci	 */
18998c2ecf20Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
19008c2ecf20Sopenharmony_ci	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	/*
19038c2ecf20Sopenharmony_ci	 * Read external LNA informations.
19048c2ecf20Sopenharmony_ci	 */
19058c2ecf20Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
19088c2ecf20Sopenharmony_ci		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
19098c2ecf20Sopenharmony_ci		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
19108c2ecf20Sopenharmony_ci	}
19118c2ecf20Sopenharmony_ci
19128c2ecf20Sopenharmony_ci	/*
19138c2ecf20Sopenharmony_ci	 * Store led settings, for correct led behaviour.
19148c2ecf20Sopenharmony_ci	 */
19158c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS
19168c2ecf20Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci	rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
19198c2ecf20Sopenharmony_ci	rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
19208c2ecf20Sopenharmony_ci	if (value == LED_MODE_SIGNAL_STRENGTH)
19218c2ecf20Sopenharmony_ci		rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
19228c2ecf20Sopenharmony_ci				 LED_TYPE_QUALITY);
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
19258c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
19268c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19278c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_GPIO_0));
19288c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
19298c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19308c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_GPIO_1));
19318c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
19328c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19338c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_GPIO_2));
19348c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
19358c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19368c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_GPIO_3));
19378c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
19388c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19398c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_GPIO_4));
19408c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
19418c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
19428c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
19438c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19448c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_RDY_G));
19458c2ecf20Sopenharmony_ci	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
19468c2ecf20Sopenharmony_ci			   rt2x00_get_field16(eeprom,
19478c2ecf20Sopenharmony_ci					      EEPROM_LED_POLARITY_RDY_A));
19488c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	return 0;
19518c2ecf20Sopenharmony_ci}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci/*
19548c2ecf20Sopenharmony_ci * RF value list for RF2528
19558c2ecf20Sopenharmony_ci * Supports: 2.4 GHz
19568c2ecf20Sopenharmony_ci */
19578c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2528[] = {
19588c2ecf20Sopenharmony_ci	{ 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
19598c2ecf20Sopenharmony_ci	{ 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
19608c2ecf20Sopenharmony_ci	{ 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
19618c2ecf20Sopenharmony_ci	{ 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
19628c2ecf20Sopenharmony_ci	{ 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
19638c2ecf20Sopenharmony_ci	{ 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
19648c2ecf20Sopenharmony_ci	{ 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
19658c2ecf20Sopenharmony_ci	{ 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
19668c2ecf20Sopenharmony_ci	{ 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
19678c2ecf20Sopenharmony_ci	{ 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
19688c2ecf20Sopenharmony_ci	{ 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
19698c2ecf20Sopenharmony_ci	{ 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
19708c2ecf20Sopenharmony_ci	{ 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
19718c2ecf20Sopenharmony_ci	{ 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
19728c2ecf20Sopenharmony_ci};
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci/*
19758c2ecf20Sopenharmony_ci * RF value list for RF5226
19768c2ecf20Sopenharmony_ci * Supports: 2.4 GHz & 5.2 GHz
19778c2ecf20Sopenharmony_ci */
19788c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_5226[] = {
19798c2ecf20Sopenharmony_ci	{ 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
19808c2ecf20Sopenharmony_ci	{ 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
19818c2ecf20Sopenharmony_ci	{ 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
19828c2ecf20Sopenharmony_ci	{ 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
19838c2ecf20Sopenharmony_ci	{ 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
19848c2ecf20Sopenharmony_ci	{ 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
19858c2ecf20Sopenharmony_ci	{ 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
19868c2ecf20Sopenharmony_ci	{ 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
19878c2ecf20Sopenharmony_ci	{ 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
19888c2ecf20Sopenharmony_ci	{ 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
19898c2ecf20Sopenharmony_ci	{ 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
19908c2ecf20Sopenharmony_ci	{ 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
19918c2ecf20Sopenharmony_ci	{ 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
19928c2ecf20Sopenharmony_ci	{ 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci	/* 802.11 UNI / HyperLan 2 */
19958c2ecf20Sopenharmony_ci	{ 36, 0x00002c0c, 0x0000099a, 0x00098255, 0x000fea23 },
19968c2ecf20Sopenharmony_ci	{ 40, 0x00002c0c, 0x000009a2, 0x00098255, 0x000fea03 },
19978c2ecf20Sopenharmony_ci	{ 44, 0x00002c0c, 0x000009a6, 0x00098255, 0x000fea0b },
19988c2ecf20Sopenharmony_ci	{ 48, 0x00002c0c, 0x000009aa, 0x00098255, 0x000fea13 },
19998c2ecf20Sopenharmony_ci	{ 52, 0x00002c0c, 0x000009ae, 0x00098255, 0x000fea1b },
20008c2ecf20Sopenharmony_ci	{ 56, 0x00002c0c, 0x000009b2, 0x00098255, 0x000fea23 },
20018c2ecf20Sopenharmony_ci	{ 60, 0x00002c0c, 0x000009ba, 0x00098255, 0x000fea03 },
20028c2ecf20Sopenharmony_ci	{ 64, 0x00002c0c, 0x000009be, 0x00098255, 0x000fea0b },
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	/* 802.11 HyperLan 2 */
20058c2ecf20Sopenharmony_ci	{ 100, 0x00002c0c, 0x00000a2a, 0x000b8255, 0x000fea03 },
20068c2ecf20Sopenharmony_ci	{ 104, 0x00002c0c, 0x00000a2e, 0x000b8255, 0x000fea0b },
20078c2ecf20Sopenharmony_ci	{ 108, 0x00002c0c, 0x00000a32, 0x000b8255, 0x000fea13 },
20088c2ecf20Sopenharmony_ci	{ 112, 0x00002c0c, 0x00000a36, 0x000b8255, 0x000fea1b },
20098c2ecf20Sopenharmony_ci	{ 116, 0x00002c0c, 0x00000a3a, 0x000b8255, 0x000fea23 },
20108c2ecf20Sopenharmony_ci	{ 120, 0x00002c0c, 0x00000a82, 0x000b8255, 0x000fea03 },
20118c2ecf20Sopenharmony_ci	{ 124, 0x00002c0c, 0x00000a86, 0x000b8255, 0x000fea0b },
20128c2ecf20Sopenharmony_ci	{ 128, 0x00002c0c, 0x00000a8a, 0x000b8255, 0x000fea13 },
20138c2ecf20Sopenharmony_ci	{ 132, 0x00002c0c, 0x00000a8e, 0x000b8255, 0x000fea1b },
20148c2ecf20Sopenharmony_ci	{ 136, 0x00002c0c, 0x00000a92, 0x000b8255, 0x000fea23 },
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	/* 802.11 UNII */
20178c2ecf20Sopenharmony_ci	{ 140, 0x00002c0c, 0x00000a9a, 0x000b8255, 0x000fea03 },
20188c2ecf20Sopenharmony_ci	{ 149, 0x00002c0c, 0x00000aa2, 0x000b8255, 0x000fea1f },
20198c2ecf20Sopenharmony_ci	{ 153, 0x00002c0c, 0x00000aa6, 0x000b8255, 0x000fea27 },
20208c2ecf20Sopenharmony_ci	{ 157, 0x00002c0c, 0x00000aae, 0x000b8255, 0x000fea07 },
20218c2ecf20Sopenharmony_ci	{ 161, 0x00002c0c, 0x00000ab2, 0x000b8255, 0x000fea0f },
20228c2ecf20Sopenharmony_ci	{ 165, 0x00002c0c, 0x00000ab6, 0x000b8255, 0x000fea17 },
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci	/* MMAC(Japan)J52 ch 34,38,42,46 */
20258c2ecf20Sopenharmony_ci	{ 34, 0x00002c0c, 0x0008099a, 0x000da255, 0x000d3a0b },
20268c2ecf20Sopenharmony_ci	{ 38, 0x00002c0c, 0x0008099e, 0x000da255, 0x000d3a13 },
20278c2ecf20Sopenharmony_ci	{ 42, 0x00002c0c, 0x000809a2, 0x000da255, 0x000d3a1b },
20288c2ecf20Sopenharmony_ci	{ 46, 0x00002c0c, 0x000809a6, 0x000da255, 0x000d3a23 },
20298c2ecf20Sopenharmony_ci};
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_ci/*
20328c2ecf20Sopenharmony_ci * RF value list for RF5225 & RF2527
20338c2ecf20Sopenharmony_ci * Supports: 2.4 GHz & 5.2 GHz
20348c2ecf20Sopenharmony_ci */
20358c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_5225_2527[] = {
20368c2ecf20Sopenharmony_ci	{ 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
20378c2ecf20Sopenharmony_ci	{ 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
20388c2ecf20Sopenharmony_ci	{ 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
20398c2ecf20Sopenharmony_ci	{ 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
20408c2ecf20Sopenharmony_ci	{ 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
20418c2ecf20Sopenharmony_ci	{ 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
20428c2ecf20Sopenharmony_ci	{ 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
20438c2ecf20Sopenharmony_ci	{ 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
20448c2ecf20Sopenharmony_ci	{ 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
20458c2ecf20Sopenharmony_ci	{ 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
20468c2ecf20Sopenharmony_ci	{ 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
20478c2ecf20Sopenharmony_ci	{ 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
20488c2ecf20Sopenharmony_ci	{ 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
20498c2ecf20Sopenharmony_ci	{ 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci	/* 802.11 UNI / HyperLan 2 */
20528c2ecf20Sopenharmony_ci	{ 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 },
20538c2ecf20Sopenharmony_ci	{ 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 },
20548c2ecf20Sopenharmony_ci	{ 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b },
20558c2ecf20Sopenharmony_ci	{ 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 },
20568c2ecf20Sopenharmony_ci	{ 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b },
20578c2ecf20Sopenharmony_ci	{ 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 },
20588c2ecf20Sopenharmony_ci	{ 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 },
20598c2ecf20Sopenharmony_ci	{ 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b },
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci	/* 802.11 HyperLan 2 */
20628c2ecf20Sopenharmony_ci	{ 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 },
20638c2ecf20Sopenharmony_ci	{ 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b },
20648c2ecf20Sopenharmony_ci	{ 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 },
20658c2ecf20Sopenharmony_ci	{ 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b },
20668c2ecf20Sopenharmony_ci	{ 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 },
20678c2ecf20Sopenharmony_ci	{ 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 },
20688c2ecf20Sopenharmony_ci	{ 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b },
20698c2ecf20Sopenharmony_ci	{ 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 },
20708c2ecf20Sopenharmony_ci	{ 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b },
20718c2ecf20Sopenharmony_ci	{ 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 },
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	/* 802.11 UNII */
20748c2ecf20Sopenharmony_ci	{ 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 },
20758c2ecf20Sopenharmony_ci	{ 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f },
20768c2ecf20Sopenharmony_ci	{ 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 },
20778c2ecf20Sopenharmony_ci	{ 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 },
20788c2ecf20Sopenharmony_ci	{ 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f },
20798c2ecf20Sopenharmony_ci	{ 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 },
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci	/* MMAC(Japan)J52 ch 34,38,42,46 */
20828c2ecf20Sopenharmony_ci	{ 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b },
20838c2ecf20Sopenharmony_ci	{ 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 },
20848c2ecf20Sopenharmony_ci	{ 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b },
20858c2ecf20Sopenharmony_ci	{ 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 },
20868c2ecf20Sopenharmony_ci};
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_cistatic int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
20908c2ecf20Sopenharmony_ci{
20918c2ecf20Sopenharmony_ci	struct hw_mode_spec *spec = &rt2x00dev->spec;
20928c2ecf20Sopenharmony_ci	struct channel_info *info;
20938c2ecf20Sopenharmony_ci	char *tx_power;
20948c2ecf20Sopenharmony_ci	unsigned int i;
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	/*
20978c2ecf20Sopenharmony_ci	 * Initialize all hw fields.
20988c2ecf20Sopenharmony_ci	 *
20998c2ecf20Sopenharmony_ci	 * Don't set IEEE80211_HOST_BROADCAST_PS_BUFFERING unless we are
21008c2ecf20Sopenharmony_ci	 * capable of sending the buffered frames out after the DTIM
21018c2ecf20Sopenharmony_ci	 * transmission using rt2x00lib_beacondone. This will send out
21028c2ecf20Sopenharmony_ci	 * multicast and broadcast traffic immediately instead of buffering it
21038c2ecf20Sopenharmony_ci	 * infinitly and thus dropping it after some time.
21048c2ecf20Sopenharmony_ci	 */
21058c2ecf20Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
21068c2ecf20Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
21078c2ecf20Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
21108c2ecf20Sopenharmony_ci	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
21118c2ecf20Sopenharmony_ci				rt2x00_eeprom_addr(rt2x00dev,
21128c2ecf20Sopenharmony_ci						   EEPROM_MAC_ADDR_0));
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci	/*
21158c2ecf20Sopenharmony_ci	 * Initialize hw_mode information.
21168c2ecf20Sopenharmony_ci	 */
21178c2ecf20Sopenharmony_ci	spec->supported_bands = SUPPORT_BAND_2GHZ;
21188c2ecf20Sopenharmony_ci	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
21198c2ecf20Sopenharmony_ci
21208c2ecf20Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF2528)) {
21218c2ecf20Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
21228c2ecf20Sopenharmony_ci		spec->channels = rf_vals_bg_2528;
21238c2ecf20Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF5226)) {
21248c2ecf20Sopenharmony_ci		spec->supported_bands |= SUPPORT_BAND_5GHZ;
21258c2ecf20Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_5226);
21268c2ecf20Sopenharmony_ci		spec->channels = rf_vals_5226;
21278c2ecf20Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF2527)) {
21288c2ecf20Sopenharmony_ci		spec->num_channels = 14;
21298c2ecf20Sopenharmony_ci		spec->channels = rf_vals_5225_2527;
21308c2ecf20Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF5225)) {
21318c2ecf20Sopenharmony_ci		spec->supported_bands |= SUPPORT_BAND_5GHZ;
21328c2ecf20Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
21338c2ecf20Sopenharmony_ci		spec->channels = rf_vals_5225_2527;
21348c2ecf20Sopenharmony_ci	}
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci	/*
21378c2ecf20Sopenharmony_ci	 * Create channel information array
21388c2ecf20Sopenharmony_ci	 */
21398c2ecf20Sopenharmony_ci	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
21408c2ecf20Sopenharmony_ci	if (!info)
21418c2ecf20Sopenharmony_ci		return -ENOMEM;
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	spec->channels_info = info;
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
21468c2ecf20Sopenharmony_ci	for (i = 0; i < 14; i++) {
21478c2ecf20Sopenharmony_ci		info[i].max_power = MAX_TXPOWER;
21488c2ecf20Sopenharmony_ci		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
21498c2ecf20Sopenharmony_ci	}
21508c2ecf20Sopenharmony_ci
21518c2ecf20Sopenharmony_ci	if (spec->num_channels > 14) {
21528c2ecf20Sopenharmony_ci		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
21538c2ecf20Sopenharmony_ci		for (i = 14; i < spec->num_channels; i++) {
21548c2ecf20Sopenharmony_ci			info[i].max_power = MAX_TXPOWER;
21558c2ecf20Sopenharmony_ci			info[i].default_power1 =
21568c2ecf20Sopenharmony_ci					TXPOWER_FROM_DEV(tx_power[i - 14]);
21578c2ecf20Sopenharmony_ci		}
21588c2ecf20Sopenharmony_ci	}
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	return 0;
21618c2ecf20Sopenharmony_ci}
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_cistatic int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
21648c2ecf20Sopenharmony_ci{
21658c2ecf20Sopenharmony_ci	int retval;
21668c2ecf20Sopenharmony_ci	u32 reg;
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_ci	/*
21698c2ecf20Sopenharmony_ci	 * Allocate eeprom data.
21708c2ecf20Sopenharmony_ci	 */
21718c2ecf20Sopenharmony_ci	retval = rt73usb_validate_eeprom(rt2x00dev);
21728c2ecf20Sopenharmony_ci	if (retval)
21738c2ecf20Sopenharmony_ci		return retval;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	retval = rt73usb_init_eeprom(rt2x00dev);
21768c2ecf20Sopenharmony_ci	if (retval)
21778c2ecf20Sopenharmony_ci		return retval;
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	/*
21808c2ecf20Sopenharmony_ci	 * Enable rfkill polling by setting GPIO direction of the
21818c2ecf20Sopenharmony_ci	 * rfkill switch GPIO pin correctly.
21828c2ecf20Sopenharmony_ci	 */
21838c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
21848c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
21858c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci	/*
21888c2ecf20Sopenharmony_ci	 * Initialize hw specifications.
21898c2ecf20Sopenharmony_ci	 */
21908c2ecf20Sopenharmony_ci	retval = rt73usb_probe_hw_mode(rt2x00dev);
21918c2ecf20Sopenharmony_ci	if (retval)
21928c2ecf20Sopenharmony_ci		return retval;
21938c2ecf20Sopenharmony_ci
21948c2ecf20Sopenharmony_ci	/*
21958c2ecf20Sopenharmony_ci	 * This device has multiple filters for control frames,
21968c2ecf20Sopenharmony_ci	 * but has no a separate filter for PS Poll frames.
21978c2ecf20Sopenharmony_ci	 */
21988c2ecf20Sopenharmony_ci	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	/*
22018c2ecf20Sopenharmony_ci	 * This device requires firmware.
22028c2ecf20Sopenharmony_ci	 */
22038c2ecf20Sopenharmony_ci	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
22048c2ecf20Sopenharmony_ci	if (!modparam_nohwcrypt)
22058c2ecf20Sopenharmony_ci		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
22068c2ecf20Sopenharmony_ci	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
22078c2ecf20Sopenharmony_ci	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	/*
22108c2ecf20Sopenharmony_ci	 * Set the rssi offset.
22118c2ecf20Sopenharmony_ci	 */
22128c2ecf20Sopenharmony_ci	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	return 0;
22158c2ecf20Sopenharmony_ci}
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci/*
22188c2ecf20Sopenharmony_ci * IEEE80211 stack callback functions.
22198c2ecf20Sopenharmony_ci */
22208c2ecf20Sopenharmony_cistatic int rt73usb_conf_tx(struct ieee80211_hw *hw,
22218c2ecf20Sopenharmony_ci			   struct ieee80211_vif *vif, u16 queue_idx,
22228c2ecf20Sopenharmony_ci			   const struct ieee80211_tx_queue_params *params)
22238c2ecf20Sopenharmony_ci{
22248c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = hw->priv;
22258c2ecf20Sopenharmony_ci	struct data_queue *queue;
22268c2ecf20Sopenharmony_ci	struct rt2x00_field32 field;
22278c2ecf20Sopenharmony_ci	int retval;
22288c2ecf20Sopenharmony_ci	u32 reg;
22298c2ecf20Sopenharmony_ci	u32 offset;
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	/*
22328c2ecf20Sopenharmony_ci	 * First pass the configuration through rt2x00lib, that will
22338c2ecf20Sopenharmony_ci	 * update the queue settings and validate the input. After that
22348c2ecf20Sopenharmony_ci	 * we are free to update the registers based on the value
22358c2ecf20Sopenharmony_ci	 * in the queue parameter.
22368c2ecf20Sopenharmony_ci	 */
22378c2ecf20Sopenharmony_ci	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
22388c2ecf20Sopenharmony_ci	if (retval)
22398c2ecf20Sopenharmony_ci		return retval;
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	/*
22428c2ecf20Sopenharmony_ci	 * We only need to perform additional register initialization
22438c2ecf20Sopenharmony_ci	 * for WMM queues/
22448c2ecf20Sopenharmony_ci	 */
22458c2ecf20Sopenharmony_ci	if (queue_idx >= 4)
22468c2ecf20Sopenharmony_ci		return 0;
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	/* Update WMM TXOP register */
22518c2ecf20Sopenharmony_ci	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
22528c2ecf20Sopenharmony_ci	field.bit_offset = (queue_idx & 1) * 16;
22538c2ecf20Sopenharmony_ci	field.bit_mask = 0xffff << field.bit_offset;
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, offset);
22568c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, field, queue->txop);
22578c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, offset, reg);
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	/* Update WMM registers */
22608c2ecf20Sopenharmony_ci	field.bit_offset = queue_idx * 4;
22618c2ecf20Sopenharmony_ci	field.bit_mask = 0xf << field.bit_offset;
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, AIFSN_CSR);
22648c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, field, queue->aifs);
22658c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, CWMIN_CSR);
22688c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, field, queue->cw_min);
22698c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, CWMAX_CSR);
22728c2ecf20Sopenharmony_ci	rt2x00_set_field32(&reg, field, queue->cw_max);
22738c2ecf20Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
22748c2ecf20Sopenharmony_ci
22758c2ecf20Sopenharmony_ci	return 0;
22768c2ecf20Sopenharmony_ci}
22778c2ecf20Sopenharmony_ci
22788c2ecf20Sopenharmony_cistatic u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
22798c2ecf20Sopenharmony_ci{
22808c2ecf20Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = hw->priv;
22818c2ecf20Sopenharmony_ci	u64 tsf;
22828c2ecf20Sopenharmony_ci	u32 reg;
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR13);
22858c2ecf20Sopenharmony_ci	tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
22868c2ecf20Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR12);
22878c2ecf20Sopenharmony_ci	tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
22888c2ecf20Sopenharmony_ci
22898c2ecf20Sopenharmony_ci	return tsf;
22908c2ecf20Sopenharmony_ci}
22918c2ecf20Sopenharmony_ci
22928c2ecf20Sopenharmony_cistatic const struct ieee80211_ops rt73usb_mac80211_ops = {
22938c2ecf20Sopenharmony_ci	.tx			= rt2x00mac_tx,
22948c2ecf20Sopenharmony_ci	.start			= rt2x00mac_start,
22958c2ecf20Sopenharmony_ci	.stop			= rt2x00mac_stop,
22968c2ecf20Sopenharmony_ci	.add_interface		= rt2x00mac_add_interface,
22978c2ecf20Sopenharmony_ci	.remove_interface	= rt2x00mac_remove_interface,
22988c2ecf20Sopenharmony_ci	.config			= rt2x00mac_config,
22998c2ecf20Sopenharmony_ci	.configure_filter	= rt2x00mac_configure_filter,
23008c2ecf20Sopenharmony_ci	.set_tim		= rt2x00mac_set_tim,
23018c2ecf20Sopenharmony_ci	.set_key		= rt2x00mac_set_key,
23028c2ecf20Sopenharmony_ci	.sw_scan_start		= rt2x00mac_sw_scan_start,
23038c2ecf20Sopenharmony_ci	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
23048c2ecf20Sopenharmony_ci	.get_stats		= rt2x00mac_get_stats,
23058c2ecf20Sopenharmony_ci	.bss_info_changed	= rt2x00mac_bss_info_changed,
23068c2ecf20Sopenharmony_ci	.conf_tx		= rt73usb_conf_tx,
23078c2ecf20Sopenharmony_ci	.get_tsf		= rt73usb_get_tsf,
23088c2ecf20Sopenharmony_ci	.rfkill_poll		= rt2x00mac_rfkill_poll,
23098c2ecf20Sopenharmony_ci	.flush			= rt2x00mac_flush,
23108c2ecf20Sopenharmony_ci	.set_antenna		= rt2x00mac_set_antenna,
23118c2ecf20Sopenharmony_ci	.get_antenna		= rt2x00mac_get_antenna,
23128c2ecf20Sopenharmony_ci	.get_ringparam		= rt2x00mac_get_ringparam,
23138c2ecf20Sopenharmony_ci	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
23148c2ecf20Sopenharmony_ci};
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_cistatic const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
23178c2ecf20Sopenharmony_ci	.probe_hw		= rt73usb_probe_hw,
23188c2ecf20Sopenharmony_ci	.get_firmware_name	= rt73usb_get_firmware_name,
23198c2ecf20Sopenharmony_ci	.check_firmware		= rt73usb_check_firmware,
23208c2ecf20Sopenharmony_ci	.load_firmware		= rt73usb_load_firmware,
23218c2ecf20Sopenharmony_ci	.initialize		= rt2x00usb_initialize,
23228c2ecf20Sopenharmony_ci	.uninitialize		= rt2x00usb_uninitialize,
23238c2ecf20Sopenharmony_ci	.clear_entry		= rt2x00usb_clear_entry,
23248c2ecf20Sopenharmony_ci	.set_device_state	= rt73usb_set_device_state,
23258c2ecf20Sopenharmony_ci	.rfkill_poll		= rt73usb_rfkill_poll,
23268c2ecf20Sopenharmony_ci	.link_stats		= rt73usb_link_stats,
23278c2ecf20Sopenharmony_ci	.reset_tuner		= rt73usb_reset_tuner,
23288c2ecf20Sopenharmony_ci	.link_tuner		= rt73usb_link_tuner,
23298c2ecf20Sopenharmony_ci	.watchdog		= rt2x00usb_watchdog,
23308c2ecf20Sopenharmony_ci	.start_queue		= rt73usb_start_queue,
23318c2ecf20Sopenharmony_ci	.kick_queue		= rt2x00usb_kick_queue,
23328c2ecf20Sopenharmony_ci	.stop_queue		= rt73usb_stop_queue,
23338c2ecf20Sopenharmony_ci	.flush_queue		= rt2x00usb_flush_queue,
23348c2ecf20Sopenharmony_ci	.write_tx_desc		= rt73usb_write_tx_desc,
23358c2ecf20Sopenharmony_ci	.write_beacon		= rt73usb_write_beacon,
23368c2ecf20Sopenharmony_ci	.clear_beacon		= rt73usb_clear_beacon,
23378c2ecf20Sopenharmony_ci	.get_tx_data_len	= rt73usb_get_tx_data_len,
23388c2ecf20Sopenharmony_ci	.fill_rxdone		= rt73usb_fill_rxdone,
23398c2ecf20Sopenharmony_ci	.config_shared_key	= rt73usb_config_shared_key,
23408c2ecf20Sopenharmony_ci	.config_pairwise_key	= rt73usb_config_pairwise_key,
23418c2ecf20Sopenharmony_ci	.config_filter		= rt73usb_config_filter,
23428c2ecf20Sopenharmony_ci	.config_intf		= rt73usb_config_intf,
23438c2ecf20Sopenharmony_ci	.config_erp		= rt73usb_config_erp,
23448c2ecf20Sopenharmony_ci	.config_ant		= rt73usb_config_ant,
23458c2ecf20Sopenharmony_ci	.config			= rt73usb_config,
23468c2ecf20Sopenharmony_ci};
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_cistatic void rt73usb_queue_init(struct data_queue *queue)
23498c2ecf20Sopenharmony_ci{
23508c2ecf20Sopenharmony_ci	switch (queue->qid) {
23518c2ecf20Sopenharmony_ci	case QID_RX:
23528c2ecf20Sopenharmony_ci		queue->limit = 32;
23538c2ecf20Sopenharmony_ci		queue->data_size = DATA_FRAME_SIZE;
23548c2ecf20Sopenharmony_ci		queue->desc_size = RXD_DESC_SIZE;
23558c2ecf20Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
23568c2ecf20Sopenharmony_ci		break;
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci	case QID_AC_VO:
23598c2ecf20Sopenharmony_ci	case QID_AC_VI:
23608c2ecf20Sopenharmony_ci	case QID_AC_BE:
23618c2ecf20Sopenharmony_ci	case QID_AC_BK:
23628c2ecf20Sopenharmony_ci		queue->limit = 32;
23638c2ecf20Sopenharmony_ci		queue->data_size = DATA_FRAME_SIZE;
23648c2ecf20Sopenharmony_ci		queue->desc_size = TXD_DESC_SIZE;
23658c2ecf20Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
23668c2ecf20Sopenharmony_ci		break;
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	case QID_BEACON:
23698c2ecf20Sopenharmony_ci		queue->limit = 4;
23708c2ecf20Sopenharmony_ci		queue->data_size = MGMT_FRAME_SIZE;
23718c2ecf20Sopenharmony_ci		queue->desc_size = TXINFO_SIZE;
23728c2ecf20Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
23738c2ecf20Sopenharmony_ci		break;
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	case QID_ATIM:
23768c2ecf20Sopenharmony_ci	default:
23778c2ecf20Sopenharmony_ci		BUG();
23788c2ecf20Sopenharmony_ci		break;
23798c2ecf20Sopenharmony_ci	}
23808c2ecf20Sopenharmony_ci}
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_cistatic const struct rt2x00_ops rt73usb_ops = {
23838c2ecf20Sopenharmony_ci	.name			= KBUILD_MODNAME,
23848c2ecf20Sopenharmony_ci	.max_ap_intf		= 4,
23858c2ecf20Sopenharmony_ci	.eeprom_size		= EEPROM_SIZE,
23868c2ecf20Sopenharmony_ci	.rf_size		= RF_SIZE,
23878c2ecf20Sopenharmony_ci	.tx_queues		= NUM_TX_QUEUES,
23888c2ecf20Sopenharmony_ci	.queue_init		= rt73usb_queue_init,
23898c2ecf20Sopenharmony_ci	.lib			= &rt73usb_rt2x00_ops,
23908c2ecf20Sopenharmony_ci	.hw			= &rt73usb_mac80211_ops,
23918c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS
23928c2ecf20Sopenharmony_ci	.debugfs		= &rt73usb_rt2x00debug,
23938c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
23948c2ecf20Sopenharmony_ci};
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci/*
23978c2ecf20Sopenharmony_ci * rt73usb module information.
23988c2ecf20Sopenharmony_ci */
23998c2ecf20Sopenharmony_cistatic const struct usb_device_id rt73usb_device_table[] = {
24008c2ecf20Sopenharmony_ci	/* AboCom */
24018c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0xb21b) },
24028c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0xb21c) },
24038c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0xb21d) },
24048c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0xb21e) },
24058c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0xb21f) },
24068c2ecf20Sopenharmony_ci	/* AL */
24078c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c10) },
24088c2ecf20Sopenharmony_ci	/* Amigo */
24098c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x9021) },
24108c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0eb0, 0x9021) },
24118c2ecf20Sopenharmony_ci	/* AMIT  */
24128c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x18c5, 0x0002) },
24138c2ecf20Sopenharmony_ci	/* Askey */
24148c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1690, 0x0722) },
24158c2ecf20Sopenharmony_ci	/* ASUS */
24168c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1723) },
24178c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1724) },
24188c2ecf20Sopenharmony_ci	/* Belkin */
24198c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x7050) },	/* FCC ID: K7SF5D7050B ver. 3.x */
24208c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x705a) },
24218c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x905b) },
24228c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x905c) },
24238c2ecf20Sopenharmony_ci	/* Billionton */
24248c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1631, 0xc019) },
24258c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x08dd, 0x0120) },
24268c2ecf20Sopenharmony_ci	/* Buffalo */
24278c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x00d8) },
24288c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x00d9) },
24298c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x00e6) },
24308c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x00f4) },
24318c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0116) },
24328c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0119) },
24338c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0137) },
24348c2ecf20Sopenharmony_ci	/* CEIVA */
24358c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x178d, 0x02be) },
24368c2ecf20Sopenharmony_ci	/* CNet */
24378c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1371, 0x9022) },
24388c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1371, 0x9032) },
24398c2ecf20Sopenharmony_ci	/* Conceptronic */
24408c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c22) },
24418c2ecf20Sopenharmony_ci	/* Corega */
24428c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x002e) },
24438c2ecf20Sopenharmony_ci	/* D-Link */
24448c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c03) },
24458c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c04) },
24468c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c06) },
24478c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c07) },
24488c2ecf20Sopenharmony_ci	/* Edimax */
24498c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7318) },
24508c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7618) },
24518c2ecf20Sopenharmony_ci	/* EnGenius */
24528c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x3701) },
24538c2ecf20Sopenharmony_ci	/* Gemtek */
24548c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x15a9, 0x0004) },
24558c2ecf20Sopenharmony_ci	/* Gigabyte */
24568c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x8008) },
24578c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x800a) },
24588c2ecf20Sopenharmony_ci	/* Huawei-3Com */
24598c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1472, 0x0009) },
24608c2ecf20Sopenharmony_ci	/* Hercules */
24618c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x06f8, 0xe002) },
24628c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x06f8, 0xe010) },
24638c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x06f8, 0xe020) },
24648c2ecf20Sopenharmony_ci	/* Linksys */
24658c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x0020) },
24668c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x0023) },
24678c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x0028) },
24688c2ecf20Sopenharmony_ci	/* MSI */
24698c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x4600) },
24708c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6877) },
24718c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6874) },
24728c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0xa861) },
24738c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0xa874) },
24748c2ecf20Sopenharmony_ci	/* Ovislink */
24758c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0x7318) },
24768c2ecf20Sopenharmony_ci	/* Ralink */
24778c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x093d) },
24788c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2573) },
24798c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2671) },
24808c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0812, 0x3101) },
24818c2ecf20Sopenharmony_ci	/* Qcom */
24828c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x18e8, 0x6196) },
24838c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x18e8, 0x6229) },
24848c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x18e8, 0x6238) },
24858c2ecf20Sopenharmony_ci	/* Samsung */
24868c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x04e8, 0x4471) },
24878c2ecf20Sopenharmony_ci	/* Senao */
24888c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x7100) },
24898c2ecf20Sopenharmony_ci	/* Sitecom */
24908c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0024) },
24918c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0027) },
24928c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x002f) },
24938c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x90ac) },
24948c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x9712) },
24958c2ecf20Sopenharmony_ci	/* Surecom */
24968c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0769, 0x31f3) },
24978c2ecf20Sopenharmony_ci	/* Tilgin */
24988c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x6933, 0x5001) },
24998c2ecf20Sopenharmony_ci	/* Philips */
25008c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x200a) },
25018c2ecf20Sopenharmony_ci	/* Planex */
25028c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xab01) },
25038c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xab50) },
25048c2ecf20Sopenharmony_ci	/* WideTell */
25058c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x7167, 0x3840) },
25068c2ecf20Sopenharmony_ci	/* Zcom */
25078c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0cde, 0x001c) },
25088c2ecf20Sopenharmony_ci	/* ZyXEL */
25098c2ecf20Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x3415) },
25108c2ecf20Sopenharmony_ci	{ 0, }
25118c2ecf20Sopenharmony_ci};
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRV_PROJECT);
25148c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION);
25158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Ralink RT73 USB Wireless LAN driver.");
25168c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("Ralink RT2571W & RT2671 USB chipset based cards");
25178c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, rt73usb_device_table);
25188c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_RT2571);
25198c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_cistatic int rt73usb_probe(struct usb_interface *usb_intf,
25228c2ecf20Sopenharmony_ci			 const struct usb_device_id *id)
25238c2ecf20Sopenharmony_ci{
25248c2ecf20Sopenharmony_ci	return rt2x00usb_probe(usb_intf, &rt73usb_ops);
25258c2ecf20Sopenharmony_ci}
25268c2ecf20Sopenharmony_ci
25278c2ecf20Sopenharmony_cistatic struct usb_driver rt73usb_driver = {
25288c2ecf20Sopenharmony_ci	.name		= KBUILD_MODNAME,
25298c2ecf20Sopenharmony_ci	.id_table	= rt73usb_device_table,
25308c2ecf20Sopenharmony_ci	.probe		= rt73usb_probe,
25318c2ecf20Sopenharmony_ci	.disconnect	= rt2x00usb_disconnect,
25328c2ecf20Sopenharmony_ci	.suspend	= rt2x00usb_suspend,
25338c2ecf20Sopenharmony_ci	.resume		= rt2x00usb_resume,
25348c2ecf20Sopenharmony_ci	.reset_resume	= rt2x00usb_resume,
25358c2ecf20Sopenharmony_ci	.disable_hub_initiated_lpm = 1,
25368c2ecf20Sopenharmony_ci};
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_cimodule_usb_driver(rt73usb_driver);
2539