mac80211: rt2x00: add support for the RT3662/RT3883 SoCs

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

SVN-Revision: 40558
This commit is contained in:
John Crispin 2014-04-23 07:52:18 +00:00
parent 720a0a1df1
commit 8be12510c9
34 changed files with 2430 additions and 0 deletions

View file

@ -0,0 +1,62 @@
From 7a69da907de668fb22a30ae218062d6f081864ea Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sat, 17 Aug 2013 19:31:41 +0200
Subject: [PATCH] rt2x00: rt2800lib: move rt2800_drv_data declaration into
rt2800lib.h
The rt2800_drv_data structure contains driver specific
information. Move the declaration into the rt2800lib.h
header which is a more logical place for it. Also fix
the comment style to avoid checkpatch warning.
The patch contains no functional changes, it is in
preparation for the next patch.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
drivers/net/wireless/rt2x00/rt2800.h | 13 -------------
drivers/net/wireless/rt2x00/rt2800lib.h | 11 +++++++++++
2 files changed, 11 insertions(+), 13 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2958,17 +2958,4 @@ enum rt2800_eeprom_word {
*/
#define BCN_TBTT_OFFSET 64
-/*
- * RT2800 driver data structure
- */
-struct rt2800_drv_data {
- u8 calibration_bw20;
- u8 calibration_bw40;
- u8 bbp25;
- u8 bbp26;
- u8 txmixer_gain_24g;
- u8 txmixer_gain_5g;
- unsigned int tbtt_tick;
-};
-
#endif /* RT2800_H */
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -20,6 +20,17 @@
#ifndef RT2800LIB_H
#define RT2800LIB_H
+/* RT2800 driver data structure */
+struct rt2800_drv_data {
+ u8 calibration_bw20;
+ u8 calibration_bw40;
+ u8 bbp25;
+ u8 bbp26;
+ u8 txmixer_gain_24g;
+ u8 txmixer_gain_5g;
+ unsigned int tbtt_tick;
+};
+
struct rt2800_ops {
void (*register_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 *value);

View file

@ -0,0 +1,80 @@
From a7f268af31dddf763fe3dbe9cbf96ea77e0540e0 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sat, 17 Aug 2013 19:31:41 +0200
Subject: [PATCH] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
Some chipsets have more than 16KB of shared memory.
Introduce a new rt2800 specific flag to indicate that
and add a helper function which helps to check the
presence of the new flag.
Also enable the new flag for the RT3593 chipset which
has 24KB of shared memory. The flag can also be used
for other chipsets, but none of those has been tested
yet.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1:
- don't enable the new flag for RT3071 and RT5592
---
drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++++
drivers/net/wireless/rt2x00/rt2800lib.h | 13 +++++++++++++
2 files changed, 17 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7712,6 +7712,7 @@ static int rt2800_probe_rt(struct rt2x00
int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
int retval;
u32 reg;
@@ -7719,6 +7720,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
if (retval)
return retval;
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
/*
* Allocate eeprom data.
*/
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -20,6 +20,10 @@
#ifndef RT2800LIB_H
#define RT2800LIB_H
+enum rt2800_flag {
+ RT2800_HAS_HIGH_SHARED_MEM,
+};
+
/* RT2800 driver data structure */
struct rt2800_drv_data {
u8 calibration_bw20;
@@ -29,6 +33,8 @@ struct rt2800_drv_data {
u8 txmixer_gain_24g;
u8 txmixer_gain_5g;
unsigned int tbtt_tick;
+
+ unsigned long rt2800_flags;
};
struct rt2800_ops {
@@ -61,6 +67,13 @@ struct rt2800_ops {
__le32 *(*drv_get_txwi)(struct queue_entry *entry);
};
+static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+}
+
static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 *value)

View file

@ -0,0 +1,531 @@
From 250a1b520cd7fdc0df4fc3fedea9066913f49ecf Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sat, 17 Aug 2013 19:31:42 +0200
Subject: [PATCH] rt2x00: rt2800: serialize shared memory access
The shared memory of the rt2800 devices is accessible
through the register offset range between 0x4000 and
0x8000. The size of this range is 16KB only and on
devices which have more than 16KB of shared memory either
the low or the high part of the memory is accessible at a
time.
Serialize all accesses to the shared memory by a mutex,
in order to avoid concurrent use of that.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
drivers/net/wireless/rt2x00/rt2800lib.c | 55 +++++++++++++++++++++++++++++-
drivers/net/wireless/rt2x00/rt2800lib.h | 32 +++++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.c | 26 ++++++++++++++
drivers/net/wireless/rt2x00/rt2800mmio.h | 4 +++
drivers/net/wireless/rt2x00/rt2800pci.c | 14 ++++++++
drivers/net/wireless/rt2x00/rt2800soc.c | 3 ++
drivers/net/wireless/rt2x00/rt2800usb.c | 31 +++++++++++++++++
7 files changed, 164 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_de
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
reg = 0;
rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
+ rt2800_shared_mem_unlock(rt2x00dev);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_d
* Wait for device to stabilize.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2800_shared_mem_unlock(rt2x00dev);
if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
break;
msleep(1);
@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_d
/*
* Initialize firmware.
*/
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
+
if (rt2x00_is_usb(rt2x00dev)) {
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
+
rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
}
msleep(1);
@@ -1001,8 +1011,10 @@ void rt2800_write_beacon(struct queue_en
beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
+ rt2800_shared_mem_unlock(rt2x00dev);
/*
* Enable beaconing again.
@@ -1027,6 +1039,8 @@ static inline void rt2800_clear_beacon_r
beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
+ rt2800_shared_mem_lock(rt2x00dev);
+
/*
* For the Beacon base registers we only need to clear
* the whole TXWI which (when set to 0) will invalidate
@@ -1034,6 +1048,8 @@ static inline void rt2800_clear_beacon_r
*/
for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+
+ rt2800_shared_mem_unlock(rt2x00dev);
}
void rt2800_clear_beacon(struct queue_entry *entry)
@@ -1217,7 +1233,9 @@ static void rt2800_delete_wcid_attr(stru
{
u32 offset;
offset = MAC_WCID_ATTR_ENTRY(wcid);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, offset, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
}
static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
@@ -1230,11 +1248,13 @@ static void rt2800_config_wcid_attr_bssi
* The BSS Idx numbers is split in a main value of 3 bits,
* and a extended field for adding one additional bit to the value.
*/
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(bssidx & 0x8) >> 3);
rt2800_register_write(rt2x00dev, offset, reg);
+ rt2800_shared_mem_unlock(rt2x00dev);
}
static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
@@ -1247,6 +1267,7 @@ static void rt2800_config_wcid_attr_ciph
offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
+ rt2800_shared_mem_lock(rt2x00dev);
if (crypto->cmd == SET_KEY) {
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
@@ -1271,6 +1292,7 @@ static void rt2800_config_wcid_attr_ciph
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
rt2800_register_write(rt2x00dev, offset, reg);
}
+ rt2800_shared_mem_unlock(rt2x00dev);
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
@@ -1280,8 +1302,11 @@ static void rt2800_config_wcid_attr_ciph
(crypto->cipher == CIPHER_AES))
iveiv_entry.iv[3] |= 0x20;
iveiv_entry.iv[3] |= key->keyidx << 6;
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));
+ rt2800_shared_mem_unlock(rt2x00dev);
}
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1304,8 +1329,11 @@ int rt2800_config_shared_key(struct rt2x
sizeof(key_entry.rx_mic));
offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_multiwrite(rt2x00dev, offset,
&key_entry, sizeof(key_entry));
+ rt2800_shared_mem_unlock(rt2x00dev);
}
/*
@@ -1320,10 +1348,12 @@ int rt2800_config_shared_key(struct rt2x
offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, field,
(crypto->cmd == SET_KEY) * crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg);
+ rt2800_shared_mem_unlock(rt2x00dev);
/*
* Update WCID information
@@ -1393,8 +1423,11 @@ int rt2800_config_pairwise_key(struct rt
sizeof(key_entry.rx_mic));
offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_multiwrite(rt2x00dev, offset,
&key_entry, sizeof(key_entry));
+ rt2800_shared_mem_unlock(rt2x00dev);
}
/*
@@ -4876,14 +4909,19 @@ static int rt2800_init_registers(struct
/*
* ASIC will keep garbage value after boot, clear encryption keys.
*/
+ rt2800_shared_mem_lock(rt2x00dev);
for (i = 0; i < 4; i++)
rt2800_register_write(rt2x00dev,
SHARED_KEY_MODE_ENTRY(i), 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
for (i = 0; i < 256; i++) {
rt2800_config_wcid(rt2x00dev, NULL, i);
rt2800_delete_wcid_attr(rt2x00dev, i);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
}
/*
@@ -5009,8 +5047,10 @@ static int rt2800_wait_bbp_ready(struct
* BBP was enabled after firmware was loaded,
* but we need to reactivate it now.
*/
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
msleep(1);
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
@@ -6706,11 +6746,19 @@ int rt2800_enable_radio(struct rt2x00_de
/*
* Send signal during boot time to initialize firmware.
*/
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- if (rt2x00_is_usb(rt2x00dev))
+ rt2800_shared_mem_unlock(rt2x00dev);
+
+ if (rt2x00_is_usb(rt2x00dev)) {
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+
msleep(1);
/*
@@ -7716,6 +7764,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
int retval;
u32 reg;
+ rt2800_shared_mem_init_lock(rt2x00dev);
+
retval = rt2800_probe_rt(rt2x00dev);
if (retval)
return retval;
@@ -7795,8 +7845,11 @@ void rt2800_get_tkip_seq(struct ieee8021
u32 offset;
offset = MAC_IVEIV_ENTRY(hw_key_idx);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2800_register_multiread(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));
+ rt2800_shared_mem_unlock(rt2x00dev);
memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -35,6 +35,11 @@ struct rt2800_drv_data {
unsigned int tbtt_tick;
unsigned long rt2800_flags;
+
+ union {
+ spinlock_t spin;
+ struct mutex mutex;
+ } shmem_lock;
};
struct rt2800_ops {
@@ -65,6 +70,10 @@ struct rt2800_ops {
const u8 *data, const size_t len);
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+
+ void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev);
+ void (*shmem_lock)(struct rt2x00_dev *rt2x00dev);
+ void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev);
};
static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
@@ -74,6 +83,29 @@ static inline bool rt2800_has_high_share
return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
}
+static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+ rt2800ops->shmem_init_lock(rt2x00dev);
+}
+
+static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev)
+{
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+ if (rt2800_has_high_shared_mem(rt2x00dev))
+ rt2800ops->shmem_lock(rt2x00dev);
+}
+
+static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+ if (rt2800_has_high_shared_mem(rt2x00dev))
+ rt2800ops->shmem_unlock(rt2x00dev);
+}
+
static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 *value)
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2800_shared_mem_unlock(rt2x00dev);
if (rt2x00_is_pcie(rt2x00dev) &&
(rt2x00_rt(rt2x00dev, RT3090) ||
@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x0
}
EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ spin_lock_init(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock);
+
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ spin_lock_bh(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock);
+
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ spin_unlock_bh(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock);
+
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("rt2800 MMIO library");
--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2
/* Device state switch handlers. */
int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev);
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev);
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev);
+
#endif /* RT2800MMIO_H */
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct
return;
for (i = 0; i < 200; i++) {
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ rt2800_shared_mem_unlock(rt2x00dev);
if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct
if (i == 200)
rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2800_shared_mem_unlock(rt2x00dev);
}
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(stru
*/
reg = 0;
rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
/*
@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(stru
rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
return 0;
}
@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct
return retval;
/* After resume MCU_BOOT_SIGNAL will trash these. */
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2800_shared_mem_unlock(rt2x00dev);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt
0, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
} else if (state == STATE_SLEEP) {
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
0xffffffff);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
0xffffffff);
+ rt2800_shared_mem_unlock(rt2x00dev);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
0xff, 0x01);
}
@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci
.drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
+ .shmem_init_lock = rt2800mmio_shmem_init_lock,
+ .shmem_lock = rt2800mmio_shmem_lock,
+ .shmem_unlock = rt2800mmio_shmem_unlock,
};
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc
.drv_write_firmware = rt2800soc_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
+ .shmem_init_lock = rt2800mmio_shmem_init_lock,
+ .shmem_lock = rt2800mmio_shmem_lock,
+ .shmem_unlock = rt2800mmio_shmem_unlock,
};
static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(s
return modparam_nohwcrypt;
}
+static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ mutex_init(&drv_data->shmem_lock.mutex);
+}
+
+static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ mutex_lock(&drv_data->shmem_lock.mutex);
+}
+
+static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+ mutex_unlock(&drv_data->shmem_lock.mutex);
+}
+
/*
* Queue handlers.
*/
@@ -260,8 +281,10 @@ static int rt2800usb_write_firmware(stru
rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
data + offset, length);
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2800_shared_mem_unlock(rt2x00dev);
/*
* Send firmware request to device to load firmware,
@@ -276,7 +299,10 @@ static int rt2800usb_write_firmware(stru
}
msleep(10);
+
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_shared_mem_unlock(rt2x00dev);
return 0;
}
@@ -294,8 +320,10 @@ static int rt2800usb_init_registers(stru
if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;
+ rt2800_shared_mem_lock(rt2x00dev);
rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+ rt2800_shared_mem_unlock(rt2x00dev);
reg = 0;
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
@@ -810,6 +838,9 @@ static const struct rt2800_ops rt2800usb
.drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers,
.drv_get_txwi = rt2800usb_get_txwi,
+ .shmem_init_lock = rt2800usb_shmem_init_lock,
+ .shmem_lock = rt2800usb_shmem_lock,
+ .shmem_unlock = rt2800usb_shmem_unlock,
};
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {

View file

@ -0,0 +1,131 @@
From dcfe3dd46242050f100162dce2bcad24d2c942c6 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sat, 17 Aug 2013 19:31:42 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix beacon generation on RT3593
On the RT3593 chipset, the beacon registers are located
in the high 8KB part of the shared memory.
The high part of the shared memory is only accessible
if it is explicitly selected. Add a helper function
in order to be able to control the SHR_MSEL bit in
the PBF_SYS_CTRL register. Also add a few more helper
functions and use those to select the correct part of
the shared memory before and after accessing the beacon
registers.
The base addresses of the beacon registers are also
different from the actually used values, so fix the
'rt2800_hw_beacon_base' function to return the correct
values.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
drivers/net/wireless/rt2x00/rt2800.h | 3 +++
drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -572,6 +572,7 @@
#define PBF_SYS_CTRL 0x0400
#define PBF_SYS_CTRL_READY FIELD32(0x00000080)
#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
+#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000)
/*
* HOST-MCU shared memory
@@ -2024,6 +2025,8 @@ struct mac_iveiv_entry {
(((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
(HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
+#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512)
+
#define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64)
/*
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st
return false;
}
+static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev,
+ bool high)
+{
+ u32 reg;
+
+ if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev)))
+ return;
+
+ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2x00_set_field32(&reg, PBF_SYS_CTRL_SHR_MSEL, high);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+}
+
+static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
+{
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return true;
+
+ return false;
+}
+
+static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+ if (rt2800_beacon_uses_high_mem(rt2x00dev))
+ rt2800_shared_mem_select(rt2x00dev, true);
+}
+
+static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+ if (rt2800_beacon_uses_high_mem(rt2x00dev))
+ rt2800_shared_mem_select(rt2x00dev, false);
+}
+
static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
unsigned int index)
{
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return HW_BEACON_BASE_HIGH(index);
+
return HW_BEACON_BASE(index);
}
@@ -1012,8 +1048,12 @@ void rt2800_write_beacon(struct queue_en
beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
rt2800_shared_mem_lock(rt2x00dev);
+
+ rt2800_select_beacon_mem(rt2x00dev);
rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
+ rt2800_deselect_beacon_mem(rt2x00dev);
+
rt2800_shared_mem_unlock(rt2x00dev);
/*
@@ -1041,6 +1081,8 @@ static inline void rt2800_clear_beacon_r
rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_select_beacon_mem(rt2x00dev);
+
/*
* For the Beacon base registers we only need to clear
* the whole TXWI which (when set to 0) will invalidate
@@ -1049,6 +1091,8 @@ static inline void rt2800_clear_beacon_r
for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+ rt2800_deselect_beacon_mem(rt2x00dev);
+
rt2800_shared_mem_unlock(rt2x00dev);
}

View file

@ -0,0 +1,62 @@
From a058825fa7b53fab3b003d8928b60e5b686b3421 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 4 Aug 2013 14:36:11 +0200
Subject: [PATCH] rt2x00: rt2800lib: add hw_beacon_count field to struct
rt2800_drv_data
Some chipsets can handle more than 8 beacons at once.
Add a new field to the rt2800_drv_data structure which
will hold the number of supported beacons of the given
chipset.
Update the rt2x00_init_registers function to get the
beacon count from the new field instead of using a
hardcoded value.
In order to keep the current behaviour, initialize the
new field with the actually used value.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++-
drivers/net/wireless/rt2x00/rt2800lib.h | 1 +
2 files changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4584,6 +4584,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
*/
static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
u32 reg;
u16 eeprom;
unsigned int i;
@@ -4971,7 +4972,7 @@ static int rt2800_init_registers(struct
/*
* Clear all beacons
*/
- for (i = 0; i < 8; i++)
+ for (i = 0; i < drv_data->hw_beacon_count; i++)
rt2800_clear_beacon_register(rt2x00dev, i);
if (rt2x00_is_usb(rt2x00dev)) {
@@ -7817,6 +7818,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
if (rt2x00_rt(rt2x00dev, RT3593))
__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+ drv_data->hw_beacon_count = 8;
+
/*
* Allocate eeprom data.
*/
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -33,6 +33,7 @@ struct rt2800_drv_data {
u8 txmixer_gain_24g;
u8 txmixer_gain_5g;
unsigned int tbtt_tick;
+ unsigned int hw_beacon_count;
unsigned long rt2800_flags;

View file

@ -0,0 +1,67 @@
From 1bfa43ca8f30be53ce4fa79cfc3e219642a812b6 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 2 Sep 2013 10:58:32 +0200
Subject: [PATCH] rt2x00: rt2800lib: init additional beacon offset registers
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++
drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++
2 files changed, 38 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -627,6 +627,20 @@
*/
#define PBF_DBG 0x043c
+/* BCN_OFFSET2 */
+#define BCN_OFFSET2 0x0444
+#define BCN_OFFSET2_BCN8 FIELD32(0x000000ff)
+#define BCN_OFFSET2_BCN9 FIELD32(0x0000ff00)
+#define BCN_OFFSET2_BCN10 FIELD32(0x00ff0000)
+#define BCN_OFFSET2_BCN11 FIELD32(0xff000000)
+
+/* BCN_OFFSET3 */
+#define BCN_OFFSET3 0x0448
+#define BCN_OFFSET3_BCN12 FIELD32(0x000000ff)
+#define BCN_OFFSET3_BCN13 FIELD32(0x0000ff00)
+#define BCN_OFFSET3_BCN14 FIELD32(0x00ff0000)
+#define BCN_OFFSET3_BCN15 FIELD32(0xff000000)
+
/*
* RF registers
*/
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4618,6 +4618,30 @@ static int rt2800_init_registers(struct
rt2800_get_beacon_offset(rt2x00dev, 7));
rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
+ if (drv_data->hw_beacon_count == 16) {
+ rt2800_register_read(rt2x00dev, BCN_OFFSET2, &reg);
+ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN8,
+ rt2800_get_beacon_offset(rt2x00dev, 8));
+ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN9,
+ rt2800_get_beacon_offset(rt2x00dev, 9));
+ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN10,
+ rt2800_get_beacon_offset(rt2x00dev, 10));
+ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN11,
+ rt2800_get_beacon_offset(rt2x00dev, 11));
+ rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg);
+
+ rt2800_register_read(rt2x00dev, BCN_OFFSET3, &reg);
+ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN12,
+ rt2800_get_beacon_offset(rt2x00dev, 12));
+ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN13,
+ rt2800_get_beacon_offset(rt2x00dev, 13));
+ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN14,
+ rt2800_get_beacon_offset(rt2x00dev, 14));
+ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN15,
+ rt2800_get_beacon_offset(rt2x00dev, 15));
+ rt2800_register_write(rt2x00dev, BCN_OFFSET3, reg);
+ }
+
rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);

View file

@ -0,0 +1,24 @@
From 9bea8b61f6025cd633bd5ac71be258620b49bcb3 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 2 Sep 2013 11:00:06 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix max supported beacon count for RT3593
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7842,7 +7842,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
if (rt2x00_rt(rt2x00dev, RT3593))
__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
- drv_data->hw_beacon_count = 8;
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ drv_data->hw_beacon_count = 16;
+ else
+ drv_data->hw_beacon_count = 8;
/*
* Allocate eeprom data.

View file

@ -0,0 +1,30 @@
From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:26 +0100
Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -210,7 +210,7 @@ endif
config RT2800SOC
tristate "Ralink WiSoC support"
depends on m
- depends on SOC_RT288X || SOC_RT305X
+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
select RT2X00_LIB_SOC
select RT2X00_LIB_MMIO
select RT2X00_LIB_CRYPTO
@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI
config RT2X00_LIB_SOC
tristate "RT2x00 SoC support"
- depends on SOC_RT288X || SOC_RT305X
+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
depends on m
select RT2X00_LIB

View file

@ -0,0 +1,20 @@
From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:26 +0100
Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7812,6 +7812,7 @@ static int rt2800_probe_rt(struct rt2x00
case RT3390:
case RT3572:
case RT3593:
+ case RT3883:
case RT5390:
case RT5392:
case RT5592:

View file

@ -0,0 +1,112 @@
From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:26 +0100
Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 4 +-
drivers/net/wireless/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -48,7 +48,8 @@
* RF2853 2.4G/5G 3T3R
* RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
* RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
+ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593)
+ * RF3853 2.4G/5G 3T3R(RT3883/RT3662)
* RF5592 2.4G/5G 2T2R
* RF3070 2.4G 1T1R
* RF5360 2.4G 1T1R
@@ -71,6 +72,7 @@
#define RF5592 0x000f
#define RF3070 0x3070
#define RF3290 0x3290
+#define RF3853 0x3853
#define RF5360 0x5360
#define RF5370 0x5370
#define RF5372 0x5372
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7432,6 +7432,66 @@ static const struct rf_channel rf_vals_3
{173, 0x61, 0, 9},
};
+static const struct rf_channel rf_vals_3853[] = {
+ {1, 241, 6, 2},
+ {2, 241, 6, 7},
+ {3, 242, 6, 2},
+ {4, 242, 6, 7},
+ {5, 243, 6, 2},
+ {6, 243, 6, 7},
+ {7, 244, 6, 2},
+ {8, 244, 6, 7},
+ {9, 245, 6, 2},
+ {10, 245, 6, 7},
+ {11, 246, 6, 2},
+ {12, 246, 6, 7},
+ {13, 247, 6, 2},
+ {14, 248, 6, 4},
+
+ {36, 0x56, 8, 4},
+ {38, 0x56, 8, 6},
+ {40, 0x56, 8, 8},
+ {44, 0x57, 8, 0},
+ {46, 0x57, 8, 2},
+ {48, 0x57, 8, 4},
+ {52, 0x57, 8, 8},
+ {54, 0x57, 8, 10},
+ {56, 0x58, 8, 0},
+ {60, 0x58, 8, 4},
+ {62, 0x58, 8, 6},
+ {64, 0x58, 8, 8},
+
+ {100, 0x5b, 8, 8},
+ {102, 0x5b, 8, 10},
+ {104, 0x5c, 8, 0},
+ {108, 0x5c, 8, 4},
+ {110, 0x5c, 8, 6},
+ {112, 0x5c, 8, 8},
+ {114, 0x5c, 8, 10},
+ {116, 0x5d, 8, 0},
+ {118, 0x5d, 8, 2},
+ {120, 0x5d, 8, 4},
+ {124, 0x5d, 8, 8},
+ {126, 0x5d, 8, 10},
+ {128, 0x5e, 8, 0},
+ {132, 0x5e, 8, 4},
+ {134, 0x5e, 8, 6},
+ {136, 0x5e, 8, 8},
+ {140, 0x5f, 8, 0},
+
+ {149, 0x5f, 8, 9},
+ {151, 0x5f, 8, 11},
+ {153, 0x60, 8, 1},
+ {157, 0x60, 8, 5},
+ {159, 0x60, 8, 7},
+ {161, 0x60, 8, 9},
+ {165, 0x61, 8, 1},
+ {167, 0x61, 8, 3},
+ {169, 0x61, 8, 5},
+ {171, 0x61, 8, 7},
+ {173, 0x61, 8, 9},
+};
+
static const struct rf_channel rf_vals_5592_xtal20[] = {
/* Channel, N, K, mod, R */
{1, 482, 4, 10, 3},
@@ -7660,6 +7720,11 @@ static int rt2800_probe_hw_mode(struct r
spec->channels = rf_vals_3x;
break;
+ case RF3853:
+ spec->num_channels = ARRAY_SIZE(rf_vals_3853);
+ spec->channels = rf_vals_3853;
+ break;
+
case RF5592:
rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {

View file

@ -0,0 +1,28 @@
From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 1 Aug 2013 14:40:44 +0200
Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4349,6 +4349,7 @@ void rt2800_vco_calibration(struct rt2x0
case RF3053:
case RF3070:
case RF3290:
+ case RF3853:
case RF5360:
case RF5370:
case RF5372:
@@ -7839,6 +7840,7 @@ static int rt2800_probe_hw_mode(struct r
case RF3053:
case RF3070:
case RF3290:
+ case RF3853:
case RF5360:
case RF5370:
case RF5372:

View file

@ -0,0 +1,235 @@
From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:27 +0100
Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for
RF3853
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++
1 file changed, 208 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2605,6 +2605,211 @@ static void rt2800_config_channel_rf3053
}
}
+static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+ u8 bbp;
+ u8 pwr1, pwr2, pwr3;
+
+ const bool txbf_enabled = false; /* TODO */
+
+ /* TODO: add band selection */
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+ else if (rf->channel < 132)
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+
+ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
+
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+ switch (rt2x00dev->default_ant.tx_chain_num) {
+ case 3:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ /* fallthrough */
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ /* fallthrough */
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+ break;
+ }
+
+ switch (rt2x00dev->default_ant.rx_chain_num) {
+ case 3:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ /* fallthrough */
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ /* fallthrough */
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+ break;
+ }
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_adjust_freq_offset(rt2x00dev);
+
+ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ if (!conf_is_ht40(conf))
+ rfcsr &= ~(0x06);
+ else
+ rfcsr |= 0x06;
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+
+ if (conf_is_ht40(conf))
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
+
+ /* loopback RF_BS */
+ rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
+ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
+
+ if (rf->channel <= 14)
+ rfcsr = 0x23;
+ else if (rf->channel < 100)
+ rfcsr = 0x36;
+ else if (rf->channel < 132)
+ rfcsr = 0x32;
+ else
+ rfcsr = 0x30;
+
+ if (txbf_enabled)
+ rfcsr |= 0x40;
+
+ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
+
+ if (rf->channel <= 14)
+ rfcsr = 0xbb;
+ else if (rf->channel < 100)
+ rfcsr = 0xeb;
+ else if (rf->channel < 132)
+ rfcsr = 0xb3;
+ else
+ rfcsr = 0x9b;
+ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
+
+ if (rf->channel <= 14)
+ rfcsr = 0x8e;
+ else
+ rfcsr = 0x8a;
+
+ if (txbf_enabled)
+ rfcsr |= 0x20;
+
+ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
+
+ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
+
+ rt2800_rfcsr_read(rt2x00dev, 52, &rfcsr);
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+
+ if (rf->channel <= 14) {
+ pwr1 = info->default_power1 & 0x1f;
+ pwr2 = info->default_power2 & 0x1f;
+ pwr3 = info->default_power3 & 0x1f;
+ } else {
+ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
+ (info->default_power1 & 0x7);
+ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
+ (info->default_power2 & 0x7);
+ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
+ (info->default_power3 & 0x7);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
+ rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
+ rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
+
+ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
+ rf->channel, pwr1, pwr2, pwr3);
+
+ bbp = (info->default_power1 >> 5) |
+ ((info->default_power2 & 0xe0) >> 1);
+ rt2800_bbp_write(rt2x00dev, 109, bbp);
+
+ rt2800_bbp_read(rt2x00dev, 110, &bbp);
+ bbp &= 0x0f;
+ bbp |= (info->default_power3 & 0xe0) >> 1;
+ rt2800_bbp_write(rt2x00dev, 110, bbp);
+
+ rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+ if (rf->channel <= 14)
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
+ else
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
+
+ /* Enable RF tuning */
+ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+ udelay(2000);
+
+ rt2800_bbp_read(rt2x00dev, 49, &bbp);
+ /* clear update flag */
+ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
+ rt2800_bbp_write(rt2x00dev, 49, bbp);
+
+ /* TODO: add calibration for TxBF */
+}
+
#define POWER_BOUND 0x27
#define POWER_BOUND_5G 0x2b
@@ -3217,6 +3422,9 @@ static void rt2800_config_channel(struct
case RF3322:
rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
break;
+ case RF3853:
+ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
+ break;
case RF3070:
case RF5360:
case RF5370:

View file

@ -0,0 +1,20 @@
From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 1 Aug 2013 14:42:05 +0200
Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7398,6 +7398,7 @@ static int rt2800_init_eeprom(struct rt2
case RF3290:
case RF3320:
case RF3322:
+ case RF3853:
case RF5360:
case RF5370:
case RF5372:

View file

@ -0,0 +1,77 @@
From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:26 +0100
Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for
RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++
drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++---
2 files changed, 30 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1586,6 +1586,20 @@
#define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00)
/*
+ * TX_TXBF_CFG:
+ */
+#define TX_TXBF_CFG_0 0x138c
+#define TX_TXBF_CFG_1 0x13a4
+#define TX_TXBF_CFG_2 0x13a8
+#define TX_TXBF_CFG_3 0x13ac
+
+/*
+ * TX_FBK_CFG_3S:
+ */
+#define TX_FBK_CFG_3S_0 0x13c4
+#define TX_FBK_CFG_3S_1 0x13c8
+
+/*
* RX_FILTER_CFG: RX configuration register.
*/
#define RX_FILTER_CFG 0x1400
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4973,6 +4973,12 @@ static int rt2800_init_registers(struct
rt2800_register_write(rt2x00dev, TX_SW_CFG2,
0x00000000);
}
+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
rt2x00_rt(rt2x00dev, RT5592)) {
@@ -5003,9 +5009,11 @@ static int rt2800_init_registers(struct
rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
- if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
- rt2x00_rt(rt2x00dev, RT2883) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
+ if (rt2x00_rt(rt2x00dev, RT3883))
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 3);
+ else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
+ rt2x00_rt(rt2x00dev, RT2883) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
else
rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
@@ -5158,6 +5166,11 @@ static int rt2800_init_registers(struct
reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
+ if (rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
+ }
+
rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,

View file

@ -0,0 +1,30 @@
From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:27 +0100
Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800soc.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s
static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
{
+ u32 reg;
+
rt2800_disable_radio(rt2x00dev);
rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
+
+ reg = 0;
+ if (rt2x00_rt(rt2x00dev, RT3883))
+ rt2x00_set_field32(&reg, TX_PIN_CFG_RFTR_EN, 1);
+
+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
}
static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,

View file

@ -0,0 +1,71 @@
From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:26 +0100
Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for
RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -5776,6 +5776,47 @@ static void rt2800_init_bbp_3593(struct
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
}
+static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev)
+{
+ rt2800_init_bbp_early(rt2x00dev);
+
+ rt2800_bbp_write(rt2x00dev, 4, 0x50);
+ rt2800_bbp_write(rt2x00dev, 47, 0x48);
+
+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
+ rt2800_bbp_write(rt2x00dev, 88, 0x90);
+
+ rt2800_bbp_write(rt2x00dev, 92, 0x02);
+
+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+ rt2800_bbp_write(rt2x00dev, 104, 0x92);
+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
+ rt2800_bbp_write(rt2x00dev, 106, 0x12);
+ rt2800_bbp_write(rt2x00dev, 120, 0x50);
+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
+
+ /* Set ITxBF timeout to 0x9C40=1000msec */
+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
+
+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
+
+ /* Reprogram the inband interface to put right values in RXWI */
+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+}
+
static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
{
int ant, div_mode;
@@ -5994,6 +6035,9 @@ static void rt2800_init_bbp(struct rt2x0
case RT3593:
rt2800_init_bbp_3593(rt2x00dev);
return;
+ case RT3883:
+ rt2800_init_bbp_3883(rt2x00dev);
+ return;
case RT5390:
case RT5392:
rt2800_init_bbp_53xx(rt2x00dev);

View file

@ -0,0 +1,178 @@
From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 29 Apr 2013 13:21:48 +0200
Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800.h | 1 +
drivers/net/wireless/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2169,6 +2169,7 @@ struct mac_iveiv_entry {
/*
* RFCSR 2:
*/
+#define RFCSR2_RESCAL_BP FIELD8(0x40)
#define RFCSR2_RESCAL_EN FIELD8(0x80)
/*
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -6811,6 +6811,144 @@ static void rt2800_init_rfcsr_3593(struc
/* TODO: enable stream mode support */
}
+static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev)
+{
+ u8 rfcsr;
+
+ /* TODO: get the actual ECO value from the SoC */
+ const unsigned int eco = 5;
+
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
+ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0);
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x08);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+
+ /* RFCSR 17 will be initialized later based on the
+ * frequency offset stored in the EEPROM
+ */
+
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
+ rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 41, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 42, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+ rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 53, 0x76);
+ rt2800_rfcsr_write(rt2x00dev, 54, 0x76);
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x76);
+ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
+ rt2800_rfcsr_write(rt2x00dev, 58, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+ /* TODO: rx filter calibration? */
+
+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
+
+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
+
+ rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
+
+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
+
+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+
+ if (eco == 5) {
+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x32);
+ }
+
+ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+ msleep(1);
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr |= 0xc0;
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rfcsr |= 0x20;
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 46, &rfcsr);
+ rfcsr |= 0x20;
+ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+ rfcsr &= ~0xee;
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+}
+
static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
{
rt2800_rf_init_calibration(rt2x00dev, 2);
@@ -7042,6 +7180,9 @@ static void rt2800_init_rfcsr(struct rt2
case RT3390:
rt2800_init_rfcsr_3390(rt2x00dev);
break;
+ case RT3883:
+ rt2800_init_rfcsr_3883(rt2x00dev);
+ break;
case RT3572:
rt2800_init_rfcsr_3572(rt2x00dev);
break;

View file

@ -0,0 +1,22 @@
From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 8 May 2013 19:35:33 +0200
Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -342,7 +342,8 @@ static unsigned int rt2800_eeprom_word_i
wiphy_name(rt2x00dev->hw->wiphy), word))
return 0;
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
map = rt2800_eeprom_map_ext;
else
map = rt2800_eeprom_map;

View file

@ -0,0 +1,21 @@
From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 1 Aug 2013 14:48:21 +0200
Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7579,6 +7579,8 @@ static int rt2800_init_eeprom(struct rt2
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+ else if (rt2x00_rt(rt2x00dev, RT3883))
+ rf = RF3853;
else
rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);

View file

@ -0,0 +1,136 @@
From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:28 +0100
Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++--
1 file changed, 69 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3385,6 +3385,36 @@ static char rt2800_txpower_to_dev(struct
return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
}
+static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf)
+{
+ u8 bbp;
+
+ bbp = (rf->channel > 14) ? 0x48 : 0x38;
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
+
+ rt2800_bbp_write(rt2x00dev, 69, 0x12);
+
+ if (rf->channel <= 14) {
+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+ } else {
+ /* Disable CCK packet detection */
+ rt2800_bbp_write(rt2x00dev, 70, 0x00);
+ }
+
+ rt2800_bbp_write(rt2x00dev, 73, 0x10);
+
+ if (rf->channel > 14) {
+ rt2800_bbp_write(rt2x00dev, 62, 0x1d);
+ rt2800_bbp_write(rt2x00dev, 63, 0x1d);
+ rt2800_bbp_write(rt2x00dev, 64, 0x1d);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 62, 0x2d);
+ rt2800_bbp_write(rt2x00dev, 63, 0x2d);
+ rt2800_bbp_write(rt2x00dev, 64, 0x2d);
+ }
+}
+
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@@ -3403,6 +3433,12 @@ static void rt2800_config_channel(struct
rt2800_txpower_to_dev(rt2x00dev, rf->channel,
info->default_power3);
+ switch (rt2x00dev->chip.rt) {
+ case RT3883:
+ rt3883_bbp_adjust(rt2x00dev, rf);
+ break;
+ }
+
switch (rt2x00dev->chip.rf) {
case RF2020:
case RF3020:
@@ -3484,6 +3520,15 @@ static void rt2800_config_channel(struct
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 77, 0x98);
+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+
+ if (rt2x00dev->default_ant.rx_chain_num > 1)
+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
+ else
+ rt2800_bbp_write(rt2x00dev, 86, 0);
} else {
rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
@@ -3496,6 +3541,7 @@ static void rt2800_config_channel(struct
!rt2x00_rt(rt2x00dev, RT5392)) {
if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
rt2800_bbp_write(rt2x00dev, 82, 0x62);
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
rt2800_bbp_write(rt2x00dev, 75, 0x46);
} else {
if (rt2x00_rt(rt2x00dev, RT3593))
@@ -3504,19 +3550,22 @@ static void rt2800_config_channel(struct
rt2800_bbp_write(rt2x00dev, 82, 0x84);
rt2800_bbp_write(rt2x00dev, 75, 0x50);
}
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
rt2800_bbp_write(rt2x00dev, 83, 0x8a);
}
} else {
if (rt2x00_rt(rt2x00dev, RT3572))
rt2800_bbp_write(rt2x00dev, 82, 0x94);
- else if (rt2x00_rt(rt2x00dev, RT3593))
+ else if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
rt2800_bbp_write(rt2x00dev, 82, 0x82);
else
rt2800_bbp_write(rt2x00dev, 82, 0xf2);
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
rt2800_bbp_write(rt2x00dev, 83, 0x9a);
if (rt2x00_has_cap_external_lna_a(rt2x00dev))
@@ -3638,6 +3687,23 @@ static void rt2800_config_channel(struct
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+ usleep_range(1000, 1500);
+ }
+
+ if (rt2x00_rt(rt2x00dev, RT3883)) {
+ if (!conf_is_ht40(conf))
+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
+ else
+ rt2800_bbp_write(rt2x00dev, 105, 0x04);
+
+ /* AGC init */
+ if (rf->channel <= 14)
+ reg = 0x2e + rt2x00dev->lna_gain;
+ else
+ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3);
+
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
usleep_range(1000, 1500);
}

View file

@ -0,0 +1,30 @@
From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 30 Sep 2013 13:57:26 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3372,13 +3372,15 @@ static char rt2800_txpower_to_dev(struct
unsigned int channel,
char txpower)
{
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
if (channel <= 14)
return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
MAX_A_TXPOWER_3593);
else

View file

@ -0,0 +1,23 @@
From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:29 +0100
Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function
for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4582,7 +4582,8 @@ static void rt2800_config_txpower(struct
struct ieee80211_channel *chan,
int power_level)
{
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
else
rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);

View file

@ -0,0 +1,33 @@
From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sat, 24 Aug 2013 11:49:55 +0200
Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for
RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7461,7 +7461,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
{
u16 word;
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
return 0;
rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
@@ -7475,7 +7476,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
{
u16 word;
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
return 0;
rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);

View file

@ -0,0 +1,20 @@
From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 18 Apr 2013 14:33:33 +0200
Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -558,6 +558,7 @@ void rt2800_get_txwi_rxwi_size(struct rt
{
switch (rt2x00dev->chip.rt) {
case RT3593:
+ case RT3883:
*txwi_size = TXWI_DESC_SIZE_4WORDS;
*rxwi_size = RXWI_DESC_SIZE_5WORDS;
break;

View file

@ -0,0 +1,22 @@
From b403bdfa00665ce6b53583bdb837ffad0b91c09f Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:29 +0100
Subject: [PATCH] rt2x00: rt2800lib: use correct beacon base for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -983,7 +983,8 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
unsigned int index)
{
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
return HW_BEACON_BASE_HIGH(index);
return HW_BEACON_BASE(index);

View file

@ -0,0 +1,22 @@
From 74b7eaf75fc6eb86292056ef705e543f9cd6086b Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 18 Aug 2013 09:57:58 +0200
Subject: [PATCH] rt2x00: rt2800lib: use correct beacon count for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -8393,7 +8393,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
if (rt2x00_rt(rt2x00dev, RT3593))
__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
drv_data->hw_beacon_count = 16;
else
drv_data->hw_beacon_count = 8;

View file

@ -0,0 +1,22 @@
From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 30 Sep 2013 16:53:33 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1917,7 +1917,8 @@ void rt2800_config_ant(struct rt2x00_dev
rt2800_bbp_write(rt2x00dev, 3, r3);
rt2800_bbp_write(rt2x00dev, 1, r1);
- if (rt2x00_rt(rt2x00dev, RT3593)) {
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883)) {
if (ant->rx_chain_num == 1)
rt2800_bbp_write(rt2x00dev, 86, 0x00);
else

View file

@ -0,0 +1,32 @@
From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 30 Sep 2013 16:58:23 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1940,7 +1940,8 @@ static void rt2800_config_lna_gain(struc
rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
} else if (libconf->rf.channel <= 128) {
- if (rt2x00_rt(rt2x00dev, RT3593)) {
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883)) {
rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_EXT_LNA2_A1);
@@ -1950,7 +1951,8 @@ static void rt2800_config_lna_gain(struc
EEPROM_RSSI_BG2_LNA_A1);
}
} else {
- if (rt2x00_rt(rt2x00dev, RT3593)) {
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883)) {
rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_EXT_LNA2_A2);

View file

@ -0,0 +1,44 @@
From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Tue, 1 Oct 2013 15:40:08 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4781,7 +4781,8 @@ static u8 rt2800_get_default_vgc(struct
else
vgc = 0x2e + rt2x00dev->lna_gain;
} else { /* 5GHZ band */
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
else if (rt2x00_rt(rt2x00dev, RT5592))
vgc = 0x24 + (2 * rt2x00dev->lna_gain);
@@ -4801,7 +4802,8 @@ static inline void rt2800_set_vgc(struct
{
if (qual->vgc_level != vgc_level) {
if (rt2x00_rt(rt2x00dev, RT3572) ||
- rt2x00_rt(rt2x00dev, RT3593)) {
+ rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883)) {
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
vgc_level);
} else if (rt2x00_rt(rt2x00dev, RT5592)) {
@@ -4848,6 +4850,11 @@ void rt2800_link_tuner(struct rt2x00_dev
}
break;
+ case RT3883:
+ if (qual->rssi > -65)
+ vgc += 0x10;
+ break;
+
case RT5592:
if (qual->rssi > -65)
vgc += 0x20;

View file

@ -0,0 +1,42 @@
From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Tue, 1 Oct 2013 17:27:57 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7598,7 +7598,8 @@ static int rt2800_validate_eeprom(struct
rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
- if (!rt2x00_rt(rt2x00dev, RT3593)) {
+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
+ !rt2x00_rt(rt2x00dev, RT3883)) {
if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
@@ -7618,7 +7619,8 @@ static int rt2800_validate_eeprom(struct
rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
- if (!rt2x00_rt(rt2x00dev, RT3593)) {
+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
+ !rt2x00_rt(rt2x00dev, RT3883)) {
if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
@@ -7626,7 +7628,8 @@ static int rt2800_validate_eeprom(struct
}
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
- if (rt2x00_rt(rt2x00dev, RT3593)) {
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883)) {
rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)

View file

@ -0,0 +1,22 @@
From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 2 Oct 2013 10:11:59 +0200
Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3959,6 +3959,9 @@ static u8 rt2800_compensate_txpower(stru
if (rt2x00_rt(rt2x00dev, RT3593))
return min_t(u8, txpower, 0xc);
+ if (rt2x00_rt(rt2x00dev, RT3883))
+ return min_t(u8, txpower, 0xf);
+
if (rt2x00_has_cap_power_limit(rt2x00dev)) {
/*
* Check if eirp txpower exceed txpower_limit.

View file

@ -0,0 +1,23 @@
From f6734ec72da936989a8ce4186b3ede28fbc47836 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 18 Aug 2013 21:57:34 +0200
Subject: [PATCH] rt2x00: rt2800lib: enable RT2800_HAS_HIGH_SHARED_MEM for
RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -8406,7 +8406,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
if (retval)
return retval;
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
if (rt2x00_rt(rt2x00dev, RT3593) ||

View file

@ -0,0 +1,22 @@
From f1acfc2f397e86548ae1b479c198d4bef57050f6 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 29 Sep 2013 18:10:34 +0200
Subject: [PATCH] rt2x00: rt2800lib: use high memory for beacons on RT3883
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -97,7 +97,8 @@ static inline void rt2800_shared_mem_sel
static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
{
- if (rt2x00_rt(rt2x00dev, RT3593))
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
return true;
return false;

View file

@ -0,0 +1,136 @@
From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Sun, 24 Mar 2013 19:26:27 +0100
Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious
TX_FIFO_STATUS interrupts
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/net/wireless/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++-----
drivers/net/wireless/rt2x00/rt2x00.h | 5 +++
2 files changed, 65 insertions(+), 12 deletions(-)
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
@@ -415,9 +415,9 @@ void rt2800mmio_autowake_tasklet(unsigne
}
EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev,
+ u32 status)
{
- u32 status;
int i;
/*
@@ -438,29 +438,77 @@ static void rt2800mmio_txstatus_interrup
* Since we have only one producer and one consumer we don't
* need to lock the kfifo.
*/
- for (i = 0; i < rt2x00dev->tx->limit; i++) {
- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
-
- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
- break;
-
+ i = 0;
+ do {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
+ rt2x00_warn(rt2x00dev,
+ "TX status FIFO overrun, drop TX status report\n");
break;
}
- }
+
+ if (++i >= rt2x00dev->tx->limit)
+ break;
+
+ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID));
/* Schedule the tasklet for processing the tx status. */
tasklet_schedule(&rt2x00dev->txstatus_tasklet);
}
+#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4
+
+static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev,
+ u32 txstatus)
+{
+ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) {
+ rt2x00dev->txstatus_irq_retries = 0;
+ return false;
+ }
+
+ rt2x00dev->txstatus_irq_retries++;
+
+ /* Ensure that we don't go into an infinite IRQ loop. */
+ if (rt2x00dev->txstatus_irq_retries >=
+ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) {
+ rt2x00_warn(rt2x00dev,
+ "%u spurious TX_FIFO_STATUS interrupt(s)\n",
+ rt2x00dev->txstatus_irq_retries);
+ rt2x00dev->txstatus_irq_retries = 0;
+ return false;
+ }
+
+ return true;
+}
+
irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg, mask;
+ u32 txstatus = 0;
- /* Read status and ACK all interrupts */
+ /* Read status */
rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+ /* Due to unknown reason the hardware generates a
+ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
+ * register contain valid data. Read the TX status
+ * here to see if we have to process the actual
+ * request.
+ */
+ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus);
+ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
+ /* Remove the TX_FIFO_STATUS bit so it won't be
+ * processed in this turn. The hardware will
+ * generate another IRQ for us.
+ */
+ rt2x00_set_field32(&reg,
+ INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
+ }
+ }
+
+ /* ACK interrupts */
rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg)
@@ -477,7 +525,7 @@ irqreturn_t rt2800mmio_interrupt(int irq
mask = ~reg;
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
- rt2800mmio_txstatus_interrupt(rt2x00dev);
+ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus);
/*
* Never disable the TX_FIFO_STATUS interrupt.
*/
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -986,6 +986,11 @@ struct rt2x00_dev {
int rf_channel;
/*
+ * Counter for tx status irq retries (rt2800pci).
+ */
+ unsigned int txstatus_irq_retries;
+
+ /*
* Protect the interrupt mask register.
*/
spinlock_t irqmask_lock;