X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/774fbe8f8ddfc1ba33ce732a2d6fc21793d9af3f..27792506a45ee30e3cc7854786594481b0f8459b:/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch diff --git a/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch b/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch index e22b0763a..7584e5a7d 100644 --- a/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch +++ b/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch @@ -1,38 +1,40 @@ -From f2219a0f2f2f61656d2c3a524836f6f1e646ea33 Mon Sep 17 00:00:00 2001 +From 67432230daedc23f808b79173703e27675fd0659 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn -Date: Wed, 4 Feb 2009 20:43:00 +0100 -Subject: [PATCH] rt2x00: Implement support for rt2800pci +Date: Sun, 26 Apr 2009 15:54:03 +0200 +Subject: [PATCH 2/4] rt2x00: Implement support for rt2800pci Add support for the rt2800pci chipset. -Includes various patches from Mattias, Mark and Felix. +Includes various patches from Mattias, Mark, Felix and Xose. +Signed-off-by: Xose Vazquez Perez Signed-off-by: Mattias Nissler Signed-off-by: Mark Asselstine Signed-off-by: Felix Fietkau Signed-off-by: Ivo van Doorn --- - drivers/net/wireless/rt2x00/Kconfig | 15 + + drivers/net/wireless/rt2x00/Kconfig | 26 + drivers/net/wireless/rt2x00/Makefile | 1 + - drivers/net/wireless/rt2x00/rt2800pci.c | 2785 +++++++++++++++++++++++++++++++ - drivers/net/wireless/rt2x00/rt2800pci.h | 1877 +++++++++++++++++++++ - drivers/net/wireless/rt2x00/rt2x00.h | 4 + - 5 files changed, 4682 insertions(+), 0 deletions(-) + drivers/net/wireless/rt2x00/rt2800pci.c | 3245 +++++++++++++++++++++++++++++++ + drivers/net/wireless/rt2x00/rt2800pci.h | 1927 ++++++++++++++++++ + drivers/net/wireless/rt2x00/rt2x00.h | 6 + + 5 files changed, 5205 insertions(+), 0 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2800pci.c create mode 100644 drivers/net/wireless/rt2x00/rt2800pci.h --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile -@@ -16,5 +16,6 @@ obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00u +@@ -17,6 +17,7 @@ obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00u obj-$(CONFIG_RT2400PCI) += rt2400pci.o obj-$(CONFIG_RT2500PCI) += rt2500pci.o obj-$(CONFIG_RT61PCI) += rt61pci.o +obj-$(CONFIG_RT2800PCI) += rt2800pci.o obj-$(CONFIG_RT2500USB) += rt2500usb.o obj-$(CONFIG_RT73USB) += rt73usb.o + obj-$(CONFIG_RT2800USB) += rt2800usb.o --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -0,0 +1,2785 @@ +@@ -0,0 +1,3245 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + @@ -66,12 +68,22 @@ Signed-off-by: Ivo van Doorn +#include +#include +#include ++#include +#include + +#include "rt2x00.h" +#include "rt2x00pci.h" ++#include "rt2x00soc.h" +#include "rt2800pci.h" + ++#ifdef CONFIG_RT2800PCI_PCI_MODULE ++#define CONFIG_RT2800PCI_PCI ++#endif ++ ++#ifdef CONFIG_RT2800PCI_WISOC_MODULE ++#define CONFIG_RT2800PCI_WISOC ++#endif ++ +/* + * Allow hardware encryption to be disabled. + */ @@ -92,6 +104,8 @@ Signed-off-by: Ivo van Doorn + */ +#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) \ @@ -155,14 +169,66 @@ Signed-off-by: Ivo van Doorn + 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) +{ + u32 reg; + -+ if (!word) -+ return; -+ + mutex_lock(&rt2x00dev->csr_mutex); + + /* @@ -189,6 +255,13 @@ Signed-off-by: Ivo van Doorn +{ + 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); + + /* @@ -210,6 +283,44 @@ Signed-off-by: Ivo van Doorn + mutex_unlock(&rt2x00dev->csr_mutex); +} + ++static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < 200; i++) { ++ rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); ++ ++ if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token)) ++ break; ++ ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ if (i == 200) ++ ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); ++ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++} ++ ++#ifdef CONFIG_RT2800PCI_WISOC ++static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ ++ ++ memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); ++} ++#else ++static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CONFIG_RT2800PCI_WISOC */ ++ ++#ifdef CONFIG_RT2800PCI_PCI +static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) +{ + struct rt2x00_dev *rt2x00dev = eeprom->data; @@ -240,6 +351,32 @@ Signed-off-by: Ivo van Doorn + rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); +} + ++static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) ++{ ++ struct eeprom_93cx6 eeprom; ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); ++ ++ eeprom.data = rt2x00dev; ++ eeprom.register_read = rt2800pci_eepromregister_read; ++ eeprom.register_write = rt2800pci_eepromregister_write; ++ eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ? ++ PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; ++ eeprom.reg_data_in = 0; ++ eeprom.reg_data_out = 0; ++ eeprom.reg_data_clock = 0; ++ eeprom.reg_chip_select = 0; ++ ++ eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, ++ EEPROM_SIZE / sizeof(u16)); ++} ++#else ++static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CONFIG_RT2800PCI_PCI */ ++ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800pci_rt2x00debug = { + .owner = THIS_MODULE, @@ -369,18 +506,19 @@ Signed-off-by: Ivo van Doorn + u32 offset; + u32 reg; + -+ offset = MAC_WCID_ATTR_ENTRY(crypto->aid); ++ offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); -+ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, crypto->cipher); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, ++ (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->cmd == SET_KEY) * crypto->bssidx); -+ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00pci_register_write(rt2x00dev, offset, reg); + -+ offset = MAC_IVEIV_ENTRY(crypto->aid); ++ offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || @@ -391,7 +529,7 @@ Signed-off-by: Ivo van Doorn + rt2x00pci_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + -+ offset = MAC_WCID_ENTRY(crypto->aid); ++ offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) @@ -431,10 +569,11 @@ Signed-off-by: Ivo van Doorn + * Using the correct defines correctly will cause overhead, + * so just calculate the correct offset. + */ -+ field.bit_offset = (4 * key->keyidx); ++ field.bit_offset = 4 * (key->hw_key_idx % 8); + field.bit_mask = 0x7 << field.bit_offset; + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); ++ + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); @@ -458,9 +597,14 @@ Signed-off-by: Ivo van Doorn + if (crypto->cmd == SET_KEY) { + /* + * 1 pairwise key is possible per AID, this means that the AID -+ * equals our hw_key_idx. ++ * equals our hw_key_idx. Make sure the WCID starts _after_ the ++ * last possible shared key entry. + */ -+ key->hw_key_idx = crypto->aid; ++ if (crypto->aid > (256 - 32)) ++ return -ENOSPC; ++ ++ key->hw_key_idx = 32 + crypto->aid; ++ + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); @@ -616,29 +760,22 @@ Signed-off-by: Ivo van Doorn +static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) +{ -+ u16 eeprom; + u8 r1; + u8 r3; + -+ /* -+ * FIXME: Use requested antenna configuration. -+ */ -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -+ + rt2800pci_bbp_read(rt2x00dev, 1, &r1); + rt2800pci_bbp_read(rt2x00dev, 3, &r3); + + /* + * Configure the TX antenna. + */ -+ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH)) { ++ switch ((int)ant->tx) { + case 1: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: -+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 16); ++ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: + /* Do nothing */ @@ -648,7 +785,7 @@ Signed-off-by: Ivo van Doorn + /* + * Configure the RX antenna. + */ -+ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { ++ switch ((int)ant->rx) { + case 1: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; @@ -687,43 +824,20 @@ Signed-off-by: Ivo van Doorn + rt2x00dev->lna_gain = lna_gain; +} + -+static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, -+ 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; -+ -+ tx_pin = 0; -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); -+ + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + -+ /* -+ * Determine antenna settings from EEPROM -+ */ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) { ++ if (rt2x00dev->default_ant.tx == 1) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); -+ /* Turn off unused PA or LNA when only 1T or 1R */ -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 0); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 0); -+ } + -+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) { ++ if (rt2x00dev->default_ant.rx == 1) { + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); -+ /* Turn off unused PA or LNA when only 1T or 1R */ -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 0); -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 0); -+ } else if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 2) ++ } else if (rt2x00dev->default_ant.rx == 2) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + + if (rf->channel > 14) { @@ -750,19 +864,14 @@ Signed-off-by: Ivo van Doorn + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power2)); -+ -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1); + } else { + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power2)); -+ -+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); + } + -+ rt2x00_set_field32(&rf->rf4, RF4_BW40, -+ test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)); ++ rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); @@ -782,6 +891,52 @@ Signed-off-by: Ivo van Doorn + 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); ++ ++ rt2800pci_rfcsr_write(rt2x00dev, 24, ++ rt2x00dev->calibration[conf_is_ht40(conf)]); ++ ++ 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; ++ u8 bbp; ++ ++ 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 @@ -799,11 +954,6 @@ Signed-off-by: Ivo van Doorn + rt2800pci_bbp_write(rt2x00dev, 82, 0x84); + rt2800pci_bbp_write(rt2x00dev, 75, 0x50); + } -+ -+ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); -+ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 0); -+ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 1); -+ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); + } else { + rt2800pci_bbp_write(rt2x00dev, 82, 0xf2); + @@ -811,15 +961,57 @@ Signed-off-by: Ivo van Doorn + rt2800pci_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800pci_bbp_write(rt2x00dev, 75, 0x50); ++ } + -+ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); -+ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 1); -+ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 0); -+ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); ++ rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); ++ rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); ++ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ ++ tx_pin = 0; ++ ++ /* Turn on unused PA or LNA when not using 1T or 1R */ ++ if (rt2x00dev->default_ant.tx != 1) { ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); ++ } ++ ++ /* Turn on unused PA or LNA when not using 1T or 1R */ ++ if (rt2x00dev->default_ant.rx != 1) { ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + } + ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); ++ + 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); +} + @@ -932,9 +1124,9 @@ Signed-off-by: Ivo van Doorn + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + -+ rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); ++ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + } else { -+ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); ++ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + + rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); @@ -952,8 +1144,8 @@ Signed-off-by: Ivo van Doorn + rt2800pci_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) -+ rt2800pci_config_channel(rt2x00dev, &libconf->rf, -+ &libconf->channel); ++ rt2800pci_config_channel(rt2x00dev, libconf->conf, ++ &libconf->rf, &libconf->channel); + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) @@ -1224,7 +1416,7 @@ Signed-off-by: Ivo van Doorn + 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); + + /* @@ -1413,6 +1605,8 @@ Signed-off-by: Ivo van Doorn + + rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, ++ IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); + @@ -1422,19 +1616,19 @@ Signed-off-by: Ivo van Doorn + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ -+ for (i = 0; i < 254; i++) { ++ for (i = 0; i < 256; i++) { + u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); ++ ++ rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); ++ rt2x00pci_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + -+ for (i = 0; i < 4; i++) ++ for (i = 0; i < 16; i++) + rt2x00pci_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + -+ for (i = 0; i < 256; i++) -+ rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); -+ + /* + * Clear all beacons + * For the Beacon base registers we only need to clear @@ -1531,8 +1725,8 @@ Signed-off-by: Ivo van Doorn + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ -+ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0x00000000); -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0x00000000); ++ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { @@ -1580,6 +1774,12 @@ Signed-off-by: Ivo van Doorn + 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); + @@ -1593,6 +1793,144 @@ Signed-off-by: Ivo van Doorn + 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[0] = ++ rt2800pci_init_rx_filter(rt2x00dev, false, 0x07, 0x16); ++ rt2x00dev->calibration[1] = ++ 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. + */ @@ -1675,7 +2013,8 @@ Signed-off-by: Ivo van Doorn + 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; + + /* @@ -1748,9 +2087,10 @@ Signed-off-by: Ivo van Doorn +{ + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + -+ if (state == STATE_AWAKE) -+ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); -+ else ++ if (state == STATE_AWAKE) { ++ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); ++ } else + rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + + return 0; @@ -1850,16 +2190,23 @@ Signed-off-by: Ivo van Doorn + test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); + rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, -+ skbdesc->entry->entry_idx); -+ rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len); ++ test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? ++ txdesc->key_idx : 0xff); ++ rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, ++ skb->len - txdesc->l2pad); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, + skbdesc->entry->queue->qid); + rt2x00_desc_write(txwi, 1, word); + -+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { -+ _rt2x00_desc_write(txwi, 2, skbdesc->iv[0]); -+ _rt2x00_desc_write(txwi, 3, skbdesc->iv[1]); -+ } ++ /* ++ * Always write 0 to IV/EIV fields, hardware will insert the IV ++ * from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0. ++ * When ENTRY_TXD_ENCRYPT_IV is set to 1 it will use the IV data ++ * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which ++ * crypto entry in the registers should be used to encrypt the frame. ++ */ ++ _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); ++ _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + + /* + * Initialize TX descriptor @@ -1886,7 +2233,8 @@ Signed-off-by: Ivo van Doorn + rt2x00_desc_write(txd, 2, word); + + rt2x00_desc_read(txd, 3, &word); -+ rt2x00_set_field32(&word, TXD_W3_WIV, 1); ++ rt2x00_set_field32(&word, TXD_W3_WIV, ++ !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W3_QSEL, 2); + rt2x00_desc_write(txd, 3, word); +} @@ -2010,7 +2358,7 @@ Signed-off-by: Ivo van Doorn + * decryption. This prevents us from correct providing + * correct statistics through debugfs. + */ -+ rxdesc->cipher = CIPHER_NONE; ++ rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = + rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); + } @@ -2033,6 +2381,9 @@ Signed-off-by: Ivo van Doorn + if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; + ++ if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) ++ rxdesc->dev_flags |= RXDONE_L2PAD; ++ + if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) + rxdesc->flags |= RX_FLAG_SHORT_GI; + @@ -2049,7 +2400,7 @@ Signed-off-by: Ivo van Doorn + /* + * Mask of 0x8 bit to remove the short preamble flag. + */ -+ if (rxdesc->dev_flags == RATE_MODE_CCK) ++ if (rxdesc->rate_mode == RATE_MODE_CCK) + rxdesc->signal &= ~0x8; + + rxdesc->rssi = @@ -2063,9 +2414,15 @@ Signed-off-by: Ivo van Doorn + 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, TXWI_DESC_SIZE); ++ skb_pull(entry->skb, RXWI_DESC_SIZE); + skb_trim(entry->skb, rxdesc->size); +} + @@ -2189,26 +2546,22 @@ Signed-off-by: Ivo van Doorn + */ +static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) +{ -+ struct eeprom_93cx6 eeprom; -+ u32 reg; + u16 word; + u8 *mac; + u8 default_lna_gain; + -+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); -+ -+ eeprom.data = rt2x00dev; -+ eeprom.register_read = rt2800pci_eepromregister_read; -+ eeprom.register_write = rt2800pci_eepromregister_write; -+ eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ? -+ PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; -+ eeprom.reg_data_in = 0; -+ eeprom.reg_data_out = 0; -+ eeprom.reg_data_clock = 0; -+ eeprom.reg_chip_select = 0; -+ -+ eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, -+ EEPROM_SIZE / sizeof(u16)); ++ /* ++ * Read EEPROM into buffer ++ */ ++ switch(rt2x00dev->chip.rt) { ++ case RT2880: ++ case RT3052: ++ rt2800pci_read_eeprom_soc(rt2x00dev); ++ break; ++ default: ++ rt2800pci_read_eeprom_pci(rt2x00dev); ++ break; ++ } + + /* + * Start validation of the data that has been read. @@ -2228,6 +2581,13 @@ Signed-off-by: Ivo van Doorn + rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); ++ } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { ++ /* ++ * There is a max of 2 RX streams for RT2860 series ++ */ ++ if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) ++ rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); ++ rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); @@ -2307,7 +2667,6 @@ Signed-off-by: Ivo van Doorn + u32 reg; + u16 value; + u16 eeprom; -+ u16 device; + + /* + * Read EEPROM word for configuration. @@ -2316,26 +2675,32 @@ Signed-off-by: Ivo van Doorn + + /* + * Identify RF chipset. -+ * To determine the RT chip we have to read the -+ * PCI header of the device. + */ -+ pci_read_config_word(to_pci_dev(rt2x00dev->dev), -+ PCI_CONFIG_HEADER_DEVICE, &device); + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); + rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); -+ rt2x00_set_chip(rt2x00dev, device, value, reg); ++ rt2x00_set_chip_rf(rt2x00dev, value, reg); + + if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && + !rt2x00_rf(&rt2x00dev->chip, RF2850) && + !rt2x00_rf(&rt2x00dev->chip, RF2720) && + !rt2x00_rf(&rt2x00dev->chip, RF2750) && + !rt2x00_rf(&rt2x00dev->chip, RF3020) && -+ !rt2x00_rf(&rt2x00dev->chip, RF2020)) { ++ !rt2x00_rf(&rt2x00dev->chip, RF2020) && ++ !rt2x00_rf(&rt2x00dev->chip, RF3021) && ++ !rt2x00_rf(&rt2x00dev->chip, RF3022)) { + ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); + return -ENODEV; + } + + /* ++ * Identify default antenna configuration. ++ */ ++ rt2x00dev->default_ant.tx = ++ rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); ++ rt2x00dev->default_ant.rx = ++ rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); ++ ++ /* + * Read frequency offset and RF programming sequence. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); @@ -2410,8 +2775,8 @@ Signed-off-by: Ivo van Doorn + /* 802.11 HyperLan 2 */ + { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, + { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 }, -+ { 104, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed1a3 }, -+ { 108, 0x18402ecc, 0x184c0a32, 0x18578a55, 0x180ed193 }, ++ { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 }, ++ { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 }, + { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, + { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, + { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, @@ -2451,6 +2816,7 @@ Signed-off-by: Ivo van Doorn + char *tx_power1; + char *tx_power2; + unsigned int i; ++ u16 eeprom; + + /* + * Initialize all hw fields. @@ -2467,6 +2833,8 @@ Signed-off-by: Ivo van Doorn + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); + ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ + /* + * Initialize hw_mode information. + */ @@ -2474,7 +2842,9 @@ Signed-off-by: Ivo van Doorn + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; + + if (rt2x00_rf(&rt2x00dev->chip, RF2820) || -+ rt2x00_rf(&rt2x00dev->chip, RF2720)) { ++ rt2x00_rf(&rt2x00dev->chip, RF2720) || ++ 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) || @@ -2498,10 +2868,22 @@ Signed-off-by: Ivo van Doorn + IEEE80211_HT_CAP_PSMP_SUPPORT; + spec->ht.ampdu_factor = 3; + spec->ht.ampdu_density = 4; -+ spec->ht.mcs.rx_mask[0] = 0xff; -+ spec->ht.mcs.rx_mask[1] = 0xff; + spec->ht.mcs.tx_params = -+ IEEE80211_HT_MCS_TX_DEFINED; ++ IEEE80211_HT_MCS_TX_DEFINED | ++ IEEE80211_HT_MCS_TX_RX_DIFF | ++ ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << ++ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); ++ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { ++ case 3: ++ spec->ht.mcs.rx_mask[2] = 0xff; ++ case 2: ++ spec->ht.mcs.rx_mask[1] = 0xff; ++ case 1: ++ spec->ht.mcs.rx_mask[0] = 0xff; ++ spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ ++ break; ++ } + + /* + * Create channel information array @@ -2558,7 +2940,10 @@ Signed-off-by: Ivo van Doorn + /* + * 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); ++ __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + if (!modparam_nohwcrypt) + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + @@ -2573,6 +2958,21 @@ Signed-off-by: Ivo van Doorn +/* + * IEEE80211 stack callback functions. + */ ++static void rt2800pci_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, ++ u32 *iv32, u16 *iv16) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ struct mac_iveiv_entry iveiv_entry; ++ u32 offset; ++ ++ offset = MAC_IVEIV_ENTRY(hw_key_idx); ++ rt2x00pci_register_multiread(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); ++ ++ memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); ++ memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); ++} ++ +static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; @@ -2702,6 +3102,7 @@ Signed-off-by: Ivo van Doorn + .configure_filter = rt2x00mac_configure_filter, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, ++ .get_tkip_seq = rt2800pci_get_tkip_seq, + .set_rts_threshold = rt2800pci_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800pci_conf_tx, @@ -2741,14 +3142,14 @@ Signed-off-by: Ivo van Doorn + +static const struct data_queue_desc rt2800pci_queue_rx = { + .entry_num = RX_ENTRIES, -+ .data_size = DATA_FRAME_SIZE, ++ .data_size = AGGREGATION_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci), +}; + +static const struct data_queue_desc rt2800pci_queue_tx = { + .entry_num = TX_ENTRIES, -+ .data_size = DATA_FRAME_SIZE, ++ .data_size = AGGREGATION_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci), +}; @@ -2781,10 +3182,25 @@ Signed-off-by: Ivo van Doorn + * RT2800pci module information. + */ +static struct pci_device_id rt2800pci_device_table[] = { ++ /* Edimax */ ++ { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ /* Awt */ + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { 0, } +}; @@ -2793,10 +3209,33 @@ Signed-off-by: Ivo van Doorn +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); +MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -+MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); ++#ifdef CONFIG_RT2800PCI_PCI +MODULE_FIRMWARE(FIRMWARE_RT2860); ++MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); ++#endif /* CONFIG_RT2800PCI_PCI */ +MODULE_LICENSE("GPL"); + ++#ifdef CONFIG_RT2800PCI_WISOC ++#if defined(CONFIG_RALINK_RT288X) ++__rt2x00soc_probe(RT2880, &rt2800pci_ops); ++#elif defined(CONFIG_RALINK_RT305X) ++__rt2x00soc_probe(RT3052, &rt2800pci_ops); ++#endif ++ ++static struct platform_driver rt2800soc_driver = { ++ .driver = { ++ .name = "rt2800_wmac", ++ .owner = THIS_MODULE, ++ .mod_name = KBUILD_MODNAME, ++ }, ++ .probe = __rt2x00soc_probe, ++ .remove = __devexit_p(rt2x00soc_remove), ++ .suspend = rt2x00soc_suspend, ++ .resume = rt2x00soc_resume, ++}; ++#endif /* CONFIG_RT2800PCI_WISOC */ ++ ++#ifdef CONFIG_RT2800PCI_PCI +static struct pci_driver rt2800pci_driver = { + .name = KBUILD_MODNAME, + .id_table = rt2800pci_device_table, @@ -2805,22 +3244,45 @@ Signed-off-by: Ivo van Doorn + .suspend = rt2x00pci_suspend, + .resume = rt2x00pci_resume, +}; ++#endif /* CONFIG_RT2800PCI_PCI */ + +static int __init rt2800pci_init(void) +{ -+ return pci_register_driver(&rt2800pci_driver); ++ int ret = 0; ++ ++#ifdef CONFIG_RT2800PCI_WISOC ++ ret = platform_driver_register(&rt2800soc_driver); ++ if (ret) ++ return ret; ++#endif ++#ifdef CONFIG_RT2800PCI_PCI ++ ret = pci_register_driver(&rt2800pci_driver); ++ if (ret) { ++#ifdef CONFIG_RT2800PCI_WISOC ++ platform_driver_unregister(&rt2800soc_driver); ++#endif ++ return ret; ++ } ++#endif ++ ++ return ret; +} + +static void __exit rt2800pci_exit(void) +{ ++#ifdef CONFIG_RT2800PCI_PCI + pci_unregister_driver(&rt2800pci_driver); ++#endif ++#ifdef CONFIG_RT2800PCI_WISOC ++ platform_driver_unregister(&rt2800soc_driver); ++#endif +} + +module_init(rt2800pci_init); +module_exit(rt2800pci_exit); --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.h -@@ -0,0 +1,1877 @@ +@@ -0,0 +1,1927 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + @@ -2859,6 +3321,8 @@ Signed-off-by: Ivo van Doorn + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G ++ * RF3021 2.4G 1T2R ++ * RF3022 2.4G 2T2R + */ +#define RF2820 0x0001 +#define RF2850 0x0002 @@ -2866,6 +3330,8 @@ Signed-off-by: Ivo van Doorn +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 ++#define RF3021 0x0007 ++#define RF3022 0x0008 + +/* + * RT2860 version @@ -2891,8 +3357,8 @@ Signed-off-by: Ivo van Doorn +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 -+#define RF_BASE 0x0000 -+#define RF_SIZE 0x0014 ++#define RF_BASE 0x0004 ++#define RF_SIZE 0x0010 + +/* + * Number of TX queues. @@ -2904,12 +3370,6 @@ Signed-off-by: Ivo van Doorn + */ + +/* -+ * PCI Configuration Header -+ */ -+#define PCI_CONFIG_HEADER_VENDOR 0x0000 -+#define PCI_CONFIG_HEADER_DEVICE 0x0002 -+ -+/* + * E2PROM_CSR: EEPROM control register. + * RELOAD: Write 1 to reload eeprom content. + * TYPE: 0: 93c46, 1:93c66. @@ -3073,11 +3533,6 @@ Signed-off-by: Ivo van Doorn +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* -+ * RINGREG_DIFF -+ */ -+#define RINGREG_DIFF 0x0010 -+ -+/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 @@ -3170,7 +3625,7 @@ Signed-off-by: Ivo van Doorn +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* -+ * PBF registers ++ * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 @@ -3198,13 +3653,22 @@ Signed-off-by: Ivo van Doorn +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* -+ * PBF registers ++ * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 +#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. + */ @@ -3619,6 +4083,7 @@ Signed-off-by: Ivo van Doorn + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c ++#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + @@ -4154,12 +4619,6 @@ Signed-off-by: Ivo van Doorn +} __attribute__ ((packed)); + +/* -+ * MAC_IVEIV: -+ */ -+#define MAC_IVEIV_EIV FIELD32(0x20000000) -+#define MAC_IVEIV_KEYIDX FIELD32(0xc0000000) -+ -+/* + * MAC_WCID_ATTRIBUTE: + */ +#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) @@ -4196,6 +4655,10 @@ Signed-off-by: Ivo van Doorn + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 ++#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) ++#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) ++#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) ++#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) + +/* + * H2M_MAILBOX_STATUS: @@ -4298,6 +4761,48 @@ Signed-off-by: Ivo van Doorn + * 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 @@ -4324,7 +4829,7 @@ Signed-off-by: Ivo van Doorn +#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) +#define RF4_TXPOWER_A FIELD32(0x00000780) +#define RF4_FREQ_OFFSET FIELD32(0x001f8000) -+#define RF4_BW40 FIELD32(0x00200000) ++#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. @@ -4458,7 +4963,7 @@ Signed-off-by: Ivo van Doorn +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* -+ * EEPROM TXPOWER 802.11G ++ * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 @@ -4493,6 +4998,7 @@ Signed-off-by: Ivo van Doorn + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 ++#define MCU_RADIO_OFF 0x35 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 @@ -4500,6 +5006,12 @@ Signed-off-by: Ivo van Doorn +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 ++#define MCU_BBP_SIGNAL 0x80 ++ ++/* ++ * MCU mailbox tokens ++ */ ++#define TOKEN_WAKUP 3 + +/* + * DMA descriptor defines. @@ -4700,7 +5212,7 @@ Signed-off-by: Ivo van Doorn +#endif /* RT2800PCI_H */ --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -138,6 +138,10 @@ struct rt2x00_chip { +@@ -147,6 +147,12 @@ struct rt2x00_chip { #define RT2561 0x0302 #define RT2661 0x0401 #define RT2571 0x1300 @@ -4708,6 +5220,8 @@ Signed-off-by: Ivo van Doorn +#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ +#define RT2890 0x0701 /* 2.4GHz PCIe */ +#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ ++#define RT2880 0x2880 /* WSOC */ ++#define RT3052 0x3052 /* WSOC */ + #define RT2870 0x1600 u16 rf; - u32 rev;