18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> 48c2ecf20Sopenharmony_ci <http://rt2x00.serialmonkey.com> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci Module: rt2500usb 108c2ecf20Sopenharmony_ci Abstract: rt2500usb device specific routines. 118c2ecf20Sopenharmony_ci Supported chipsets: RT2570. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci#include <linux/usb.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "rt2x00.h" 228c2ecf20Sopenharmony_ci#include "rt2x00usb.h" 238c2ecf20Sopenharmony_ci#include "rt2500usb.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* 268c2ecf20Sopenharmony_ci * Allow hardware encryption to be disabled. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_cistatic bool modparam_nohwcrypt; 298c2ecf20Sopenharmony_cimodule_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444); 308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Register access. 348c2ecf20Sopenharmony_ci * All access to the CSR registers will go through the methods 358c2ecf20Sopenharmony_ci * rt2500usb_register_read and rt2500usb_register_write. 368c2ecf20Sopenharmony_ci * BBP and RF register require indirect register access, 378c2ecf20Sopenharmony_ci * and use the CSR registers BBPCSR and RFCSR to achieve this. 388c2ecf20Sopenharmony_ci * These indirect registers work with busy bits, 398c2ecf20Sopenharmony_ci * and we will try maximal REGISTER_USB_BUSY_COUNT times to access 408c2ecf20Sopenharmony_ci * the register while taking a REGISTER_BUSY_DELAY us delay 418c2ecf20Sopenharmony_ci * between each attampt. When the busy bit is still set at that time, 428c2ecf20Sopenharmony_ci * the access attempt is considered to have failed, 438c2ecf20Sopenharmony_ci * and we will print an error. 448c2ecf20Sopenharmony_ci * If the csr_mutex is already held then the _lock variants must 458c2ecf20Sopenharmony_ci * be used instead. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_cistatic u16 rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, 488c2ecf20Sopenharmony_ci const unsigned int offset) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci __le16 reg; 518c2ecf20Sopenharmony_ci rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, 528c2ecf20Sopenharmony_ci USB_VENDOR_REQUEST_IN, offset, 538c2ecf20Sopenharmony_ci ®, sizeof(reg)); 548c2ecf20Sopenharmony_ci return le16_to_cpu(reg); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic u16 rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, 588c2ecf20Sopenharmony_ci const unsigned int offset) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci __le16 reg; 618c2ecf20Sopenharmony_ci rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, 628c2ecf20Sopenharmony_ci USB_VENDOR_REQUEST_IN, offset, 638c2ecf20Sopenharmony_ci ®, sizeof(reg), REGISTER_TIMEOUT); 648c2ecf20Sopenharmony_ci return le16_to_cpu(reg); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, 688c2ecf20Sopenharmony_ci const unsigned int offset, 698c2ecf20Sopenharmony_ci u16 value) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci __le16 reg = cpu_to_le16(value); 728c2ecf20Sopenharmony_ci rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, 738c2ecf20Sopenharmony_ci USB_VENDOR_REQUEST_OUT, offset, 748c2ecf20Sopenharmony_ci ®, sizeof(reg)); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, 788c2ecf20Sopenharmony_ci const unsigned int offset, 798c2ecf20Sopenharmony_ci u16 value) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci __le16 reg = cpu_to_le16(value); 828c2ecf20Sopenharmony_ci rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, 838c2ecf20Sopenharmony_ci USB_VENDOR_REQUEST_OUT, offset, 848c2ecf20Sopenharmony_ci ®, sizeof(reg), REGISTER_TIMEOUT); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, 888c2ecf20Sopenharmony_ci const unsigned int offset, 898c2ecf20Sopenharmony_ci void *value, const u16 length) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, 928c2ecf20Sopenharmony_ci USB_VENDOR_REQUEST_OUT, offset, 938c2ecf20Sopenharmony_ci value, length); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, 978c2ecf20Sopenharmony_ci const unsigned int offset, 988c2ecf20Sopenharmony_ci struct rt2x00_field16 field, 998c2ecf20Sopenharmony_ci u16 *reg) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci unsigned int i; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) { 1048c2ecf20Sopenharmony_ci *reg = rt2500usb_register_read_lock(rt2x00dev, offset); 1058c2ecf20Sopenharmony_ci if (!rt2x00_get_field16(*reg, field)) 1068c2ecf20Sopenharmony_ci return 1; 1078c2ecf20Sopenharmony_ci udelay(REGISTER_BUSY_DELAY); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n", 1118c2ecf20Sopenharmony_ci offset, *reg); 1128c2ecf20Sopenharmony_ci *reg = ~0; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return 0; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define WAIT_FOR_BBP(__dev, __reg) \ 1188c2ecf20Sopenharmony_ci rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) 1198c2ecf20Sopenharmony_ci#define WAIT_FOR_RF(__dev, __reg) \ 1208c2ecf20Sopenharmony_ci rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, 1238c2ecf20Sopenharmony_ci const unsigned int word, const u8 value) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci u16 reg; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* 1308c2ecf20Sopenharmony_ci * Wait until the BBP becomes available, afterwards we 1318c2ecf20Sopenharmony_ci * can safely write the new data into the register. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci if (WAIT_FOR_BBP(rt2x00dev, ®)) { 1348c2ecf20Sopenharmony_ci reg = 0; 1358c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR7_DATA, value); 1368c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); 1378c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic u8 rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, 1468c2ecf20Sopenharmony_ci const unsigned int word) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci u16 reg; 1498c2ecf20Sopenharmony_ci u8 value; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * Wait until the BBP becomes available, afterwards we 1558c2ecf20Sopenharmony_ci * can safely write the read request into the register. 1568c2ecf20Sopenharmony_ci * After the data has been written, we wait until hardware 1578c2ecf20Sopenharmony_ci * returns the correct value, if at any time the register 1588c2ecf20Sopenharmony_ci * doesn't become available in time, reg will be 0xffffffff 1598c2ecf20Sopenharmony_ci * which means we return 0xff to the caller. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_ci if (WAIT_FOR_BBP(rt2x00dev, ®)) { 1628c2ecf20Sopenharmony_ci reg = 0; 1638c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); 1648c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (WAIT_FOR_BBP(rt2x00dev, ®)) 1698c2ecf20Sopenharmony_ci reg = rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7); 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci value = rt2x00_get_field16(reg, PHY_CSR7_DATA); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return value; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, 1808c2ecf20Sopenharmony_ci const unsigned int word, const u32 value) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci u16 reg; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* 1878c2ecf20Sopenharmony_ci * Wait until the RF becomes available, afterwards we 1888c2ecf20Sopenharmony_ci * can safely write the new data into the register. 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci if (WAIT_FOR_RF(rt2x00dev, ®)) { 1918c2ecf20Sopenharmony_ci reg = 0; 1928c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); 1938c2ecf20Sopenharmony_ci rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci reg = 0; 1968c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); 1978c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); 1988c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); 1998c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); 2028c2ecf20Sopenharmony_ci rt2x00_rf_write(rt2x00dev, word, value); 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS 2098c2ecf20Sopenharmony_cistatic u32 _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, 2108c2ecf20Sopenharmony_ci const unsigned int offset) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci return rt2500usb_register_read(rt2x00dev, offset); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, 2168c2ecf20Sopenharmony_ci const unsigned int offset, 2178c2ecf20Sopenharmony_ci u32 value) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, offset, value); 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic const struct rt2x00debug rt2500usb_rt2x00debug = { 2238c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2248c2ecf20Sopenharmony_ci .csr = { 2258c2ecf20Sopenharmony_ci .read = _rt2500usb_register_read, 2268c2ecf20Sopenharmony_ci .write = _rt2500usb_register_write, 2278c2ecf20Sopenharmony_ci .flags = RT2X00DEBUGFS_OFFSET, 2288c2ecf20Sopenharmony_ci .word_base = CSR_REG_BASE, 2298c2ecf20Sopenharmony_ci .word_size = sizeof(u16), 2308c2ecf20Sopenharmony_ci .word_count = CSR_REG_SIZE / sizeof(u16), 2318c2ecf20Sopenharmony_ci }, 2328c2ecf20Sopenharmony_ci .eeprom = { 2338c2ecf20Sopenharmony_ci .read = rt2x00_eeprom_read, 2348c2ecf20Sopenharmony_ci .write = rt2x00_eeprom_write, 2358c2ecf20Sopenharmony_ci .word_base = EEPROM_BASE, 2368c2ecf20Sopenharmony_ci .word_size = sizeof(u16), 2378c2ecf20Sopenharmony_ci .word_count = EEPROM_SIZE / sizeof(u16), 2388c2ecf20Sopenharmony_ci }, 2398c2ecf20Sopenharmony_ci .bbp = { 2408c2ecf20Sopenharmony_ci .read = rt2500usb_bbp_read, 2418c2ecf20Sopenharmony_ci .write = rt2500usb_bbp_write, 2428c2ecf20Sopenharmony_ci .word_base = BBP_BASE, 2438c2ecf20Sopenharmony_ci .word_size = sizeof(u8), 2448c2ecf20Sopenharmony_ci .word_count = BBP_SIZE / sizeof(u8), 2458c2ecf20Sopenharmony_ci }, 2468c2ecf20Sopenharmony_ci .rf = { 2478c2ecf20Sopenharmony_ci .read = rt2x00_rf_read, 2488c2ecf20Sopenharmony_ci .write = rt2500usb_rf_write, 2498c2ecf20Sopenharmony_ci .word_base = RF_BASE, 2508c2ecf20Sopenharmony_ci .word_size = sizeof(u32), 2518c2ecf20Sopenharmony_ci .word_count = RF_SIZE / sizeof(u32), 2528c2ecf20Sopenharmony_ci }, 2538c2ecf20Sopenharmony_ci}; 2548c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci u16 reg; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19); 2618c2ecf20Sopenharmony_ci return rt2x00_get_field16(reg, MAC_CSR19_VAL7); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS 2658c2ecf20Sopenharmony_cistatic void rt2500usb_brightness_set(struct led_classdev *led_cdev, 2668c2ecf20Sopenharmony_ci enum led_brightness brightness) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct rt2x00_led *led = 2698c2ecf20Sopenharmony_ci container_of(led_cdev, struct rt2x00_led, led_dev); 2708c2ecf20Sopenharmony_ci unsigned int enabled = brightness != LED_OFF; 2718c2ecf20Sopenharmony_ci u16 reg; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR20); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) 2768c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR20_LINK, enabled); 2778c2ecf20Sopenharmony_ci else if (led->type == LED_TYPE_ACTIVITY) 2788c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, enabled); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int rt2500usb_blink_set(struct led_classdev *led_cdev, 2848c2ecf20Sopenharmony_ci unsigned long *delay_on, 2858c2ecf20Sopenharmony_ci unsigned long *delay_off) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci struct rt2x00_led *led = 2888c2ecf20Sopenharmony_ci container_of(led_cdev, struct rt2x00_led, led_dev); 2898c2ecf20Sopenharmony_ci u16 reg; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR21); 2928c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, *delay_on); 2938c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, *delay_off); 2948c2ecf20Sopenharmony_ci rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci return 0; 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev, 3008c2ecf20Sopenharmony_ci struct rt2x00_led *led, 3018c2ecf20Sopenharmony_ci enum led_type type) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci led->rt2x00dev = rt2x00dev; 3048c2ecf20Sopenharmony_ci led->type = type; 3058c2ecf20Sopenharmony_ci led->led_dev.brightness_set = rt2500usb_brightness_set; 3068c2ecf20Sopenharmony_ci led->led_dev.blink_set = rt2500usb_blink_set; 3078c2ecf20Sopenharmony_ci led->flags = LED_INITIALIZED; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */ 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/* 3128c2ecf20Sopenharmony_ci * Configuration handlers. 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci/* 3168c2ecf20Sopenharmony_ci * rt2500usb does not differentiate between shared and pairwise 3178c2ecf20Sopenharmony_ci * keys, so we should use the same function for both key types. 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_cistatic int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, 3208c2ecf20Sopenharmony_ci struct rt2x00lib_crypto *crypto, 3218c2ecf20Sopenharmony_ci struct ieee80211_key_conf *key) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci u32 mask; 3248c2ecf20Sopenharmony_ci u16 reg; 3258c2ecf20Sopenharmony_ci enum cipher curr_cipher; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (crypto->cmd == SET_KEY) { 3288c2ecf20Sopenharmony_ci /* 3298c2ecf20Sopenharmony_ci * Disallow to set WEP key other than with index 0, 3308c2ecf20Sopenharmony_ci * it is known that not work at least on some hardware. 3318c2ecf20Sopenharmony_ci * SW crypto will be used in that case. 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_ci if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || 3348c2ecf20Sopenharmony_ci key->cipher == WLAN_CIPHER_SUITE_WEP104) && 3358c2ecf20Sopenharmony_ci key->keyidx != 0) 3368c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* 3398c2ecf20Sopenharmony_ci * Pairwise key will always be entry 0, but this 3408c2ecf20Sopenharmony_ci * could collide with a shared key on the same 3418c2ecf20Sopenharmony_ci * position... 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_ci mask = TXRX_CSR0_KEY_ID.bit_mask; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0); 3468c2ecf20Sopenharmony_ci curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM); 3478c2ecf20Sopenharmony_ci reg &= mask; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (reg && reg == mask) 3508c2ecf20Sopenharmony_ci return -ENOSPC; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci key->hw_key_idx += reg ? ffz(reg) : 0; 3558c2ecf20Sopenharmony_ci /* 3568c2ecf20Sopenharmony_ci * Hardware requires that all keys use the same cipher 3578c2ecf20Sopenharmony_ci * (e.g. TKIP-only, AES-only, but not TKIP+AES). 3588c2ecf20Sopenharmony_ci * If this is not the first key, compare the cipher with the 3598c2ecf20Sopenharmony_ci * first one and fall back to SW crypto if not the same. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ci if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher) 3628c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx), 3658c2ecf20Sopenharmony_ci crypto->key, sizeof(crypto->key)); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* 3688c2ecf20Sopenharmony_ci * The driver does not support the IV/EIV generation 3698c2ecf20Sopenharmony_ci * in hardware. However it demands the data to be provided 3708c2ecf20Sopenharmony_ci * both separately as well as inside the frame. 3718c2ecf20Sopenharmony_ci * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib 3728c2ecf20Sopenharmony_ci * to ensure rt2x00lib will not strip the data from the 3738c2ecf20Sopenharmony_ci * frame after the copy, now we must tell mac80211 3748c2ecf20Sopenharmony_ci * to generate the IV/EIV data. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ci key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 3778c2ecf20Sopenharmony_ci key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* 3818c2ecf20Sopenharmony_ci * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate 3828c2ecf20Sopenharmony_ci * a particular key is valid. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0); 3858c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, crypto->cipher); 3868c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); 3898c2ecf20Sopenharmony_ci if (crypto->cmd == SET_KEY) 3908c2ecf20Sopenharmony_ci mask |= 1 << key->hw_key_idx; 3918c2ecf20Sopenharmony_ci else if (crypto->cmd == DISABLE_KEY) 3928c2ecf20Sopenharmony_ci mask &= ~(1 << key->hw_key_idx); 3938c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, mask); 3948c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci return 0; 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_cistatic void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, 4008c2ecf20Sopenharmony_ci const unsigned int filter_flags) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci u16 reg; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* 4058c2ecf20Sopenharmony_ci * Start configuration steps. 4068c2ecf20Sopenharmony_ci * Note that the version error will always be dropped 4078c2ecf20Sopenharmony_ci * and broadcast frames will always be accepted since 4088c2ecf20Sopenharmony_ci * there is no filter for it at this time. 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2); 4118c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, 4128c2ecf20Sopenharmony_ci !(filter_flags & FIF_FCSFAIL)); 4138c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, 4148c2ecf20Sopenharmony_ci !(filter_flags & FIF_PLCPFAIL)); 4158c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, 4168c2ecf20Sopenharmony_ci !(filter_flags & FIF_CONTROL)); 4178c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, 4188c2ecf20Sopenharmony_ci !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); 4198c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, 4208c2ecf20Sopenharmony_ci !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && 4218c2ecf20Sopenharmony_ci !rt2x00dev->intf_ap_count); 4228c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); 4238c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, 4248c2ecf20Sopenharmony_ci !(filter_flags & FIF_ALLMULTI)); 4258c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); 4268c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, 4308c2ecf20Sopenharmony_ci struct rt2x00_intf *intf, 4318c2ecf20Sopenharmony_ci struct rt2x00intf_conf *conf, 4328c2ecf20Sopenharmony_ci const unsigned int flags) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci unsigned int bcn_preload; 4358c2ecf20Sopenharmony_ci u16 reg; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_TYPE) { 4388c2ecf20Sopenharmony_ci /* 4398c2ecf20Sopenharmony_ci * Enable beacon config 4408c2ecf20Sopenharmony_ci */ 4418c2ecf20Sopenharmony_ci bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); 4428c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR20); 4438c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); 4448c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 4458c2ecf20Sopenharmony_ci 2 * (conf->type != NL80211_IFTYPE_STATION)); 4468c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci /* 4498c2ecf20Sopenharmony_ci * Enable synchronisation. 4508c2ecf20Sopenharmony_ci */ 4518c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18); 4528c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); 4538c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19); 4568c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); 4578c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_MAC) 4618c2ecf20Sopenharmony_ci rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, 4628c2ecf20Sopenharmony_ci (3 * sizeof(__le16))); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_BSSID) 4658c2ecf20Sopenharmony_ci rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid, 4668c2ecf20Sopenharmony_ci (3 * sizeof(__le16))); 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, 4708c2ecf20Sopenharmony_ci struct rt2x00lib_erp *erp, 4718c2ecf20Sopenharmony_ci u32 changed) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci u16 reg; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_ERP_PREAMBLE) { 4768c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR10); 4778c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, 4788c2ecf20Sopenharmony_ci !!erp->short_preamble); 4798c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_BASIC_RATES) 4838c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR11, 4848c2ecf20Sopenharmony_ci erp->basic_rates); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_BEACON_INT) { 4878c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18); 4888c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, 4898c2ecf20Sopenharmony_ci erp->beacon_int * 4); 4908c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_ERP_SLOT) { 4948c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); 4958c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); 4968c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistatic void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, 5018c2ecf20Sopenharmony_ci struct antenna_setup *ant) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci u8 r2; 5048c2ecf20Sopenharmony_ci u8 r14; 5058c2ecf20Sopenharmony_ci u16 csr5; 5068c2ecf20Sopenharmony_ci u16 csr6; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* 5098c2ecf20Sopenharmony_ci * We should never come here because rt2x00lib is supposed 5108c2ecf20Sopenharmony_ci * to catch this and send us the correct antenna explicitely. 5118c2ecf20Sopenharmony_ci */ 5128c2ecf20Sopenharmony_ci BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || 5138c2ecf20Sopenharmony_ci ant->tx == ANTENNA_SW_DIVERSITY); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci r2 = rt2500usb_bbp_read(rt2x00dev, 2); 5168c2ecf20Sopenharmony_ci r14 = rt2500usb_bbp_read(rt2x00dev, 14); 5178c2ecf20Sopenharmony_ci csr5 = rt2500usb_register_read(rt2x00dev, PHY_CSR5); 5188c2ecf20Sopenharmony_ci csr6 = rt2500usb_register_read(rt2x00dev, PHY_CSR6); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* 5218c2ecf20Sopenharmony_ci * Configure the TX antenna. 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_ci switch (ant->tx) { 5248c2ecf20Sopenharmony_ci case ANTENNA_HW_DIVERSITY: 5258c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1); 5268c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1); 5278c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1); 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci case ANTENNA_A: 5308c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); 5318c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0); 5328c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0); 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci case ANTENNA_B: 5358c2ecf20Sopenharmony_ci default: 5368c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); 5378c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2); 5388c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2); 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci /* 5438c2ecf20Sopenharmony_ci * Configure the RX antenna. 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_ci switch (ant->rx) { 5468c2ecf20Sopenharmony_ci case ANTENNA_HW_DIVERSITY: 5478c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1); 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case ANTENNA_A: 5508c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); 5518c2ecf20Sopenharmony_ci break; 5528c2ecf20Sopenharmony_ci case ANTENNA_B: 5538c2ecf20Sopenharmony_ci default: 5548c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); 5558c2ecf20Sopenharmony_ci break; 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* 5598c2ecf20Sopenharmony_ci * RT2525E and RT5222 need to flip TX I/Q 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { 5628c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); 5638c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); 5648c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* 5678c2ecf20Sopenharmony_ci * RT2525E does not need RX I/Q Flip. 5688c2ecf20Sopenharmony_ci */ 5698c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525E)) 5708c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); 5718c2ecf20Sopenharmony_ci } else { 5728c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); 5738c2ecf20Sopenharmony_ci rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 0); 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 2, r2); 5778c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 14, r14); 5788c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, PHY_CSR5, csr5); 5798c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, 5838c2ecf20Sopenharmony_ci struct rf_channel *rf, const int txpower) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci /* 5868c2ecf20Sopenharmony_ci * Set TXpower. 5878c2ecf20Sopenharmony_ci */ 5888c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* 5918c2ecf20Sopenharmony_ci * For RT2525E we should first set the channel to half band higher. 5928c2ecf20Sopenharmony_ci */ 5938c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525E)) { 5948c2ecf20Sopenharmony_ci static const u32 vals[] = { 5958c2ecf20Sopenharmony_ci 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, 5968c2ecf20Sopenharmony_ci 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, 5978c2ecf20Sopenharmony_ci 0x000008ba, 0x000008be, 0x000008b7, 0x00000902, 5988c2ecf20Sopenharmony_ci 0x00000902, 0x00000906 5998c2ecf20Sopenharmony_ci }; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); 6028c2ecf20Sopenharmony_ci if (rf->rf4) 6038c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 1, rf->rf1); 6078c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 2, rf->rf2); 6088c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 3, rf->rf3); 6098c2ecf20Sopenharmony_ci if (rf->rf4) 6108c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, 6148c2ecf20Sopenharmony_ci const int txpower) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci u32 rf3; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci rf3 = rt2x00_rf_read(rt2x00dev, 3); 6198c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); 6208c2ecf20Sopenharmony_ci rt2500usb_rf_write(rt2x00dev, 3, rf3); 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_cistatic void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, 6248c2ecf20Sopenharmony_ci struct rt2x00lib_conf *libconf) 6258c2ecf20Sopenharmony_ci{ 6268c2ecf20Sopenharmony_ci enum dev_state state = 6278c2ecf20Sopenharmony_ci (libconf->conf->flags & IEEE80211_CONF_PS) ? 6288c2ecf20Sopenharmony_ci STATE_SLEEP : STATE_AWAKE; 6298c2ecf20Sopenharmony_ci u16 reg; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (state == STATE_SLEEP) { 6328c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18); 6338c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, 6348c2ecf20Sopenharmony_ci rt2x00dev->beacon_int - 20); 6358c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, 6368c2ecf20Sopenharmony_ci libconf->conf->listen_interval - 1); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* We must first disable autowake before it can be enabled */ 6398c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); 6408c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); 6438c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); 6448c2ecf20Sopenharmony_ci } else { 6458c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18); 6468c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); 6478c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic void rt2500usb_config(struct rt2x00_dev *rt2x00dev, 6548c2ecf20Sopenharmony_ci struct rt2x00lib_conf *libconf, 6558c2ecf20Sopenharmony_ci const unsigned int flags) 6568c2ecf20Sopenharmony_ci{ 6578c2ecf20Sopenharmony_ci if (flags & IEEE80211_CONF_CHANGE_CHANNEL) 6588c2ecf20Sopenharmony_ci rt2500usb_config_channel(rt2x00dev, &libconf->rf, 6598c2ecf20Sopenharmony_ci libconf->conf->power_level); 6608c2ecf20Sopenharmony_ci if ((flags & IEEE80211_CONF_CHANGE_POWER) && 6618c2ecf20Sopenharmony_ci !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) 6628c2ecf20Sopenharmony_ci rt2500usb_config_txpower(rt2x00dev, 6638c2ecf20Sopenharmony_ci libconf->conf->power_level); 6648c2ecf20Sopenharmony_ci if (flags & IEEE80211_CONF_CHANGE_PS) 6658c2ecf20Sopenharmony_ci rt2500usb_config_ps(rt2x00dev, libconf); 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci/* 6698c2ecf20Sopenharmony_ci * Link tuning 6708c2ecf20Sopenharmony_ci */ 6718c2ecf20Sopenharmony_cistatic void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, 6728c2ecf20Sopenharmony_ci struct link_qual *qual) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci u16 reg; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* 6778c2ecf20Sopenharmony_ci * Update FCS error count from register. 6788c2ecf20Sopenharmony_ci */ 6798c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, STA_CSR0); 6808c2ecf20Sopenharmony_ci qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* 6838c2ecf20Sopenharmony_ci * Update False CCA count from register. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, STA_CSR3); 6868c2ecf20Sopenharmony_ci qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, 6908c2ecf20Sopenharmony_ci struct link_qual *qual) 6918c2ecf20Sopenharmony_ci{ 6928c2ecf20Sopenharmony_ci u16 eeprom; 6938c2ecf20Sopenharmony_ci u16 value; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24); 6968c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW); 6978c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 24, value); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25); 7008c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW); 7018c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 25, value); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61); 7048c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW); 7058c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 61, value); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC); 7088c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); 7098c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 17, value); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci qual->vgc_level = value; 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci/* 7158c2ecf20Sopenharmony_ci * Queue handlers. 7168c2ecf20Sopenharmony_ci */ 7178c2ecf20Sopenharmony_cistatic void rt2500usb_start_queue(struct data_queue *queue) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; 7208c2ecf20Sopenharmony_ci u16 reg; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci switch (queue->qid) { 7238c2ecf20Sopenharmony_ci case QID_RX: 7248c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2); 7258c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 0); 7268c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci case QID_BEACON: 7298c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19); 7308c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); 7318c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); 7328c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); 7338c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 7348c2ecf20Sopenharmony_ci break; 7358c2ecf20Sopenharmony_ci default: 7368c2ecf20Sopenharmony_ci break; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_cistatic void rt2500usb_stop_queue(struct data_queue *queue) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; 7438c2ecf20Sopenharmony_ci u16 reg; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci switch (queue->qid) { 7468c2ecf20Sopenharmony_ci case QID_RX: 7478c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2); 7488c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); 7498c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); 7508c2ecf20Sopenharmony_ci break; 7518c2ecf20Sopenharmony_ci case QID_BEACON: 7528c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19); 7538c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); 7548c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); 7558c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); 7568c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 7578c2ecf20Sopenharmony_ci break; 7588c2ecf20Sopenharmony_ci default: 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci} 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci/* 7648c2ecf20Sopenharmony_ci * Initialization functions. 7658c2ecf20Sopenharmony_ci */ 7668c2ecf20Sopenharmony_cistatic int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci u16 reg; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001, 7718c2ecf20Sopenharmony_ci USB_MODE_TEST, REGISTER_TIMEOUT); 7728c2ecf20Sopenharmony_ci rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308, 7738c2ecf20Sopenharmony_ci 0x00f0, REGISTER_TIMEOUT); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2); 7768c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); 7778c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111); 7808c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1); 7838c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 1); 7848c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 1); 7858c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); 7868c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1); 7898c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); 7908c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); 7918c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); 7928c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR5); 7958c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13); 7968c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0_VALID, 1); 7978c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1, 12); 7988c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1_VALID, 1); 7998c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR6); 8028c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0, 10); 8038c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0_VALID, 1); 8048c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1, 11); 8058c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1_VALID, 1); 8068c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR7); 8098c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0, 7); 8108c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0_VALID, 1); 8118c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1, 6); 8128c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1_VALID, 1); 8138c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR8); 8168c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0, 5); 8178c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0_VALID, 1); 8188c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1, 0); 8198c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1_VALID, 0); 8208c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19); 8238c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); 8248c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 0); 8258c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); 8268c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); 8278c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f); 8308c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) 8338c2ecf20Sopenharmony_ci return -EBUSY; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1); 8368c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); 8378c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); 8388c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); 8398c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { 8428c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, PHY_CSR2); 8438c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR2_LNA, 0); 8448c2ecf20Sopenharmony_ci } else { 8458c2ecf20Sopenharmony_ci reg = 0; 8468c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR2_LNA, 1); 8478c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR2_LNA_MODE, 3); 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0002); 8528c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR22, 0x0053); 8538c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee); 8548c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR8); 8578c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR8_MAX_FRAME_UNIT, 8588c2ecf20Sopenharmony_ci rt2x00dev->rx->data_size); 8598c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0); 8628c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, CIPHER_NONE); 8638c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); 8648c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0); 8658c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18); 8688c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, 90); 8698c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, PHY_CSR4); 8728c2ecf20Sopenharmony_ci rt2x00_set_field16(®, PHY_CSR4_LOW_RF_LE, 1); 8738c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR1); 8768c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR1_AUTO_SEQUENCE, 1); 8778c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci return 0; 8808c2ecf20Sopenharmony_ci} 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cistatic int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci unsigned int i; 8858c2ecf20Sopenharmony_ci u8 value; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) { 8888c2ecf20Sopenharmony_ci value = rt2500usb_bbp_read(rt2x00dev, 0); 8898c2ecf20Sopenharmony_ci if ((value != 0xff) && (value != 0x00)) 8908c2ecf20Sopenharmony_ci return 0; 8918c2ecf20Sopenharmony_ci udelay(REGISTER_BUSY_DELAY); 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n"); 8958c2ecf20Sopenharmony_ci return -EACCES; 8968c2ecf20Sopenharmony_ci} 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_cistatic int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) 8998c2ecf20Sopenharmony_ci{ 9008c2ecf20Sopenharmony_ci unsigned int i; 9018c2ecf20Sopenharmony_ci u16 eeprom; 9028c2ecf20Sopenharmony_ci u8 value; 9038c2ecf20Sopenharmony_ci u8 reg_id; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev))) 9068c2ecf20Sopenharmony_ci return -EACCES; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 3, 0x02); 9098c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 4, 0x19); 9108c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 14, 0x1c); 9118c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 15, 0x30); 9128c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 16, 0xac); 9138c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 18, 0x18); 9148c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 19, 0xff); 9158c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 20, 0x1e); 9168c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 21, 0x08); 9178c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 22, 0x08); 9188c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 23, 0x08); 9198c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 24, 0x80); 9208c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 25, 0x50); 9218c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 26, 0x08); 9228c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 27, 0x23); 9238c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 30, 0x10); 9248c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 31, 0x2b); 9258c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 32, 0xb9); 9268c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 34, 0x12); 9278c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 35, 0x50); 9288c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 39, 0xc4); 9298c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 40, 0x02); 9308c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 41, 0x60); 9318c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 53, 0x10); 9328c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 54, 0x18); 9338c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 56, 0x08); 9348c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 57, 0x10); 9358c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 58, 0x08); 9368c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 61, 0x60); 9378c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 62, 0x10); 9388c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, 75, 0xff); 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci for (i = 0; i < EEPROM_BBP_SIZE; i++) { 9418c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci if (eeprom != 0xffff && eeprom != 0x0000) { 9448c2ecf20Sopenharmony_ci reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); 9458c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); 9468c2ecf20Sopenharmony_ci rt2500usb_bbp_write(rt2x00dev, reg_id, value); 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci return 0; 9518c2ecf20Sopenharmony_ci} 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci/* 9548c2ecf20Sopenharmony_ci * Device state switch handlers. 9558c2ecf20Sopenharmony_ci */ 9568c2ecf20Sopenharmony_cistatic int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) 9578c2ecf20Sopenharmony_ci{ 9588c2ecf20Sopenharmony_ci /* 9598c2ecf20Sopenharmony_ci * Initialize all registers. 9608c2ecf20Sopenharmony_ci */ 9618c2ecf20Sopenharmony_ci if (unlikely(rt2500usb_init_registers(rt2x00dev) || 9628c2ecf20Sopenharmony_ci rt2500usb_init_bbp(rt2x00dev))) 9638c2ecf20Sopenharmony_ci return -EIO; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci return 0; 9668c2ecf20Sopenharmony_ci} 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_cistatic void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev) 9698c2ecf20Sopenharmony_ci{ 9708c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121); 9718c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* 9748c2ecf20Sopenharmony_ci * Disable synchronisation. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci rt2x00usb_disable_radio(rt2x00dev); 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_cistatic int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, 9828c2ecf20Sopenharmony_ci enum dev_state state) 9838c2ecf20Sopenharmony_ci{ 9848c2ecf20Sopenharmony_ci u16 reg; 9858c2ecf20Sopenharmony_ci u16 reg2; 9868c2ecf20Sopenharmony_ci unsigned int i; 9878c2ecf20Sopenharmony_ci char put_to_sleep; 9888c2ecf20Sopenharmony_ci char bbp_state; 9898c2ecf20Sopenharmony_ci char rf_state; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci put_to_sleep = (state != STATE_AWAKE); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci reg = 0; 9948c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR17_BBP_DESIRE_STATE, state); 9958c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR17_RF_DESIRE_STATE, state); 9968c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep); 9978c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); 9988c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR17_SET_STATE, 1); 9998c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci /* 10028c2ecf20Sopenharmony_ci * Device is not guaranteed to be in the requested state yet. 10038c2ecf20Sopenharmony_ci * We must wait until the register indicates that the 10048c2ecf20Sopenharmony_ci * device has entered the correct state. 10058c2ecf20Sopenharmony_ci */ 10068c2ecf20Sopenharmony_ci for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) { 10078c2ecf20Sopenharmony_ci reg2 = rt2500usb_register_read(rt2x00dev, MAC_CSR17); 10088c2ecf20Sopenharmony_ci bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE); 10098c2ecf20Sopenharmony_ci rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE); 10108c2ecf20Sopenharmony_ci if (bbp_state == state && rf_state == state) 10118c2ecf20Sopenharmony_ci return 0; 10128c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); 10138c2ecf20Sopenharmony_ci msleep(30); 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci return -EBUSY; 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, 10208c2ecf20Sopenharmony_ci enum dev_state state) 10218c2ecf20Sopenharmony_ci{ 10228c2ecf20Sopenharmony_ci int retval = 0; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci switch (state) { 10258c2ecf20Sopenharmony_ci case STATE_RADIO_ON: 10268c2ecf20Sopenharmony_ci retval = rt2500usb_enable_radio(rt2x00dev); 10278c2ecf20Sopenharmony_ci break; 10288c2ecf20Sopenharmony_ci case STATE_RADIO_OFF: 10298c2ecf20Sopenharmony_ci rt2500usb_disable_radio(rt2x00dev); 10308c2ecf20Sopenharmony_ci break; 10318c2ecf20Sopenharmony_ci case STATE_RADIO_IRQ_ON: 10328c2ecf20Sopenharmony_ci case STATE_RADIO_IRQ_OFF: 10338c2ecf20Sopenharmony_ci /* No support, but no error either */ 10348c2ecf20Sopenharmony_ci break; 10358c2ecf20Sopenharmony_ci case STATE_DEEP_SLEEP: 10368c2ecf20Sopenharmony_ci case STATE_SLEEP: 10378c2ecf20Sopenharmony_ci case STATE_STANDBY: 10388c2ecf20Sopenharmony_ci case STATE_AWAKE: 10398c2ecf20Sopenharmony_ci retval = rt2500usb_set_state(rt2x00dev, state); 10408c2ecf20Sopenharmony_ci break; 10418c2ecf20Sopenharmony_ci default: 10428c2ecf20Sopenharmony_ci retval = -ENOTSUPP; 10438c2ecf20Sopenharmony_ci break; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if (unlikely(retval)) 10478c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", 10488c2ecf20Sopenharmony_ci state, retval); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci return retval; 10518c2ecf20Sopenharmony_ci} 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci/* 10548c2ecf20Sopenharmony_ci * TX descriptor initialization 10558c2ecf20Sopenharmony_ci */ 10568c2ecf20Sopenharmony_cistatic void rt2500usb_write_tx_desc(struct queue_entry *entry, 10578c2ecf20Sopenharmony_ci struct txentry_desc *txdesc) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); 10608c2ecf20Sopenharmony_ci __le32 *txd = (__le32 *) entry->skb->data; 10618c2ecf20Sopenharmony_ci u32 word; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* 10648c2ecf20Sopenharmony_ci * Start writing the descriptor words. 10658c2ecf20Sopenharmony_ci */ 10668c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 0); 10678c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); 10688c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, 10698c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); 10708c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_ACK, 10718c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_ACK, &txdesc->flags)); 10728c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, 10738c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); 10748c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_OFDM, 10758c2ecf20Sopenharmony_ci (txdesc->rate_mode == RATE_MODE_OFDM)); 10768c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, 10778c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); 10788c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs); 10798c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); 10808c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); 10818c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); 10828c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 0, word); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 1); 10858c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); 10868c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs); 10878c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); 10888c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); 10898c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 1, word); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 2); 10928c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal); 10938c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service); 10948c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, 10958c2ecf20Sopenharmony_ci txdesc->u.plcp.length_low); 10968c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, 10978c2ecf20Sopenharmony_ci txdesc->u.plcp.length_high); 10988c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 2, word); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { 11018c2ecf20Sopenharmony_ci _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); 11028c2ecf20Sopenharmony_ci _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci /* 11068c2ecf20Sopenharmony_ci * Register descriptor details in skb frame descriptor. 11078c2ecf20Sopenharmony_ci */ 11088c2ecf20Sopenharmony_ci skbdesc->flags |= SKBDESC_DESC_IN_SKB; 11098c2ecf20Sopenharmony_ci skbdesc->desc = txd; 11108c2ecf20Sopenharmony_ci skbdesc->desc_len = TXD_DESC_SIZE; 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci/* 11148c2ecf20Sopenharmony_ci * TX data initialization 11158c2ecf20Sopenharmony_ci */ 11168c2ecf20Sopenharmony_cistatic void rt2500usb_beacondone(struct urb *urb); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic void rt2500usb_write_beacon(struct queue_entry *entry, 11198c2ecf20Sopenharmony_ci struct txentry_desc *txdesc) 11208c2ecf20Sopenharmony_ci{ 11218c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 11228c2ecf20Sopenharmony_ci struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 11238c2ecf20Sopenharmony_ci struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; 11248c2ecf20Sopenharmony_ci int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); 11258c2ecf20Sopenharmony_ci int length; 11268c2ecf20Sopenharmony_ci u16 reg, reg0; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* 11298c2ecf20Sopenharmony_ci * Disable beaconing while we are reloading the beacon data, 11308c2ecf20Sopenharmony_ci * otherwise we might be sending out invalid data. 11318c2ecf20Sopenharmony_ci */ 11328c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19); 11338c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); 11348c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci /* 11378c2ecf20Sopenharmony_ci * Add space for the descriptor in front of the skb. 11388c2ecf20Sopenharmony_ci */ 11398c2ecf20Sopenharmony_ci skb_push(entry->skb, TXD_DESC_SIZE); 11408c2ecf20Sopenharmony_ci memset(entry->skb->data, 0, TXD_DESC_SIZE); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci /* 11438c2ecf20Sopenharmony_ci * Write the TX descriptor for the beacon. 11448c2ecf20Sopenharmony_ci */ 11458c2ecf20Sopenharmony_ci rt2500usb_write_tx_desc(entry, txdesc); 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci /* 11488c2ecf20Sopenharmony_ci * Dump beacon to userspace through debugfs. 11498c2ecf20Sopenharmony_ci */ 11508c2ecf20Sopenharmony_ci rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* 11538c2ecf20Sopenharmony_ci * USB devices cannot blindly pass the skb->len as the 11548c2ecf20Sopenharmony_ci * length of the data to usb_fill_bulk_urb. Pass the skb 11558c2ecf20Sopenharmony_ci * to the driver to determine what the length should be. 11568c2ecf20Sopenharmony_ci */ 11578c2ecf20Sopenharmony_ci length = rt2x00dev->ops->lib->get_tx_data_len(entry); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, 11608c2ecf20Sopenharmony_ci entry->skb->data, length, rt2500usb_beacondone, 11618c2ecf20Sopenharmony_ci entry); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci /* 11648c2ecf20Sopenharmony_ci * Second we need to create the guardian byte. 11658c2ecf20Sopenharmony_ci * We only need a single byte, so lets recycle 11668c2ecf20Sopenharmony_ci * the 'flags' field we are not using for beacons. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_ci bcn_priv->guardian_data = 0; 11698c2ecf20Sopenharmony_ci usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, 11708c2ecf20Sopenharmony_ci &bcn_priv->guardian_data, 1, rt2500usb_beacondone, 11718c2ecf20Sopenharmony_ci entry); 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci /* 11748c2ecf20Sopenharmony_ci * Send out the guardian byte. 11758c2ecf20Sopenharmony_ci */ 11768c2ecf20Sopenharmony_ci usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci /* 11798c2ecf20Sopenharmony_ci * Enable beaconing again. 11808c2ecf20Sopenharmony_ci */ 11818c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); 11828c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); 11838c2ecf20Sopenharmony_ci reg0 = reg; 11848c2ecf20Sopenharmony_ci rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); 11858c2ecf20Sopenharmony_ci /* 11868c2ecf20Sopenharmony_ci * Beacon generation will fail initially. 11878c2ecf20Sopenharmony_ci * To prevent this we need to change the TXRX_CSR19 11888c2ecf20Sopenharmony_ci * register several times (reg0 is the same as reg 11898c2ecf20Sopenharmony_ci * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0 11908c2ecf20Sopenharmony_ci * and 1 in reg). 11918c2ecf20Sopenharmony_ci */ 11928c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 11938c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); 11948c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 11958c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); 11968c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_cistatic int rt2500usb_get_tx_data_len(struct queue_entry *entry) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci int length; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci /* 12048c2ecf20Sopenharmony_ci * The length _must_ be a multiple of 2, 12058c2ecf20Sopenharmony_ci * but it must _not_ be a multiple of the USB packet size. 12068c2ecf20Sopenharmony_ci */ 12078c2ecf20Sopenharmony_ci length = roundup(entry->skb->len, 2); 12088c2ecf20Sopenharmony_ci length += (2 * !(length % entry->queue->usb_maxpacket)); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci return length; 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci/* 12148c2ecf20Sopenharmony_ci * RX control handlers 12158c2ecf20Sopenharmony_ci */ 12168c2ecf20Sopenharmony_cistatic void rt2500usb_fill_rxdone(struct queue_entry *entry, 12178c2ecf20Sopenharmony_ci struct rxdone_entry_desc *rxdesc) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 12208c2ecf20Sopenharmony_ci struct queue_entry_priv_usb *entry_priv = entry->priv_data; 12218c2ecf20Sopenharmony_ci struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); 12228c2ecf20Sopenharmony_ci __le32 *rxd = 12238c2ecf20Sopenharmony_ci (__le32 *)(entry->skb->data + 12248c2ecf20Sopenharmony_ci (entry_priv->urb->actual_length - 12258c2ecf20Sopenharmony_ci entry->queue->desc_size)); 12268c2ecf20Sopenharmony_ci u32 word0; 12278c2ecf20Sopenharmony_ci u32 word1; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci /* 12308c2ecf20Sopenharmony_ci * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of 12318c2ecf20Sopenharmony_ci * frame data in rt2x00usb. 12328c2ecf20Sopenharmony_ci */ 12338c2ecf20Sopenharmony_ci memcpy(skbdesc->desc, rxd, skbdesc->desc_len); 12348c2ecf20Sopenharmony_ci rxd = (__le32 *)skbdesc->desc; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci /* 12378c2ecf20Sopenharmony_ci * It is now safe to read the descriptor on all architectures. 12388c2ecf20Sopenharmony_ci */ 12398c2ecf20Sopenharmony_ci word0 = rt2x00_desc_read(rxd, 0); 12408c2ecf20Sopenharmony_ci word1 = rt2x00_desc_read(rxd, 1); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) 12438c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; 12448c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) 12458c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); 12488c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) 12498c2ecf20Sopenharmony_ci rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci if (rxdesc->cipher != CIPHER_NONE) { 12528c2ecf20Sopenharmony_ci rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2); 12538c2ecf20Sopenharmony_ci rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3); 12548c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_CRYPTO_IV; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* ICV is located at the end of frame */ 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; 12598c2ecf20Sopenharmony_ci if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) 12608c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_DECRYPTED; 12618c2ecf20Sopenharmony_ci else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) 12628c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_MMIC_ERROR; 12638c2ecf20Sopenharmony_ci } 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci /* 12668c2ecf20Sopenharmony_ci * Obtain the status about this packet. 12678c2ecf20Sopenharmony_ci * When frame was received with an OFDM bitrate, 12688c2ecf20Sopenharmony_ci * the signal is the PLCP value. If it was received with 12698c2ecf20Sopenharmony_ci * a CCK bitrate the signal is the rate in 100kbit/s. 12708c2ecf20Sopenharmony_ci */ 12718c2ecf20Sopenharmony_ci rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); 12728c2ecf20Sopenharmony_ci rxdesc->rssi = 12738c2ecf20Sopenharmony_ci rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset; 12748c2ecf20Sopenharmony_ci rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_OFDM)) 12778c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; 12788c2ecf20Sopenharmony_ci else 12798c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; 12808c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) 12818c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_MY_BSS; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci /* 12848c2ecf20Sopenharmony_ci * Adjust the skb memory window to the frame boundaries. 12858c2ecf20Sopenharmony_ci */ 12868c2ecf20Sopenharmony_ci skb_trim(entry->skb, rxdesc->size); 12878c2ecf20Sopenharmony_ci} 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci/* 12908c2ecf20Sopenharmony_ci * Interrupt functions. 12918c2ecf20Sopenharmony_ci */ 12928c2ecf20Sopenharmony_cistatic void rt2500usb_beacondone(struct urb *urb) 12938c2ecf20Sopenharmony_ci{ 12948c2ecf20Sopenharmony_ci struct queue_entry *entry = (struct queue_entry *)urb->context; 12958c2ecf20Sopenharmony_ci struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) 12988c2ecf20Sopenharmony_ci return; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci /* 13018c2ecf20Sopenharmony_ci * Check if this was the guardian beacon, 13028c2ecf20Sopenharmony_ci * if that was the case we need to send the real beacon now. 13038c2ecf20Sopenharmony_ci * Otherwise we should free the sk_buffer, the device 13048c2ecf20Sopenharmony_ci * should be doing the rest of the work now. 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_ci if (bcn_priv->guardian_urb == urb) { 13078c2ecf20Sopenharmony_ci usb_submit_urb(bcn_priv->urb, GFP_ATOMIC); 13088c2ecf20Sopenharmony_ci } else if (bcn_priv->urb == urb) { 13098c2ecf20Sopenharmony_ci dev_kfree_skb(entry->skb); 13108c2ecf20Sopenharmony_ci entry->skb = NULL; 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci/* 13158c2ecf20Sopenharmony_ci * Device probe functions. 13168c2ecf20Sopenharmony_ci */ 13178c2ecf20Sopenharmony_cistatic int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci u16 word; 13208c2ecf20Sopenharmony_ci u8 *mac; 13218c2ecf20Sopenharmony_ci u8 bbp; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* 13268c2ecf20Sopenharmony_ci * Start validation of the data that has been read. 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); 13298c2ecf20Sopenharmony_ci rt2x00lib_set_mac_address(rt2x00dev, mac); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA); 13328c2ecf20Sopenharmony_ci if (word == 0xffff) { 13338c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); 13348c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 13358c2ecf20Sopenharmony_ci ANTENNA_SW_DIVERSITY); 13368c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 13378c2ecf20Sopenharmony_ci ANTENNA_SW_DIVERSITY); 13388c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 13398c2ecf20Sopenharmony_ci LED_MODE_DEFAULT); 13408c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); 13418c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); 13428c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); 13438c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); 13448c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC); 13488c2ecf20Sopenharmony_ci if (word == 0xffff) { 13498c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); 13508c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0); 13518c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0); 13528c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); 13538c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET); 13578c2ecf20Sopenharmony_ci if (word == 0xffff) { 13588c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, 13598c2ecf20Sopenharmony_ci DEFAULT_RSSI_OFFSET); 13608c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); 13618c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n", 13628c2ecf20Sopenharmony_ci word); 13638c2ecf20Sopenharmony_ci } 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE); 13668c2ecf20Sopenharmony_ci if (word == 0xffff) { 13678c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45); 13688c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word); 13698c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word); 13708c2ecf20Sopenharmony_ci } 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* 13738c2ecf20Sopenharmony_ci * Switch lower vgc bound to current BBP R17 value, 13748c2ecf20Sopenharmony_ci * lower the value a bit for better quality. 13758c2ecf20Sopenharmony_ci */ 13768c2ecf20Sopenharmony_ci bbp = rt2500usb_bbp_read(rt2x00dev, 17); 13778c2ecf20Sopenharmony_ci bbp -= 6; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC); 13808c2ecf20Sopenharmony_ci if (word == 0xffff) { 13818c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40); 13828c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); 13838c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); 13848c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); 13858c2ecf20Sopenharmony_ci } else { 13868c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); 13878c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); 13888c2ecf20Sopenharmony_ci } 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17); 13918c2ecf20Sopenharmony_ci if (word == 0xffff) { 13928c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48); 13938c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); 13948c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); 13958c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word); 13968c2ecf20Sopenharmony_ci } 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24); 13998c2ecf20Sopenharmony_ci if (word == 0xffff) { 14008c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40); 14018c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80); 14028c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word); 14038c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word); 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25); 14078c2ecf20Sopenharmony_ci if (word == 0xffff) { 14088c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40); 14098c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50); 14108c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word); 14118c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word); 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61); 14158c2ecf20Sopenharmony_ci if (word == 0xffff) { 14168c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60); 14178c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d); 14188c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word); 14198c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word); 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci return 0; 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_cistatic int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) 14268c2ecf20Sopenharmony_ci{ 14278c2ecf20Sopenharmony_ci u16 reg; 14288c2ecf20Sopenharmony_ci u16 value; 14298c2ecf20Sopenharmony_ci u16 eeprom; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci /* 14328c2ecf20Sopenharmony_ci * Read EEPROM word for configuration. 14338c2ecf20Sopenharmony_ci */ 14348c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci /* 14378c2ecf20Sopenharmony_ci * Identify RF chipset. 14388c2ecf20Sopenharmony_ci */ 14398c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); 14408c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR0); 14418c2ecf20Sopenharmony_ci rt2x00_set_chip(rt2x00dev, RT2570, value, reg); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { 14448c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n"); 14458c2ecf20Sopenharmony_ci return -ENODEV; 14468c2ecf20Sopenharmony_ci } 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci if (!rt2x00_rf(rt2x00dev, RF2522) && 14498c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2523) && 14508c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2524) && 14518c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2525) && 14528c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2525E) && 14538c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF5222)) { 14548c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n"); 14558c2ecf20Sopenharmony_ci return -ENODEV; 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci /* 14598c2ecf20Sopenharmony_ci * Identify default antenna configuration. 14608c2ecf20Sopenharmony_ci */ 14618c2ecf20Sopenharmony_ci rt2x00dev->default_ant.tx = 14628c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); 14638c2ecf20Sopenharmony_ci rt2x00dev->default_ant.rx = 14648c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci /* 14678c2ecf20Sopenharmony_ci * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead. 14688c2ecf20Sopenharmony_ci * I am not 100% sure about this, but the legacy drivers do not 14698c2ecf20Sopenharmony_ci * indicate antenna swapping in software is required when 14708c2ecf20Sopenharmony_ci * diversity is enabled. 14718c2ecf20Sopenharmony_ci */ 14728c2ecf20Sopenharmony_ci if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) 14738c2ecf20Sopenharmony_ci rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; 14748c2ecf20Sopenharmony_ci if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) 14758c2ecf20Sopenharmony_ci rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci /* 14788c2ecf20Sopenharmony_ci * Store led mode, for correct led behaviour. 14798c2ecf20Sopenharmony_ci */ 14808c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS 14818c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); 14848c2ecf20Sopenharmony_ci if (value == LED_MODE_TXRX_ACTIVITY || 14858c2ecf20Sopenharmony_ci value == LED_MODE_DEFAULT || 14868c2ecf20Sopenharmony_ci value == LED_MODE_ASUS) 14878c2ecf20Sopenharmony_ci rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, 14888c2ecf20Sopenharmony_ci LED_TYPE_ACTIVITY); 14898c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */ 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci /* 14928c2ecf20Sopenharmony_ci * Detect if this device has an hardware controlled radio. 14938c2ecf20Sopenharmony_ci */ 14948c2ecf20Sopenharmony_ci if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) 14958c2ecf20Sopenharmony_ci __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci /* 14988c2ecf20Sopenharmony_ci * Read the RSSI <-> dBm offset information. 14998c2ecf20Sopenharmony_ci */ 15008c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET); 15018c2ecf20Sopenharmony_ci rt2x00dev->rssi_offset = 15028c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci return 0; 15058c2ecf20Sopenharmony_ci} 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci/* 15088c2ecf20Sopenharmony_ci * RF value list for RF2522 15098c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 15108c2ecf20Sopenharmony_ci */ 15118c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2522[] = { 15128c2ecf20Sopenharmony_ci { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, 15138c2ecf20Sopenharmony_ci { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, 15148c2ecf20Sopenharmony_ci { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, 15158c2ecf20Sopenharmony_ci { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, 15168c2ecf20Sopenharmony_ci { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, 15178c2ecf20Sopenharmony_ci { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, 15188c2ecf20Sopenharmony_ci { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, 15198c2ecf20Sopenharmony_ci { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, 15208c2ecf20Sopenharmony_ci { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, 15218c2ecf20Sopenharmony_ci { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, 15228c2ecf20Sopenharmony_ci { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, 15238c2ecf20Sopenharmony_ci { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, 15248c2ecf20Sopenharmony_ci { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, 15258c2ecf20Sopenharmony_ci { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, 15268c2ecf20Sopenharmony_ci}; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci/* 15298c2ecf20Sopenharmony_ci * RF value list for RF2523 15308c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 15318c2ecf20Sopenharmony_ci */ 15328c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2523[] = { 15338c2ecf20Sopenharmony_ci { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, 15348c2ecf20Sopenharmony_ci { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, 15358c2ecf20Sopenharmony_ci { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, 15368c2ecf20Sopenharmony_ci { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, 15378c2ecf20Sopenharmony_ci { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, 15388c2ecf20Sopenharmony_ci { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, 15398c2ecf20Sopenharmony_ci { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, 15408c2ecf20Sopenharmony_ci { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, 15418c2ecf20Sopenharmony_ci { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, 15428c2ecf20Sopenharmony_ci { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, 15438c2ecf20Sopenharmony_ci { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, 15448c2ecf20Sopenharmony_ci { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, 15458c2ecf20Sopenharmony_ci { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, 15468c2ecf20Sopenharmony_ci { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, 15478c2ecf20Sopenharmony_ci}; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci/* 15508c2ecf20Sopenharmony_ci * RF value list for RF2524 15518c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 15528c2ecf20Sopenharmony_ci */ 15538c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2524[] = { 15548c2ecf20Sopenharmony_ci { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, 15558c2ecf20Sopenharmony_ci { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, 15568c2ecf20Sopenharmony_ci { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, 15578c2ecf20Sopenharmony_ci { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, 15588c2ecf20Sopenharmony_ci { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, 15598c2ecf20Sopenharmony_ci { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, 15608c2ecf20Sopenharmony_ci { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, 15618c2ecf20Sopenharmony_ci { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, 15628c2ecf20Sopenharmony_ci { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, 15638c2ecf20Sopenharmony_ci { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, 15648c2ecf20Sopenharmony_ci { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, 15658c2ecf20Sopenharmony_ci { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, 15668c2ecf20Sopenharmony_ci { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, 15678c2ecf20Sopenharmony_ci { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, 15688c2ecf20Sopenharmony_ci}; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci/* 15718c2ecf20Sopenharmony_ci * RF value list for RF2525 15728c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 15738c2ecf20Sopenharmony_ci */ 15748c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525[] = { 15758c2ecf20Sopenharmony_ci { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, 15768c2ecf20Sopenharmony_ci { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, 15778c2ecf20Sopenharmony_ci { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, 15788c2ecf20Sopenharmony_ci { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, 15798c2ecf20Sopenharmony_ci { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, 15808c2ecf20Sopenharmony_ci { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, 15818c2ecf20Sopenharmony_ci { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, 15828c2ecf20Sopenharmony_ci { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, 15838c2ecf20Sopenharmony_ci { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, 15848c2ecf20Sopenharmony_ci { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, 15858c2ecf20Sopenharmony_ci { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, 15868c2ecf20Sopenharmony_ci { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, 15878c2ecf20Sopenharmony_ci { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, 15888c2ecf20Sopenharmony_ci { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, 15898c2ecf20Sopenharmony_ci}; 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci/* 15928c2ecf20Sopenharmony_ci * RF value list for RF2525e 15938c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525e[] = { 15968c2ecf20Sopenharmony_ci { 1, 0x00022010, 0x0000089a, 0x00060111, 0x00000e1b }, 15978c2ecf20Sopenharmony_ci { 2, 0x00022010, 0x0000089e, 0x00060111, 0x00000e07 }, 15988c2ecf20Sopenharmony_ci { 3, 0x00022010, 0x0000089e, 0x00060111, 0x00000e1b }, 15998c2ecf20Sopenharmony_ci { 4, 0x00022010, 0x000008a2, 0x00060111, 0x00000e07 }, 16008c2ecf20Sopenharmony_ci { 5, 0x00022010, 0x000008a2, 0x00060111, 0x00000e1b }, 16018c2ecf20Sopenharmony_ci { 6, 0x00022010, 0x000008a6, 0x00060111, 0x00000e07 }, 16028c2ecf20Sopenharmony_ci { 7, 0x00022010, 0x000008a6, 0x00060111, 0x00000e1b }, 16038c2ecf20Sopenharmony_ci { 8, 0x00022010, 0x000008aa, 0x00060111, 0x00000e07 }, 16048c2ecf20Sopenharmony_ci { 9, 0x00022010, 0x000008aa, 0x00060111, 0x00000e1b }, 16058c2ecf20Sopenharmony_ci { 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 }, 16068c2ecf20Sopenharmony_ci { 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b }, 16078c2ecf20Sopenharmony_ci { 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 }, 16088c2ecf20Sopenharmony_ci { 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b }, 16098c2ecf20Sopenharmony_ci { 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 }, 16108c2ecf20Sopenharmony_ci}; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci/* 16138c2ecf20Sopenharmony_ci * RF value list for RF5222 16148c2ecf20Sopenharmony_ci * Supports: 2.4 GHz & 5.2 GHz 16158c2ecf20Sopenharmony_ci */ 16168c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_5222[] = { 16178c2ecf20Sopenharmony_ci { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, 16188c2ecf20Sopenharmony_ci { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, 16198c2ecf20Sopenharmony_ci { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, 16208c2ecf20Sopenharmony_ci { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, 16218c2ecf20Sopenharmony_ci { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, 16228c2ecf20Sopenharmony_ci { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, 16238c2ecf20Sopenharmony_ci { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, 16248c2ecf20Sopenharmony_ci { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, 16258c2ecf20Sopenharmony_ci { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, 16268c2ecf20Sopenharmony_ci { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, 16278c2ecf20Sopenharmony_ci { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, 16288c2ecf20Sopenharmony_ci { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, 16298c2ecf20Sopenharmony_ci { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, 16308c2ecf20Sopenharmony_ci { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci /* 802.11 UNI / HyperLan 2 */ 16338c2ecf20Sopenharmony_ci { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, 16348c2ecf20Sopenharmony_ci { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, 16358c2ecf20Sopenharmony_ci { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, 16368c2ecf20Sopenharmony_ci { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, 16378c2ecf20Sopenharmony_ci { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, 16388c2ecf20Sopenharmony_ci { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, 16398c2ecf20Sopenharmony_ci { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, 16408c2ecf20Sopenharmony_ci { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* 802.11 HyperLan 2 */ 16438c2ecf20Sopenharmony_ci { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, 16448c2ecf20Sopenharmony_ci { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, 16458c2ecf20Sopenharmony_ci { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, 16468c2ecf20Sopenharmony_ci { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, 16478c2ecf20Sopenharmony_ci { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, 16488c2ecf20Sopenharmony_ci { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, 16498c2ecf20Sopenharmony_ci { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, 16508c2ecf20Sopenharmony_ci { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, 16518c2ecf20Sopenharmony_ci { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, 16528c2ecf20Sopenharmony_ci { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci /* 802.11 UNII */ 16558c2ecf20Sopenharmony_ci { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, 16568c2ecf20Sopenharmony_ci { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, 16578c2ecf20Sopenharmony_ci { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, 16588c2ecf20Sopenharmony_ci { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, 16598c2ecf20Sopenharmony_ci { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, 16608c2ecf20Sopenharmony_ci}; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_cistatic int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci struct hw_mode_spec *spec = &rt2x00dev->spec; 16658c2ecf20Sopenharmony_ci struct channel_info *info; 16668c2ecf20Sopenharmony_ci char *tx_power; 16678c2ecf20Sopenharmony_ci unsigned int i; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* 16708c2ecf20Sopenharmony_ci * Initialize all hw fields. 16718c2ecf20Sopenharmony_ci * 16728c2ecf20Sopenharmony_ci * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are 16738c2ecf20Sopenharmony_ci * capable of sending the buffered frames out after the DTIM 16748c2ecf20Sopenharmony_ci * transmission using rt2x00lib_beacondone. This will send out 16758c2ecf20Sopenharmony_ci * multicast and broadcast traffic immediately instead of buffering it 16768c2ecf20Sopenharmony_ci * infinitly and thus dropping it after some time. 16778c2ecf20Sopenharmony_ci */ 16788c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK); 16798c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS); 16808c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, RX_INCLUDES_FCS); 16818c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM); 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* 16848c2ecf20Sopenharmony_ci * Disable powersaving as default. 16858c2ecf20Sopenharmony_ci */ 16868c2ecf20Sopenharmony_ci rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 16898c2ecf20Sopenharmony_ci SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 16908c2ecf20Sopenharmony_ci rt2x00_eeprom_addr(rt2x00dev, 16918c2ecf20Sopenharmony_ci EEPROM_MAC_ADDR_0)); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci /* 16948c2ecf20Sopenharmony_ci * Initialize hw_mode information. 16958c2ecf20Sopenharmony_ci */ 16968c2ecf20Sopenharmony_ci spec->supported_bands = SUPPORT_BAND_2GHZ; 16978c2ecf20Sopenharmony_ci spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2522)) { 17008c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); 17018c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2522; 17028c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2523)) { 17038c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); 17048c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2523; 17058c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2524)) { 17068c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); 17078c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2524; 17088c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2525)) { 17098c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); 17108c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2525; 17118c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2525E)) { 17128c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); 17138c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2525e; 17148c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF5222)) { 17158c2ecf20Sopenharmony_ci spec->supported_bands |= SUPPORT_BAND_5GHZ; 17168c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_5222); 17178c2ecf20Sopenharmony_ci spec->channels = rf_vals_5222; 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci /* 17218c2ecf20Sopenharmony_ci * Create channel information array 17228c2ecf20Sopenharmony_ci */ 17238c2ecf20Sopenharmony_ci info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); 17248c2ecf20Sopenharmony_ci if (!info) 17258c2ecf20Sopenharmony_ci return -ENOMEM; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci spec->channels_info = info; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); 17308c2ecf20Sopenharmony_ci for (i = 0; i < 14; i++) { 17318c2ecf20Sopenharmony_ci info[i].max_power = MAX_TXPOWER; 17328c2ecf20Sopenharmony_ci info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci if (spec->num_channels > 14) { 17368c2ecf20Sopenharmony_ci for (i = 14; i < spec->num_channels; i++) { 17378c2ecf20Sopenharmony_ci info[i].max_power = MAX_TXPOWER; 17388c2ecf20Sopenharmony_ci info[i].default_power1 = DEFAULT_TXPOWER; 17398c2ecf20Sopenharmony_ci } 17408c2ecf20Sopenharmony_ci } 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci return 0; 17438c2ecf20Sopenharmony_ci} 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_cistatic int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) 17468c2ecf20Sopenharmony_ci{ 17478c2ecf20Sopenharmony_ci int retval; 17488c2ecf20Sopenharmony_ci u16 reg; 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci /* 17518c2ecf20Sopenharmony_ci * Allocate eeprom data. 17528c2ecf20Sopenharmony_ci */ 17538c2ecf20Sopenharmony_ci retval = rt2500usb_validate_eeprom(rt2x00dev); 17548c2ecf20Sopenharmony_ci if (retval) 17558c2ecf20Sopenharmony_ci return retval; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci retval = rt2500usb_init_eeprom(rt2x00dev); 17588c2ecf20Sopenharmony_ci if (retval) 17598c2ecf20Sopenharmony_ci return retval; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci /* 17628c2ecf20Sopenharmony_ci * Enable rfkill polling by setting GPIO direction of the 17638c2ecf20Sopenharmony_ci * rfkill switch GPIO pin correctly. 17648c2ecf20Sopenharmony_ci */ 17658c2ecf20Sopenharmony_ci reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19); 17668c2ecf20Sopenharmony_ci rt2x00_set_field16(®, MAC_CSR19_DIR0, 0); 17678c2ecf20Sopenharmony_ci rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci /* 17708c2ecf20Sopenharmony_ci * Initialize hw specifications. 17718c2ecf20Sopenharmony_ci */ 17728c2ecf20Sopenharmony_ci retval = rt2500usb_probe_hw_mode(rt2x00dev); 17738c2ecf20Sopenharmony_ci if (retval) 17748c2ecf20Sopenharmony_ci return retval; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci /* 17778c2ecf20Sopenharmony_ci * This device requires the atim queue 17788c2ecf20Sopenharmony_ci */ 17798c2ecf20Sopenharmony_ci __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); 17808c2ecf20Sopenharmony_ci __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags); 17818c2ecf20Sopenharmony_ci if (!modparam_nohwcrypt) { 17828c2ecf20Sopenharmony_ci __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); 17838c2ecf20Sopenharmony_ci __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags); 17848c2ecf20Sopenharmony_ci } 17858c2ecf20Sopenharmony_ci __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); 17868c2ecf20Sopenharmony_ci __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci /* 17898c2ecf20Sopenharmony_ci * Set the rssi offset. 17908c2ecf20Sopenharmony_ci */ 17918c2ecf20Sopenharmony_ci rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci return 0; 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_cistatic const struct ieee80211_ops rt2500usb_mac80211_ops = { 17978c2ecf20Sopenharmony_ci .tx = rt2x00mac_tx, 17988c2ecf20Sopenharmony_ci .start = rt2x00mac_start, 17998c2ecf20Sopenharmony_ci .stop = rt2x00mac_stop, 18008c2ecf20Sopenharmony_ci .add_interface = rt2x00mac_add_interface, 18018c2ecf20Sopenharmony_ci .remove_interface = rt2x00mac_remove_interface, 18028c2ecf20Sopenharmony_ci .config = rt2x00mac_config, 18038c2ecf20Sopenharmony_ci .configure_filter = rt2x00mac_configure_filter, 18048c2ecf20Sopenharmony_ci .set_tim = rt2x00mac_set_tim, 18058c2ecf20Sopenharmony_ci .set_key = rt2x00mac_set_key, 18068c2ecf20Sopenharmony_ci .sw_scan_start = rt2x00mac_sw_scan_start, 18078c2ecf20Sopenharmony_ci .sw_scan_complete = rt2x00mac_sw_scan_complete, 18088c2ecf20Sopenharmony_ci .get_stats = rt2x00mac_get_stats, 18098c2ecf20Sopenharmony_ci .bss_info_changed = rt2x00mac_bss_info_changed, 18108c2ecf20Sopenharmony_ci .conf_tx = rt2x00mac_conf_tx, 18118c2ecf20Sopenharmony_ci .rfkill_poll = rt2x00mac_rfkill_poll, 18128c2ecf20Sopenharmony_ci .flush = rt2x00mac_flush, 18138c2ecf20Sopenharmony_ci .set_antenna = rt2x00mac_set_antenna, 18148c2ecf20Sopenharmony_ci .get_antenna = rt2x00mac_get_antenna, 18158c2ecf20Sopenharmony_ci .get_ringparam = rt2x00mac_get_ringparam, 18168c2ecf20Sopenharmony_ci .tx_frames_pending = rt2x00mac_tx_frames_pending, 18178c2ecf20Sopenharmony_ci}; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_cistatic const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { 18208c2ecf20Sopenharmony_ci .probe_hw = rt2500usb_probe_hw, 18218c2ecf20Sopenharmony_ci .initialize = rt2x00usb_initialize, 18228c2ecf20Sopenharmony_ci .uninitialize = rt2x00usb_uninitialize, 18238c2ecf20Sopenharmony_ci .clear_entry = rt2x00usb_clear_entry, 18248c2ecf20Sopenharmony_ci .set_device_state = rt2500usb_set_device_state, 18258c2ecf20Sopenharmony_ci .rfkill_poll = rt2500usb_rfkill_poll, 18268c2ecf20Sopenharmony_ci .link_stats = rt2500usb_link_stats, 18278c2ecf20Sopenharmony_ci .reset_tuner = rt2500usb_reset_tuner, 18288c2ecf20Sopenharmony_ci .watchdog = rt2x00usb_watchdog, 18298c2ecf20Sopenharmony_ci .start_queue = rt2500usb_start_queue, 18308c2ecf20Sopenharmony_ci .kick_queue = rt2x00usb_kick_queue, 18318c2ecf20Sopenharmony_ci .stop_queue = rt2500usb_stop_queue, 18328c2ecf20Sopenharmony_ci .flush_queue = rt2x00usb_flush_queue, 18338c2ecf20Sopenharmony_ci .write_tx_desc = rt2500usb_write_tx_desc, 18348c2ecf20Sopenharmony_ci .write_beacon = rt2500usb_write_beacon, 18358c2ecf20Sopenharmony_ci .get_tx_data_len = rt2500usb_get_tx_data_len, 18368c2ecf20Sopenharmony_ci .fill_rxdone = rt2500usb_fill_rxdone, 18378c2ecf20Sopenharmony_ci .config_shared_key = rt2500usb_config_key, 18388c2ecf20Sopenharmony_ci .config_pairwise_key = rt2500usb_config_key, 18398c2ecf20Sopenharmony_ci .config_filter = rt2500usb_config_filter, 18408c2ecf20Sopenharmony_ci .config_intf = rt2500usb_config_intf, 18418c2ecf20Sopenharmony_ci .config_erp = rt2500usb_config_erp, 18428c2ecf20Sopenharmony_ci .config_ant = rt2500usb_config_ant, 18438c2ecf20Sopenharmony_ci .config = rt2500usb_config, 18448c2ecf20Sopenharmony_ci}; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_cistatic void rt2500usb_queue_init(struct data_queue *queue) 18478c2ecf20Sopenharmony_ci{ 18488c2ecf20Sopenharmony_ci switch (queue->qid) { 18498c2ecf20Sopenharmony_ci case QID_RX: 18508c2ecf20Sopenharmony_ci queue->limit = 32; 18518c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 18528c2ecf20Sopenharmony_ci queue->desc_size = RXD_DESC_SIZE; 18538c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_usb); 18548c2ecf20Sopenharmony_ci break; 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci case QID_AC_VO: 18578c2ecf20Sopenharmony_ci case QID_AC_VI: 18588c2ecf20Sopenharmony_ci case QID_AC_BE: 18598c2ecf20Sopenharmony_ci case QID_AC_BK: 18608c2ecf20Sopenharmony_ci queue->limit = 32; 18618c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 18628c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 18638c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_usb); 18648c2ecf20Sopenharmony_ci break; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci case QID_BEACON: 18678c2ecf20Sopenharmony_ci queue->limit = 1; 18688c2ecf20Sopenharmony_ci queue->data_size = MGMT_FRAME_SIZE; 18698c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 18708c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn); 18718c2ecf20Sopenharmony_ci break; 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci case QID_ATIM: 18748c2ecf20Sopenharmony_ci queue->limit = 8; 18758c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 18768c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 18778c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_usb); 18788c2ecf20Sopenharmony_ci break; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci default: 18818c2ecf20Sopenharmony_ci BUG(); 18828c2ecf20Sopenharmony_ci break; 18838c2ecf20Sopenharmony_ci } 18848c2ecf20Sopenharmony_ci} 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_cistatic const struct rt2x00_ops rt2500usb_ops = { 18878c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 18888c2ecf20Sopenharmony_ci .max_ap_intf = 1, 18898c2ecf20Sopenharmony_ci .eeprom_size = EEPROM_SIZE, 18908c2ecf20Sopenharmony_ci .rf_size = RF_SIZE, 18918c2ecf20Sopenharmony_ci .tx_queues = NUM_TX_QUEUES, 18928c2ecf20Sopenharmony_ci .queue_init = rt2500usb_queue_init, 18938c2ecf20Sopenharmony_ci .lib = &rt2500usb_rt2x00_ops, 18948c2ecf20Sopenharmony_ci .hw = &rt2500usb_mac80211_ops, 18958c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS 18968c2ecf20Sopenharmony_ci .debugfs = &rt2500usb_rt2x00debug, 18978c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 18988c2ecf20Sopenharmony_ci}; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci/* 19018c2ecf20Sopenharmony_ci * rt2500usb module information. 19028c2ecf20Sopenharmony_ci */ 19038c2ecf20Sopenharmony_cistatic const struct usb_device_id rt2500usb_device_table[] = { 19048c2ecf20Sopenharmony_ci /* ASUS */ 19058c2ecf20Sopenharmony_ci { USB_DEVICE(0x0b05, 0x1706) }, 19068c2ecf20Sopenharmony_ci { USB_DEVICE(0x0b05, 0x1707) }, 19078c2ecf20Sopenharmony_ci /* Belkin */ 19088c2ecf20Sopenharmony_ci { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050A ver. 2.x */ 19098c2ecf20Sopenharmony_ci { USB_DEVICE(0x050d, 0x7051) }, 19108c2ecf20Sopenharmony_ci /* Cisco Systems */ 19118c2ecf20Sopenharmony_ci { USB_DEVICE(0x13b1, 0x000d) }, 19128c2ecf20Sopenharmony_ci { USB_DEVICE(0x13b1, 0x0011) }, 19138c2ecf20Sopenharmony_ci { USB_DEVICE(0x13b1, 0x001a) }, 19148c2ecf20Sopenharmony_ci /* Conceptronic */ 19158c2ecf20Sopenharmony_ci { USB_DEVICE(0x14b2, 0x3c02) }, 19168c2ecf20Sopenharmony_ci /* D-LINK */ 19178c2ecf20Sopenharmony_ci { USB_DEVICE(0x2001, 0x3c00) }, 19188c2ecf20Sopenharmony_ci /* Gigabyte */ 19198c2ecf20Sopenharmony_ci { USB_DEVICE(0x1044, 0x8001) }, 19208c2ecf20Sopenharmony_ci { USB_DEVICE(0x1044, 0x8007) }, 19218c2ecf20Sopenharmony_ci /* Hercules */ 19228c2ecf20Sopenharmony_ci { USB_DEVICE(0x06f8, 0xe000) }, 19238c2ecf20Sopenharmony_ci /* Melco */ 19248c2ecf20Sopenharmony_ci { USB_DEVICE(0x0411, 0x005e) }, 19258c2ecf20Sopenharmony_ci { USB_DEVICE(0x0411, 0x0066) }, 19268c2ecf20Sopenharmony_ci { USB_DEVICE(0x0411, 0x0067) }, 19278c2ecf20Sopenharmony_ci { USB_DEVICE(0x0411, 0x008b) }, 19288c2ecf20Sopenharmony_ci { USB_DEVICE(0x0411, 0x0097) }, 19298c2ecf20Sopenharmony_ci /* MSI */ 19308c2ecf20Sopenharmony_ci { USB_DEVICE(0x0db0, 0x6861) }, 19318c2ecf20Sopenharmony_ci { USB_DEVICE(0x0db0, 0x6865) }, 19328c2ecf20Sopenharmony_ci { USB_DEVICE(0x0db0, 0x6869) }, 19338c2ecf20Sopenharmony_ci /* Ralink */ 19348c2ecf20Sopenharmony_ci { USB_DEVICE(0x148f, 0x1706) }, 19358c2ecf20Sopenharmony_ci { USB_DEVICE(0x148f, 0x2570) }, 19368c2ecf20Sopenharmony_ci { USB_DEVICE(0x148f, 0x9020) }, 19378c2ecf20Sopenharmony_ci /* Sagem */ 19388c2ecf20Sopenharmony_ci { USB_DEVICE(0x079b, 0x004b) }, 19398c2ecf20Sopenharmony_ci /* Siemens */ 19408c2ecf20Sopenharmony_ci { USB_DEVICE(0x0681, 0x3c06) }, 19418c2ecf20Sopenharmony_ci /* SMC */ 19428c2ecf20Sopenharmony_ci { USB_DEVICE(0x0707, 0xee13) }, 19438c2ecf20Sopenharmony_ci /* Spairon */ 19448c2ecf20Sopenharmony_ci { USB_DEVICE(0x114b, 0x0110) }, 19458c2ecf20Sopenharmony_ci /* SURECOM */ 19468c2ecf20Sopenharmony_ci { USB_DEVICE(0x0769, 0x11f3) }, 19478c2ecf20Sopenharmony_ci /* Trust */ 19488c2ecf20Sopenharmony_ci { USB_DEVICE(0x0eb0, 0x9020) }, 19498c2ecf20Sopenharmony_ci /* VTech */ 19508c2ecf20Sopenharmony_ci { USB_DEVICE(0x0f88, 0x3012) }, 19518c2ecf20Sopenharmony_ci /* Zinwell */ 19528c2ecf20Sopenharmony_ci { USB_DEVICE(0x5a57, 0x0260) }, 19538c2ecf20Sopenharmony_ci { 0, } 19548c2ecf20Sopenharmony_ci}; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRV_PROJECT); 19578c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 19588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver."); 19598c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards"); 19608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, rt2500usb_device_table); 19618c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_cistatic int rt2500usb_probe(struct usb_interface *usb_intf, 19648c2ecf20Sopenharmony_ci const struct usb_device_id *id) 19658c2ecf20Sopenharmony_ci{ 19668c2ecf20Sopenharmony_ci return rt2x00usb_probe(usb_intf, &rt2500usb_ops); 19678c2ecf20Sopenharmony_ci} 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_cistatic struct usb_driver rt2500usb_driver = { 19708c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 19718c2ecf20Sopenharmony_ci .id_table = rt2500usb_device_table, 19728c2ecf20Sopenharmony_ci .probe = rt2500usb_probe, 19738c2ecf20Sopenharmony_ci .disconnect = rt2x00usb_disconnect, 19748c2ecf20Sopenharmony_ci .suspend = rt2x00usb_suspend, 19758c2ecf20Sopenharmony_ci .resume = rt2x00usb_resume, 19768c2ecf20Sopenharmony_ci .reset_resume = rt2x00usb_resume, 19778c2ecf20Sopenharmony_ci .disable_hub_initiated_lpm = 1, 19788c2ecf20Sopenharmony_ci}; 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_cimodule_usb_driver(rt2500usb_driver); 1981