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