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: rt2500pci 108c2ecf20Sopenharmony_ci Abstract: rt2500pci device specific routines. 118c2ecf20Sopenharmony_ci Supported chipsets: RT2560. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/pci.h> 198c2ecf20Sopenharmony_ci#include <linux/eeprom_93cx6.h> 208c2ecf20Sopenharmony_ci#include <linux/slab.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "rt2x00.h" 238c2ecf20Sopenharmony_ci#include "rt2x00mmio.h" 248c2ecf20Sopenharmony_ci#include "rt2x00pci.h" 258c2ecf20Sopenharmony_ci#include "rt2500pci.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* 288c2ecf20Sopenharmony_ci * Register access. 298c2ecf20Sopenharmony_ci * All access to the CSR registers will go through the methods 308c2ecf20Sopenharmony_ci * rt2x00mmio_register_read and rt2x00mmio_register_write. 318c2ecf20Sopenharmony_ci * BBP and RF register require indirect register access, 328c2ecf20Sopenharmony_ci * and use the CSR registers BBPCSR and RFCSR to achieve this. 338c2ecf20Sopenharmony_ci * These indirect registers work with busy bits, 348c2ecf20Sopenharmony_ci * and we will try maximal REGISTER_BUSY_COUNT times to access 358c2ecf20Sopenharmony_ci * the register while taking a REGISTER_BUSY_DELAY us delay 368c2ecf20Sopenharmony_ci * between each attampt. When the busy bit is still set at that time, 378c2ecf20Sopenharmony_ci * the access attempt is considered to have failed, 388c2ecf20Sopenharmony_ci * and we will print an error. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci#define WAIT_FOR_BBP(__dev, __reg) \ 418c2ecf20Sopenharmony_ci rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) 428c2ecf20Sopenharmony_ci#define WAIT_FOR_RF(__dev, __reg) \ 438c2ecf20Sopenharmony_ci rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, 468c2ecf20Sopenharmony_ci const unsigned int word, const u8 value) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci u32 reg; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* 538c2ecf20Sopenharmony_ci * Wait until the BBP becomes available, afterwards we 548c2ecf20Sopenharmony_ci * can safely write the new data into the register. 558c2ecf20Sopenharmony_ci */ 568c2ecf20Sopenharmony_ci if (WAIT_FOR_BBP(rt2x00dev, ®)) { 578c2ecf20Sopenharmony_ci reg = 0; 588c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_VALUE, value); 598c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_REGNUM, word); 608c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_BUSY, 1); 618c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic u8 rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, 708c2ecf20Sopenharmony_ci const unsigned int word) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci u32 reg; 738c2ecf20Sopenharmony_ci u8 value; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Wait until the BBP becomes available, afterwards we 798c2ecf20Sopenharmony_ci * can safely write the read request into the register. 808c2ecf20Sopenharmony_ci * After the data has been written, we wait until hardware 818c2ecf20Sopenharmony_ci * returns the correct value, if at any time the register 828c2ecf20Sopenharmony_ci * doesn't become available in time, reg will be 0xffffffff 838c2ecf20Sopenharmony_ci * which means we return 0xff to the caller. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci if (WAIT_FOR_BBP(rt2x00dev, ®)) { 868c2ecf20Sopenharmony_ci reg = 0; 878c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_REGNUM, word); 888c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_BUSY, 1); 898c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci WAIT_FOR_BBP(rt2x00dev, ®); 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci value = rt2x00_get_field32(reg, BBPCSR_VALUE); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci return value; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, 1048c2ecf20Sopenharmony_ci const unsigned int word, const u32 value) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci u32 reg; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci mutex_lock(&rt2x00dev->csr_mutex); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* 1118c2ecf20Sopenharmony_ci * Wait until the RF becomes available, afterwards we 1128c2ecf20Sopenharmony_ci * can safely write the new data into the register. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci if (WAIT_FOR_RF(rt2x00dev, ®)) { 1158c2ecf20Sopenharmony_ci reg = 0; 1168c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RFCSR_VALUE, value); 1178c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); 1188c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); 1198c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RFCSR_BUSY, 1); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RFCSR, reg); 1228c2ecf20Sopenharmony_ci rt2x00_rf_write(rt2x00dev, word, value); 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci mutex_unlock(&rt2x00dev->csr_mutex); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = eeprom->data; 1318c2ecf20Sopenharmony_ci u32 reg; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR21); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); 1368c2ecf20Sopenharmony_ci eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); 1378c2ecf20Sopenharmony_ci eeprom->reg_data_clock = 1388c2ecf20Sopenharmony_ci !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK); 1398c2ecf20Sopenharmony_ci eeprom->reg_chip_select = 1408c2ecf20Sopenharmony_ci !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = eeprom->data; 1468c2ecf20Sopenharmony_ci u32 reg = 0; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in); 1498c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out); 1508c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK, 1518c2ecf20Sopenharmony_ci !!eeprom->reg_data_clock); 1528c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, 1538c2ecf20Sopenharmony_ci !!eeprom->reg_chip_select); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR21, reg); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS 1598c2ecf20Sopenharmony_cistatic const struct rt2x00debug rt2500pci_rt2x00debug = { 1608c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1618c2ecf20Sopenharmony_ci .csr = { 1628c2ecf20Sopenharmony_ci .read = rt2x00mmio_register_read, 1638c2ecf20Sopenharmony_ci .write = rt2x00mmio_register_write, 1648c2ecf20Sopenharmony_ci .flags = RT2X00DEBUGFS_OFFSET, 1658c2ecf20Sopenharmony_ci .word_base = CSR_REG_BASE, 1668c2ecf20Sopenharmony_ci .word_size = sizeof(u32), 1678c2ecf20Sopenharmony_ci .word_count = CSR_REG_SIZE / sizeof(u32), 1688c2ecf20Sopenharmony_ci }, 1698c2ecf20Sopenharmony_ci .eeprom = { 1708c2ecf20Sopenharmony_ci .read = rt2x00_eeprom_read, 1718c2ecf20Sopenharmony_ci .write = rt2x00_eeprom_write, 1728c2ecf20Sopenharmony_ci .word_base = EEPROM_BASE, 1738c2ecf20Sopenharmony_ci .word_size = sizeof(u16), 1748c2ecf20Sopenharmony_ci .word_count = EEPROM_SIZE / sizeof(u16), 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci .bbp = { 1778c2ecf20Sopenharmony_ci .read = rt2500pci_bbp_read, 1788c2ecf20Sopenharmony_ci .write = rt2500pci_bbp_write, 1798c2ecf20Sopenharmony_ci .word_base = BBP_BASE, 1808c2ecf20Sopenharmony_ci .word_size = sizeof(u8), 1818c2ecf20Sopenharmony_ci .word_count = BBP_SIZE / sizeof(u8), 1828c2ecf20Sopenharmony_ci }, 1838c2ecf20Sopenharmony_ci .rf = { 1848c2ecf20Sopenharmony_ci .read = rt2x00_rf_read, 1858c2ecf20Sopenharmony_ci .write = rt2500pci_rf_write, 1868c2ecf20Sopenharmony_ci .word_base = RF_BASE, 1878c2ecf20Sopenharmony_ci .word_size = sizeof(u32), 1888c2ecf20Sopenharmony_ci .word_count = RF_SIZE / sizeof(u32), 1898c2ecf20Sopenharmony_ci }, 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci u32 reg; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR); 1988c2ecf20Sopenharmony_ci return rt2x00_get_field32(reg, GPIOCSR_VAL0); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS 2028c2ecf20Sopenharmony_cistatic void rt2500pci_brightness_set(struct led_classdev *led_cdev, 2038c2ecf20Sopenharmony_ci enum led_brightness brightness) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct rt2x00_led *led = 2068c2ecf20Sopenharmony_ci container_of(led_cdev, struct rt2x00_led, led_dev); 2078c2ecf20Sopenharmony_ci unsigned int enabled = brightness != LED_OFF; 2088c2ecf20Sopenharmony_ci u32 reg; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) 2138c2ecf20Sopenharmony_ci rt2x00_set_field32(®, LEDCSR_LINK, enabled); 2148c2ecf20Sopenharmony_ci else if (led->type == LED_TYPE_ACTIVITY) 2158c2ecf20Sopenharmony_ci rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic int rt2500pci_blink_set(struct led_classdev *led_cdev, 2218c2ecf20Sopenharmony_ci unsigned long *delay_on, 2228c2ecf20Sopenharmony_ci unsigned long *delay_off) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci struct rt2x00_led *led = 2258c2ecf20Sopenharmony_ci container_of(led_cdev, struct rt2x00_led, led_dev); 2268c2ecf20Sopenharmony_ci u32 reg; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR); 2298c2ecf20Sopenharmony_ci rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); 2308c2ecf20Sopenharmony_ci rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); 2318c2ecf20Sopenharmony_ci rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return 0; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev, 2378c2ecf20Sopenharmony_ci struct rt2x00_led *led, 2388c2ecf20Sopenharmony_ci enum led_type type) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci led->rt2x00dev = rt2x00dev; 2418c2ecf20Sopenharmony_ci led->type = type; 2428c2ecf20Sopenharmony_ci led->led_dev.brightness_set = rt2500pci_brightness_set; 2438c2ecf20Sopenharmony_ci led->led_dev.blink_set = rt2500pci_blink_set; 2448c2ecf20Sopenharmony_ci led->flags = LED_INITIALIZED; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */ 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/* 2498c2ecf20Sopenharmony_ci * Configuration handlers. 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_cistatic void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, 2528c2ecf20Sopenharmony_ci const unsigned int filter_flags) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci u32 reg; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* 2578c2ecf20Sopenharmony_ci * Start configuration steps. 2588c2ecf20Sopenharmony_ci * Note that the version error will always be dropped 2598c2ecf20Sopenharmony_ci * and broadcast frames will always be accepted since 2608c2ecf20Sopenharmony_ci * there is no filter for it at this time. 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0); 2638c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_CRC, 2648c2ecf20Sopenharmony_ci !(filter_flags & FIF_FCSFAIL)); 2658c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 2668c2ecf20Sopenharmony_ci !(filter_flags & FIF_PLCPFAIL)); 2678c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 2688c2ecf20Sopenharmony_ci !(filter_flags & FIF_CONTROL)); 2698c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 2708c2ecf20Sopenharmony_ci !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); 2718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_TODS, 2728c2ecf20Sopenharmony_ci !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && 2738c2ecf20Sopenharmony_ci !rt2x00dev->intf_ap_count); 2748c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); 2758c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_MCAST, 2768c2ecf20Sopenharmony_ci !(filter_flags & FIF_ALLMULTI)); 2778c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); 2788c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, 2828c2ecf20Sopenharmony_ci struct rt2x00_intf *intf, 2838c2ecf20Sopenharmony_ci struct rt2x00intf_conf *conf, 2848c2ecf20Sopenharmony_ci const unsigned int flags) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci struct data_queue *queue = rt2x00dev->bcn; 2878c2ecf20Sopenharmony_ci unsigned int bcn_preload; 2888c2ecf20Sopenharmony_ci u32 reg; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_TYPE) { 2918c2ecf20Sopenharmony_ci /* 2928c2ecf20Sopenharmony_ci * Enable beacon config 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_ci bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); 2958c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, BCNCSR1); 2968c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); 2978c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); 2988c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* 3018c2ecf20Sopenharmony_ci * Enable synchronisation. 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR14); 3048c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); 3058c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_MAC) 3098c2ecf20Sopenharmony_ci rt2x00mmio_register_multiwrite(rt2x00dev, CSR3, 3108c2ecf20Sopenharmony_ci conf->mac, sizeof(conf->mac)); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (flags & CONFIG_UPDATE_BSSID) 3138c2ecf20Sopenharmony_ci rt2x00mmio_register_multiwrite(rt2x00dev, CSR5, 3148c2ecf20Sopenharmony_ci conf->bssid, sizeof(conf->bssid)); 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, 3188c2ecf20Sopenharmony_ci struct rt2x00lib_erp *erp, 3198c2ecf20Sopenharmony_ci u32 changed) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci int preamble_mask; 3228c2ecf20Sopenharmony_ci u32 reg; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* 3258c2ecf20Sopenharmony_ci * When short preamble is enabled, we should set bit 0x08 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_ERP_PREAMBLE) { 3288c2ecf20Sopenharmony_ci preamble_mask = erp->short_preamble << 3; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR1); 3318c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); 3328c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); 3338c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); 3348c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); 3358c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARCSR2); 3388c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); 3398c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); 3408c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_LENGTH, 3418c2ecf20Sopenharmony_ci GET_DURATION(ACK_SIZE, 10)); 3428c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARCSR3); 3458c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); 3468c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); 3478c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_LENGTH, 3488c2ecf20Sopenharmony_ci GET_DURATION(ACK_SIZE, 20)); 3498c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARCSR4); 3528c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); 3538c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); 3548c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_LENGTH, 3558c2ecf20Sopenharmony_ci GET_DURATION(ACK_SIZE, 55)); 3568c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARCSR5); 3598c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); 3608c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); 3618c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARCSR2_LENGTH, 3628c2ecf20Sopenharmony_ci GET_DURATION(ACK_SIZE, 110)); 3638c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg); 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_BASIC_RATES) 3678c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_ERP_SLOT) { 3708c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR11); 3718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); 3728c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR11, reg); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR18); 3758c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); 3768c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); 3778c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR18, reg); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR19); 3808c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR19_DIFS, erp->difs); 3818c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); 3828c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR19, reg); 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (changed & BSS_CHANGED_BEACON_INT) { 3868c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR12); 3878c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, 3888c2ecf20Sopenharmony_ci erp->beacon_int * 16); 3898c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, 3908c2ecf20Sopenharmony_ci erp->beacon_int * 16); 3918c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR12, reg); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, 3978c2ecf20Sopenharmony_ci struct antenna_setup *ant) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci u32 reg; 4008c2ecf20Sopenharmony_ci u8 r14; 4018c2ecf20Sopenharmony_ci u8 r2; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* 4048c2ecf20Sopenharmony_ci * We should never come here because rt2x00lib is supposed 4058c2ecf20Sopenharmony_ci * to catch this and send us the correct antenna explicitely. 4068c2ecf20Sopenharmony_ci */ 4078c2ecf20Sopenharmony_ci BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || 4088c2ecf20Sopenharmony_ci ant->tx == ANTENNA_SW_DIVERSITY); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, BBPCSR1); 4118c2ecf20Sopenharmony_ci r14 = rt2500pci_bbp_read(rt2x00dev, 14); 4128c2ecf20Sopenharmony_ci r2 = rt2500pci_bbp_read(rt2x00dev, 2); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* 4158c2ecf20Sopenharmony_ci * Configure the TX antenna. 4168c2ecf20Sopenharmony_ci */ 4178c2ecf20Sopenharmony_ci switch (ant->tx) { 4188c2ecf20Sopenharmony_ci case ANTENNA_A: 4198c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); 4208c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_CCK, 0); 4218c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_OFDM, 0); 4228c2ecf20Sopenharmony_ci break; 4238c2ecf20Sopenharmony_ci case ANTENNA_B: 4248c2ecf20Sopenharmony_ci default: 4258c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); 4268c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_CCK, 2); 4278c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_OFDM, 2); 4288c2ecf20Sopenharmony_ci break; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* 4328c2ecf20Sopenharmony_ci * Configure the RX antenna. 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_ci switch (ant->rx) { 4358c2ecf20Sopenharmony_ci case ANTENNA_A: 4368c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); 4378c2ecf20Sopenharmony_ci break; 4388c2ecf20Sopenharmony_ci case ANTENNA_B: 4398c2ecf20Sopenharmony_ci default: 4408c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* 4458c2ecf20Sopenharmony_ci * RT2525E and RT5222 need to flip TX I/Q 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { 4488c2ecf20Sopenharmony_ci rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); 4498c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); 4508c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* 4538c2ecf20Sopenharmony_ci * RT2525E does not need RX I/Q Flip. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525E)) 4568c2ecf20Sopenharmony_ci rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); 4578c2ecf20Sopenharmony_ci } else { 4588c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); 4598c2ecf20Sopenharmony_ci rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0); 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg); 4638c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 14, r14); 4648c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 2, r2); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, 4688c2ecf20Sopenharmony_ci struct rf_channel *rf, const int txpower) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci u8 r70; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* 4738c2ecf20Sopenharmony_ci * Set TXpower. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci /* 4788c2ecf20Sopenharmony_ci * Switch on tuning bits. 4798c2ecf20Sopenharmony_ci * For RT2523 devices we do not need to update the R1 register. 4808c2ecf20Sopenharmony_ci */ 4818c2ecf20Sopenharmony_ci if (!rt2x00_rf(rt2x00dev, RF2523)) 4828c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); 4838c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* 4868c2ecf20Sopenharmony_ci * For RT2525 we should first set the channel to half band higher. 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2525)) { 4898c2ecf20Sopenharmony_ci static const u32 vals[] = { 4908c2ecf20Sopenharmony_ci 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, 4918c2ecf20Sopenharmony_ci 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, 4928c2ecf20Sopenharmony_ci 0x00080d1e, 0x00080d22, 0x00080d26, 0x00080d2a, 4938c2ecf20Sopenharmony_ci 0x00080d2e, 0x00080d3a 4948c2ecf20Sopenharmony_ci }; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); 4978c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); 4988c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); 4998c2ecf20Sopenharmony_ci if (rf->rf4) 5008c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); 5048c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 2, rf->rf2); 5058c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); 5068c2ecf20Sopenharmony_ci if (rf->rf4) 5078c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* 5108c2ecf20Sopenharmony_ci * Channel 14 requires the Japan filter bit to be set. 5118c2ecf20Sopenharmony_ci */ 5128c2ecf20Sopenharmony_ci r70 = 0x46; 5138c2ecf20Sopenharmony_ci rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14); 5148c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 70, r70); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci msleep(1); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* 5198c2ecf20Sopenharmony_ci * Switch off tuning bits. 5208c2ecf20Sopenharmony_ci * For RT2523 devices we do not need to update the R1 register. 5218c2ecf20Sopenharmony_ci */ 5228c2ecf20Sopenharmony_ci if (!rt2x00_rf(rt2x00dev, RF2523)) { 5238c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); 5248c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0); 5288c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* 5318c2ecf20Sopenharmony_ci * Clear false CRC during channel switch. 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_ci rf->rf1 = rt2x00mmio_register_read(rt2x00dev, CNT0); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, 5378c2ecf20Sopenharmony_ci const int txpower) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci u32 rf3; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci rf3 = rt2x00_rf_read(rt2x00dev, 3); 5428c2ecf20Sopenharmony_ci rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); 5438c2ecf20Sopenharmony_ci rt2500pci_rf_write(rt2x00dev, 3, rf3); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, 5478c2ecf20Sopenharmony_ci struct rt2x00lib_conf *libconf) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci u32 reg; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR11); 5528c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR11_LONG_RETRY, 5538c2ecf20Sopenharmony_ci libconf->conf->long_frame_max_tx_count); 5548c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR11_SHORT_RETRY, 5558c2ecf20Sopenharmony_ci libconf->conf->short_frame_max_tx_count); 5568c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR11, reg); 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, 5608c2ecf20Sopenharmony_ci struct rt2x00lib_conf *libconf) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci enum dev_state state = 5638c2ecf20Sopenharmony_ci (libconf->conf->flags & IEEE80211_CONF_PS) ? 5648c2ecf20Sopenharmony_ci STATE_SLEEP : STATE_AWAKE; 5658c2ecf20Sopenharmony_ci u32 reg; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (state == STATE_SLEEP) { 5688c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR20); 5698c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, 5708c2ecf20Sopenharmony_ci (rt2x00dev->beacon_int - 20) * 16); 5718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, 5728c2ecf20Sopenharmony_ci libconf->conf->listen_interval - 1); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci /* We must first disable autowake before it can be enabled */ 5758c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); 5768c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR20, reg); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); 5798c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR20, reg); 5808c2ecf20Sopenharmony_ci } else { 5818c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR20); 5828c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); 5838c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR20, reg); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic void rt2500pci_config(struct rt2x00_dev *rt2x00dev, 5908c2ecf20Sopenharmony_ci struct rt2x00lib_conf *libconf, 5918c2ecf20Sopenharmony_ci const unsigned int flags) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci if (flags & IEEE80211_CONF_CHANGE_CHANNEL) 5948c2ecf20Sopenharmony_ci rt2500pci_config_channel(rt2x00dev, &libconf->rf, 5958c2ecf20Sopenharmony_ci libconf->conf->power_level); 5968c2ecf20Sopenharmony_ci if ((flags & IEEE80211_CONF_CHANGE_POWER) && 5978c2ecf20Sopenharmony_ci !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) 5988c2ecf20Sopenharmony_ci rt2500pci_config_txpower(rt2x00dev, 5998c2ecf20Sopenharmony_ci libconf->conf->power_level); 6008c2ecf20Sopenharmony_ci if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 6018c2ecf20Sopenharmony_ci rt2500pci_config_retry_limit(rt2x00dev, libconf); 6028c2ecf20Sopenharmony_ci if (flags & IEEE80211_CONF_CHANGE_PS) 6038c2ecf20Sopenharmony_ci rt2500pci_config_ps(rt2x00dev, libconf); 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci/* 6078c2ecf20Sopenharmony_ci * Link tuning 6088c2ecf20Sopenharmony_ci */ 6098c2ecf20Sopenharmony_cistatic void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, 6108c2ecf20Sopenharmony_ci struct link_qual *qual) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci u32 reg; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* 6158c2ecf20Sopenharmony_ci * Update FCS error count from register. 6168c2ecf20Sopenharmony_ci */ 6178c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CNT0); 6188c2ecf20Sopenharmony_ci qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci /* 6218c2ecf20Sopenharmony_ci * Update False CCA count from register. 6228c2ecf20Sopenharmony_ci */ 6238c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CNT3); 6248c2ecf20Sopenharmony_ci qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, 6288c2ecf20Sopenharmony_ci struct link_qual *qual, u8 vgc_level) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci if (qual->vgc_level_reg != vgc_level) { 6318c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); 6328c2ecf20Sopenharmony_ci qual->vgc_level = vgc_level; 6338c2ecf20Sopenharmony_ci qual->vgc_level_reg = vgc_level; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev, 6388c2ecf20Sopenharmony_ci struct link_qual *qual) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, 0x48); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, 6448c2ecf20Sopenharmony_ci struct link_qual *qual, const u32 count) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci /* 6478c2ecf20Sopenharmony_ci * To prevent collisions with MAC ASIC on chipsets 6488c2ecf20Sopenharmony_ci * up to version C the link tuning should halt after 20 6498c2ecf20Sopenharmony_ci * seconds while being associated. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ci if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D && 6528c2ecf20Sopenharmony_ci rt2x00dev->intf_associated && count > 20) 6538c2ecf20Sopenharmony_ci return; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* 6568c2ecf20Sopenharmony_ci * Chipset versions C and lower should directly continue 6578c2ecf20Sopenharmony_ci * to the dynamic CCA tuning. Chipset version D and higher 6588c2ecf20Sopenharmony_ci * should go straight to dynamic CCA tuning when they 6598c2ecf20Sopenharmony_ci * are not associated. 6608c2ecf20Sopenharmony_ci */ 6618c2ecf20Sopenharmony_ci if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D || 6628c2ecf20Sopenharmony_ci !rt2x00dev->intf_associated) 6638c2ecf20Sopenharmony_ci goto dynamic_cca_tune; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci /* 6668c2ecf20Sopenharmony_ci * A too low RSSI will cause too much false CCA which will 6678c2ecf20Sopenharmony_ci * then corrupt the R17 tuning. To remidy this the tuning should 6688c2ecf20Sopenharmony_ci * be stopped (While making sure the R17 value will not exceed limits) 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci if (qual->rssi < -80 && count > 20) { 6718c2ecf20Sopenharmony_ci if (qual->vgc_level_reg >= 0x41) 6728c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); 6738c2ecf20Sopenharmony_ci return; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* 6778c2ecf20Sopenharmony_ci * Special big-R17 for short distance 6788c2ecf20Sopenharmony_ci */ 6798c2ecf20Sopenharmony_ci if (qual->rssi >= -58) { 6808c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, 0x50); 6818c2ecf20Sopenharmony_ci return; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci /* 6858c2ecf20Sopenharmony_ci * Special mid-R17 for middle distance 6868c2ecf20Sopenharmony_ci */ 6878c2ecf20Sopenharmony_ci if (qual->rssi >= -74) { 6888c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, 0x41); 6898c2ecf20Sopenharmony_ci return; 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* 6938c2ecf20Sopenharmony_ci * Leave short or middle distance condition, restore r17 6948c2ecf20Sopenharmony_ci * to the dynamic tuning range. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_ci if (qual->vgc_level_reg >= 0x41) { 6978c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); 6988c2ecf20Sopenharmony_ci return; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cidynamic_cca_tune: 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* 7048c2ecf20Sopenharmony_ci * R17 is inside the dynamic tuning range, 7058c2ecf20Sopenharmony_ci * start tuning the link based on the false cca counter. 7068c2ecf20Sopenharmony_ci */ 7078c2ecf20Sopenharmony_ci if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) 7088c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); 7098c2ecf20Sopenharmony_ci else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) 7108c2ecf20Sopenharmony_ci rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci/* 7148c2ecf20Sopenharmony_ci * Queue handlers. 7158c2ecf20Sopenharmony_ci */ 7168c2ecf20Sopenharmony_cistatic void rt2500pci_start_queue(struct data_queue *queue) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; 7198c2ecf20Sopenharmony_ci u32 reg; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci switch (queue->qid) { 7228c2ecf20Sopenharmony_ci case QID_RX: 7238c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0); 7248c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); 7258c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); 7268c2ecf20Sopenharmony_ci break; 7278c2ecf20Sopenharmony_ci case QID_BEACON: 7288c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR14); 7298c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); 7308c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TBCN, 1); 7318c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); 7328c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci default: 7358c2ecf20Sopenharmony_ci break; 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_cistatic void rt2500pci_kick_queue(struct data_queue *queue) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; 7428c2ecf20Sopenharmony_ci u32 reg; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci switch (queue->qid) { 7458c2ecf20Sopenharmony_ci case QID_AC_VO: 7468c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0); 7478c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); 7488c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); 7498c2ecf20Sopenharmony_ci break; 7508c2ecf20Sopenharmony_ci case QID_AC_VI: 7518c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0); 7528c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); 7538c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); 7548c2ecf20Sopenharmony_ci break; 7558c2ecf20Sopenharmony_ci case QID_ATIM: 7568c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0); 7578c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); 7588c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci default: 7618c2ecf20Sopenharmony_ci break; 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_cistatic void rt2500pci_stop_queue(struct data_queue *queue) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; 7688c2ecf20Sopenharmony_ci u32 reg; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci switch (queue->qid) { 7718c2ecf20Sopenharmony_ci case QID_AC_VO: 7728c2ecf20Sopenharmony_ci case QID_AC_VI: 7738c2ecf20Sopenharmony_ci case QID_ATIM: 7748c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0); 7758c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR0_ABORT, 1); 7768c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); 7778c2ecf20Sopenharmony_ci break; 7788c2ecf20Sopenharmony_ci case QID_RX: 7798c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0); 7808c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); 7818c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); 7828c2ecf20Sopenharmony_ci break; 7838c2ecf20Sopenharmony_ci case QID_BEACON: 7848c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR14); 7858c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); 7868c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TBCN, 0); 7878c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); 7888c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* 7918c2ecf20Sopenharmony_ci * Wait for possibly running tbtt tasklets. 7928c2ecf20Sopenharmony_ci */ 7938c2ecf20Sopenharmony_ci tasklet_kill(&rt2x00dev->tbtt_tasklet); 7948c2ecf20Sopenharmony_ci break; 7958c2ecf20Sopenharmony_ci default: 7968c2ecf20Sopenharmony_ci break; 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci/* 8018c2ecf20Sopenharmony_ci * Initialization functions. 8028c2ecf20Sopenharmony_ci */ 8038c2ecf20Sopenharmony_cistatic bool rt2500pci_get_entry_state(struct queue_entry *entry) 8048c2ecf20Sopenharmony_ci{ 8058c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv = entry->priv_data; 8068c2ecf20Sopenharmony_ci u32 word; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (entry->queue->qid == QID_RX) { 8098c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 0); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); 8128c2ecf20Sopenharmony_ci } else { 8138c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 0); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || 8168c2ecf20Sopenharmony_ci rt2x00_get_field32(word, TXD_W0_VALID)); 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic void rt2500pci_clear_entry(struct queue_entry *entry) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv = entry->priv_data; 8238c2ecf20Sopenharmony_ci struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); 8248c2ecf20Sopenharmony_ci u32 word; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (entry->queue->qid == QID_RX) { 8278c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 1); 8288c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); 8298c2ecf20Sopenharmony_ci rt2x00_desc_write(entry_priv->desc, 1, word); 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 0); 8328c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); 8338c2ecf20Sopenharmony_ci rt2x00_desc_write(entry_priv->desc, 0, word); 8348c2ecf20Sopenharmony_ci } else { 8358c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 0); 8368c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_VALID, 0); 8378c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); 8388c2ecf20Sopenharmony_ci rt2x00_desc_write(entry_priv->desc, 0, word); 8398c2ecf20Sopenharmony_ci } 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_cistatic int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv; 8458c2ecf20Sopenharmony_ci u32 reg; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* 8488c2ecf20Sopenharmony_ci * Initialize registers. 8498c2ecf20Sopenharmony_ci */ 8508c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR2); 8518c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); 8528c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); 8538c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit); 8548c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); 8558c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci entry_priv = rt2x00dev->tx[1].entries[0].priv_data; 8588c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR3); 8598c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, 8608c2ecf20Sopenharmony_ci entry_priv->desc_dma); 8618c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci entry_priv = rt2x00dev->tx[0].entries[0].priv_data; 8648c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR5); 8658c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, 8668c2ecf20Sopenharmony_ci entry_priv->desc_dma); 8678c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci entry_priv = rt2x00dev->atim->entries[0].priv_data; 8708c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR4); 8718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, 8728c2ecf20Sopenharmony_ci entry_priv->desc_dma); 8738c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci entry_priv = rt2x00dev->bcn->entries[0].priv_data; 8768c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR6); 8778c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, 8788c2ecf20Sopenharmony_ci entry_priv->desc_dma); 8798c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR1); 8828c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); 8838c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); 8848c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci entry_priv = rt2x00dev->rx->entries[0].priv_data; 8878c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR2); 8888c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, 8898c2ecf20Sopenharmony_ci entry_priv->desc_dma); 8908c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci return 0; 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci u32 reg; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002); 9008c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002); 9018c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002); 9028c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TIMECSR); 9058c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); 9068c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); 9078c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); 9088c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR9); 9118c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, 9128c2ecf20Sopenharmony_ci rt2x00dev->rx->data_size / 128); 9138c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR9, reg); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci /* 9168c2ecf20Sopenharmony_ci * Always use CWmin and CWmax set in descriptor. 9178c2ecf20Sopenharmony_ci */ 9188c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR11); 9198c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR11_CW_SELECT, 0); 9208c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR11, reg); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR14); 9238c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); 9248c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); 9258c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TBCN, 0); 9268c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TCFP, 0); 9278c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TATIMW, 0); 9288c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); 9298c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); 9308c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); 9318c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CNT3, 0); 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, TXCSR8); 9368c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID0, 10); 9378c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID0_VALID, 1); 9388c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID1, 11); 9398c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID1_VALID, 1); 9408c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID2, 13); 9418c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID2_VALID, 1); 9428c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID3, 12); 9438c2ecf20Sopenharmony_ci rt2x00_set_field32(®, TXCSR8_BBP_ID3_VALID, 1); 9448c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR0); 9478c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR0_ACK_CTS_1MBS, 112); 9488c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR0_ACK_CTS_2MBS, 56); 9498c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR0_ACK_CTS_5_5MBS, 20); 9508c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR0_ACK_CTS_11MBS, 10); 9518c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR1); 9548c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR1_ACK_CTS_6MBS, 45); 9558c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR1_ACK_CTS_9MBS, 37); 9568c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR1_ACK_CTS_12MBS, 33); 9578c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR1_ACK_CTS_18MBS, 29); 9588c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR2); 9618c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR2_ACK_CTS_24MBS, 29); 9628c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR2_ACK_CTS_36MBS, 25); 9638c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR2_ACK_CTS_48MBS, 25); 9648c2ecf20Sopenharmony_ci rt2x00_set_field32(®, ARTCSR2_ACK_CTS_54MBS, 25); 9658c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RXCSR3); 9688c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */ 9698c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); 9708c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ 9718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); 9728c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID2, 42); /* OFDM Rate */ 9738c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); 9748c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */ 9758c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); 9768c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, PCICSR); 9798c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); 9808c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); 9818c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); 9828c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_BURST_LENTH, 1); 9838c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); 9848c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); 9858c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); 9868c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PCICSR, reg); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); 9918c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) 9948c2ecf20Sopenharmony_ci return -EBUSY; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223); 9978c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518); 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, MACCSR2); 10008c2ecf20Sopenharmony_ci rt2x00_set_field32(®, MACCSR2_DELAY, 64); 10018c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, RALINKCSR); 10048c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); 10058c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26); 10068c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID0, 1); 10078c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); 10088c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 26); 10098c2ecf20Sopenharmony_ci rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID1, 1); 10108c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR1); 10178c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); 10188c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR1_BBP_RESET, 0); 10198c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR1_HOST_READY, 0); 10208c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR1, reg); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR1); 10238c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); 10248c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR1_HOST_READY, 1); 10258c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR1, reg); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* 10288c2ecf20Sopenharmony_ci * We must clear the FCS and FIFO error count. 10298c2ecf20Sopenharmony_ci * These registers are cleared on read, 10308c2ecf20Sopenharmony_ci * so we may pass a useless variable to store the value. 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CNT0); 10338c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CNT4); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci unsigned int i; 10418c2ecf20Sopenharmony_ci u8 value; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 10448c2ecf20Sopenharmony_ci value = rt2500pci_bbp_read(rt2x00dev, 0); 10458c2ecf20Sopenharmony_ci if ((value != 0xff) && (value != 0x00)) 10468c2ecf20Sopenharmony_ci return 0; 10478c2ecf20Sopenharmony_ci udelay(REGISTER_BUSY_DELAY); 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n"); 10518c2ecf20Sopenharmony_ci return -EACCES; 10528c2ecf20Sopenharmony_ci} 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_cistatic int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci unsigned int i; 10578c2ecf20Sopenharmony_ci u16 eeprom; 10588c2ecf20Sopenharmony_ci u8 reg_id; 10598c2ecf20Sopenharmony_ci u8 value; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev))) 10628c2ecf20Sopenharmony_ci return -EACCES; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 3, 0x02); 10658c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 4, 0x19); 10668c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 14, 0x1c); 10678c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 15, 0x30); 10688c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 16, 0xac); 10698c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 18, 0x18); 10708c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 19, 0xff); 10718c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 20, 0x1e); 10728c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 21, 0x08); 10738c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 22, 0x08); 10748c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 23, 0x08); 10758c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 24, 0x70); 10768c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 25, 0x40); 10778c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 26, 0x08); 10788c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 27, 0x23); 10798c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 30, 0x10); 10808c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 31, 0x2b); 10818c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 32, 0xb9); 10828c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 34, 0x12); 10838c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 35, 0x50); 10848c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 39, 0xc4); 10858c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 40, 0x02); 10868c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 41, 0x60); 10878c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 53, 0x10); 10888c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 54, 0x18); 10898c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 56, 0x08); 10908c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 57, 0x10); 10918c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 58, 0x08); 10928c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 61, 0x6d); 10938c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, 62, 0x10); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci for (i = 0; i < EEPROM_BBP_SIZE; i++) { 10968c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci if (eeprom != 0xffff && eeprom != 0x0000) { 10998c2ecf20Sopenharmony_ci reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); 11008c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); 11018c2ecf20Sopenharmony_ci rt2500pci_bbp_write(rt2x00dev, reg_id, value); 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci return 0; 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci/* 11098c2ecf20Sopenharmony_ci * Device state switch handlers. 11108c2ecf20Sopenharmony_ci */ 11118c2ecf20Sopenharmony_cistatic void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 11128c2ecf20Sopenharmony_ci enum dev_state state) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci int mask = (state == STATE_RADIO_IRQ_OFF); 11158c2ecf20Sopenharmony_ci u32 reg; 11168c2ecf20Sopenharmony_ci unsigned long flags; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci /* 11198c2ecf20Sopenharmony_ci * When interrupts are being enabled, the interrupt registers 11208c2ecf20Sopenharmony_ci * should clear the register to assure a clean state. 11218c2ecf20Sopenharmony_ci */ 11228c2ecf20Sopenharmony_ci if (state == STATE_RADIO_IRQ_ON) { 11238c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR7); 11248c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR7, reg); 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci /* 11288c2ecf20Sopenharmony_ci * Only toggle the interrupts bits we are going to use. 11298c2ecf20Sopenharmony_ci * Non-checked interrupt bits are disabled by default. 11308c2ecf20Sopenharmony_ci */ 11318c2ecf20Sopenharmony_ci spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR8); 11348c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); 11358c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); 11368c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); 11378c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); 11388c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_RXDONE, mask); 11398c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR8, reg); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (state == STATE_RADIO_IRQ_OFF) { 11448c2ecf20Sopenharmony_ci /* 11458c2ecf20Sopenharmony_ci * Ensure that all tasklets are finished. 11468c2ecf20Sopenharmony_ci */ 11478c2ecf20Sopenharmony_ci tasklet_kill(&rt2x00dev->txstatus_tasklet); 11488c2ecf20Sopenharmony_ci tasklet_kill(&rt2x00dev->rxdone_tasklet); 11498c2ecf20Sopenharmony_ci tasklet_kill(&rt2x00dev->tbtt_tasklet); 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci} 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_cistatic int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) 11548c2ecf20Sopenharmony_ci{ 11558c2ecf20Sopenharmony_ci /* 11568c2ecf20Sopenharmony_ci * Initialize all registers. 11578c2ecf20Sopenharmony_ci */ 11588c2ecf20Sopenharmony_ci if (unlikely(rt2500pci_init_queues(rt2x00dev) || 11598c2ecf20Sopenharmony_ci rt2500pci_init_registers(rt2x00dev) || 11608c2ecf20Sopenharmony_ci rt2500pci_init_bbp(rt2x00dev))) 11618c2ecf20Sopenharmony_ci return -EIO; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci return 0; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci /* 11698c2ecf20Sopenharmony_ci * Disable power 11708c2ecf20Sopenharmony_ci */ 11718c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0); 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, 11758c2ecf20Sopenharmony_ci enum dev_state state) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci u32 reg, reg2; 11788c2ecf20Sopenharmony_ci unsigned int i; 11798c2ecf20Sopenharmony_ci char put_to_sleep; 11808c2ecf20Sopenharmony_ci char bbp_state; 11818c2ecf20Sopenharmony_ci char rf_state; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci put_to_sleep = (state != STATE_AWAKE); 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, PWRCSR1); 11868c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); 11878c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); 11888c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); 11898c2ecf20Sopenharmony_ci rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); 11908c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* 11938c2ecf20Sopenharmony_ci * Device is not guaranteed to be in the requested state yet. 11948c2ecf20Sopenharmony_ci * We must wait until the register indicates that the 11958c2ecf20Sopenharmony_ci * device has entered the correct state. 11968c2ecf20Sopenharmony_ci */ 11978c2ecf20Sopenharmony_ci for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 11988c2ecf20Sopenharmony_ci reg2 = rt2x00mmio_register_read(rt2x00dev, PWRCSR1); 11998c2ecf20Sopenharmony_ci bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); 12008c2ecf20Sopenharmony_ci rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); 12018c2ecf20Sopenharmony_ci if (bbp_state == state && rf_state == state) 12028c2ecf20Sopenharmony_ci return 0; 12038c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); 12048c2ecf20Sopenharmony_ci msleep(10); 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci return -EBUSY; 12088c2ecf20Sopenharmony_ci} 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_cistatic int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, 12118c2ecf20Sopenharmony_ci enum dev_state state) 12128c2ecf20Sopenharmony_ci{ 12138c2ecf20Sopenharmony_ci int retval = 0; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci switch (state) { 12168c2ecf20Sopenharmony_ci case STATE_RADIO_ON: 12178c2ecf20Sopenharmony_ci retval = rt2500pci_enable_radio(rt2x00dev); 12188c2ecf20Sopenharmony_ci break; 12198c2ecf20Sopenharmony_ci case STATE_RADIO_OFF: 12208c2ecf20Sopenharmony_ci rt2500pci_disable_radio(rt2x00dev); 12218c2ecf20Sopenharmony_ci break; 12228c2ecf20Sopenharmony_ci case STATE_RADIO_IRQ_ON: 12238c2ecf20Sopenharmony_ci case STATE_RADIO_IRQ_OFF: 12248c2ecf20Sopenharmony_ci rt2500pci_toggle_irq(rt2x00dev, state); 12258c2ecf20Sopenharmony_ci break; 12268c2ecf20Sopenharmony_ci case STATE_DEEP_SLEEP: 12278c2ecf20Sopenharmony_ci case STATE_SLEEP: 12288c2ecf20Sopenharmony_ci case STATE_STANDBY: 12298c2ecf20Sopenharmony_ci case STATE_AWAKE: 12308c2ecf20Sopenharmony_ci retval = rt2500pci_set_state(rt2x00dev, state); 12318c2ecf20Sopenharmony_ci break; 12328c2ecf20Sopenharmony_ci default: 12338c2ecf20Sopenharmony_ci retval = -ENOTSUPP; 12348c2ecf20Sopenharmony_ci break; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci if (unlikely(retval)) 12388c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", 12398c2ecf20Sopenharmony_ci state, retval); 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci return retval; 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci/* 12458c2ecf20Sopenharmony_ci * TX descriptor initialization 12468c2ecf20Sopenharmony_ci */ 12478c2ecf20Sopenharmony_cistatic void rt2500pci_write_tx_desc(struct queue_entry *entry, 12488c2ecf20Sopenharmony_ci struct txentry_desc *txdesc) 12498c2ecf20Sopenharmony_ci{ 12508c2ecf20Sopenharmony_ci struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); 12518c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv = entry->priv_data; 12528c2ecf20Sopenharmony_ci __le32 *txd = entry_priv->desc; 12538c2ecf20Sopenharmony_ci u32 word; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci /* 12568c2ecf20Sopenharmony_ci * Start writing the descriptor words. 12578c2ecf20Sopenharmony_ci */ 12588c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 1); 12598c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); 12608c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 1, word); 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 2); 12638c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); 12648c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs); 12658c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min); 12668c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max); 12678c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 2, word); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 3); 12708c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal); 12718c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service); 12728c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, 12738c2ecf20Sopenharmony_ci txdesc->u.plcp.length_low); 12748c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, 12758c2ecf20Sopenharmony_ci txdesc->u.plcp.length_high); 12768c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 3, word); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 10); 12798c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W10_RTS, 12808c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); 12818c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 10, word); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci /* 12848c2ecf20Sopenharmony_ci * Writing TXD word 0 must the last to prevent a race condition with 12858c2ecf20Sopenharmony_ci * the device, whereby the device may take hold of the TXD before we 12868c2ecf20Sopenharmony_ci * finished updating it. 12878c2ecf20Sopenharmony_ci */ 12888c2ecf20Sopenharmony_ci word = rt2x00_desc_read(txd, 0); 12898c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); 12908c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_VALID, 1); 12918c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, 12928c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); 12938c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_ACK, 12948c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_ACK, &txdesc->flags)); 12958c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, 12968c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); 12978c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_OFDM, 12988c2ecf20Sopenharmony_ci (txdesc->rate_mode == RATE_MODE_OFDM)); 12998c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); 13008c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs); 13018c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, 13028c2ecf20Sopenharmony_ci test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); 13038c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); 13048c2ecf20Sopenharmony_ci rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); 13058c2ecf20Sopenharmony_ci rt2x00_desc_write(txd, 0, word); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci /* 13088c2ecf20Sopenharmony_ci * Register descriptor details in skb frame descriptor. 13098c2ecf20Sopenharmony_ci */ 13108c2ecf20Sopenharmony_ci skbdesc->desc = txd; 13118c2ecf20Sopenharmony_ci skbdesc->desc_len = TXD_DESC_SIZE; 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci/* 13158c2ecf20Sopenharmony_ci * TX data initialization 13168c2ecf20Sopenharmony_ci */ 13178c2ecf20Sopenharmony_cistatic void rt2500pci_write_beacon(struct queue_entry *entry, 13188c2ecf20Sopenharmony_ci struct txentry_desc *txdesc) 13198c2ecf20Sopenharmony_ci{ 13208c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 13218c2ecf20Sopenharmony_ci u32 reg; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci /* 13248c2ecf20Sopenharmony_ci * Disable beaconing while we are reloading the beacon data, 13258c2ecf20Sopenharmony_ci * otherwise we might be sending out invalid data. 13268c2ecf20Sopenharmony_ci */ 13278c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR14); 13288c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); 13298c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (rt2x00queue_map_txskb(entry)) { 13328c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n"); 13338c2ecf20Sopenharmony_ci goto out; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* 13378c2ecf20Sopenharmony_ci * Write the TX descriptor for the beacon. 13388c2ecf20Sopenharmony_ci */ 13398c2ecf20Sopenharmony_ci rt2500pci_write_tx_desc(entry, txdesc); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci /* 13428c2ecf20Sopenharmony_ci * Dump beacon to userspace through debugfs. 13438c2ecf20Sopenharmony_ci */ 13448c2ecf20Sopenharmony_ci rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry); 13458c2ecf20Sopenharmony_ciout: 13468c2ecf20Sopenharmony_ci /* 13478c2ecf20Sopenharmony_ci * Enable beaconing again. 13488c2ecf20Sopenharmony_ci */ 13498c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); 13508c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR14, reg); 13518c2ecf20Sopenharmony_ci} 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci/* 13548c2ecf20Sopenharmony_ci * RX control handlers 13558c2ecf20Sopenharmony_ci */ 13568c2ecf20Sopenharmony_cistatic void rt2500pci_fill_rxdone(struct queue_entry *entry, 13578c2ecf20Sopenharmony_ci struct rxdone_entry_desc *rxdesc) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv = entry->priv_data; 13608c2ecf20Sopenharmony_ci u32 word0; 13618c2ecf20Sopenharmony_ci u32 word2; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci word0 = rt2x00_desc_read(entry_priv->desc, 0); 13648c2ecf20Sopenharmony_ci word2 = rt2x00_desc_read(entry_priv->desc, 2); 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) 13678c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; 13688c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) 13698c2ecf20Sopenharmony_ci rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* 13728c2ecf20Sopenharmony_ci * Obtain the status about this packet. 13738c2ecf20Sopenharmony_ci * When frame was received with an OFDM bitrate, 13748c2ecf20Sopenharmony_ci * the signal is the PLCP value. If it was received with 13758c2ecf20Sopenharmony_ci * a CCK bitrate the signal is the rate in 100kbit/s. 13768c2ecf20Sopenharmony_ci */ 13778c2ecf20Sopenharmony_ci rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); 13788c2ecf20Sopenharmony_ci rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - 13798c2ecf20Sopenharmony_ci entry->queue->rt2x00dev->rssi_offset; 13808c2ecf20Sopenharmony_ci rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_OFDM)) 13838c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; 13848c2ecf20Sopenharmony_ci else 13858c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; 13868c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) 13878c2ecf20Sopenharmony_ci rxdesc->dev_flags |= RXDONE_MY_BSS; 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci/* 13918c2ecf20Sopenharmony_ci * Interrupt functions. 13928c2ecf20Sopenharmony_ci */ 13938c2ecf20Sopenharmony_cistatic void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, 13948c2ecf20Sopenharmony_ci const enum data_queue_qid queue_idx) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); 13978c2ecf20Sopenharmony_ci struct queue_entry_priv_mmio *entry_priv; 13988c2ecf20Sopenharmony_ci struct queue_entry *entry; 13998c2ecf20Sopenharmony_ci struct txdone_entry_desc txdesc; 14008c2ecf20Sopenharmony_ci u32 word; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci while (!rt2x00queue_empty(queue)) { 14038c2ecf20Sopenharmony_ci entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); 14048c2ecf20Sopenharmony_ci entry_priv = entry->priv_data; 14058c2ecf20Sopenharmony_ci word = rt2x00_desc_read(entry_priv->desc, 0); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || 14088c2ecf20Sopenharmony_ci !rt2x00_get_field32(word, TXD_W0_VALID)) 14098c2ecf20Sopenharmony_ci break; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci /* 14128c2ecf20Sopenharmony_ci * Obtain the status about this packet. 14138c2ecf20Sopenharmony_ci */ 14148c2ecf20Sopenharmony_ci txdesc.flags = 0; 14158c2ecf20Sopenharmony_ci switch (rt2x00_get_field32(word, TXD_W0_RESULT)) { 14168c2ecf20Sopenharmony_ci case 0: /* Success */ 14178c2ecf20Sopenharmony_ci case 1: /* Success with retry */ 14188c2ecf20Sopenharmony_ci __set_bit(TXDONE_SUCCESS, &txdesc.flags); 14198c2ecf20Sopenharmony_ci break; 14208c2ecf20Sopenharmony_ci case 2: /* Failure, excessive retries */ 14218c2ecf20Sopenharmony_ci __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); 14228c2ecf20Sopenharmony_ci fallthrough; /* this is a failed frame! */ 14238c2ecf20Sopenharmony_ci default: /* Failure */ 14248c2ecf20Sopenharmony_ci __set_bit(TXDONE_FAILURE, &txdesc.flags); 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci rt2x00lib_txdone(entry, &txdesc); 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cistatic inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, 14338c2ecf20Sopenharmony_ci struct rt2x00_field32 irq_field) 14348c2ecf20Sopenharmony_ci{ 14358c2ecf20Sopenharmony_ci u32 reg; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* 14388c2ecf20Sopenharmony_ci * Enable a single interrupt. The interrupt mask register 14398c2ecf20Sopenharmony_ci * access needs locking. 14408c2ecf20Sopenharmony_ci */ 14418c2ecf20Sopenharmony_ci spin_lock_irq(&rt2x00dev->irqmask_lock); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR8); 14448c2ecf20Sopenharmony_ci rt2x00_set_field32(®, irq_field, 0); 14458c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR8, reg); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci spin_unlock_irq(&rt2x00dev->irqmask_lock); 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic void rt2500pci_txstatus_tasklet(struct tasklet_struct *t) 14518c2ecf20Sopenharmony_ci{ 14528c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = from_tasklet(rt2x00dev, t, 14538c2ecf20Sopenharmony_ci txstatus_tasklet); 14548c2ecf20Sopenharmony_ci u32 reg; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci /* 14578c2ecf20Sopenharmony_ci * Handle all tx queues. 14588c2ecf20Sopenharmony_ci */ 14598c2ecf20Sopenharmony_ci rt2500pci_txdone(rt2x00dev, QID_ATIM); 14608c2ecf20Sopenharmony_ci rt2500pci_txdone(rt2x00dev, QID_AC_VO); 14618c2ecf20Sopenharmony_ci rt2500pci_txdone(rt2x00dev, QID_AC_VI); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* 14648c2ecf20Sopenharmony_ci * Enable all TXDONE interrupts again. 14658c2ecf20Sopenharmony_ci */ 14668c2ecf20Sopenharmony_ci if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { 14678c2ecf20Sopenharmony_ci spin_lock_irq(&rt2x00dev->irqmask_lock); 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR8); 14708c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); 14718c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); 14728c2ecf20Sopenharmony_ci rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); 14738c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR8, reg); 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci spin_unlock_irq(&rt2x00dev->irqmask_lock); 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci} 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_cistatic void rt2500pci_tbtt_tasklet(struct tasklet_struct *t) 14808c2ecf20Sopenharmony_ci{ 14818c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = from_tasklet(rt2x00dev, t, tbtt_tasklet); 14828c2ecf20Sopenharmony_ci rt2x00lib_beacondone(rt2x00dev); 14838c2ecf20Sopenharmony_ci if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 14848c2ecf20Sopenharmony_ci rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); 14858c2ecf20Sopenharmony_ci} 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic void rt2500pci_rxdone_tasklet(struct tasklet_struct *t) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = from_tasklet(rt2x00dev, t, 14908c2ecf20Sopenharmony_ci rxdone_tasklet); 14918c2ecf20Sopenharmony_ci if (rt2x00mmio_rxdone(rt2x00dev)) 14928c2ecf20Sopenharmony_ci tasklet_schedule(&rt2x00dev->rxdone_tasklet); 14938c2ecf20Sopenharmony_ci else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 14948c2ecf20Sopenharmony_ci rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); 14958c2ecf20Sopenharmony_ci} 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_cistatic irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = dev_instance; 15008c2ecf20Sopenharmony_ci u32 reg, mask; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* 15038c2ecf20Sopenharmony_ci * Get the interrupt sources & saved to local variable. 15048c2ecf20Sopenharmony_ci * Write register value back to clear pending interrupts. 15058c2ecf20Sopenharmony_ci */ 15068c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR7); 15078c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR7, reg); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci if (!reg) 15108c2ecf20Sopenharmony_ci return IRQ_NONE; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 15138c2ecf20Sopenharmony_ci return IRQ_HANDLED; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci mask = reg; 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci /* 15188c2ecf20Sopenharmony_ci * Schedule tasklets for interrupt handling. 15198c2ecf20Sopenharmony_ci */ 15208c2ecf20Sopenharmony_ci if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) 15218c2ecf20Sopenharmony_ci tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci if (rt2x00_get_field32(reg, CSR7_RXDONE)) 15248c2ecf20Sopenharmony_ci tasklet_schedule(&rt2x00dev->rxdone_tasklet); 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || 15278c2ecf20Sopenharmony_ci rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || 15288c2ecf20Sopenharmony_ci rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { 15298c2ecf20Sopenharmony_ci tasklet_schedule(&rt2x00dev->txstatus_tasklet); 15308c2ecf20Sopenharmony_ci /* 15318c2ecf20Sopenharmony_ci * Mask out all txdone interrupts. 15328c2ecf20Sopenharmony_ci */ 15338c2ecf20Sopenharmony_ci rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); 15348c2ecf20Sopenharmony_ci rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); 15358c2ecf20Sopenharmony_ci rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci /* 15398c2ecf20Sopenharmony_ci * Disable all interrupts for which a tasklet was scheduled right now, 15408c2ecf20Sopenharmony_ci * the tasklet will reenable the appropriate interrupts. 15418c2ecf20Sopenharmony_ci */ 15428c2ecf20Sopenharmony_ci spin_lock(&rt2x00dev->irqmask_lock); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR8); 15458c2ecf20Sopenharmony_ci reg |= mask; 15468c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, CSR8, reg); 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci spin_unlock(&rt2x00dev->irqmask_lock); 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci return IRQ_HANDLED; 15518c2ecf20Sopenharmony_ci} 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci/* 15548c2ecf20Sopenharmony_ci * Device probe functions. 15558c2ecf20Sopenharmony_ci */ 15568c2ecf20Sopenharmony_cistatic int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) 15578c2ecf20Sopenharmony_ci{ 15588c2ecf20Sopenharmony_ci struct eeprom_93cx6 eeprom; 15598c2ecf20Sopenharmony_ci u32 reg; 15608c2ecf20Sopenharmony_ci u16 word; 15618c2ecf20Sopenharmony_ci u8 *mac; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR21); 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci eeprom.data = rt2x00dev; 15668c2ecf20Sopenharmony_ci eeprom.register_read = rt2500pci_eepromregister_read; 15678c2ecf20Sopenharmony_ci eeprom.register_write = rt2500pci_eepromregister_write; 15688c2ecf20Sopenharmony_ci eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? 15698c2ecf20Sopenharmony_ci PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; 15708c2ecf20Sopenharmony_ci eeprom.reg_data_in = 0; 15718c2ecf20Sopenharmony_ci eeprom.reg_data_out = 0; 15728c2ecf20Sopenharmony_ci eeprom.reg_data_clock = 0; 15738c2ecf20Sopenharmony_ci eeprom.reg_chip_select = 0; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, 15768c2ecf20Sopenharmony_ci EEPROM_SIZE / sizeof(u16)); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* 15798c2ecf20Sopenharmony_ci * Start validation of the data that has been read. 15808c2ecf20Sopenharmony_ci */ 15818c2ecf20Sopenharmony_ci mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); 15828c2ecf20Sopenharmony_ci rt2x00lib_set_mac_address(rt2x00dev, mac); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA); 15858c2ecf20Sopenharmony_ci if (word == 0xffff) { 15868c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); 15878c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 15888c2ecf20Sopenharmony_ci ANTENNA_SW_DIVERSITY); 15898c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 15908c2ecf20Sopenharmony_ci ANTENNA_SW_DIVERSITY); 15918c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 15928c2ecf20Sopenharmony_ci LED_MODE_DEFAULT); 15938c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); 15948c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); 15958c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); 15968c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); 15978c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC); 16018c2ecf20Sopenharmony_ci if (word == 0xffff) { 16028c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); 16038c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0); 16048c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0); 16058c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); 16068c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET); 16108c2ecf20Sopenharmony_ci if (word == 0xffff) { 16118c2ecf20Sopenharmony_ci rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, 16128c2ecf20Sopenharmony_ci DEFAULT_RSSI_OFFSET); 16138c2ecf20Sopenharmony_ci rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); 16148c2ecf20Sopenharmony_ci rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n", 16158c2ecf20Sopenharmony_ci word); 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci return 0; 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_cistatic int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) 16228c2ecf20Sopenharmony_ci{ 16238c2ecf20Sopenharmony_ci u32 reg; 16248c2ecf20Sopenharmony_ci u16 value; 16258c2ecf20Sopenharmony_ci u16 eeprom; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci /* 16288c2ecf20Sopenharmony_ci * Read EEPROM word for configuration. 16298c2ecf20Sopenharmony_ci */ 16308c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci /* 16338c2ecf20Sopenharmony_ci * Identify RF chipset. 16348c2ecf20Sopenharmony_ci */ 16358c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); 16368c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR0); 16378c2ecf20Sopenharmony_ci rt2x00_set_chip(rt2x00dev, RT2560, value, 16388c2ecf20Sopenharmony_ci rt2x00_get_field32(reg, CSR0_REVISION)); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci if (!rt2x00_rf(rt2x00dev, RF2522) && 16418c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2523) && 16428c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2524) && 16438c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2525) && 16448c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF2525E) && 16458c2ecf20Sopenharmony_ci !rt2x00_rf(rt2x00dev, RF5222)) { 16468c2ecf20Sopenharmony_ci rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n"); 16478c2ecf20Sopenharmony_ci return -ENODEV; 16488c2ecf20Sopenharmony_ci } 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci /* 16518c2ecf20Sopenharmony_ci * Identify default antenna configuration. 16528c2ecf20Sopenharmony_ci */ 16538c2ecf20Sopenharmony_ci rt2x00dev->default_ant.tx = 16548c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); 16558c2ecf20Sopenharmony_ci rt2x00dev->default_ant.rx = 16568c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci /* 16598c2ecf20Sopenharmony_ci * Store led mode, for correct led behaviour. 16608c2ecf20Sopenharmony_ci */ 16618c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_LEDS 16628c2ecf20Sopenharmony_ci value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); 16658c2ecf20Sopenharmony_ci if (value == LED_MODE_TXRX_ACTIVITY || 16668c2ecf20Sopenharmony_ci value == LED_MODE_DEFAULT || 16678c2ecf20Sopenharmony_ci value == LED_MODE_ASUS) 16688c2ecf20Sopenharmony_ci rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual, 16698c2ecf20Sopenharmony_ci LED_TYPE_ACTIVITY); 16708c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_LEDS */ 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci /* 16738c2ecf20Sopenharmony_ci * Detect if this device has an hardware controlled radio. 16748c2ecf20Sopenharmony_ci */ 16758c2ecf20Sopenharmony_ci if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) { 16768c2ecf20Sopenharmony_ci __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); 16778c2ecf20Sopenharmony_ci /* 16788c2ecf20Sopenharmony_ci * On this device RFKILL initialized during probe does not work. 16798c2ecf20Sopenharmony_ci */ 16808c2ecf20Sopenharmony_ci __set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags); 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* 16848c2ecf20Sopenharmony_ci * Check if the BBP tuning should be enabled. 16858c2ecf20Sopenharmony_ci */ 16868c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC); 16878c2ecf20Sopenharmony_ci if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) 16888c2ecf20Sopenharmony_ci __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci /* 16918c2ecf20Sopenharmony_ci * Read the RSSI <-> dBm offset information. 16928c2ecf20Sopenharmony_ci */ 16938c2ecf20Sopenharmony_ci eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET); 16948c2ecf20Sopenharmony_ci rt2x00dev->rssi_offset = 16958c2ecf20Sopenharmony_ci rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci return 0; 16988c2ecf20Sopenharmony_ci} 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci/* 17018c2ecf20Sopenharmony_ci * RF value list for RF2522 17028c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 17038c2ecf20Sopenharmony_ci */ 17048c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2522[] = { 17058c2ecf20Sopenharmony_ci { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, 17068c2ecf20Sopenharmony_ci { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, 17078c2ecf20Sopenharmony_ci { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, 17088c2ecf20Sopenharmony_ci { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, 17098c2ecf20Sopenharmony_ci { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, 17108c2ecf20Sopenharmony_ci { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, 17118c2ecf20Sopenharmony_ci { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, 17128c2ecf20Sopenharmony_ci { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, 17138c2ecf20Sopenharmony_ci { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, 17148c2ecf20Sopenharmony_ci { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, 17158c2ecf20Sopenharmony_ci { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, 17168c2ecf20Sopenharmony_ci { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, 17178c2ecf20Sopenharmony_ci { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, 17188c2ecf20Sopenharmony_ci { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, 17198c2ecf20Sopenharmony_ci}; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci/* 17228c2ecf20Sopenharmony_ci * RF value list for RF2523 17238c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 17248c2ecf20Sopenharmony_ci */ 17258c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2523[] = { 17268c2ecf20Sopenharmony_ci { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, 17278c2ecf20Sopenharmony_ci { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, 17288c2ecf20Sopenharmony_ci { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, 17298c2ecf20Sopenharmony_ci { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, 17308c2ecf20Sopenharmony_ci { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, 17318c2ecf20Sopenharmony_ci { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, 17328c2ecf20Sopenharmony_ci { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, 17338c2ecf20Sopenharmony_ci { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, 17348c2ecf20Sopenharmony_ci { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, 17358c2ecf20Sopenharmony_ci { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, 17368c2ecf20Sopenharmony_ci { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, 17378c2ecf20Sopenharmony_ci { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, 17388c2ecf20Sopenharmony_ci { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, 17398c2ecf20Sopenharmony_ci { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, 17408c2ecf20Sopenharmony_ci}; 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci/* 17438c2ecf20Sopenharmony_ci * RF value list for RF2524 17448c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 17458c2ecf20Sopenharmony_ci */ 17468c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2524[] = { 17478c2ecf20Sopenharmony_ci { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, 17488c2ecf20Sopenharmony_ci { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, 17498c2ecf20Sopenharmony_ci { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, 17508c2ecf20Sopenharmony_ci { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, 17518c2ecf20Sopenharmony_ci { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, 17528c2ecf20Sopenharmony_ci { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, 17538c2ecf20Sopenharmony_ci { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, 17548c2ecf20Sopenharmony_ci { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, 17558c2ecf20Sopenharmony_ci { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, 17568c2ecf20Sopenharmony_ci { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, 17578c2ecf20Sopenharmony_ci { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, 17588c2ecf20Sopenharmony_ci { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, 17598c2ecf20Sopenharmony_ci { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, 17608c2ecf20Sopenharmony_ci { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, 17618c2ecf20Sopenharmony_ci}; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci/* 17648c2ecf20Sopenharmony_ci * RF value list for RF2525 17658c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 17668c2ecf20Sopenharmony_ci */ 17678c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525[] = { 17688c2ecf20Sopenharmony_ci { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, 17698c2ecf20Sopenharmony_ci { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, 17708c2ecf20Sopenharmony_ci { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, 17718c2ecf20Sopenharmony_ci { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, 17728c2ecf20Sopenharmony_ci { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, 17738c2ecf20Sopenharmony_ci { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, 17748c2ecf20Sopenharmony_ci { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, 17758c2ecf20Sopenharmony_ci { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, 17768c2ecf20Sopenharmony_ci { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, 17778c2ecf20Sopenharmony_ci { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, 17788c2ecf20Sopenharmony_ci { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, 17798c2ecf20Sopenharmony_ci { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, 17808c2ecf20Sopenharmony_ci { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, 17818c2ecf20Sopenharmony_ci { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, 17828c2ecf20Sopenharmony_ci}; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci/* 17858c2ecf20Sopenharmony_ci * RF value list for RF2525e 17868c2ecf20Sopenharmony_ci * Supports: 2.4 GHz 17878c2ecf20Sopenharmony_ci */ 17888c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_bg_2525e[] = { 17898c2ecf20Sopenharmony_ci { 1, 0x00022020, 0x00081136, 0x00060111, 0x00000a0b }, 17908c2ecf20Sopenharmony_ci { 2, 0x00022020, 0x0008113a, 0x00060111, 0x00000a0b }, 17918c2ecf20Sopenharmony_ci { 3, 0x00022020, 0x0008113e, 0x00060111, 0x00000a0b }, 17928c2ecf20Sopenharmony_ci { 4, 0x00022020, 0x00081182, 0x00060111, 0x00000a0b }, 17938c2ecf20Sopenharmony_ci { 5, 0x00022020, 0x00081186, 0x00060111, 0x00000a0b }, 17948c2ecf20Sopenharmony_ci { 6, 0x00022020, 0x0008118a, 0x00060111, 0x00000a0b }, 17958c2ecf20Sopenharmony_ci { 7, 0x00022020, 0x0008118e, 0x00060111, 0x00000a0b }, 17968c2ecf20Sopenharmony_ci { 8, 0x00022020, 0x00081192, 0x00060111, 0x00000a0b }, 17978c2ecf20Sopenharmony_ci { 9, 0x00022020, 0x00081196, 0x00060111, 0x00000a0b }, 17988c2ecf20Sopenharmony_ci { 10, 0x00022020, 0x0008119a, 0x00060111, 0x00000a0b }, 17998c2ecf20Sopenharmony_ci { 11, 0x00022020, 0x0008119e, 0x00060111, 0x00000a0b }, 18008c2ecf20Sopenharmony_ci { 12, 0x00022020, 0x000811a2, 0x00060111, 0x00000a0b }, 18018c2ecf20Sopenharmony_ci { 13, 0x00022020, 0x000811a6, 0x00060111, 0x00000a0b }, 18028c2ecf20Sopenharmony_ci { 14, 0x00022020, 0x000811ae, 0x00060111, 0x00000a1b }, 18038c2ecf20Sopenharmony_ci}; 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci/* 18068c2ecf20Sopenharmony_ci * RF value list for RF5222 18078c2ecf20Sopenharmony_ci * Supports: 2.4 GHz & 5.2 GHz 18088c2ecf20Sopenharmony_ci */ 18098c2ecf20Sopenharmony_cistatic const struct rf_channel rf_vals_5222[] = { 18108c2ecf20Sopenharmony_ci { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, 18118c2ecf20Sopenharmony_ci { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, 18128c2ecf20Sopenharmony_ci { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, 18138c2ecf20Sopenharmony_ci { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, 18148c2ecf20Sopenharmony_ci { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, 18158c2ecf20Sopenharmony_ci { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, 18168c2ecf20Sopenharmony_ci { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, 18178c2ecf20Sopenharmony_ci { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, 18188c2ecf20Sopenharmony_ci { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, 18198c2ecf20Sopenharmony_ci { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, 18208c2ecf20Sopenharmony_ci { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, 18218c2ecf20Sopenharmony_ci { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, 18228c2ecf20Sopenharmony_ci { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, 18238c2ecf20Sopenharmony_ci { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci /* 802.11 UNI / HyperLan 2 */ 18268c2ecf20Sopenharmony_ci { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, 18278c2ecf20Sopenharmony_ci { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, 18288c2ecf20Sopenharmony_ci { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, 18298c2ecf20Sopenharmony_ci { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, 18308c2ecf20Sopenharmony_ci { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, 18318c2ecf20Sopenharmony_ci { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, 18328c2ecf20Sopenharmony_ci { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, 18338c2ecf20Sopenharmony_ci { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci /* 802.11 HyperLan 2 */ 18368c2ecf20Sopenharmony_ci { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, 18378c2ecf20Sopenharmony_ci { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, 18388c2ecf20Sopenharmony_ci { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, 18398c2ecf20Sopenharmony_ci { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, 18408c2ecf20Sopenharmony_ci { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, 18418c2ecf20Sopenharmony_ci { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, 18428c2ecf20Sopenharmony_ci { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, 18438c2ecf20Sopenharmony_ci { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, 18448c2ecf20Sopenharmony_ci { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, 18458c2ecf20Sopenharmony_ci { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci /* 802.11 UNII */ 18488c2ecf20Sopenharmony_ci { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, 18498c2ecf20Sopenharmony_ci { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, 18508c2ecf20Sopenharmony_ci { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, 18518c2ecf20Sopenharmony_ci { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, 18528c2ecf20Sopenharmony_ci { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, 18538c2ecf20Sopenharmony_ci}; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci struct hw_mode_spec *spec = &rt2x00dev->spec; 18588c2ecf20Sopenharmony_ci struct channel_info *info; 18598c2ecf20Sopenharmony_ci char *tx_power; 18608c2ecf20Sopenharmony_ci unsigned int i; 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci /* 18638c2ecf20Sopenharmony_ci * Initialize all hw fields. 18648c2ecf20Sopenharmony_ci */ 18658c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK); 18668c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS); 18678c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING); 18688c2ecf20Sopenharmony_ci ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM); 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 18718c2ecf20Sopenharmony_ci SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 18728c2ecf20Sopenharmony_ci rt2x00_eeprom_addr(rt2x00dev, 18738c2ecf20Sopenharmony_ci EEPROM_MAC_ADDR_0)); 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci /* 18768c2ecf20Sopenharmony_ci * Disable powersaving as default. 18778c2ecf20Sopenharmony_ci */ 18788c2ecf20Sopenharmony_ci rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci /* 18818c2ecf20Sopenharmony_ci * Initialize hw_mode information. 18828c2ecf20Sopenharmony_ci */ 18838c2ecf20Sopenharmony_ci spec->supported_bands = SUPPORT_BAND_2GHZ; 18848c2ecf20Sopenharmony_ci spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (rt2x00_rf(rt2x00dev, RF2522)) { 18878c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); 18888c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2522; 18898c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2523)) { 18908c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); 18918c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2523; 18928c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2524)) { 18938c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); 18948c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2524; 18958c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2525)) { 18968c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); 18978c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2525; 18988c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF2525E)) { 18998c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); 19008c2ecf20Sopenharmony_ci spec->channels = rf_vals_bg_2525e; 19018c2ecf20Sopenharmony_ci } else if (rt2x00_rf(rt2x00dev, RF5222)) { 19028c2ecf20Sopenharmony_ci spec->supported_bands |= SUPPORT_BAND_5GHZ; 19038c2ecf20Sopenharmony_ci spec->num_channels = ARRAY_SIZE(rf_vals_5222); 19048c2ecf20Sopenharmony_ci spec->channels = rf_vals_5222; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci /* 19088c2ecf20Sopenharmony_ci * Create channel information array 19098c2ecf20Sopenharmony_ci */ 19108c2ecf20Sopenharmony_ci info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); 19118c2ecf20Sopenharmony_ci if (!info) 19128c2ecf20Sopenharmony_ci return -ENOMEM; 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci spec->channels_info = info; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); 19178c2ecf20Sopenharmony_ci for (i = 0; i < 14; i++) { 19188c2ecf20Sopenharmony_ci info[i].max_power = MAX_TXPOWER; 19198c2ecf20Sopenharmony_ci info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci if (spec->num_channels > 14) { 19238c2ecf20Sopenharmony_ci for (i = 14; i < spec->num_channels; i++) { 19248c2ecf20Sopenharmony_ci info[i].max_power = MAX_TXPOWER; 19258c2ecf20Sopenharmony_ci info[i].default_power1 = DEFAULT_TXPOWER; 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci } 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci return 0; 19308c2ecf20Sopenharmony_ci} 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_cistatic int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) 19338c2ecf20Sopenharmony_ci{ 19348c2ecf20Sopenharmony_ci int retval; 19358c2ecf20Sopenharmony_ci u32 reg; 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci /* 19388c2ecf20Sopenharmony_ci * Allocate eeprom data. 19398c2ecf20Sopenharmony_ci */ 19408c2ecf20Sopenharmony_ci retval = rt2500pci_validate_eeprom(rt2x00dev); 19418c2ecf20Sopenharmony_ci if (retval) 19428c2ecf20Sopenharmony_ci return retval; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci retval = rt2500pci_init_eeprom(rt2x00dev); 19458c2ecf20Sopenharmony_ci if (retval) 19468c2ecf20Sopenharmony_ci return retval; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci /* 19498c2ecf20Sopenharmony_ci * Enable rfkill polling by setting GPIO direction of the 19508c2ecf20Sopenharmony_ci * rfkill switch GPIO pin correctly. 19518c2ecf20Sopenharmony_ci */ 19528c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR); 19538c2ecf20Sopenharmony_ci rt2x00_set_field32(®, GPIOCSR_DIR0, 1); 19548c2ecf20Sopenharmony_ci rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg); 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci /* 19578c2ecf20Sopenharmony_ci * Initialize hw specifications. 19588c2ecf20Sopenharmony_ci */ 19598c2ecf20Sopenharmony_ci retval = rt2500pci_probe_hw_mode(rt2x00dev); 19608c2ecf20Sopenharmony_ci if (retval) 19618c2ecf20Sopenharmony_ci return retval; 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci /* 19648c2ecf20Sopenharmony_ci * This device requires the atim queue and DMA-mapped skbs. 19658c2ecf20Sopenharmony_ci */ 19668c2ecf20Sopenharmony_ci __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); 19678c2ecf20Sopenharmony_ci __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); 19688c2ecf20Sopenharmony_ci __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci /* 19718c2ecf20Sopenharmony_ci * Set the rssi offset. 19728c2ecf20Sopenharmony_ci */ 19738c2ecf20Sopenharmony_ci rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci return 0; 19768c2ecf20Sopenharmony_ci} 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci/* 19798c2ecf20Sopenharmony_ci * IEEE80211 stack callback functions. 19808c2ecf20Sopenharmony_ci */ 19818c2ecf20Sopenharmony_cistatic u64 rt2500pci_get_tsf(struct ieee80211_hw *hw, 19828c2ecf20Sopenharmony_ci struct ieee80211_vif *vif) 19838c2ecf20Sopenharmony_ci{ 19848c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = hw->priv; 19858c2ecf20Sopenharmony_ci u64 tsf; 19868c2ecf20Sopenharmony_ci u32 reg; 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR17); 19898c2ecf20Sopenharmony_ci tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; 19908c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR16); 19918c2ecf20Sopenharmony_ci tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci return tsf; 19948c2ecf20Sopenharmony_ci} 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_cistatic int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) 19978c2ecf20Sopenharmony_ci{ 19988c2ecf20Sopenharmony_ci struct rt2x00_dev *rt2x00dev = hw->priv; 19998c2ecf20Sopenharmony_ci u32 reg; 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci reg = rt2x00mmio_register_read(rt2x00dev, CSR15); 20028c2ecf20Sopenharmony_ci return rt2x00_get_field32(reg, CSR15_BEACON_SENT); 20038c2ecf20Sopenharmony_ci} 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_cistatic const struct ieee80211_ops rt2500pci_mac80211_ops = { 20068c2ecf20Sopenharmony_ci .tx = rt2x00mac_tx, 20078c2ecf20Sopenharmony_ci .start = rt2x00mac_start, 20088c2ecf20Sopenharmony_ci .stop = rt2x00mac_stop, 20098c2ecf20Sopenharmony_ci .add_interface = rt2x00mac_add_interface, 20108c2ecf20Sopenharmony_ci .remove_interface = rt2x00mac_remove_interface, 20118c2ecf20Sopenharmony_ci .config = rt2x00mac_config, 20128c2ecf20Sopenharmony_ci .configure_filter = rt2x00mac_configure_filter, 20138c2ecf20Sopenharmony_ci .sw_scan_start = rt2x00mac_sw_scan_start, 20148c2ecf20Sopenharmony_ci .sw_scan_complete = rt2x00mac_sw_scan_complete, 20158c2ecf20Sopenharmony_ci .get_stats = rt2x00mac_get_stats, 20168c2ecf20Sopenharmony_ci .bss_info_changed = rt2x00mac_bss_info_changed, 20178c2ecf20Sopenharmony_ci .conf_tx = rt2x00mac_conf_tx, 20188c2ecf20Sopenharmony_ci .get_tsf = rt2500pci_get_tsf, 20198c2ecf20Sopenharmony_ci .tx_last_beacon = rt2500pci_tx_last_beacon, 20208c2ecf20Sopenharmony_ci .rfkill_poll = rt2x00mac_rfkill_poll, 20218c2ecf20Sopenharmony_ci .flush = rt2x00mac_flush, 20228c2ecf20Sopenharmony_ci .set_antenna = rt2x00mac_set_antenna, 20238c2ecf20Sopenharmony_ci .get_antenna = rt2x00mac_get_antenna, 20248c2ecf20Sopenharmony_ci .get_ringparam = rt2x00mac_get_ringparam, 20258c2ecf20Sopenharmony_ci .tx_frames_pending = rt2x00mac_tx_frames_pending, 20268c2ecf20Sopenharmony_ci}; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_cistatic const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { 20298c2ecf20Sopenharmony_ci .irq_handler = rt2500pci_interrupt, 20308c2ecf20Sopenharmony_ci .txstatus_tasklet = rt2500pci_txstatus_tasklet, 20318c2ecf20Sopenharmony_ci .tbtt_tasklet = rt2500pci_tbtt_tasklet, 20328c2ecf20Sopenharmony_ci .rxdone_tasklet = rt2500pci_rxdone_tasklet, 20338c2ecf20Sopenharmony_ci .probe_hw = rt2500pci_probe_hw, 20348c2ecf20Sopenharmony_ci .initialize = rt2x00mmio_initialize, 20358c2ecf20Sopenharmony_ci .uninitialize = rt2x00mmio_uninitialize, 20368c2ecf20Sopenharmony_ci .get_entry_state = rt2500pci_get_entry_state, 20378c2ecf20Sopenharmony_ci .clear_entry = rt2500pci_clear_entry, 20388c2ecf20Sopenharmony_ci .set_device_state = rt2500pci_set_device_state, 20398c2ecf20Sopenharmony_ci .rfkill_poll = rt2500pci_rfkill_poll, 20408c2ecf20Sopenharmony_ci .link_stats = rt2500pci_link_stats, 20418c2ecf20Sopenharmony_ci .reset_tuner = rt2500pci_reset_tuner, 20428c2ecf20Sopenharmony_ci .link_tuner = rt2500pci_link_tuner, 20438c2ecf20Sopenharmony_ci .start_queue = rt2500pci_start_queue, 20448c2ecf20Sopenharmony_ci .kick_queue = rt2500pci_kick_queue, 20458c2ecf20Sopenharmony_ci .stop_queue = rt2500pci_stop_queue, 20468c2ecf20Sopenharmony_ci .flush_queue = rt2x00mmio_flush_queue, 20478c2ecf20Sopenharmony_ci .write_tx_desc = rt2500pci_write_tx_desc, 20488c2ecf20Sopenharmony_ci .write_beacon = rt2500pci_write_beacon, 20498c2ecf20Sopenharmony_ci .fill_rxdone = rt2500pci_fill_rxdone, 20508c2ecf20Sopenharmony_ci .config_filter = rt2500pci_config_filter, 20518c2ecf20Sopenharmony_ci .config_intf = rt2500pci_config_intf, 20528c2ecf20Sopenharmony_ci .config_erp = rt2500pci_config_erp, 20538c2ecf20Sopenharmony_ci .config_ant = rt2500pci_config_ant, 20548c2ecf20Sopenharmony_ci .config = rt2500pci_config, 20558c2ecf20Sopenharmony_ci}; 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_cistatic void rt2500pci_queue_init(struct data_queue *queue) 20588c2ecf20Sopenharmony_ci{ 20598c2ecf20Sopenharmony_ci switch (queue->qid) { 20608c2ecf20Sopenharmony_ci case QID_RX: 20618c2ecf20Sopenharmony_ci queue->limit = 32; 20628c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 20638c2ecf20Sopenharmony_ci queue->desc_size = RXD_DESC_SIZE; 20648c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_mmio); 20658c2ecf20Sopenharmony_ci break; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci case QID_AC_VO: 20688c2ecf20Sopenharmony_ci case QID_AC_VI: 20698c2ecf20Sopenharmony_ci case QID_AC_BE: 20708c2ecf20Sopenharmony_ci case QID_AC_BK: 20718c2ecf20Sopenharmony_ci queue->limit = 32; 20728c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 20738c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 20748c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_mmio); 20758c2ecf20Sopenharmony_ci break; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci case QID_BEACON: 20788c2ecf20Sopenharmony_ci queue->limit = 1; 20798c2ecf20Sopenharmony_ci queue->data_size = MGMT_FRAME_SIZE; 20808c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 20818c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_mmio); 20828c2ecf20Sopenharmony_ci break; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci case QID_ATIM: 20858c2ecf20Sopenharmony_ci queue->limit = 8; 20868c2ecf20Sopenharmony_ci queue->data_size = DATA_FRAME_SIZE; 20878c2ecf20Sopenharmony_ci queue->desc_size = TXD_DESC_SIZE; 20888c2ecf20Sopenharmony_ci queue->priv_size = sizeof(struct queue_entry_priv_mmio); 20898c2ecf20Sopenharmony_ci break; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci default: 20928c2ecf20Sopenharmony_ci BUG(); 20938c2ecf20Sopenharmony_ci break; 20948c2ecf20Sopenharmony_ci } 20958c2ecf20Sopenharmony_ci} 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_cistatic const struct rt2x00_ops rt2500pci_ops = { 20988c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 20998c2ecf20Sopenharmony_ci .max_ap_intf = 1, 21008c2ecf20Sopenharmony_ci .eeprom_size = EEPROM_SIZE, 21018c2ecf20Sopenharmony_ci .rf_size = RF_SIZE, 21028c2ecf20Sopenharmony_ci .tx_queues = NUM_TX_QUEUES, 21038c2ecf20Sopenharmony_ci .queue_init = rt2500pci_queue_init, 21048c2ecf20Sopenharmony_ci .lib = &rt2500pci_rt2x00_ops, 21058c2ecf20Sopenharmony_ci .hw = &rt2500pci_mac80211_ops, 21068c2ecf20Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS 21078c2ecf20Sopenharmony_ci .debugfs = &rt2500pci_rt2x00debug, 21088c2ecf20Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 21098c2ecf20Sopenharmony_ci}; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci/* 21128c2ecf20Sopenharmony_ci * RT2500pci module information. 21138c2ecf20Sopenharmony_ci */ 21148c2ecf20Sopenharmony_cistatic const struct pci_device_id rt2500pci_device_table[] = { 21158c2ecf20Sopenharmony_ci { PCI_DEVICE(0x1814, 0x0201) }, 21168c2ecf20Sopenharmony_ci { 0, } 21178c2ecf20Sopenharmony_ci}; 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRV_PROJECT); 21208c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 21218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Ralink RT2500 PCI & PCMCIA Wireless LAN driver."); 21228c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards"); 21238c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, rt2500pci_device_table); 21248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cistatic int rt2500pci_probe(struct pci_dev *pci_dev, 21278c2ecf20Sopenharmony_ci const struct pci_device_id *id) 21288c2ecf20Sopenharmony_ci{ 21298c2ecf20Sopenharmony_ci return rt2x00pci_probe(pci_dev, &rt2500pci_ops); 21308c2ecf20Sopenharmony_ci} 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_cistatic struct pci_driver rt2500pci_driver = { 21338c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 21348c2ecf20Sopenharmony_ci .id_table = rt2500pci_device_table, 21358c2ecf20Sopenharmony_ci .probe = rt2500pci_probe, 21368c2ecf20Sopenharmony_ci .remove = rt2x00pci_remove, 21378c2ecf20Sopenharmony_ci .driver.pm = &rt2x00pci_pm_ops, 21388c2ecf20Sopenharmony_ci}; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_cimodule_pci_driver(rt2500pci_driver); 2141