536 lines
16 KiB
Diff
536 lines
16 KiB
Diff
|
From bfa282e0f525b074ec9a21372ab906156ce0aa20 Mon Sep 17 00:00:00 2001
|
||
|
From: Ivo van Doorn <IvDoorn@gmail.com>
|
||
|
Date: Mon, 16 Mar 2009 20:16:59 +0100
|
||
|
Subject: [PATCH] rt2x00: DMA fixes & new chipset support (rt2800pci)
|
||
|
|
||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||
|
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
|
||
|
---
|
||
|
drivers/net/wireless/rt2x00/rt2800pci.c | 320 +++++++++++++++++++++++++++++--
|
||
|
drivers/net/wireless/rt2x00/rt2800pci.h | 57 ++++++-
|
||
|
2 files changed, 361 insertions(+), 16 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
|
||
|
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
|
||
|
@@ -66,6 +66,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable har
|
||
|
*/
|
||
|
#define WAIT_FOR_BBP(__dev, __reg) \
|
||
|
rt2x00pci_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
|
||
|
+#define WAIT_FOR_RFCSR(__dev, __reg) \
|
||
|
+ rt2x00pci_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
|
||
|
#define WAIT_FOR_RF(__dev, __reg) \
|
||
|
rt2x00pci_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
|
||
|
#define WAIT_FOR_MCU(__dev, __reg) \
|
||
|
@@ -129,6 +131,61 @@ static void rt2800pci_bbp_read(struct rt
|
||
|
mutex_unlock(&rt2x00dev->csr_mutex);
|
||
|
}
|
||
|
|
||
|
+static void rt2800pci_rfcsr_write(struct rt2x00_dev *rt2x00dev,
|
||
|
+ const unsigned int word, const u8 value)
|
||
|
+{
|
||
|
+ u32 reg;
|
||
|
+
|
||
|
+ mutex_lock(&rt2x00dev->csr_mutex);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Wait until the RFCSR becomes available, afterwards we
|
||
|
+ * can safely write the new data into the register.
|
||
|
+ */
|
||
|
+ if (WAIT_FOR_RFCSR(rt2x00dev, ®)) {
|
||
|
+ reg = 0;
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_DATA, value);
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word);
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1);
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1);
|
||
|
+
|
||
|
+ rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg);
|
||
|
+ }
|
||
|
+
|
||
|
+ mutex_unlock(&rt2x00dev->csr_mutex);
|
||
|
+}
|
||
|
+
|
||
|
+static void rt2800pci_rfcsr_read(struct rt2x00_dev *rt2x00dev,
|
||
|
+ const unsigned int word, u8 *value)
|
||
|
+{
|
||
|
+ u32 reg;
|
||
|
+
|
||
|
+ mutex_lock(&rt2x00dev->csr_mutex);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Wait until the RFCSR becomes available, afterwards we
|
||
|
+ * can safely write the read request into the register.
|
||
|
+ * After the data has been written, we wait until hardware
|
||
|
+ * returns the correct value, if at any time the register
|
||
|
+ * doesn't become available in time, reg will be 0xffffffff
|
||
|
+ * which means we return 0xff to the caller.
|
||
|
+ */
|
||
|
+ if (WAIT_FOR_RFCSR(rt2x00dev, ®)) {
|
||
|
+ reg = 0;
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word);
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0);
|
||
|
+ rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1);
|
||
|
+
|
||
|
+ rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg);
|
||
|
+
|
||
|
+ WAIT_FOR_RFCSR(rt2x00dev, ®);
|
||
|
+ }
|
||
|
+
|
||
|
+ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
|
||
|
+
|
||
|
+ mutex_unlock(&rt2x00dev->csr_mutex);
|
||
|
+}
|
||
|
+
|
||
|
static void rt2800pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
||
|
const unsigned int word, const u32 value)
|
||
|
{
|
||
|
@@ -160,6 +217,13 @@ static void rt2800pci_mcu_request(struct
|
||
|
{
|
||
|
u32 reg;
|
||
|
|
||
|
+ /*
|
||
|
+ * RT2880 and RT3052 don't support MCU requests.
|
||
|
+ */
|
||
|
+ if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
|
||
|
+ rt2x00_rt(&rt2x00dev->chip, RT3052))
|
||
|
+ return;
|
||
|
+
|
||
|
mutex_lock(&rt2x00dev->csr_mutex);
|
||
|
|
||
|
/*
|
||
|
@@ -729,13 +793,11 @@ static void rt2800pci_config_lna_gain(st
|
||
|
rt2x00dev->lna_gain = lna_gain;
|
||
|
}
|
||
|
|
||
|
-static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||
|
- struct ieee80211_conf *conf,
|
||
|
- struct rf_channel *rf,
|
||
|
- struct channel_info *info)
|
||
|
+static void rt2800pci_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
|
||
|
+ struct ieee80211_conf *conf,
|
||
|
+ struct rf_channel *rf,
|
||
|
+ struct channel_info *info)
|
||
|
{
|
||
|
- u32 reg;
|
||
|
- unsigned int tx_pin;
|
||
|
u16 eeprom;
|
||
|
|
||
|
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||
|
@@ -745,9 +807,8 @@ static void rt2800pci_config_channel(str
|
||
|
*/
|
||
|
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||
|
|
||
|
- if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) {
|
||
|
+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
|
||
|
rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
|
||
|
- }
|
||
|
|
||
|
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) {
|
||
|
rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
|
||
|
@@ -806,6 +867,62 @@ static void rt2800pci_config_channel(str
|
||
|
rt2800pci_rf_write(rt2x00dev, 2, rf->rf2);
|
||
|
rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
|
||
|
rt2800pci_rf_write(rt2x00dev, 4, rf->rf4);
|
||
|
+}
|
||
|
+
|
||
|
+static void rt2800pci_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
|
||
|
+ struct ieee80211_conf *conf,
|
||
|
+ struct rf_channel *rf,
|
||
|
+ struct channel_info *info)
|
||
|
+{
|
||
|
+ u8 rfcsr;
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf1);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf3);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 6, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 6, rfcsr);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 12, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
|
||
|
+ TXPOWER_G_TO_DEV(info->tx_power1));
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 12, rfcsr);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr);
|
||
|
+
|
||
|
+ if (conf_is_ht40(conf))
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24,
|
||
|
+ rt2x00dev->calibration_bw40);
|
||
|
+ else
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24,
|
||
|
+ rt2x00dev->calibration_bw20);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr);
|
||
|
+}
|
||
|
+
|
||
|
+static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||
|
+ struct ieee80211_conf *conf,
|
||
|
+ struct rf_channel *rf,
|
||
|
+ struct channel_info *info)
|
||
|
+{
|
||
|
+ u32 reg;
|
||
|
+ unsigned int tx_pin;
|
||
|
+ u16 eeprom;
|
||
|
+ u8 bbp;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Determine antenna settings from EEPROM
|
||
|
+ */
|
||
|
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||
|
+
|
||
|
+ if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
|
||
|
+ rt2800pci_config_channel_rt2x(rt2x00dev, conf, rf, info);
|
||
|
+ else
|
||
|
+ rt2800pci_config_channel_rt3x(rt2x00dev, conf, rf, info);
|
||
|
|
||
|
/*
|
||
|
* Change BBP settings
|
||
|
@@ -861,6 +978,26 @@ static void rt2800pci_config_channel(str
|
||
|
|
||
|
rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
|
||
|
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
|
||
|
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 4, bbp);
|
||
|
+
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 3, &bbp);
|
||
|
+ rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 3, bbp);
|
||
|
+
|
||
|
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
|
||
|
+ if (conf_is_ht40(conf)) {
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 69, 0x1a);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 70, 0x0a);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 73, 0x16);
|
||
|
+ } else {
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 69, 0x16);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 70, 0x08);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 73, 0x11);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
msleep(1);
|
||
|
}
|
||
|
|
||
|
@@ -1265,7 +1402,7 @@ static int rt2800pci_init_queues(struct
|
||
|
entry_priv = rt2x00dev->rx->entries[0].priv_data;
|
||
|
rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
|
||
|
rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
|
||
|
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, 0);
|
||
|
+ rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
|
||
|
rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
|
||
|
|
||
|
/*
|
||
|
@@ -1613,7 +1750,7 @@ static int rt2800pci_init_bbp(struct rt2
|
||
|
rt2800pci_bbp_write(rt2x00dev, 91, 0x04);
|
||
|
rt2800pci_bbp_write(rt2x00dev, 92, 0x00);
|
||
|
rt2800pci_bbp_write(rt2x00dev, 103, 0x00);
|
||
|
- rt2800pci_bbp_write(rt2x00dev, 105, 0x05);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 105, 0x01);
|
||
|
|
||
|
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
|
||
|
rt2800pci_bbp_write(rt2x00dev, 69, 0x16);
|
||
|
@@ -1623,6 +1760,12 @@ static int rt2800pci_init_bbp(struct rt2
|
||
|
if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION)
|
||
|
rt2800pci_bbp_write(rt2x00dev, 84, 0x19);
|
||
|
|
||
|
+ if (rt2x00_rt(&rt2x00dev->chip, RT3052)) {
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 31, 0x08);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 78, 0x0e);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 80, 0x08);
|
||
|
+ }
|
||
|
+
|
||
|
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
|
||
|
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
|
||
|
|
||
|
@@ -1636,6 +1779,144 @@ static int rt2800pci_init_bbp(struct rt2
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static u8 rt2800pci_init_rx_filter(struct rt2x00_dev *rt2x00dev,
|
||
|
+ bool bw40, u8 rfcsr24, u8 filter_target)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+ u8 bbp;
|
||
|
+ u8 rfcsr;
|
||
|
+ u8 passband;
|
||
|
+ u8 stopband;
|
||
|
+ u8 overtuned = 0;
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
|
||
|
+
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
|
||
|
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 4, bbp);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Set power & frequency of passband test tone
|
||
|
+ */
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 24, 0);
|
||
|
+
|
||
|
+ for (i = 0; i < 100; i++) {
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 25, 0x90);
|
||
|
+ msleep(1);
|
||
|
+
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 55, &passband);
|
||
|
+ if (passband)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Set power & frequency of stopband test tone
|
||
|
+ */
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 24, 0x06);
|
||
|
+
|
||
|
+ for (i = 0; i < 100; i++) {
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 25, 0x90);
|
||
|
+ msleep(1);
|
||
|
+
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 55, &stopband);
|
||
|
+
|
||
|
+ if ((passband - stopband) <= filter_target) {
|
||
|
+ rfcsr24++;
|
||
|
+ overtuned += ((passband - stopband) == filter_target);
|
||
|
+ } else
|
||
|
+ break;
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
|
||
|
+ }
|
||
|
+
|
||
|
+ rfcsr24 -= !!overtuned;
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
|
||
|
+ return rfcsr24;
|
||
|
+}
|
||
|
+
|
||
|
+static int rt2800pci_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||
|
+{
|
||
|
+ u8 rfcsr;
|
||
|
+ u8 bbp;
|
||
|
+
|
||
|
+ if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||
|
+ !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||
|
+ !rt2x00_rf(&rt2x00dev->chip, RF3022))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Init RF calibration.
|
||
|
+ */
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 30, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr);
|
||
|
+ msleep(1);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 0, 0x50);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 1, 0x01);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 2, 0xf7);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 3, 0x75);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 4, 0x40);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 5, 0x03);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 6, 0x02);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 7, 0x50);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 8, 0x39);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 9, 0x0f);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 10, 0x60);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 11, 0x21);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 12, 0x75);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 13, 0x75);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 14, 0x90);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 15, 0x58);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 16, 0xb3);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 17, 0x92);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 18, 0x2c);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 19, 0x02);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 20, 0xba);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 21, 0xdb);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 22, 0x00);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 23, 0x31);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 24, 0x08);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 25, 0x01);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 26, 0x25);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 27, 0x23);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 28, 0x13);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 29, 0x83);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Set RX Filter calibration for 20MHz and 40MHz
|
||
|
+ */
|
||
|
+ rt2x00dev->calibration_bw20 =
|
||
|
+ rt2800pci_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
|
||
|
+ rt2x00dev->calibration_bw40 =
|
||
|
+ rt2800pci_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Set back to initial state
|
||
|
+ */
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 24, 0);
|
||
|
+
|
||
|
+ rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr);
|
||
|
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
|
||
|
+ rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * set BBP back to BW20
|
||
|
+ */
|
||
|
+ rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
|
||
|
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
|
||
|
+ rt2800pci_bbp_write(rt2x00dev, 4, bbp);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Device state switch handlers.
|
||
|
*/
|
||
|
@@ -1718,7 +1999,8 @@ static int rt2800pci_enable_radio(struct
|
||
|
rt2800pci_init_queues(rt2x00dev) ||
|
||
|
rt2800pci_init_registers(rt2x00dev) ||
|
||
|
rt2800pci_wait_wpdma_ready(rt2x00dev) ||
|
||
|
- rt2800pci_init_bbp(rt2x00dev)))
|
||
|
+ rt2800pci_init_bbp(rt2x00dev) ||
|
||
|
+ rt2800pci_init_rfcsr(rt2x00dev)))
|
||
|
return -EIO;
|
||
|
|
||
|
/*
|
||
|
@@ -2114,6 +2396,12 @@ static void rt2800pci_fill_rxdone(struct
|
||
|
rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
|
||
|
|
||
|
/*
|
||
|
+ * Set RX IDX in register to inform hardware that we have handled
|
||
|
+ * this entry and it is available for reuse again.
|
||
|
+ */
|
||
|
+ rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
|
||
|
+
|
||
|
+ /*
|
||
|
* Remove TXWI descriptor from start of buffer.
|
||
|
*/
|
||
|
skb_pull(entry->skb, RXWI_DESC_SIZE);
|
||
|
@@ -2380,7 +2668,8 @@ static int rt2800pci_init_eeprom(struct
|
||
|
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
||
|
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||
|
!rt2x00_rf(&rt2x00dev->chip, RF2020) &&
|
||
|
- !rt2x00_rf(&rt2x00dev->chip, RF3052)) {
|
||
|
+ !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||
|
+ !rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
||
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
@@ -2528,7 +2817,8 @@ static int rt2800pci_probe_hw_mode(struc
|
||
|
|
||
|
if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
|
||
|
rt2x00_rf(&rt2x00dev->chip, RF2720) ||
|
||
|
- rt2x00_rf(&rt2x00dev->chip, RF3052)) {
|
||
|
+ rt2x00_rf(&rt2x00dev->chip, RF3021) ||
|
||
|
+ rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
||
|
spec->num_channels = 14;
|
||
|
spec->channels = rf_vals;
|
||
|
} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
|
||
|
@@ -2624,7 +2914,9 @@ static int rt2800pci_probe_hw(struct rt2
|
||
|
/*
|
||
|
* This device requires firmware.
|
||
|
*/
|
||
|
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||
|
+ if (!rt2x00_rt(&rt2x00dev->chip, RT2880) &&
|
||
|
+ !rt2x00_rt(&rt2x00dev->chip, RT3052))
|
||
|
+ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||
|
if (!modparam_nohwcrypt)
|
||
|
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
|
||
|
|
||
|
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
|
||
|
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
|
||
|
@@ -36,7 +36,8 @@
|
||
|
* RF2750 2.4G/5G 1T2R
|
||
|
* RF3020 2.4G 1T1R
|
||
|
* RF2020 2.4G B/G
|
||
|
- * RF3052 2.4G 2T2R
|
||
|
+ * RF3021 2.4G 1T2R
|
||
|
+ * RF3022 2.4G 2T2R
|
||
|
*/
|
||
|
#define RF2820 0x0001
|
||
|
#define RF2850 0x0002
|
||
|
@@ -44,7 +45,8 @@
|
||
|
#define RF2750 0x0004
|
||
|
#define RF3020 0x0005
|
||
|
#define RF2020 0x0006
|
||
|
-#define RF3052 0x0008
|
||
|
+#define RF3021 0x0007
|
||
|
+#define RF3022 0x0008
|
||
|
|
||
|
/*
|
||
|
* RT2860 version
|
||
|
@@ -373,6 +375,15 @@
|
||
|
#define PBF_DBG 0x043c
|
||
|
|
||
|
/*
|
||
|
+ * RF registers
|
||
|
+ */
|
||
|
+#define RF_CSR_CFG 0x0500
|
||
|
+#define RF_CSR_CFG_DATA FIELD32(0x000000ff)
|
||
|
+#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00)
|
||
|
+#define RF_CSR_CFG_WRITE FIELD32(0x00010000)
|
||
|
+#define RF_CSR_CFG_BUSY FIELD32(0x00020000)
|
||
|
+
|
||
|
+/*
|
||
|
* MAC Control/Status Registers(CSR).
|
||
|
* Some values are set in TU, whereas 1 TU == 1024 us.
|
||
|
*/
|
||
|
@@ -1465,6 +1476,48 @@ struct mac_iveiv_entry {
|
||
|
* BBP 3: RX Antenna
|
||
|
*/
|
||
|
#define BBP3_RX_ANTENNA FIELD8(0x18)
|
||
|
+#define BBP3_HT40_PLUS FIELD8(0x20)
|
||
|
+
|
||
|
+/*
|
||
|
+ * BBP 4: Bandwidth
|
||
|
+ */
|
||
|
+#define BBP4_TX_BF FIELD8(0x01)
|
||
|
+#define BBP4_BANDWIDTH FIELD8(0x18)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR registers
|
||
|
+ * The wordsize of the RFCSR is 8 bits.
|
||
|
+ */
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 6:
|
||
|
+ */
|
||
|
+#define RFCSR6_R FIELD8(0x03)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 7:
|
||
|
+ */
|
||
|
+#define RFCSR7_RF_TUNING FIELD8(0x01)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 12:
|
||
|
+ */
|
||
|
+#define RFCSR12_TX_POWER FIELD8(0x1f)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 22:
|
||
|
+ */
|
||
|
+#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 23:
|
||
|
+ */
|
||
|
+#define RFCSR23_FREQ_OFFSET FIELD8(0x7f)
|
||
|
+
|
||
|
+/*
|
||
|
+ * RFCSR 30:
|
||
|
+ */
|
||
|
+#define RFCSR30_RF_CALIBRATION FIELD8(0x80)
|
||
|
|
||
|
/*
|
||
|
* RF registers
|