162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
462306a36Sopenharmony_ci	<http://rt2x00.serialmonkey.com>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci	Module: rt2500usb
1062306a36Sopenharmony_ci	Abstract: rt2500usb device specific routines.
1162306a36Sopenharmony_ci	Supported chipsets: RT2570.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/etherdevice.h>
1662306a36Sopenharmony_ci#include <linux/kernel.h>
1762306a36Sopenharmony_ci#include <linux/module.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/usb.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "rt2x00.h"
2262306a36Sopenharmony_ci#include "rt2x00usb.h"
2362306a36Sopenharmony_ci#include "rt2500usb.h"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * Allow hardware encryption to be disabled.
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_cistatic bool modparam_nohwcrypt;
2962306a36Sopenharmony_cimodule_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
3062306a36Sopenharmony_ciMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * Register access.
3462306a36Sopenharmony_ci * All access to the CSR registers will go through the methods
3562306a36Sopenharmony_ci * rt2500usb_register_read and rt2500usb_register_write.
3662306a36Sopenharmony_ci * BBP and RF register require indirect register access,
3762306a36Sopenharmony_ci * and use the CSR registers BBPCSR and RFCSR to achieve this.
3862306a36Sopenharmony_ci * These indirect registers work with busy bits,
3962306a36Sopenharmony_ci * and we will try maximal REGISTER_USB_BUSY_COUNT times to access
4062306a36Sopenharmony_ci * the register while taking a REGISTER_BUSY_DELAY us delay
4162306a36Sopenharmony_ci * between each attampt. When the busy bit is still set at that time,
4262306a36Sopenharmony_ci * the access attempt is considered to have failed,
4362306a36Sopenharmony_ci * and we will print an error.
4462306a36Sopenharmony_ci * If the csr_mutex is already held then the _lock variants must
4562306a36Sopenharmony_ci * be used instead.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_cistatic u16 rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
4862306a36Sopenharmony_ci				   const unsigned int offset)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	__le16 reg;
5162306a36Sopenharmony_ci	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
5262306a36Sopenharmony_ci				      USB_VENDOR_REQUEST_IN, offset,
5362306a36Sopenharmony_ci				      &reg, sizeof(reg));
5462306a36Sopenharmony_ci	return le16_to_cpu(reg);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic u16 rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
5862306a36Sopenharmony_ci					const unsigned int offset)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	__le16 reg;
6162306a36Sopenharmony_ci	rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
6262306a36Sopenharmony_ci				       USB_VENDOR_REQUEST_IN, offset,
6362306a36Sopenharmony_ci				       &reg, sizeof(reg), REGISTER_TIMEOUT);
6462306a36Sopenharmony_ci	return le16_to_cpu(reg);
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
6862306a36Sopenharmony_ci					    const unsigned int offset,
6962306a36Sopenharmony_ci					    u16 value)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	__le16 reg = cpu_to_le16(value);
7262306a36Sopenharmony_ci	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
7362306a36Sopenharmony_ci				      USB_VENDOR_REQUEST_OUT, offset,
7462306a36Sopenharmony_ci				      &reg, sizeof(reg));
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
7862306a36Sopenharmony_ci						 const unsigned int offset,
7962306a36Sopenharmony_ci						 u16 value)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	__le16 reg = cpu_to_le16(value);
8262306a36Sopenharmony_ci	rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
8362306a36Sopenharmony_ci				       USB_VENDOR_REQUEST_OUT, offset,
8462306a36Sopenharmony_ci				       &reg, sizeof(reg), REGISTER_TIMEOUT);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
8862306a36Sopenharmony_ci						 const unsigned int offset,
8962306a36Sopenharmony_ci						 void *value, const u16 length)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
9262306a36Sopenharmony_ci				      USB_VENDOR_REQUEST_OUT, offset,
9362306a36Sopenharmony_ci				      value, length);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
9762306a36Sopenharmony_ci				  const unsigned int offset,
9862306a36Sopenharmony_ci				  struct rt2x00_field16 field,
9962306a36Sopenharmony_ci				  u16 *reg)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	unsigned int i;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
10462306a36Sopenharmony_ci		*reg = rt2500usb_register_read_lock(rt2x00dev, offset);
10562306a36Sopenharmony_ci		if (!rt2x00_get_field16(*reg, field))
10662306a36Sopenharmony_ci			return 1;
10762306a36Sopenharmony_ci		udelay(REGISTER_BUSY_DELAY);
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
11162306a36Sopenharmony_ci		   offset, *reg);
11262306a36Sopenharmony_ci	*reg = ~0;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define WAIT_FOR_BBP(__dev, __reg) \
11862306a36Sopenharmony_ci	rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
11962306a36Sopenharmony_ci#define WAIT_FOR_RF(__dev, __reg) \
12062306a36Sopenharmony_ci	rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
12362306a36Sopenharmony_ci				const unsigned int word, const u8 value)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	u16 reg;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	/*
13062306a36Sopenharmony_ci	 * Wait until the BBP becomes available, afterwards we
13162306a36Sopenharmony_ci	 * can safely write the new data into the register.
13262306a36Sopenharmony_ci	 */
13362306a36Sopenharmony_ci	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
13462306a36Sopenharmony_ci		reg = 0;
13562306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR7_DATA, value);
13662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
13762306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic u8 rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
14662306a36Sopenharmony_ci			     const unsigned int word)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	u16 reg;
14962306a36Sopenharmony_ci	u8 value;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/*
15462306a36Sopenharmony_ci	 * Wait until the BBP becomes available, afterwards we
15562306a36Sopenharmony_ci	 * can safely write the read request into the register.
15662306a36Sopenharmony_ci	 * After the data has been written, we wait until hardware
15762306a36Sopenharmony_ci	 * returns the correct value, if at any time the register
15862306a36Sopenharmony_ci	 * doesn't become available in time, reg will be 0xffffffff
15962306a36Sopenharmony_ci	 * which means we return 0xff to the caller.
16062306a36Sopenharmony_ci	 */
16162306a36Sopenharmony_ci	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
16262306a36Sopenharmony_ci		reg = 0;
16362306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
16462306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci		rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		if (WAIT_FOR_BBP(rt2x00dev, &reg))
16962306a36Sopenharmony_ci			reg = rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7);
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	return value;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistatic void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
18062306a36Sopenharmony_ci			       const unsigned int word, const u32 value)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	u16 reg;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	mutex_lock(&rt2x00dev->csr_mutex);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	/*
18762306a36Sopenharmony_ci	 * Wait until the RF becomes available, afterwards we
18862306a36Sopenharmony_ci	 * can safely write the new data into the register.
18962306a36Sopenharmony_ci	 */
19062306a36Sopenharmony_ci	if (WAIT_FOR_RF(rt2x00dev, &reg)) {
19162306a36Sopenharmony_ci		reg = 0;
19262306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
19362306a36Sopenharmony_ci		rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		reg = 0;
19662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
19762306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
19862306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
19962306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci		rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
20262306a36Sopenharmony_ci		rt2x00_rf_write(rt2x00dev, word, value);
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	mutex_unlock(&rt2x00dev->csr_mutex);
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS
20962306a36Sopenharmony_cistatic u32 _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
21062306a36Sopenharmony_ci				     const unsigned int offset)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	return rt2500usb_register_read(rt2x00dev, offset);
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
21662306a36Sopenharmony_ci				      const unsigned int offset,
21762306a36Sopenharmony_ci				      u32 value)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, offset, value);
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic const struct rt2x00debug rt2500usb_rt2x00debug = {
22362306a36Sopenharmony_ci	.owner	= THIS_MODULE,
22462306a36Sopenharmony_ci	.csr	= {
22562306a36Sopenharmony_ci		.read		= _rt2500usb_register_read,
22662306a36Sopenharmony_ci		.write		= _rt2500usb_register_write,
22762306a36Sopenharmony_ci		.flags		= RT2X00DEBUGFS_OFFSET,
22862306a36Sopenharmony_ci		.word_base	= CSR_REG_BASE,
22962306a36Sopenharmony_ci		.word_size	= sizeof(u16),
23062306a36Sopenharmony_ci		.word_count	= CSR_REG_SIZE / sizeof(u16),
23162306a36Sopenharmony_ci	},
23262306a36Sopenharmony_ci	.eeprom	= {
23362306a36Sopenharmony_ci		.read		= rt2x00_eeprom_read,
23462306a36Sopenharmony_ci		.write		= rt2x00_eeprom_write,
23562306a36Sopenharmony_ci		.word_base	= EEPROM_BASE,
23662306a36Sopenharmony_ci		.word_size	= sizeof(u16),
23762306a36Sopenharmony_ci		.word_count	= EEPROM_SIZE / sizeof(u16),
23862306a36Sopenharmony_ci	},
23962306a36Sopenharmony_ci	.bbp	= {
24062306a36Sopenharmony_ci		.read		= rt2500usb_bbp_read,
24162306a36Sopenharmony_ci		.write		= rt2500usb_bbp_write,
24262306a36Sopenharmony_ci		.word_base	= BBP_BASE,
24362306a36Sopenharmony_ci		.word_size	= sizeof(u8),
24462306a36Sopenharmony_ci		.word_count	= BBP_SIZE / sizeof(u8),
24562306a36Sopenharmony_ci	},
24662306a36Sopenharmony_ci	.rf	= {
24762306a36Sopenharmony_ci		.read		= rt2x00_rf_read,
24862306a36Sopenharmony_ci		.write		= rt2500usb_rf_write,
24962306a36Sopenharmony_ci		.word_base	= RF_BASE,
25062306a36Sopenharmony_ci		.word_size	= sizeof(u32),
25162306a36Sopenharmony_ci		.word_count	= RF_SIZE / sizeof(u32),
25262306a36Sopenharmony_ci	},
25362306a36Sopenharmony_ci};
25462306a36Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	u16 reg;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
26162306a36Sopenharmony_ci	return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS
26562306a36Sopenharmony_cistatic void rt2500usb_brightness_set(struct led_classdev *led_cdev,
26662306a36Sopenharmony_ci				     enum led_brightness brightness)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct rt2x00_led *led =
26962306a36Sopenharmony_ci	    container_of(led_cdev, struct rt2x00_led, led_dev);
27062306a36Sopenharmony_ci	unsigned int enabled = brightness != LED_OFF;
27162306a36Sopenharmony_ci	u16 reg;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR20);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
27662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
27762306a36Sopenharmony_ci	else if (led->type == LED_TYPE_ACTIVITY)
27862306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, enabled);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic int rt2500usb_blink_set(struct led_classdev *led_cdev,
28462306a36Sopenharmony_ci			       unsigned long *delay_on,
28562306a36Sopenharmony_ci			       unsigned long *delay_off)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct rt2x00_led *led =
28862306a36Sopenharmony_ci	    container_of(led_cdev, struct rt2x00_led, led_dev);
28962306a36Sopenharmony_ci	u16 reg;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR21);
29262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
29362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
29462306a36Sopenharmony_ci	rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return 0;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
30062306a36Sopenharmony_ci			       struct rt2x00_led *led,
30162306a36Sopenharmony_ci			       enum led_type type)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	led->rt2x00dev = rt2x00dev;
30462306a36Sopenharmony_ci	led->type = type;
30562306a36Sopenharmony_ci	led->led_dev.brightness_set = rt2500usb_brightness_set;
30662306a36Sopenharmony_ci	led->led_dev.blink_set = rt2500usb_blink_set;
30762306a36Sopenharmony_ci	led->flags = LED_INITIALIZED;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci/*
31262306a36Sopenharmony_ci * Configuration handlers.
31362306a36Sopenharmony_ci */
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci/*
31662306a36Sopenharmony_ci * rt2500usb does not differentiate between shared and pairwise
31762306a36Sopenharmony_ci * keys, so we should use the same function for both key types.
31862306a36Sopenharmony_ci */
31962306a36Sopenharmony_cistatic int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
32062306a36Sopenharmony_ci				struct rt2x00lib_crypto *crypto,
32162306a36Sopenharmony_ci				struct ieee80211_key_conf *key)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	u32 mask;
32462306a36Sopenharmony_ci	u16 reg;
32562306a36Sopenharmony_ci	enum cipher curr_cipher;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	if (crypto->cmd == SET_KEY) {
32862306a36Sopenharmony_ci		/*
32962306a36Sopenharmony_ci		 * Disallow to set WEP key other than with index 0,
33062306a36Sopenharmony_ci		 * it is known that not work at least on some hardware.
33162306a36Sopenharmony_ci		 * SW crypto will be used in that case.
33262306a36Sopenharmony_ci		 */
33362306a36Sopenharmony_ci		if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
33462306a36Sopenharmony_ci		     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
33562306a36Sopenharmony_ci		    key->keyidx != 0)
33662306a36Sopenharmony_ci			return -EOPNOTSUPP;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci		/*
33962306a36Sopenharmony_ci		 * Pairwise key will always be entry 0, but this
34062306a36Sopenharmony_ci		 * could collide with a shared key on the same
34162306a36Sopenharmony_ci		 * position...
34262306a36Sopenharmony_ci		 */
34362306a36Sopenharmony_ci		mask = TXRX_CSR0_KEY_ID.bit_mask;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
34662306a36Sopenharmony_ci		curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
34762306a36Sopenharmony_ci		reg &= mask;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci		if (reg && reg == mask)
35062306a36Sopenharmony_ci			return -ENOSPC;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		key->hw_key_idx += reg ? ffz(reg) : 0;
35562306a36Sopenharmony_ci		/*
35662306a36Sopenharmony_ci		 * Hardware requires that all keys use the same cipher
35762306a36Sopenharmony_ci		 * (e.g. TKIP-only, AES-only, but not TKIP+AES).
35862306a36Sopenharmony_ci		 * If this is not the first key, compare the cipher with the
35962306a36Sopenharmony_ci		 * first one and fall back to SW crypto if not the same.
36062306a36Sopenharmony_ci		 */
36162306a36Sopenharmony_ci		if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
36262306a36Sopenharmony_ci			return -EOPNOTSUPP;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx),
36562306a36Sopenharmony_ci					      crypto->key, sizeof(crypto->key));
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci		/*
36862306a36Sopenharmony_ci		 * The driver does not support the IV/EIV generation
36962306a36Sopenharmony_ci		 * in hardware. However it demands the data to be provided
37062306a36Sopenharmony_ci		 * both separately as well as inside the frame.
37162306a36Sopenharmony_ci		 * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
37262306a36Sopenharmony_ci		 * to ensure rt2x00lib will not strip the data from the
37362306a36Sopenharmony_ci		 * frame after the copy, now we must tell mac80211
37462306a36Sopenharmony_ci		 * to generate the IV/EIV data.
37562306a36Sopenharmony_ci		 */
37662306a36Sopenharmony_ci		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
37762306a36Sopenharmony_ci		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	/*
38162306a36Sopenharmony_ci	 * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
38262306a36Sopenharmony_ci	 * a particular key is valid.
38362306a36Sopenharmony_ci	 */
38462306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
38562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
38662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
38962306a36Sopenharmony_ci	if (crypto->cmd == SET_KEY)
39062306a36Sopenharmony_ci		mask |= 1 << key->hw_key_idx;
39162306a36Sopenharmony_ci	else if (crypto->cmd == DISABLE_KEY)
39262306a36Sopenharmony_ci		mask &= ~(1 << key->hw_key_idx);
39362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, mask);
39462306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	return 0;
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cistatic void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
40062306a36Sopenharmony_ci				    const unsigned int filter_flags)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	u16 reg;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/*
40562306a36Sopenharmony_ci	 * Start configuration steps.
40662306a36Sopenharmony_ci	 * Note that the version error will always be dropped
40762306a36Sopenharmony_ci	 * and broadcast frames will always be accepted since
40862306a36Sopenharmony_ci	 * there is no filter for it at this time.
40962306a36Sopenharmony_ci	 */
41062306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
41162306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
41262306a36Sopenharmony_ci			   !(filter_flags & FIF_FCSFAIL));
41362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
41462306a36Sopenharmony_ci			   !(filter_flags & FIF_PLCPFAIL));
41562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
41662306a36Sopenharmony_ci			   !(filter_flags & FIF_CONTROL));
41762306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
41862306a36Sopenharmony_ci			   !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
41962306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
42062306a36Sopenharmony_ci			   !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
42162306a36Sopenharmony_ci			   !rt2x00dev->intf_ap_count);
42262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
42362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
42462306a36Sopenharmony_ci			   !(filter_flags & FIF_ALLMULTI));
42562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
42662306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_cistatic void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
43062306a36Sopenharmony_ci				  struct rt2x00_intf *intf,
43162306a36Sopenharmony_ci				  struct rt2x00intf_conf *conf,
43262306a36Sopenharmony_ci				  const unsigned int flags)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	unsigned int bcn_preload;
43562306a36Sopenharmony_ci	u16 reg;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	if (flags & CONFIG_UPDATE_TYPE) {
43862306a36Sopenharmony_ci		/*
43962306a36Sopenharmony_ci		 * Enable beacon config
44062306a36Sopenharmony_ci		 */
44162306a36Sopenharmony_ci		bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
44262306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR20);
44362306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
44462306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
44562306a36Sopenharmony_ci				   2 * (conf->type != NL80211_IFTYPE_STATION));
44662306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci		/*
44962306a36Sopenharmony_ci		 * Enable synchronisation.
45062306a36Sopenharmony_ci		 */
45162306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
45262306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
45362306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
45662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
45762306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (flags & CONFIG_UPDATE_MAC)
46162306a36Sopenharmony_ci		rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
46262306a36Sopenharmony_ci					      (3 * sizeof(__le16)));
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if (flags & CONFIG_UPDATE_BSSID)
46562306a36Sopenharmony_ci		rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
46662306a36Sopenharmony_ci					      (3 * sizeof(__le16)));
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
47062306a36Sopenharmony_ci				 struct rt2x00lib_erp *erp,
47162306a36Sopenharmony_ci				 u32 changed)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	u16 reg;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
47662306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR10);
47762306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
47862306a36Sopenharmony_ci				   !!erp->short_preamble);
47962306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	if (changed & BSS_CHANGED_BASIC_RATES)
48362306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
48462306a36Sopenharmony_ci					 erp->basic_rates);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	if (changed & BSS_CHANGED_BEACON_INT) {
48762306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
48862306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
48962306a36Sopenharmony_ci				   erp->beacon_int * 4);
49062306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (changed & BSS_CHANGED_ERP_SLOT) {
49462306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
49562306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
49662306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistatic void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
50162306a36Sopenharmony_ci				 struct antenna_setup *ant)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	u8 r2;
50462306a36Sopenharmony_ci	u8 r14;
50562306a36Sopenharmony_ci	u16 csr5;
50662306a36Sopenharmony_ci	u16 csr6;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	/*
50962306a36Sopenharmony_ci	 * We should never come here because rt2x00lib is supposed
51062306a36Sopenharmony_ci	 * to catch this and send us the correct antenna explicitely.
51162306a36Sopenharmony_ci	 */
51262306a36Sopenharmony_ci	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
51362306a36Sopenharmony_ci	       ant->tx == ANTENNA_SW_DIVERSITY);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	r2 = rt2500usb_bbp_read(rt2x00dev, 2);
51662306a36Sopenharmony_ci	r14 = rt2500usb_bbp_read(rt2x00dev, 14);
51762306a36Sopenharmony_ci	csr5 = rt2500usb_register_read(rt2x00dev, PHY_CSR5);
51862306a36Sopenharmony_ci	csr6 = rt2500usb_register_read(rt2x00dev, PHY_CSR6);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	/*
52162306a36Sopenharmony_ci	 * Configure the TX antenna.
52262306a36Sopenharmony_ci	 */
52362306a36Sopenharmony_ci	switch (ant->tx) {
52462306a36Sopenharmony_ci	case ANTENNA_HW_DIVERSITY:
52562306a36Sopenharmony_ci		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1);
52662306a36Sopenharmony_ci		rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1);
52762306a36Sopenharmony_ci		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1);
52862306a36Sopenharmony_ci		break;
52962306a36Sopenharmony_ci	case ANTENNA_A:
53062306a36Sopenharmony_ci		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
53162306a36Sopenharmony_ci		rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
53262306a36Sopenharmony_ci		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
53362306a36Sopenharmony_ci		break;
53462306a36Sopenharmony_ci	case ANTENNA_B:
53562306a36Sopenharmony_ci	default:
53662306a36Sopenharmony_ci		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
53762306a36Sopenharmony_ci		rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
53862306a36Sopenharmony_ci		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
53962306a36Sopenharmony_ci		break;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	/*
54362306a36Sopenharmony_ci	 * Configure the RX antenna.
54462306a36Sopenharmony_ci	 */
54562306a36Sopenharmony_ci	switch (ant->rx) {
54662306a36Sopenharmony_ci	case ANTENNA_HW_DIVERSITY:
54762306a36Sopenharmony_ci		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1);
54862306a36Sopenharmony_ci		break;
54962306a36Sopenharmony_ci	case ANTENNA_A:
55062306a36Sopenharmony_ci		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
55162306a36Sopenharmony_ci		break;
55262306a36Sopenharmony_ci	case ANTENNA_B:
55362306a36Sopenharmony_ci	default:
55462306a36Sopenharmony_ci		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
55562306a36Sopenharmony_ci		break;
55662306a36Sopenharmony_ci	}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	/*
55962306a36Sopenharmony_ci	 * RT2525E and RT5222 need to flip TX I/Q
56062306a36Sopenharmony_ci	 */
56162306a36Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
56262306a36Sopenharmony_ci		rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
56362306a36Sopenharmony_ci		rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
56462306a36Sopenharmony_ci		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		/*
56762306a36Sopenharmony_ci		 * RT2525E does not need RX I/Q Flip.
56862306a36Sopenharmony_ci		 */
56962306a36Sopenharmony_ci		if (rt2x00_rf(rt2x00dev, RF2525E))
57062306a36Sopenharmony_ci			rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
57162306a36Sopenharmony_ci	} else {
57262306a36Sopenharmony_ci		rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
57362306a36Sopenharmony_ci		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 0);
57462306a36Sopenharmony_ci	}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 2, r2);
57762306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 14, r14);
57862306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, PHY_CSR5, csr5);
57962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6);
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
58362306a36Sopenharmony_ci				     struct rf_channel *rf, const int txpower)
58462306a36Sopenharmony_ci{
58562306a36Sopenharmony_ci	/*
58662306a36Sopenharmony_ci	 * Set TXpower.
58762306a36Sopenharmony_ci	 */
58862306a36Sopenharmony_ci	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	/*
59162306a36Sopenharmony_ci	 * For RT2525E we should first set the channel to half band higher.
59262306a36Sopenharmony_ci	 */
59362306a36Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF2525E)) {
59462306a36Sopenharmony_ci		static const u32 vals[] = {
59562306a36Sopenharmony_ci			0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
59662306a36Sopenharmony_ci			0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
59762306a36Sopenharmony_ci			0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
59862306a36Sopenharmony_ci			0x00000902, 0x00000906
59962306a36Sopenharmony_ci		};
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci		rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
60262306a36Sopenharmony_ci		if (rf->rf4)
60362306a36Sopenharmony_ci			rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
60762306a36Sopenharmony_ci	rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
60862306a36Sopenharmony_ci	rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
60962306a36Sopenharmony_ci	if (rf->rf4)
61062306a36Sopenharmony_ci		rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
61462306a36Sopenharmony_ci				     const int txpower)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	u32 rf3;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	rf3 = rt2x00_rf_read(rt2x00dev, 3);
61962306a36Sopenharmony_ci	rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
62062306a36Sopenharmony_ci	rt2500usb_rf_write(rt2x00dev, 3, rf3);
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_cistatic void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
62462306a36Sopenharmony_ci				struct rt2x00lib_conf *libconf)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	enum dev_state state =
62762306a36Sopenharmony_ci	    (libconf->conf->flags & IEEE80211_CONF_PS) ?
62862306a36Sopenharmony_ci		STATE_SLEEP : STATE_AWAKE;
62962306a36Sopenharmony_ci	u16 reg;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	if (state == STATE_SLEEP) {
63262306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
63362306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
63462306a36Sopenharmony_ci				   rt2x00dev->beacon_int - 20);
63562306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
63662306a36Sopenharmony_ci				   libconf->conf->listen_interval - 1);
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci		/* We must first disable autowake before it can be enabled */
63962306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
64062306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
64362306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
64462306a36Sopenharmony_ci	} else {
64562306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
64662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
64762306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
64862306a36Sopenharmony_ci	}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
65462306a36Sopenharmony_ci			     struct rt2x00lib_conf *libconf,
65562306a36Sopenharmony_ci			     const unsigned int flags)
65662306a36Sopenharmony_ci{
65762306a36Sopenharmony_ci	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
65862306a36Sopenharmony_ci		rt2500usb_config_channel(rt2x00dev, &libconf->rf,
65962306a36Sopenharmony_ci					 libconf->conf->power_level);
66062306a36Sopenharmony_ci	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
66162306a36Sopenharmony_ci	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
66262306a36Sopenharmony_ci		rt2500usb_config_txpower(rt2x00dev,
66362306a36Sopenharmony_ci					 libconf->conf->power_level);
66462306a36Sopenharmony_ci	if (flags & IEEE80211_CONF_CHANGE_PS)
66562306a36Sopenharmony_ci		rt2500usb_config_ps(rt2x00dev, libconf);
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci/*
66962306a36Sopenharmony_ci * Link tuning
67062306a36Sopenharmony_ci */
67162306a36Sopenharmony_cistatic void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
67262306a36Sopenharmony_ci				 struct link_qual *qual)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	u16 reg;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	/*
67762306a36Sopenharmony_ci	 * Update FCS error count from register.
67862306a36Sopenharmony_ci	 */
67962306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, STA_CSR0);
68062306a36Sopenharmony_ci	qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	/*
68362306a36Sopenharmony_ci	 * Update False CCA count from register.
68462306a36Sopenharmony_ci	 */
68562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, STA_CSR3);
68662306a36Sopenharmony_ci	qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
68762306a36Sopenharmony_ci}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_cistatic void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
69062306a36Sopenharmony_ci				  struct link_qual *qual)
69162306a36Sopenharmony_ci{
69262306a36Sopenharmony_ci	u16 eeprom;
69362306a36Sopenharmony_ci	u16 value;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
69662306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW);
69762306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 24, value);
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
70062306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW);
70162306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 25, value);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
70462306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW);
70562306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 61, value);
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
70862306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
70962306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 17, value);
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	qual->vgc_level = value;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci/*
71562306a36Sopenharmony_ci * Queue handlers.
71662306a36Sopenharmony_ci */
71762306a36Sopenharmony_cistatic void rt2500usb_start_queue(struct data_queue *queue)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
72062306a36Sopenharmony_ci	u16 reg;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	switch (queue->qid) {
72362306a36Sopenharmony_ci	case QID_RX:
72462306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
72562306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
72662306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
72762306a36Sopenharmony_ci		break;
72862306a36Sopenharmony_ci	case QID_BEACON:
72962306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
73062306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
73162306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
73262306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
73362306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
73462306a36Sopenharmony_ci		break;
73562306a36Sopenharmony_ci	default:
73662306a36Sopenharmony_ci		break;
73762306a36Sopenharmony_ci	}
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic void rt2500usb_stop_queue(struct data_queue *queue)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
74362306a36Sopenharmony_ci	u16 reg;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	switch (queue->qid) {
74662306a36Sopenharmony_ci	case QID_RX:
74762306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
74862306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
74962306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
75062306a36Sopenharmony_ci		break;
75162306a36Sopenharmony_ci	case QID_BEACON:
75262306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
75362306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
75462306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
75562306a36Sopenharmony_ci		rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
75662306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
75762306a36Sopenharmony_ci		break;
75862306a36Sopenharmony_ci	default:
75962306a36Sopenharmony_ci		break;
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci/*
76462306a36Sopenharmony_ci * Initialization functions.
76562306a36Sopenharmony_ci */
76662306a36Sopenharmony_cistatic int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	u16 reg;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001,
77162306a36Sopenharmony_ci				    USB_MODE_TEST, REGISTER_TIMEOUT);
77262306a36Sopenharmony_ci	rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308,
77362306a36Sopenharmony_ci				    0x00f0, REGISTER_TIMEOUT);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
77662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
77762306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
78062306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
78362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 1);
78462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 1);
78562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
78662306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
78962306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
79062306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
79162306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
79262306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR5);
79562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
79662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
79762306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1, 12);
79862306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1_VALID, 1);
79962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg);
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR6);
80262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0, 10);
80362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0_VALID, 1);
80462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1, 11);
80562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1_VALID, 1);
80662306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR7);
80962306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0, 7);
81062306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0_VALID, 1);
81162306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1, 6);
81262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1_VALID, 1);
81362306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg);
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR8);
81662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0, 5);
81762306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0_VALID, 1);
81862306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1, 0);
81962306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
82062306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
82362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
82462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
82562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
82662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
82762306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
83062306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
83362306a36Sopenharmony_ci		return -EBUSY;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
83662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
83762306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
83862306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
83962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
84262306a36Sopenharmony_ci		reg = rt2500usb_register_read(rt2x00dev, PHY_CSR2);
84362306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
84462306a36Sopenharmony_ci	} else {
84562306a36Sopenharmony_ci		reg = 0;
84662306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR2_LNA, 1);
84762306a36Sopenharmony_ci		rt2x00_set_field16(&reg, PHY_CSR2_LNA_MODE, 3);
84862306a36Sopenharmony_ci	}
84962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0002);
85262306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR22, 0x0053);
85362306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
85462306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR8);
85762306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR8_MAX_FRAME_UNIT,
85862306a36Sopenharmony_ci			   rt2x00dev->rx->data_size);
85962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
86262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
86362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
86462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
86562306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
86862306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON, 90);
86962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, PHY_CSR4);
87262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, PHY_CSR4_LOW_RF_LE, 1);
87362306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR1);
87662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR1_AUTO_SEQUENCE, 1);
87762306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	return 0;
88062306a36Sopenharmony_ci}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_cistatic int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
88362306a36Sopenharmony_ci{
88462306a36Sopenharmony_ci	unsigned int i;
88562306a36Sopenharmony_ci	u8 value;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
88862306a36Sopenharmony_ci		value = rt2500usb_bbp_read(rt2x00dev, 0);
88962306a36Sopenharmony_ci		if ((value != 0xff) && (value != 0x00))
89062306a36Sopenharmony_ci			return 0;
89162306a36Sopenharmony_ci		udelay(REGISTER_BUSY_DELAY);
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
89562306a36Sopenharmony_ci	return -EACCES;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistatic int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	unsigned int i;
90162306a36Sopenharmony_ci	u16 eeprom;
90262306a36Sopenharmony_ci	u8 value;
90362306a36Sopenharmony_ci	u8 reg_id;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev)))
90662306a36Sopenharmony_ci		return -EACCES;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 3, 0x02);
90962306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 4, 0x19);
91062306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 14, 0x1c);
91162306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 15, 0x30);
91262306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 16, 0xac);
91362306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 18, 0x18);
91462306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 19, 0xff);
91562306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 20, 0x1e);
91662306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 21, 0x08);
91762306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 22, 0x08);
91862306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 23, 0x08);
91962306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 24, 0x80);
92062306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 25, 0x50);
92162306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 26, 0x08);
92262306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 27, 0x23);
92362306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 30, 0x10);
92462306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 31, 0x2b);
92562306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 32, 0xb9);
92662306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 34, 0x12);
92762306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 35, 0x50);
92862306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 39, 0xc4);
92962306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 40, 0x02);
93062306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 41, 0x60);
93162306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 53, 0x10);
93262306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 54, 0x18);
93362306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 56, 0x08);
93462306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 57, 0x10);
93562306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 58, 0x08);
93662306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 61, 0x60);
93762306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
93862306a36Sopenharmony_ci	rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
94162306a36Sopenharmony_ci		eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci		if (eeprom != 0xffff && eeprom != 0x0000) {
94462306a36Sopenharmony_ci			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
94562306a36Sopenharmony_ci			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
94662306a36Sopenharmony_ci			rt2500usb_bbp_write(rt2x00dev, reg_id, value);
94762306a36Sopenharmony_ci		}
94862306a36Sopenharmony_ci	}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	return 0;
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci/*
95462306a36Sopenharmony_ci * Device state switch handlers.
95562306a36Sopenharmony_ci */
95662306a36Sopenharmony_cistatic int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	/*
95962306a36Sopenharmony_ci	 * Initialize all registers.
96062306a36Sopenharmony_ci	 */
96162306a36Sopenharmony_ci	if (unlikely(rt2500usb_init_registers(rt2x00dev) ||
96262306a36Sopenharmony_ci		     rt2500usb_init_bbp(rt2x00dev)))
96362306a36Sopenharmony_ci		return -EIO;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	return 0;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
96962306a36Sopenharmony_ci{
97062306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
97162306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	/*
97462306a36Sopenharmony_ci	 * Disable synchronisation.
97562306a36Sopenharmony_ci	 */
97662306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	rt2x00usb_disable_radio(rt2x00dev);
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cistatic int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev,
98262306a36Sopenharmony_ci			       enum dev_state state)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	u16 reg;
98562306a36Sopenharmony_ci	u16 reg2;
98662306a36Sopenharmony_ci	unsigned int i;
98762306a36Sopenharmony_ci	bool put_to_sleep;
98862306a36Sopenharmony_ci	u8 bbp_state;
98962306a36Sopenharmony_ci	u8 rf_state;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	put_to_sleep = (state != STATE_AWAKE);
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	reg = 0;
99462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
99562306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
99662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
99762306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
99862306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR17_SET_STATE, 1);
99962306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	/*
100262306a36Sopenharmony_ci	 * Device is not guaranteed to be in the requested state yet.
100362306a36Sopenharmony_ci	 * We must wait until the register indicates that the
100462306a36Sopenharmony_ci	 * device has entered the correct state.
100562306a36Sopenharmony_ci	 */
100662306a36Sopenharmony_ci	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
100762306a36Sopenharmony_ci		reg2 = rt2500usb_register_read(rt2x00dev, MAC_CSR17);
100862306a36Sopenharmony_ci		bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
100962306a36Sopenharmony_ci		rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
101062306a36Sopenharmony_ci		if (bbp_state == state && rf_state == state)
101162306a36Sopenharmony_ci			return 0;
101262306a36Sopenharmony_ci		rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
101362306a36Sopenharmony_ci		msleep(30);
101462306a36Sopenharmony_ci	}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	return -EBUSY;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_cistatic int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
102062306a36Sopenharmony_ci				      enum dev_state state)
102162306a36Sopenharmony_ci{
102262306a36Sopenharmony_ci	int retval = 0;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	switch (state) {
102562306a36Sopenharmony_ci	case STATE_RADIO_ON:
102662306a36Sopenharmony_ci		retval = rt2500usb_enable_radio(rt2x00dev);
102762306a36Sopenharmony_ci		break;
102862306a36Sopenharmony_ci	case STATE_RADIO_OFF:
102962306a36Sopenharmony_ci		rt2500usb_disable_radio(rt2x00dev);
103062306a36Sopenharmony_ci		break;
103162306a36Sopenharmony_ci	case STATE_RADIO_IRQ_ON:
103262306a36Sopenharmony_ci	case STATE_RADIO_IRQ_OFF:
103362306a36Sopenharmony_ci		/* No support, but no error either */
103462306a36Sopenharmony_ci		break;
103562306a36Sopenharmony_ci	case STATE_DEEP_SLEEP:
103662306a36Sopenharmony_ci	case STATE_SLEEP:
103762306a36Sopenharmony_ci	case STATE_STANDBY:
103862306a36Sopenharmony_ci	case STATE_AWAKE:
103962306a36Sopenharmony_ci		retval = rt2500usb_set_state(rt2x00dev, state);
104062306a36Sopenharmony_ci		break;
104162306a36Sopenharmony_ci	default:
104262306a36Sopenharmony_ci		retval = -ENOTSUPP;
104362306a36Sopenharmony_ci		break;
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	if (unlikely(retval))
104762306a36Sopenharmony_ci		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
104862306a36Sopenharmony_ci			   state, retval);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	return retval;
105162306a36Sopenharmony_ci}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci/*
105462306a36Sopenharmony_ci * TX descriptor initialization
105562306a36Sopenharmony_ci */
105662306a36Sopenharmony_cistatic void rt2500usb_write_tx_desc(struct queue_entry *entry,
105762306a36Sopenharmony_ci				    struct txentry_desc *txdesc)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
106062306a36Sopenharmony_ci	__le32 *txd = (__le32 *) entry->skb->data;
106162306a36Sopenharmony_ci	u32 word;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	/*
106462306a36Sopenharmony_ci	 * Start writing the descriptor words.
106562306a36Sopenharmony_ci	 */
106662306a36Sopenharmony_ci	word = rt2x00_desc_read(txd, 0);
106762306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
106862306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
106962306a36Sopenharmony_ci			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
107062306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_ACK,
107162306a36Sopenharmony_ci			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
107262306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
107362306a36Sopenharmony_ci			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
107462306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_OFDM,
107562306a36Sopenharmony_ci			   (txdesc->rate_mode == RATE_MODE_OFDM));
107662306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
107762306a36Sopenharmony_ci			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
107862306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
107962306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
108062306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
108162306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
108262306a36Sopenharmony_ci	rt2x00_desc_write(txd, 0, word);
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	word = rt2x00_desc_read(txd, 1);
108562306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
108662306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
108762306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
108862306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
108962306a36Sopenharmony_ci	rt2x00_desc_write(txd, 1, word);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	word = rt2x00_desc_read(txd, 2);
109262306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
109362306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
109462306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
109562306a36Sopenharmony_ci			   txdesc->u.plcp.length_low);
109662306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
109762306a36Sopenharmony_ci			   txdesc->u.plcp.length_high);
109862306a36Sopenharmony_ci	rt2x00_desc_write(txd, 2, word);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
110162306a36Sopenharmony_ci		_rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
110262306a36Sopenharmony_ci		_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
110362306a36Sopenharmony_ci	}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	/*
110662306a36Sopenharmony_ci	 * Register descriptor details in skb frame descriptor.
110762306a36Sopenharmony_ci	 */
110862306a36Sopenharmony_ci	skbdesc->flags |= SKBDESC_DESC_IN_SKB;
110962306a36Sopenharmony_ci	skbdesc->desc = txd;
111062306a36Sopenharmony_ci	skbdesc->desc_len = TXD_DESC_SIZE;
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci/*
111462306a36Sopenharmony_ci * TX data initialization
111562306a36Sopenharmony_ci */
111662306a36Sopenharmony_cistatic void rt2500usb_beacondone(struct urb *urb);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_cistatic void rt2500usb_write_beacon(struct queue_entry *entry,
111962306a36Sopenharmony_ci				   struct txentry_desc *txdesc)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
112262306a36Sopenharmony_ci	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
112362306a36Sopenharmony_ci	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
112462306a36Sopenharmony_ci	int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
112562306a36Sopenharmony_ci	int length;
112662306a36Sopenharmony_ci	u16 reg, reg0;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	/*
112962306a36Sopenharmony_ci	 * Disable beaconing while we are reloading the beacon data,
113062306a36Sopenharmony_ci	 * otherwise we might be sending out invalid data.
113162306a36Sopenharmony_ci	 */
113262306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
113362306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
113462306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	/*
113762306a36Sopenharmony_ci	 * Add space for the descriptor in front of the skb.
113862306a36Sopenharmony_ci	 */
113962306a36Sopenharmony_ci	skb_push(entry->skb, TXD_DESC_SIZE);
114062306a36Sopenharmony_ci	memset(entry->skb->data, 0, TXD_DESC_SIZE);
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	/*
114362306a36Sopenharmony_ci	 * Write the TX descriptor for the beacon.
114462306a36Sopenharmony_ci	 */
114562306a36Sopenharmony_ci	rt2500usb_write_tx_desc(entry, txdesc);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	/*
114862306a36Sopenharmony_ci	 * Dump beacon to userspace through debugfs.
114962306a36Sopenharmony_ci	 */
115062306a36Sopenharmony_ci	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	/*
115362306a36Sopenharmony_ci	 * USB devices cannot blindly pass the skb->len as the
115462306a36Sopenharmony_ci	 * length of the data to usb_fill_bulk_urb. Pass the skb
115562306a36Sopenharmony_ci	 * to the driver to determine what the length should be.
115662306a36Sopenharmony_ci	 */
115762306a36Sopenharmony_ci	length = rt2x00dev->ops->lib->get_tx_data_len(entry);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
116062306a36Sopenharmony_ci			  entry->skb->data, length, rt2500usb_beacondone,
116162306a36Sopenharmony_ci			  entry);
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	/*
116462306a36Sopenharmony_ci	 * Second we need to create the guardian byte.
116562306a36Sopenharmony_ci	 * We only need a single byte, so lets recycle
116662306a36Sopenharmony_ci	 * the 'flags' field we are not using for beacons.
116762306a36Sopenharmony_ci	 */
116862306a36Sopenharmony_ci	bcn_priv->guardian_data = 0;
116962306a36Sopenharmony_ci	usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
117062306a36Sopenharmony_ci			  &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
117162306a36Sopenharmony_ci			  entry);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	/*
117462306a36Sopenharmony_ci	 * Send out the guardian byte.
117562306a36Sopenharmony_ci	 */
117662306a36Sopenharmony_ci	usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	/*
117962306a36Sopenharmony_ci	 * Enable beaconing again.
118062306a36Sopenharmony_ci	 */
118162306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
118262306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
118362306a36Sopenharmony_ci	reg0 = reg;
118462306a36Sopenharmony_ci	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
118562306a36Sopenharmony_ci	/*
118662306a36Sopenharmony_ci	 * Beacon generation will fail initially.
118762306a36Sopenharmony_ci	 * To prevent this we need to change the TXRX_CSR19
118862306a36Sopenharmony_ci	 * register several times (reg0 is the same as reg
118962306a36Sopenharmony_ci	 * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
119062306a36Sopenharmony_ci	 * and 1 in reg).
119162306a36Sopenharmony_ci	 */
119262306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
119362306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
119462306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
119562306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
119662306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_cistatic int rt2500usb_get_tx_data_len(struct queue_entry *entry)
120062306a36Sopenharmony_ci{
120162306a36Sopenharmony_ci	int length;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	/*
120462306a36Sopenharmony_ci	 * The length _must_ be a multiple of 2,
120562306a36Sopenharmony_ci	 * but it must _not_ be a multiple of the USB packet size.
120662306a36Sopenharmony_ci	 */
120762306a36Sopenharmony_ci	length = roundup(entry->skb->len, 2);
120862306a36Sopenharmony_ci	length += (2 * !(length % entry->queue->usb_maxpacket));
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	return length;
121162306a36Sopenharmony_ci}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci/*
121462306a36Sopenharmony_ci * RX control handlers
121562306a36Sopenharmony_ci */
121662306a36Sopenharmony_cistatic void rt2500usb_fill_rxdone(struct queue_entry *entry,
121762306a36Sopenharmony_ci				  struct rxdone_entry_desc *rxdesc)
121862306a36Sopenharmony_ci{
121962306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
122062306a36Sopenharmony_ci	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
122162306a36Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
122262306a36Sopenharmony_ci	__le32 *rxd =
122362306a36Sopenharmony_ci	    (__le32 *)(entry->skb->data +
122462306a36Sopenharmony_ci		       (entry_priv->urb->actual_length -
122562306a36Sopenharmony_ci			entry->queue->desc_size));
122662306a36Sopenharmony_ci	u32 word0;
122762306a36Sopenharmony_ci	u32 word1;
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	/*
123062306a36Sopenharmony_ci	 * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
123162306a36Sopenharmony_ci	 * frame data in rt2x00usb.
123262306a36Sopenharmony_ci	 */
123362306a36Sopenharmony_ci	memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
123462306a36Sopenharmony_ci	rxd = (__le32 *)skbdesc->desc;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	/*
123762306a36Sopenharmony_ci	 * It is now safe to read the descriptor on all architectures.
123862306a36Sopenharmony_ci	 */
123962306a36Sopenharmony_ci	word0 = rt2x00_desc_read(rxd, 0);
124062306a36Sopenharmony_ci	word1 = rt2x00_desc_read(rxd, 1);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
124362306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
124462306a36Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
124562306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
124862306a36Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
124962306a36Sopenharmony_ci		rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	if (rxdesc->cipher != CIPHER_NONE) {
125262306a36Sopenharmony_ci		rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
125362306a36Sopenharmony_ci		rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
125462306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci		/* ICV is located at the end of frame */
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
125962306a36Sopenharmony_ci		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
126062306a36Sopenharmony_ci			rxdesc->flags |= RX_FLAG_DECRYPTED;
126162306a36Sopenharmony_ci		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
126262306a36Sopenharmony_ci			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
126362306a36Sopenharmony_ci	}
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	/*
126662306a36Sopenharmony_ci	 * Obtain the status about this packet.
126762306a36Sopenharmony_ci	 * When frame was received with an OFDM bitrate,
126862306a36Sopenharmony_ci	 * the signal is the PLCP value. If it was received with
126962306a36Sopenharmony_ci	 * a CCK bitrate the signal is the rate in 100kbit/s.
127062306a36Sopenharmony_ci	 */
127162306a36Sopenharmony_ci	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
127262306a36Sopenharmony_ci	rxdesc->rssi =
127362306a36Sopenharmony_ci	    rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset;
127462306a36Sopenharmony_ci	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
127762306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
127862306a36Sopenharmony_ci	else
127962306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
128062306a36Sopenharmony_ci	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
128162306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_MY_BSS;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	/*
128462306a36Sopenharmony_ci	 * Adjust the skb memory window to the frame boundaries.
128562306a36Sopenharmony_ci	 */
128662306a36Sopenharmony_ci	skb_trim(entry->skb, rxdesc->size);
128762306a36Sopenharmony_ci}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci/*
129062306a36Sopenharmony_ci * Interrupt functions.
129162306a36Sopenharmony_ci */
129262306a36Sopenharmony_cistatic void rt2500usb_beacondone(struct urb *urb)
129362306a36Sopenharmony_ci{
129462306a36Sopenharmony_ci	struct queue_entry *entry = (struct queue_entry *)urb->context;
129562306a36Sopenharmony_ci	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
129862306a36Sopenharmony_ci		return;
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	/*
130162306a36Sopenharmony_ci	 * Check if this was the guardian beacon,
130262306a36Sopenharmony_ci	 * if that was the case we need to send the real beacon now.
130362306a36Sopenharmony_ci	 * Otherwise we should free the sk_buffer, the device
130462306a36Sopenharmony_ci	 * should be doing the rest of the work now.
130562306a36Sopenharmony_ci	 */
130662306a36Sopenharmony_ci	if (bcn_priv->guardian_urb == urb) {
130762306a36Sopenharmony_ci		usb_submit_urb(bcn_priv->urb, GFP_ATOMIC);
130862306a36Sopenharmony_ci	} else if (bcn_priv->urb == urb) {
130962306a36Sopenharmony_ci		dev_kfree_skb(entry->skb);
131062306a36Sopenharmony_ci		entry->skb = NULL;
131162306a36Sopenharmony_ci	}
131262306a36Sopenharmony_ci}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci/*
131562306a36Sopenharmony_ci * Device probe functions.
131662306a36Sopenharmony_ci */
131762306a36Sopenharmony_cistatic int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
131862306a36Sopenharmony_ci{
131962306a36Sopenharmony_ci	u16 word;
132062306a36Sopenharmony_ci	u8 *mac;
132162306a36Sopenharmony_ci	u8 bbp;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	/*
132662306a36Sopenharmony_ci	 * Start validation of the data that has been read.
132762306a36Sopenharmony_ci	 */
132862306a36Sopenharmony_ci	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
132962306a36Sopenharmony_ci	rt2x00lib_set_mac_address(rt2x00dev, mac);
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
133262306a36Sopenharmony_ci	if (word == 0xffff) {
133362306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
133462306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
133562306a36Sopenharmony_ci				   ANTENNA_SW_DIVERSITY);
133662306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
133762306a36Sopenharmony_ci				   ANTENNA_SW_DIVERSITY);
133862306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
133962306a36Sopenharmony_ci				   LED_MODE_DEFAULT);
134062306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
134162306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
134262306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
134362306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
134462306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
134562306a36Sopenharmony_ci	}
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
134862306a36Sopenharmony_ci	if (word == 0xffff) {
134962306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
135062306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
135162306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
135262306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
135362306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
135462306a36Sopenharmony_ci	}
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
135762306a36Sopenharmony_ci	if (word == 0xffff) {
135862306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
135962306a36Sopenharmony_ci				   DEFAULT_RSSI_OFFSET);
136062306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
136162306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
136262306a36Sopenharmony_ci				  word);
136362306a36Sopenharmony_ci	}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE);
136662306a36Sopenharmony_ci	if (word == 0xffff) {
136762306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
136862306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
136962306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);
137062306a36Sopenharmony_ci	}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	/*
137362306a36Sopenharmony_ci	 * Switch lower vgc bound to current BBP R17 value,
137462306a36Sopenharmony_ci	 * lower the value a bit for better quality.
137562306a36Sopenharmony_ci	 */
137662306a36Sopenharmony_ci	bbp = rt2500usb_bbp_read(rt2x00dev, 17);
137762306a36Sopenharmony_ci	bbp -= 6;
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
138062306a36Sopenharmony_ci	if (word == 0xffff) {
138162306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
138262306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
138362306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
138462306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
138562306a36Sopenharmony_ci	} else {
138662306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
138762306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17);
139162306a36Sopenharmony_ci	if (word == 0xffff) {
139262306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
139362306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
139462306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
139562306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
139662306a36Sopenharmony_ci	}
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
139962306a36Sopenharmony_ci	if (word == 0xffff) {
140062306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
140162306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
140262306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word);
140362306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
140462306a36Sopenharmony_ci	}
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
140762306a36Sopenharmony_ci	if (word == 0xffff) {
140862306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
140962306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
141062306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word);
141162306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
141262306a36Sopenharmony_ci	}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
141562306a36Sopenharmony_ci	if (word == 0xffff) {
141662306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
141762306a36Sopenharmony_ci		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
141862306a36Sopenharmony_ci		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word);
141962306a36Sopenharmony_ci		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	return 0;
142362306a36Sopenharmony_ci}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_cistatic int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
142662306a36Sopenharmony_ci{
142762306a36Sopenharmony_ci	u16 reg;
142862306a36Sopenharmony_ci	u16 value;
142962306a36Sopenharmony_ci	u16 eeprom;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	/*
143262306a36Sopenharmony_ci	 * Read EEPROM word for configuration.
143362306a36Sopenharmony_ci	 */
143462306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	/*
143762306a36Sopenharmony_ci	 * Identify RF chipset.
143862306a36Sopenharmony_ci	 */
143962306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
144062306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR0);
144162306a36Sopenharmony_ci	rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
144462306a36Sopenharmony_ci		rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
144562306a36Sopenharmony_ci		return -ENODEV;
144662306a36Sopenharmony_ci	}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (!rt2x00_rf(rt2x00dev, RF2522) &&
144962306a36Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2523) &&
145062306a36Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2524) &&
145162306a36Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2525) &&
145262306a36Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF2525E) &&
145362306a36Sopenharmony_ci	    !rt2x00_rf(rt2x00dev, RF5222)) {
145462306a36Sopenharmony_ci		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
145562306a36Sopenharmony_ci		return -ENODEV;
145662306a36Sopenharmony_ci	}
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	/*
145962306a36Sopenharmony_ci	 * Identify default antenna configuration.
146062306a36Sopenharmony_ci	 */
146162306a36Sopenharmony_ci	rt2x00dev->default_ant.tx =
146262306a36Sopenharmony_ci	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
146362306a36Sopenharmony_ci	rt2x00dev->default_ant.rx =
146462306a36Sopenharmony_ci	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	/*
146762306a36Sopenharmony_ci	 * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
146862306a36Sopenharmony_ci	 * I am not 100% sure about this, but the legacy drivers do not
146962306a36Sopenharmony_ci	 * indicate antenna swapping in software is required when
147062306a36Sopenharmony_ci	 * diversity is enabled.
147162306a36Sopenharmony_ci	 */
147262306a36Sopenharmony_ci	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
147362306a36Sopenharmony_ci		rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
147462306a36Sopenharmony_ci	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
147562306a36Sopenharmony_ci		rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	/*
147862306a36Sopenharmony_ci	 * Store led mode, for correct led behaviour.
147962306a36Sopenharmony_ci	 */
148062306a36Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS
148162306a36Sopenharmony_ci	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
148462306a36Sopenharmony_ci	if (value == LED_MODE_TXRX_ACTIVITY ||
148562306a36Sopenharmony_ci	    value == LED_MODE_DEFAULT ||
148662306a36Sopenharmony_ci	    value == LED_MODE_ASUS)
148762306a36Sopenharmony_ci		rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
148862306a36Sopenharmony_ci				   LED_TYPE_ACTIVITY);
148962306a36Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	/*
149262306a36Sopenharmony_ci	 * Detect if this device has an hardware controlled radio.
149362306a36Sopenharmony_ci	 */
149462306a36Sopenharmony_ci	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
149562306a36Sopenharmony_ci		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	/*
149862306a36Sopenharmony_ci	 * Read the RSSI <-> dBm offset information.
149962306a36Sopenharmony_ci	 */
150062306a36Sopenharmony_ci	eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
150162306a36Sopenharmony_ci	rt2x00dev->rssi_offset =
150262306a36Sopenharmony_ci	    rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	return 0;
150562306a36Sopenharmony_ci}
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci/*
150862306a36Sopenharmony_ci * RF value list for RF2522
150962306a36Sopenharmony_ci * Supports: 2.4 GHz
151062306a36Sopenharmony_ci */
151162306a36Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2522[] = {
151262306a36Sopenharmony_ci	{ 1,  0x00002050, 0x000c1fda, 0x00000101, 0 },
151362306a36Sopenharmony_ci	{ 2,  0x00002050, 0x000c1fee, 0x00000101, 0 },
151462306a36Sopenharmony_ci	{ 3,  0x00002050, 0x000c2002, 0x00000101, 0 },
151562306a36Sopenharmony_ci	{ 4,  0x00002050, 0x000c2016, 0x00000101, 0 },
151662306a36Sopenharmony_ci	{ 5,  0x00002050, 0x000c202a, 0x00000101, 0 },
151762306a36Sopenharmony_ci	{ 6,  0x00002050, 0x000c203e, 0x00000101, 0 },
151862306a36Sopenharmony_ci	{ 7,  0x00002050, 0x000c2052, 0x00000101, 0 },
151962306a36Sopenharmony_ci	{ 8,  0x00002050, 0x000c2066, 0x00000101, 0 },
152062306a36Sopenharmony_ci	{ 9,  0x00002050, 0x000c207a, 0x00000101, 0 },
152162306a36Sopenharmony_ci	{ 10, 0x00002050, 0x000c208e, 0x00000101, 0 },
152262306a36Sopenharmony_ci	{ 11, 0x00002050, 0x000c20a2, 0x00000101, 0 },
152362306a36Sopenharmony_ci	{ 12, 0x00002050, 0x000c20b6, 0x00000101, 0 },
152462306a36Sopenharmony_ci	{ 13, 0x00002050, 0x000c20ca, 0x00000101, 0 },
152562306a36Sopenharmony_ci	{ 14, 0x00002050, 0x000c20fa, 0x00000101, 0 },
152662306a36Sopenharmony_ci};
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci/*
152962306a36Sopenharmony_ci * RF value list for RF2523
153062306a36Sopenharmony_ci * Supports: 2.4 GHz
153162306a36Sopenharmony_ci */
153262306a36Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2523[] = {
153362306a36Sopenharmony_ci	{ 1,  0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b },
153462306a36Sopenharmony_ci	{ 2,  0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b },
153562306a36Sopenharmony_ci	{ 3,  0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b },
153662306a36Sopenharmony_ci	{ 4,  0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b },
153762306a36Sopenharmony_ci	{ 5,  0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b },
153862306a36Sopenharmony_ci	{ 6,  0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b },
153962306a36Sopenharmony_ci	{ 7,  0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b },
154062306a36Sopenharmony_ci	{ 8,  0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b },
154162306a36Sopenharmony_ci	{ 9,  0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b },
154262306a36Sopenharmony_ci	{ 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b },
154362306a36Sopenharmony_ci	{ 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b },
154462306a36Sopenharmony_ci	{ 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b },
154562306a36Sopenharmony_ci	{ 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b },
154662306a36Sopenharmony_ci	{ 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 },
154762306a36Sopenharmony_ci};
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci/*
155062306a36Sopenharmony_ci * RF value list for RF2524
155162306a36Sopenharmony_ci * Supports: 2.4 GHz
155262306a36Sopenharmony_ci */
155362306a36Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2524[] = {
155462306a36Sopenharmony_ci	{ 1,  0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b },
155562306a36Sopenharmony_ci	{ 2,  0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b },
155662306a36Sopenharmony_ci	{ 3,  0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b },
155762306a36Sopenharmony_ci	{ 4,  0x00032020, 0x00000caa, 0x00000101, 0x00000a1b },
155862306a36Sopenharmony_ci	{ 5,  0x00032020, 0x00000cae, 0x00000101, 0x00000a1b },
155962306a36Sopenharmony_ci	{ 6,  0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b },
156062306a36Sopenharmony_ci	{ 7,  0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b },
156162306a36Sopenharmony_ci	{ 8,  0x00032020, 0x00000cba, 0x00000101, 0x00000a1b },
156262306a36Sopenharmony_ci	{ 9,  0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b },
156362306a36Sopenharmony_ci	{ 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b },
156462306a36Sopenharmony_ci	{ 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b },
156562306a36Sopenharmony_ci	{ 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b },
156662306a36Sopenharmony_ci	{ 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b },
156762306a36Sopenharmony_ci	{ 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 },
156862306a36Sopenharmony_ci};
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci/*
157162306a36Sopenharmony_ci * RF value list for RF2525
157262306a36Sopenharmony_ci * Supports: 2.4 GHz
157362306a36Sopenharmony_ci */
157462306a36Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525[] = {
157562306a36Sopenharmony_ci	{ 1,  0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b },
157662306a36Sopenharmony_ci	{ 2,  0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b },
157762306a36Sopenharmony_ci	{ 3,  0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b },
157862306a36Sopenharmony_ci	{ 4,  0x00022020, 0x00080caa, 0x00060111, 0x00000a1b },
157962306a36Sopenharmony_ci	{ 5,  0x00022020, 0x00080cae, 0x00060111, 0x00000a1b },
158062306a36Sopenharmony_ci	{ 6,  0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b },
158162306a36Sopenharmony_ci	{ 7,  0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b },
158262306a36Sopenharmony_ci	{ 8,  0x00022020, 0x00080cba, 0x00060111, 0x00000a1b },
158362306a36Sopenharmony_ci	{ 9,  0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b },
158462306a36Sopenharmony_ci	{ 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b },
158562306a36Sopenharmony_ci	{ 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b },
158662306a36Sopenharmony_ci	{ 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b },
158762306a36Sopenharmony_ci	{ 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b },
158862306a36Sopenharmony_ci	{ 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 },
158962306a36Sopenharmony_ci};
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci/*
159262306a36Sopenharmony_ci * RF value list for RF2525e
159362306a36Sopenharmony_ci * Supports: 2.4 GHz
159462306a36Sopenharmony_ci */
159562306a36Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525e[] = {
159662306a36Sopenharmony_ci	{ 1,  0x00022010, 0x0000089a, 0x00060111, 0x00000e1b },
159762306a36Sopenharmony_ci	{ 2,  0x00022010, 0x0000089e, 0x00060111, 0x00000e07 },
159862306a36Sopenharmony_ci	{ 3,  0x00022010, 0x0000089e, 0x00060111, 0x00000e1b },
159962306a36Sopenharmony_ci	{ 4,  0x00022010, 0x000008a2, 0x00060111, 0x00000e07 },
160062306a36Sopenharmony_ci	{ 5,  0x00022010, 0x000008a2, 0x00060111, 0x00000e1b },
160162306a36Sopenharmony_ci	{ 6,  0x00022010, 0x000008a6, 0x00060111, 0x00000e07 },
160262306a36Sopenharmony_ci	{ 7,  0x00022010, 0x000008a6, 0x00060111, 0x00000e1b },
160362306a36Sopenharmony_ci	{ 8,  0x00022010, 0x000008aa, 0x00060111, 0x00000e07 },
160462306a36Sopenharmony_ci	{ 9,  0x00022010, 0x000008aa, 0x00060111, 0x00000e1b },
160562306a36Sopenharmony_ci	{ 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 },
160662306a36Sopenharmony_ci	{ 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b },
160762306a36Sopenharmony_ci	{ 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 },
160862306a36Sopenharmony_ci	{ 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b },
160962306a36Sopenharmony_ci	{ 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 },
161062306a36Sopenharmony_ci};
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci/*
161362306a36Sopenharmony_ci * RF value list for RF5222
161462306a36Sopenharmony_ci * Supports: 2.4 GHz & 5.2 GHz
161562306a36Sopenharmony_ci */
161662306a36Sopenharmony_cistatic const struct rf_channel rf_vals_5222[] = {
161762306a36Sopenharmony_ci	{ 1,  0x00022020, 0x00001136, 0x00000101, 0x00000a0b },
161862306a36Sopenharmony_ci	{ 2,  0x00022020, 0x0000113a, 0x00000101, 0x00000a0b },
161962306a36Sopenharmony_ci	{ 3,  0x00022020, 0x0000113e, 0x00000101, 0x00000a0b },
162062306a36Sopenharmony_ci	{ 4,  0x00022020, 0x00001182, 0x00000101, 0x00000a0b },
162162306a36Sopenharmony_ci	{ 5,  0x00022020, 0x00001186, 0x00000101, 0x00000a0b },
162262306a36Sopenharmony_ci	{ 6,  0x00022020, 0x0000118a, 0x00000101, 0x00000a0b },
162362306a36Sopenharmony_ci	{ 7,  0x00022020, 0x0000118e, 0x00000101, 0x00000a0b },
162462306a36Sopenharmony_ci	{ 8,  0x00022020, 0x00001192, 0x00000101, 0x00000a0b },
162562306a36Sopenharmony_ci	{ 9,  0x00022020, 0x00001196, 0x00000101, 0x00000a0b },
162662306a36Sopenharmony_ci	{ 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b },
162762306a36Sopenharmony_ci	{ 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b },
162862306a36Sopenharmony_ci	{ 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b },
162962306a36Sopenharmony_ci	{ 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b },
163062306a36Sopenharmony_ci	{ 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b },
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	/* 802.11 UNI / HyperLan 2 */
163362306a36Sopenharmony_ci	{ 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f },
163462306a36Sopenharmony_ci	{ 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f },
163562306a36Sopenharmony_ci	{ 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f },
163662306a36Sopenharmony_ci	{ 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f },
163762306a36Sopenharmony_ci	{ 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f },
163862306a36Sopenharmony_ci	{ 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f },
163962306a36Sopenharmony_ci	{ 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f },
164062306a36Sopenharmony_ci	{ 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f },
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	/* 802.11 HyperLan 2 */
164362306a36Sopenharmony_ci	{ 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f },
164462306a36Sopenharmony_ci	{ 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f },
164562306a36Sopenharmony_ci	{ 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f },
164662306a36Sopenharmony_ci	{ 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f },
164762306a36Sopenharmony_ci	{ 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f },
164862306a36Sopenharmony_ci	{ 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f },
164962306a36Sopenharmony_ci	{ 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f },
165062306a36Sopenharmony_ci	{ 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f },
165162306a36Sopenharmony_ci	{ 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f },
165262306a36Sopenharmony_ci	{ 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f },
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	/* 802.11 UNII */
165562306a36Sopenharmony_ci	{ 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f },
165662306a36Sopenharmony_ci	{ 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 },
165762306a36Sopenharmony_ci	{ 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 },
165862306a36Sopenharmony_ci	{ 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 },
165962306a36Sopenharmony_ci	{ 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
166062306a36Sopenharmony_ci};
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_cistatic int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
166362306a36Sopenharmony_ci{
166462306a36Sopenharmony_ci	struct hw_mode_spec *spec = &rt2x00dev->spec;
166562306a36Sopenharmony_ci	struct channel_info *info;
166662306a36Sopenharmony_ci	u8 *tx_power;
166762306a36Sopenharmony_ci	unsigned int i;
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	/*
167062306a36Sopenharmony_ci	 * Initialize all hw fields.
167162306a36Sopenharmony_ci	 *
167262306a36Sopenharmony_ci	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
167362306a36Sopenharmony_ci	 * capable of sending the buffered frames out after the DTIM
167462306a36Sopenharmony_ci	 * transmission using rt2x00lib_beacondone. This will send out
167562306a36Sopenharmony_ci	 * multicast and broadcast traffic immediately instead of buffering it
167662306a36Sopenharmony_ci	 * infinitly and thus dropping it after some time.
167762306a36Sopenharmony_ci	 */
167862306a36Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
167962306a36Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
168062306a36Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, RX_INCLUDES_FCS);
168162306a36Sopenharmony_ci	ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	/*
168462306a36Sopenharmony_ci	 * Disable powersaving as default.
168562306a36Sopenharmony_ci	 */
168662306a36Sopenharmony_ci	rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
168962306a36Sopenharmony_ci	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
169062306a36Sopenharmony_ci				rt2x00_eeprom_addr(rt2x00dev,
169162306a36Sopenharmony_ci						   EEPROM_MAC_ADDR_0));
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci	/*
169462306a36Sopenharmony_ci	 * Initialize hw_mode information.
169562306a36Sopenharmony_ci	 */
169662306a36Sopenharmony_ci	spec->supported_bands = SUPPORT_BAND_2GHZ;
169762306a36Sopenharmony_ci	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	if (rt2x00_rf(rt2x00dev, RF2522)) {
170062306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
170162306a36Sopenharmony_ci		spec->channels = rf_vals_bg_2522;
170262306a36Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF2523)) {
170362306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
170462306a36Sopenharmony_ci		spec->channels = rf_vals_bg_2523;
170562306a36Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF2524)) {
170662306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
170762306a36Sopenharmony_ci		spec->channels = rf_vals_bg_2524;
170862306a36Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF2525)) {
170962306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
171062306a36Sopenharmony_ci		spec->channels = rf_vals_bg_2525;
171162306a36Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF2525E)) {
171262306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
171362306a36Sopenharmony_ci		spec->channels = rf_vals_bg_2525e;
171462306a36Sopenharmony_ci	} else if (rt2x00_rf(rt2x00dev, RF5222)) {
171562306a36Sopenharmony_ci		spec->supported_bands |= SUPPORT_BAND_5GHZ;
171662306a36Sopenharmony_ci		spec->num_channels = ARRAY_SIZE(rf_vals_5222);
171762306a36Sopenharmony_ci		spec->channels = rf_vals_5222;
171862306a36Sopenharmony_ci	}
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	/*
172162306a36Sopenharmony_ci	 * Create channel information array
172262306a36Sopenharmony_ci	 */
172362306a36Sopenharmony_ci	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
172462306a36Sopenharmony_ci	if (!info)
172562306a36Sopenharmony_ci		return -ENOMEM;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	spec->channels_info = info;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
173062306a36Sopenharmony_ci	for (i = 0; i < 14; i++) {
173162306a36Sopenharmony_ci		info[i].max_power = MAX_TXPOWER;
173262306a36Sopenharmony_ci		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
173362306a36Sopenharmony_ci	}
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	if (spec->num_channels > 14) {
173662306a36Sopenharmony_ci		for (i = 14; i < spec->num_channels; i++) {
173762306a36Sopenharmony_ci			info[i].max_power = MAX_TXPOWER;
173862306a36Sopenharmony_ci			info[i].default_power1 = DEFAULT_TXPOWER;
173962306a36Sopenharmony_ci		}
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	return 0;
174362306a36Sopenharmony_ci}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_cistatic int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
174662306a36Sopenharmony_ci{
174762306a36Sopenharmony_ci	int retval;
174862306a36Sopenharmony_ci	u16 reg;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	/*
175162306a36Sopenharmony_ci	 * Allocate eeprom data.
175262306a36Sopenharmony_ci	 */
175362306a36Sopenharmony_ci	retval = rt2500usb_validate_eeprom(rt2x00dev);
175462306a36Sopenharmony_ci	if (retval)
175562306a36Sopenharmony_ci		return retval;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	retval = rt2500usb_init_eeprom(rt2x00dev);
175862306a36Sopenharmony_ci	if (retval)
175962306a36Sopenharmony_ci		return retval;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	/*
176262306a36Sopenharmony_ci	 * Enable rfkill polling by setting GPIO direction of the
176362306a36Sopenharmony_ci	 * rfkill switch GPIO pin correctly.
176462306a36Sopenharmony_ci	 */
176562306a36Sopenharmony_ci	reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
176662306a36Sopenharmony_ci	rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
176762306a36Sopenharmony_ci	rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	/*
177062306a36Sopenharmony_ci	 * Initialize hw specifications.
177162306a36Sopenharmony_ci	 */
177262306a36Sopenharmony_ci	retval = rt2500usb_probe_hw_mode(rt2x00dev);
177362306a36Sopenharmony_ci	if (retval)
177462306a36Sopenharmony_ci		return retval;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	/*
177762306a36Sopenharmony_ci	 * This device requires the atim queue
177862306a36Sopenharmony_ci	 */
177962306a36Sopenharmony_ci	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
178062306a36Sopenharmony_ci	__set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
178162306a36Sopenharmony_ci	if (!modparam_nohwcrypt) {
178262306a36Sopenharmony_ci		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
178362306a36Sopenharmony_ci		__set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
178462306a36Sopenharmony_ci	}
178562306a36Sopenharmony_ci	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
178662306a36Sopenharmony_ci	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	/*
178962306a36Sopenharmony_ci	 * Set the rssi offset.
179062306a36Sopenharmony_ci	 */
179162306a36Sopenharmony_ci	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	return 0;
179462306a36Sopenharmony_ci}
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_cistatic const struct ieee80211_ops rt2500usb_mac80211_ops = {
179762306a36Sopenharmony_ci	.tx			= rt2x00mac_tx,
179862306a36Sopenharmony_ci	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,
179962306a36Sopenharmony_ci	.start			= rt2x00mac_start,
180062306a36Sopenharmony_ci	.stop			= rt2x00mac_stop,
180162306a36Sopenharmony_ci	.add_interface		= rt2x00mac_add_interface,
180262306a36Sopenharmony_ci	.remove_interface	= rt2x00mac_remove_interface,
180362306a36Sopenharmony_ci	.config			= rt2x00mac_config,
180462306a36Sopenharmony_ci	.configure_filter	= rt2x00mac_configure_filter,
180562306a36Sopenharmony_ci	.set_tim		= rt2x00mac_set_tim,
180662306a36Sopenharmony_ci	.set_key		= rt2x00mac_set_key,
180762306a36Sopenharmony_ci	.sw_scan_start		= rt2x00mac_sw_scan_start,
180862306a36Sopenharmony_ci	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
180962306a36Sopenharmony_ci	.get_stats		= rt2x00mac_get_stats,
181062306a36Sopenharmony_ci	.bss_info_changed	= rt2x00mac_bss_info_changed,
181162306a36Sopenharmony_ci	.conf_tx		= rt2x00mac_conf_tx,
181262306a36Sopenharmony_ci	.rfkill_poll		= rt2x00mac_rfkill_poll,
181362306a36Sopenharmony_ci	.flush			= rt2x00mac_flush,
181462306a36Sopenharmony_ci	.set_antenna		= rt2x00mac_set_antenna,
181562306a36Sopenharmony_ci	.get_antenna		= rt2x00mac_get_antenna,
181662306a36Sopenharmony_ci	.get_ringparam		= rt2x00mac_get_ringparam,
181762306a36Sopenharmony_ci	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
181862306a36Sopenharmony_ci};
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_cistatic const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
182162306a36Sopenharmony_ci	.probe_hw		= rt2500usb_probe_hw,
182262306a36Sopenharmony_ci	.initialize		= rt2x00usb_initialize,
182362306a36Sopenharmony_ci	.uninitialize		= rt2x00usb_uninitialize,
182462306a36Sopenharmony_ci	.clear_entry		= rt2x00usb_clear_entry,
182562306a36Sopenharmony_ci	.set_device_state	= rt2500usb_set_device_state,
182662306a36Sopenharmony_ci	.rfkill_poll		= rt2500usb_rfkill_poll,
182762306a36Sopenharmony_ci	.link_stats		= rt2500usb_link_stats,
182862306a36Sopenharmony_ci	.reset_tuner		= rt2500usb_reset_tuner,
182962306a36Sopenharmony_ci	.watchdog		= rt2x00usb_watchdog,
183062306a36Sopenharmony_ci	.start_queue		= rt2500usb_start_queue,
183162306a36Sopenharmony_ci	.kick_queue		= rt2x00usb_kick_queue,
183262306a36Sopenharmony_ci	.stop_queue		= rt2500usb_stop_queue,
183362306a36Sopenharmony_ci	.flush_queue		= rt2x00usb_flush_queue,
183462306a36Sopenharmony_ci	.write_tx_desc		= rt2500usb_write_tx_desc,
183562306a36Sopenharmony_ci	.write_beacon		= rt2500usb_write_beacon,
183662306a36Sopenharmony_ci	.get_tx_data_len	= rt2500usb_get_tx_data_len,
183762306a36Sopenharmony_ci	.fill_rxdone		= rt2500usb_fill_rxdone,
183862306a36Sopenharmony_ci	.config_shared_key	= rt2500usb_config_key,
183962306a36Sopenharmony_ci	.config_pairwise_key	= rt2500usb_config_key,
184062306a36Sopenharmony_ci	.config_filter		= rt2500usb_config_filter,
184162306a36Sopenharmony_ci	.config_intf		= rt2500usb_config_intf,
184262306a36Sopenharmony_ci	.config_erp		= rt2500usb_config_erp,
184362306a36Sopenharmony_ci	.config_ant		= rt2500usb_config_ant,
184462306a36Sopenharmony_ci	.config			= rt2500usb_config,
184562306a36Sopenharmony_ci};
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_cistatic void rt2500usb_queue_init(struct data_queue *queue)
184862306a36Sopenharmony_ci{
184962306a36Sopenharmony_ci	switch (queue->qid) {
185062306a36Sopenharmony_ci	case QID_RX:
185162306a36Sopenharmony_ci		queue->limit = 32;
185262306a36Sopenharmony_ci		queue->data_size = DATA_FRAME_SIZE;
185362306a36Sopenharmony_ci		queue->desc_size = RXD_DESC_SIZE;
185462306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
185562306a36Sopenharmony_ci		break;
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	case QID_AC_VO:
185862306a36Sopenharmony_ci	case QID_AC_VI:
185962306a36Sopenharmony_ci	case QID_AC_BE:
186062306a36Sopenharmony_ci	case QID_AC_BK:
186162306a36Sopenharmony_ci		queue->limit = 32;
186262306a36Sopenharmony_ci		queue->data_size = DATA_FRAME_SIZE;
186362306a36Sopenharmony_ci		queue->desc_size = TXD_DESC_SIZE;
186462306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
186562306a36Sopenharmony_ci		break;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	case QID_BEACON:
186862306a36Sopenharmony_ci		queue->limit = 1;
186962306a36Sopenharmony_ci		queue->data_size = MGMT_FRAME_SIZE;
187062306a36Sopenharmony_ci		queue->desc_size = TXD_DESC_SIZE;
187162306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn);
187262306a36Sopenharmony_ci		break;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	case QID_ATIM:
187562306a36Sopenharmony_ci		queue->limit = 8;
187662306a36Sopenharmony_ci		queue->data_size = DATA_FRAME_SIZE;
187762306a36Sopenharmony_ci		queue->desc_size = TXD_DESC_SIZE;
187862306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
187962306a36Sopenharmony_ci		break;
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	default:
188262306a36Sopenharmony_ci		BUG();
188362306a36Sopenharmony_ci		break;
188462306a36Sopenharmony_ci	}
188562306a36Sopenharmony_ci}
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_cistatic const struct rt2x00_ops rt2500usb_ops = {
188862306a36Sopenharmony_ci	.name			= KBUILD_MODNAME,
188962306a36Sopenharmony_ci	.max_ap_intf		= 1,
189062306a36Sopenharmony_ci	.eeprom_size		= EEPROM_SIZE,
189162306a36Sopenharmony_ci	.rf_size		= RF_SIZE,
189262306a36Sopenharmony_ci	.tx_queues		= NUM_TX_QUEUES,
189362306a36Sopenharmony_ci	.queue_init		= rt2500usb_queue_init,
189462306a36Sopenharmony_ci	.lib			= &rt2500usb_rt2x00_ops,
189562306a36Sopenharmony_ci	.hw			= &rt2500usb_mac80211_ops,
189662306a36Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS
189762306a36Sopenharmony_ci	.debugfs		= &rt2500usb_rt2x00debug,
189862306a36Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
189962306a36Sopenharmony_ci};
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci/*
190262306a36Sopenharmony_ci * rt2500usb module information.
190362306a36Sopenharmony_ci */
190462306a36Sopenharmony_cistatic const struct usb_device_id rt2500usb_device_table[] = {
190562306a36Sopenharmony_ci	/* ASUS */
190662306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1706) },
190762306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1707) },
190862306a36Sopenharmony_ci	/* Belkin */
190962306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x7050) },	/* FCC ID: K7SF5D7050A ver. 2.x */
191062306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x7051) },
191162306a36Sopenharmony_ci	/* Cisco Systems */
191262306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x000d) },
191362306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x0011) },
191462306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x001a) },
191562306a36Sopenharmony_ci	/* Conceptronic */
191662306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c02) },
191762306a36Sopenharmony_ci	/* D-LINK */
191862306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c00) },
191962306a36Sopenharmony_ci	/* Gigabyte */
192062306a36Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x8001) },
192162306a36Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x8007) },
192262306a36Sopenharmony_ci	/* Hercules */
192362306a36Sopenharmony_ci	{ USB_DEVICE(0x06f8, 0xe000) },
192462306a36Sopenharmony_ci	/* Melco */
192562306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x005e) },
192662306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0066) },
192762306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0067) },
192862306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x008b) },
192962306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0097) },
193062306a36Sopenharmony_ci	/* MSI */
193162306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6861) },
193262306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6865) },
193362306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6869) },
193462306a36Sopenharmony_ci	/* Ralink */
193562306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x1706) },
193662306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2570) },
193762306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x9020) },
193862306a36Sopenharmony_ci	/* Sagem */
193962306a36Sopenharmony_ci	{ USB_DEVICE(0x079b, 0x004b) },
194062306a36Sopenharmony_ci	/* Siemens */
194162306a36Sopenharmony_ci	{ USB_DEVICE(0x0681, 0x3c06) },
194262306a36Sopenharmony_ci	/* SMC */
194362306a36Sopenharmony_ci	{ USB_DEVICE(0x0707, 0xee13) },
194462306a36Sopenharmony_ci	/* Spairon */
194562306a36Sopenharmony_ci	{ USB_DEVICE(0x114b, 0x0110) },
194662306a36Sopenharmony_ci	/* SURECOM */
194762306a36Sopenharmony_ci	{ USB_DEVICE(0x0769, 0x11f3) },
194862306a36Sopenharmony_ci	/* Trust */
194962306a36Sopenharmony_ci	{ USB_DEVICE(0x0eb0, 0x9020) },
195062306a36Sopenharmony_ci	/* VTech */
195162306a36Sopenharmony_ci	{ USB_DEVICE(0x0f88, 0x3012) },
195262306a36Sopenharmony_ci	/* Zinwell */
195362306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x0260) },
195462306a36Sopenharmony_ci	{ 0, }
195562306a36Sopenharmony_ci};
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ciMODULE_AUTHOR(DRV_PROJECT);
195862306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION);
195962306a36Sopenharmony_ciMODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver.");
196062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
196162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_cistatic int rt2500usb_probe(struct usb_interface *usb_intf,
196462306a36Sopenharmony_ci			   const struct usb_device_id *id)
196562306a36Sopenharmony_ci{
196662306a36Sopenharmony_ci	return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
196762306a36Sopenharmony_ci}
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_cistatic struct usb_driver rt2500usb_driver = {
197062306a36Sopenharmony_ci	.name		= KBUILD_MODNAME,
197162306a36Sopenharmony_ci	.id_table	= rt2500usb_device_table,
197262306a36Sopenharmony_ci	.probe		= rt2500usb_probe,
197362306a36Sopenharmony_ci	.disconnect	= rt2x00usb_disconnect,
197462306a36Sopenharmony_ci	.suspend	= rt2x00usb_suspend,
197562306a36Sopenharmony_ci	.resume		= rt2x00usb_resume,
197662306a36Sopenharmony_ci	.reset_resume	= rt2x00usb_resume,
197762306a36Sopenharmony_ci	.disable_hub_initiated_lpm = 1,
197862306a36Sopenharmony_ci};
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_cimodule_usb_driver(rt2500usb_driver);
1981