From: Gabor Juhos Date: Tue, 27 Aug 2013 10:44:06 +0000 (+0000) Subject: mac80211: add a bunch of rt2x00 specific changes X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6c29525f42d2d793c4eef647c023e9afd7af6e35;p=librecmc%2Flibrecmc.git mac80211: add a bunch of rt2x00 specific changes Backport some rt2x00 specific changes from wireless-testing/master-2013-08-26 to add support for RT3573 based devices. Also refresh the rt2x00 specific patches. Signed-off-by: Gabor Juhos SVN-Revision: 37843 --- diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 5bef361650..05b43f30a8 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -1361,7 +1361,7 @@ config-$(call config_package,rt2800-pci) += RT2800PCI config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290 config-$(call config_package,rt2800-usb) += RT2800USB -config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT53XX RT2800USB_RT55XX +config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX config-$(call config_package,iwl-legacy) += IWLEGACY config-$(call config_package,iwl3945) += IWL3945 diff --git a/package/kernel/mac80211/patches/301-pending_work-rt2x00.patch b/package/kernel/mac80211/patches/301-pending_work-rt2x00.patch new file mode 100644 index 0000000000..b4c0225686 --- /dev/null +++ b/package/kernel/mac80211/patches/301-pending_work-rt2x00.patch @@ -0,0 +1,3300 @@ +Contains the following changes from wireless-testing/master-2013-08-26: + + commit 8951b79a4e6d8228babf56ae79a345e4abc5ac82 + Author: Gabor Juhos + Date: Mon Jul 8 11:25:52 2013 +0200 + + rt2x00: rt2800lib: introduce rt2800_eeprom_word enum + + commit 3e38d3daf881a78ac13e93504a8ac5777040797e + Author: Gabor Juhos + Date: Mon Jul 8 11:25:53 2013 +0200 + + rt2x00: rt2800lib: introduce local EEPROM access functions + + commit 022138ca93f016374d5d3f69c070c75596c5ecac + Author: Gabor Juhos + Date: Mon Jul 8 11:25:54 2013 +0200 + + rt2x00: rt2800lib: introduce rt2800_eeprom_read_from_array helper + + commit 379448fe34e289fdcc473399d4f6cac19e757fb8 + Author: Gabor Juhos + Date: Mon Jul 8 11:25:55 2013 +0200 + + rt2x00: rt2800lib: introduce rt2800_eeprom_word_index helper + + commit fa31d157f83ef71b6530aacf0400bafe7816acbd + Author: Gabor Juhos + Date: Mon Jul 8 11:25:56 2013 +0200 + + rt2x00: rt2800lib: add EEPROM map for the RT3593 chipset + + commit 1706d15d82f4a579119b419cd673987af60f1d9b + Author: Gabor Juhos + Date: Mon Jul 8 16:08:16 2013 +0200 + + rt2x00: rt2800lib: add MAC register initialization for RT3593 + + commit b189a1814135bc52f516ca61a1fa161914d57a54 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:17 2013 +0200 + + rt2x00: rt2800lib: add BBP register initialization for RT3593 + + commit ab7078ac3d920e0d49b17e92f327f3ada25600e8 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:18 2013 +0200 + + rt2x00: rt2800lib: add RFCSR register initialization for RT3593 + + commit d63f7e8ca560dc9a76a15c323cb9cba14b25f430 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:19 2013 +0200 + + rt2x00: rt2800lib: add BBP post initialization for RT3593 + + commit 34542ff5a665061d548c3f860807df341f718adf + Author: Gabor Juhos + Date: Mon Jul 8 16:08:20 2013 +0200 + + rt2x00: rt2800lib: add TX power configuration for RT3593 + + commit 4788ac1e4842d8ef46ee620cfccf96c426043177 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:21 2013 +0200 + + rt2x00: rt2800lib: fix BBP1_TX_ANTENNA field configuration for 3T devices + + commit 5cddb3c2d5102d9a6b1b809e1518da54c8be8296 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:22 2013 +0200 + + rt2x00: rt2800lib: fix antenna configuration for RT3593 + + commit 97aa03f15e83174df74aa468eea127c5cee480f0 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:23 2013 +0200 + + rt2x00: rt2800lib: add rt2800_txpower_to_dev helper + + commit fc739cfe0f305647677edbf99a76d9ece96e3795 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:24 2013 +0200 + + rt2x00: rt2800lib: fix default TX power values for RT3593 + + commit a3f1625dae58f06c5df1ec0094b275e9a46fd8b3 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:25 2013 +0200 + + rt2x00: rt2800lib: introduce rt2800_get_txmixer_gain_{24,5}g helpers + + commit 6316c786cc8aff762530ea740233bf2da10fea33 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:26 2013 +0200 + + rt2x00: rt2800lib: hardcode TX mixer gain values for RT3593 + + commit f36bb0ca1be5bcb7148ad32263626f8609dfc0d7 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:27 2013 +0200 + + rt2x00: rt2800lib: fix LNA_A[12] gain values for RT3593 + + commit c0a14369ebd3e7940e70e397ecc3dd7eaf81e9ab + Author: Gabor Juhos + Date: Mon Jul 8 16:08:28 2013 +0200 + + rt2x00: rt2800lib: add default_power3 field for three-chain devices + + commit c8b9d3dc83cab569de6054a10e355a143e2b52a0 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:29 2013 +0200 + + rt2x00: rt2800lib: add rf_vals for RF3053 + + commit f42b046578efb018064302fd9b66586f5da7d75b + Author: Gabor Juhos + Date: Mon Jul 8 16:08:30 2013 +0200 + + rt2x00: rt2800lib: add channel configuration for RF3053 + + commit 1095df07bfc5924e100f1748e6ebc9e5a5881565 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:31 2013 +0200 + + rt2x00: rt2800lib: enable VCO recalibration for RF3053 + + commit 0f5af26a49c8d6a50ecec2f1b66174069c9f9581 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:32 2013 +0200 + + rt2x00: rt2800lib: enable RF3053 support + + commit 2dc2bd2f8aa8eb79184fb3c7e5f530006500897f + Author: Gabor Juhos + Date: Mon Jul 8 16:08:33 2013 +0200 + + rt2x00: rt2800lib: enable RT3593 support + + commit 65d3c0d5cffb9f1227927544e418a9ac231eae42 + Author: Gabor Juhos + Date: Mon Jul 8 16:08:34 2013 +0200 + + rt2x00: rt2800usb: use correct [RT]XWI size for RT3593 + + commit d02433d15566f542e42e3c469dfade0de332dc7b + Author: Gabor Juhos + Date: Mon Jul 8 16:08:35 2013 +0200 + + rt2x00: rt2800usb: add USB device ID for Linksys AE3000 + + commit 637065267eab4817c0b06cbf3c7fc80842acab99 + Author: Xose Vazquez Perez + Date: Tue Jul 23 14:55:15 2013 +0200 + + wireless: rt2x00: rt2800usb: add RT3573 devices + + commit ae1b1c5dcdef1ebd4b37a7d56ad767add757a660 + Author: Gabor Juhos + Date: Fri Aug 16 10:23:29 2013 +0200 + + rt2x00: rt2800lib: introduce rt2800_get_txwi_rxwi_size helper + + commit 41caa760d6acaf47cbd44c3d78307fb9be089111 + Author: Gabor Juhos + Date: Fri Aug 16 10:23:30 2013 +0200 + + rt2x00: rt2800pci: fix AUX_CTRL register setup for RT3090/3390/3593/5592 + + commit 91a3fa39ddf2f85a15cb20ccc3a54c1f0497af1e + Author: Gabor Juhos + Date: Sat Aug 17 00:15:49 2013 +0200 + + rt2x00: rt2800: rename HW_BEACON_OFFSET macro + + commit 77f7c0f3b8f2d464e841c5c35f3da8b4999a885c + Author: Gabor Juhos + Date: Sat Aug 17 00:15:50 2013 +0200 + + rt2x00: rt2800lib: pass beacon index to rt2800_clear_beacon_register + + commit c1fada4e5e53d88a8edd3ff01cee9d316cbf6025 + Author: Gabor Juhos + Date: Sat Aug 17 14:09:28 2013 +0200 + + rt2x00: rt2800lib: fix frequency offset boundary calculation + + commit 6af1bdccabe956a08a37f2ae049d37307ec0c91c + Author: Gabor Juhos + Date: Sat Aug 17 14:09:29 2013 +0200 + + rt2x00: rt2800lib: optimize frequency offset adjustment + + commit 76773f301f2210dcc20c466aebda7118062673eb + Author: Gabor Juhos + Date: Sat Aug 17 14:09:30 2013 +0200 + + rt2x00: rt2800lib: use a MCU command for frequency adjustment on USB devices + + commit 8d38eca8e089179b6858ca5f3ea03f571a5892a5 + Author: Gabor Juhos + Date: Sat Aug 17 14:09:31 2013 +0200 + + rt2x00: rt2800lib: use step-by-step frequency offset adjustment on MMIO devices + + commit 3f1b8739a498c7570ca2fae6c49fd1561ef2358c + Author: Gabor Juhos + Date: Sat Aug 17 14:09:32 2013 +0200 + + rt2x00: rt2800lib: move rt2800_adjust_freq_offset function + + commit e979a8ab204edbf7b0815162109ee9c85e4d7ea5 + Author: Gabor Juhos + Date: Sat Aug 17 14:09:33 2013 +0200 + + rt2x00: rt2800lib: adjust frequency offset for RF3053 + + commit 21c6af6b69b609b7934caaccda1b4535dceb402c + Author: Gabor Juhos + Date: Thu Aug 22 20:53:21 2013 +0200 + + rt2x00: rt2800lib: add rt2800_hw_beacon_base helper + + commit 634b80595fef79071d82bc231b7f82c4f808a1e8 + Author: Gabor Juhos + Date: Thu Aug 22 20:53:22 2013 +0200 + + rt2x00: rt2800lib: don't hardcode beacon offsets + + commit 6e956da2027c767859128b9bfef085cf2a8e233b + Author: Stanislaw Gruszka + Date: Mon Aug 26 15:18:53 2013 +0200 + + rt2800: fix wrong TX power compensation + +--- +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -174,6 +174,12 @@ config RT2800USB_RT35XX + rt2800usb driver. + Supported chips: RT3572 + ++config RT2800USB_RT3573 ++ bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)" ++ ---help--- ++ This enables support for RT3573 chipset based wireless USB devices ++ in the rt2800usb driver. ++ + config RT2800USB_RT53XX + bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)" + ---help--- +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -88,6 +88,7 @@ + #define REV_RT3071E 0x0211 + #define REV_RT3090E 0x0211 + #define REV_RT3390E 0x0211 ++#define REV_RT3593E 0x0211 + #define REV_RT5390F 0x0502 + #define REV_RT5390R 0x1502 + #define REV_RT5592C 0x0221 +@@ -1082,6 +1083,15 @@ + #define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) + #define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) + #define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) ++/* bits for 3T devices */ ++#define TX_PWR_CFG_0_CCK1_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_0_CCK1_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_0_CCK5_CH0 FIELD32(0x00000f00) ++#define TX_PWR_CFG_0_CCK5_CH1 FIELD32(0x0000f000) ++#define TX_PWR_CFG_0_OFDM6_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_0_OFDM6_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_0_OFDM12_CH0 FIELD32(0x0f000000) ++#define TX_PWR_CFG_0_OFDM12_CH1 FIELD32(0xf0000000) + + /* + * TX_PWR_CFG_1: +@@ -1095,6 +1105,15 @@ + #define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) + #define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) + #define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) ++/* bits for 3T devices */ ++#define TX_PWR_CFG_1_OFDM24_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_1_OFDM24_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_1_OFDM48_CH0 FIELD32(0x00000f00) ++#define TX_PWR_CFG_1_OFDM48_CH1 FIELD32(0x0000f000) ++#define TX_PWR_CFG_1_MCS0_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_1_MCS0_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_1_MCS2_CH0 FIELD32(0x0f000000) ++#define TX_PWR_CFG_1_MCS2_CH1 FIELD32(0xf0000000) + + /* + * TX_PWR_CFG_2: +@@ -1108,6 +1127,15 @@ + #define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) + #define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) + #define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) ++/* bits for 3T devices */ ++#define TX_PWR_CFG_2_MCS4_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_2_MCS4_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_2_MCS6_CH0 FIELD32(0x00000f00) ++#define TX_PWR_CFG_2_MCS6_CH1 FIELD32(0x0000f000) ++#define TX_PWR_CFG_2_MCS8_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_2_MCS8_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_2_MCS10_CH0 FIELD32(0x0f000000) ++#define TX_PWR_CFG_2_MCS10_CH1 FIELD32(0xf0000000) + + /* + * TX_PWR_CFG_3: +@@ -1121,6 +1149,15 @@ + #define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) + #define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) + #define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) ++/* bits for 3T devices */ ++#define TX_PWR_CFG_3_MCS12_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_3_MCS12_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_3_MCS14_CH0 FIELD32(0x00000f00) ++#define TX_PWR_CFG_3_MCS14_CH1 FIELD32(0x0000f000) ++#define TX_PWR_CFG_3_STBC0_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_3_STBC0_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_3_STBC2_CH0 FIELD32(0x0f000000) ++#define TX_PWR_CFG_3_STBC2_CH1 FIELD32(0xf0000000) + + /* + * TX_PWR_CFG_4: +@@ -1130,6 +1167,11 @@ + #define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) + #define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) + #define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) ++/* bits for 3T devices */ ++#define TX_PWR_CFG_3_STBC4_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_3_STBC4_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_3_STBC6_CH0 FIELD32(0x00000f00) ++#define TX_PWR_CFG_3_STBC6_CH1 FIELD32(0x0000f000) + + /* + * TX_PIN_CFG: +@@ -1451,6 +1493,81 @@ + */ + #define EXP_ACK_TIME 0x1380 + ++/* TX_PWR_CFG_5 */ ++#define TX_PWR_CFG_5 0x1384 ++#define TX_PWR_CFG_5_MCS16_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_5_MCS16_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_5_MCS16_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_5_MCS18_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_5_MCS18_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_5_MCS18_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_6 */ ++#define TX_PWR_CFG_6 0x1388 ++#define TX_PWR_CFG_6_MCS20_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_6_MCS20_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_6_MCS20_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_6_MCS22_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_6_MCS22_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_6_MCS22_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_0_EXT */ ++#define TX_PWR_CFG_0_EXT 0x1390 ++#define TX_PWR_CFG_0_EXT_CCK1_CH2 FIELD32(0x0000000f) ++#define TX_PWR_CFG_0_EXT_CCK5_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_0_EXT_OFDM6_CH2 FIELD32(0x000f0000) ++#define TX_PWR_CFG_0_EXT_OFDM12_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_1_EXT */ ++#define TX_PWR_CFG_1_EXT 0x1394 ++#define TX_PWR_CFG_1_EXT_OFDM24_CH2 FIELD32(0x0000000f) ++#define TX_PWR_CFG_1_EXT_OFDM48_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_1_EXT_MCS0_CH2 FIELD32(0x000f0000) ++#define TX_PWR_CFG_1_EXT_MCS2_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_2_EXT */ ++#define TX_PWR_CFG_2_EXT 0x1398 ++#define TX_PWR_CFG_2_EXT_MCS4_CH2 FIELD32(0x0000000f) ++#define TX_PWR_CFG_2_EXT_MCS6_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_2_EXT_MCS8_CH2 FIELD32(0x000f0000) ++#define TX_PWR_CFG_2_EXT_MCS10_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_3_EXT */ ++#define TX_PWR_CFG_3_EXT 0x139c ++#define TX_PWR_CFG_3_EXT_MCS12_CH2 FIELD32(0x0000000f) ++#define TX_PWR_CFG_3_EXT_MCS14_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_3_EXT_STBC0_CH2 FIELD32(0x000f0000) ++#define TX_PWR_CFG_3_EXT_STBC2_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_4_EXT */ ++#define TX_PWR_CFG_4_EXT 0x13a0 ++#define TX_PWR_CFG_4_EXT_STBC4_CH2 FIELD32(0x0000000f) ++#define TX_PWR_CFG_4_EXT_STBC6_CH2 FIELD32(0x00000f00) ++ ++/* TX_PWR_CFG_7 */ ++#define TX_PWR_CFG_7 0x13d4 ++#define TX_PWR_CFG_7_OFDM54_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_7_OFDM54_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_7_OFDM54_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_7_MCS7_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_7_MCS7_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_7_MCS7_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_8 */ ++#define TX_PWR_CFG_8 0x13d8 ++#define TX_PWR_CFG_8_MCS15_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_8_MCS15_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_8_MCS15_CH2 FIELD32(0x00000f00) ++#define TX_PWR_CFG_8_MCS23_CH0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_8_MCS23_CH1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_8_MCS23_CH2 FIELD32(0x0f000000) ++ ++/* TX_PWR_CFG_9 */ ++#define TX_PWR_CFG_9 0x13dc ++#define TX_PWR_CFG_9_STBC7_CH0 FIELD32(0x0000000f) ++#define TX_PWR_CFG_9_STBC7_CH1 FIELD32(0x000000f0) ++#define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00) ++ + /* + * RX_FILTER_CFG: RX configuration register. + */ +@@ -1902,11 +2019,13 @@ struct mac_iveiv_entry { + #define HW_BEACON_BASE6 0x5dc0 + #define HW_BEACON_BASE7 0x5bc0 + +-#define HW_BEACON_OFFSET(__index) \ ++#define HW_BEACON_BASE(__index) \ + (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \ + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) + ++#define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64) ++ + /* + * BBP registers. + * The wordsize of the BBP is 8 bits. +@@ -1975,6 +2094,10 @@ struct mac_iveiv_entry { + #define BBP109_TX0_POWER FIELD8(0x0f) + #define BBP109_TX1_POWER FIELD8(0xf0) + ++/* BBP 110 */ ++#define BBP110_TX2_POWER FIELD8(0x0f) ++ ++ + /* + * BBP 138: Unknown + */ +@@ -2024,6 +2147,12 @@ struct mac_iveiv_entry { + #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80) + /* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ + #define RFCSR3_VCOCAL_EN FIELD8(0x80) ++/* Bits for RF3050 */ ++#define RFCSR3_BIT1 FIELD8(0x02) ++#define RFCSR3_BIT2 FIELD8(0x04) ++#define RFCSR3_BIT3 FIELD8(0x08) ++#define RFCSR3_BIT4 FIELD8(0x10) ++#define RFCSR3_BIT5 FIELD8(0x20) + + /* + * FRCSR 5: +@@ -2036,6 +2165,8 @@ struct mac_iveiv_entry { + #define RFCSR6_R1 FIELD8(0x03) + #define RFCSR6_R2 FIELD8(0x40) + #define RFCSR6_TXDIV FIELD8(0x0c) ++/* bits for RF3053 */ ++#define RFCSR6_VCO_IC FIELD8(0xc0) + + /* + * RFCSR 7: +@@ -2060,7 +2191,12 @@ struct mac_iveiv_entry { + * RFCSR 11: + */ + #define RFCSR11_R FIELD8(0x03) ++#define RFCSR11_PLL_MOD FIELD8(0x0c) + #define RFCSR11_MOD FIELD8(0xc0) ++/* bits for RF3053 */ ++/* TODO: verify RFCSR11_MOD usage on other chips */ ++#define RFCSR11_PLL_IDOH FIELD8(0x40) ++ + + /* + * RFCSR 12: +@@ -2092,6 +2228,10 @@ struct mac_iveiv_entry { + #define RFCSR17_R FIELD8(0x20) + #define RFCSR17_CODE FIELD8(0x7f) + ++/* RFCSR 18 */ ++#define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) ++ ++ + /* + * RFCSR 20: + */ +@@ -2152,6 +2292,12 @@ struct mac_iveiv_entry { + #define RFCSR31_RX_H20M FIELD8(0x20) + #define RFCSR31_RX_CALIB FIELD8(0x7f) + ++/* RFCSR 32 bits for RF3053 */ ++#define RFCSR32_TX_AGC_FC FIELD8(0xf8) ++ ++/* RFCSR 36 bits for RF3053 */ ++#define RFCSR36_RF_BS FIELD8(0x80) ++ + /* + * RFCSR 38: + */ +@@ -2160,6 +2306,7 @@ struct mac_iveiv_entry { + /* + * RFCSR 39: + */ ++#define RFCSR39_RX_DIV FIELD8(0x40) + #define RFCSR39_RX_LO2_EN FIELD8(0x80) + + /* +@@ -2167,12 +2314,36 @@ struct mac_iveiv_entry { + */ + #define RFCSR49_TX FIELD8(0x3f) + #define RFCSR49_EP FIELD8(0xc0) ++/* bits for RT3593 */ ++#define RFCSR49_TX_LO1_IC FIELD8(0x1c) ++#define RFCSR49_TX_DIV FIELD8(0x20) + + /* + * RFCSR 50: + */ + #define RFCSR50_TX FIELD8(0x3f) + #define RFCSR50_EP FIELD8(0xc0) ++/* bits for RT3593 */ ++#define RFCSR50_TX_LO1_EN FIELD8(0x20) ++#define RFCSR50_TX_LO2_EN FIELD8(0x10) ++ ++/* RFCSR 51 */ ++/* bits for RT3593 */ ++#define RFCSR51_BITS01 FIELD8(0x03) ++#define RFCSR51_BITS24 FIELD8(0x1c) ++#define RFCSR51_BITS57 FIELD8(0xe0) ++ ++#define RFCSR53_TX_POWER FIELD8(0x3f) ++#define RFCSR53_UNKNOWN FIELD8(0xc0) ++ ++#define RFCSR54_TX_POWER FIELD8(0x3f) ++#define RFCSR54_UNKNOWN FIELD8(0xc0) ++ ++#define RFCSR55_TX_POWER FIELD8(0x3f) ++#define RFCSR55_UNKNOWN FIELD8(0xc0) ++ ++#define RFCSR57_DRV_CC FIELD8(0xfc) ++ + + /* + * RF registers +@@ -2206,28 +2377,67 @@ struct mac_iveiv_entry { + * The wordsize of the EEPROM is 16 bits. + */ + +-/* +- * Chip ID +- */ +-#define EEPROM_CHIP_ID 0x0000 ++enum rt2800_eeprom_word { ++ EEPROM_CHIP_ID = 0, ++ EEPROM_VERSION, ++ EEPROM_MAC_ADDR_0, ++ EEPROM_MAC_ADDR_1, ++ EEPROM_MAC_ADDR_2, ++ EEPROM_NIC_CONF0, ++ EEPROM_NIC_CONF1, ++ EEPROM_FREQ, ++ EEPROM_LED_AG_CONF, ++ EEPROM_LED_ACT_CONF, ++ EEPROM_LED_POLARITY, ++ EEPROM_NIC_CONF2, ++ EEPROM_LNA, ++ EEPROM_RSSI_BG, ++ EEPROM_RSSI_BG2, ++ EEPROM_TXMIXER_GAIN_BG, ++ EEPROM_RSSI_A, ++ EEPROM_RSSI_A2, ++ EEPROM_TXMIXER_GAIN_A, ++ EEPROM_EIRP_MAX_TX_POWER, ++ EEPROM_TXPOWER_DELTA, ++ EEPROM_TXPOWER_BG1, ++ EEPROM_TXPOWER_BG2, ++ EEPROM_TSSI_BOUND_BG1, ++ EEPROM_TSSI_BOUND_BG2, ++ EEPROM_TSSI_BOUND_BG3, ++ EEPROM_TSSI_BOUND_BG4, ++ EEPROM_TSSI_BOUND_BG5, ++ EEPROM_TXPOWER_A1, ++ EEPROM_TXPOWER_A2, ++ EEPROM_TSSI_BOUND_A1, ++ EEPROM_TSSI_BOUND_A2, ++ EEPROM_TSSI_BOUND_A3, ++ EEPROM_TSSI_BOUND_A4, ++ EEPROM_TSSI_BOUND_A5, ++ EEPROM_TXPOWER_BYRATE, ++ EEPROM_BBP_START, ++ ++ /* IDs for extended EEPROM format used by three-chain devices */ ++ EEPROM_EXT_LNA2, ++ EEPROM_EXT_TXPOWER_BG3, ++ EEPROM_EXT_TXPOWER_A3, ++ ++ /* New values must be added before this */ ++ EEPROM_WORD_COUNT ++}; + + /* + * EEPROM Version + */ +-#define EEPROM_VERSION 0x0001 + #define EEPROM_VERSION_FAE FIELD16(0x00ff) + #define EEPROM_VERSION_VERSION FIELD16(0xff00) + + /* + * HW MAC address. + */ +-#define EEPROM_MAC_ADDR_0 0x0002 + #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) + #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) +-#define EEPROM_MAC_ADDR_1 0x0003 + #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) + #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) +-#define EEPROM_MAC_ADDR_2 0x0004 + #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) + #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) + +@@ -2237,7 +2447,6 @@ struct mac_iveiv_entry { + * TXPATH: 1: 1T, 2: 2T, 3: 3T + * RF_TYPE: RFIC type + */ +-#define EEPROM_NIC_CONF0 0x001a + #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) + #define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) + #define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) +@@ -2261,7 +2470,6 @@ struct mac_iveiv_entry { + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable + */ +-#define EEPROM_NIC_CONF1 0x001b + #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) + #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) + #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) +@@ -2281,7 +2489,6 @@ struct mac_iveiv_entry { + /* + * EEPROM frequency + */ +-#define EEPROM_FREQ 0x001d + #define EEPROM_FREQ_OFFSET FIELD16(0x00ff) + #define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) + #define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) +@@ -2298,9 +2505,6 @@ struct mac_iveiv_entry { + * POLARITY_GPIO_4: Polarity GPIO4 setting. + * LED_MODE: Led mode. + */ +-#define EEPROM_LED_AG_CONF 0x001e +-#define EEPROM_LED_ACT_CONF 0x001f +-#define EEPROM_LED_POLARITY 0x0020 + #define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) + #define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) + #define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) +@@ -2317,7 +2521,6 @@ struct mac_iveiv_entry { + * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved + */ +-#define EEPROM_NIC_CONF2 0x0021 + #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) + #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) + #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) +@@ -2325,54 +2528,46 @@ struct mac_iveiv_entry { + /* + * EEPROM LNA + */ +-#define EEPROM_LNA 0x0022 + #define EEPROM_LNA_BG FIELD16(0x00ff) + #define EEPROM_LNA_A0 FIELD16(0xff00) + + /* + * EEPROM RSSI BG offset + */ +-#define EEPROM_RSSI_BG 0x0023 + #define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) + #define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) + + /* + * EEPROM RSSI BG2 offset + */ +-#define EEPROM_RSSI_BG2 0x0024 + #define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) + #define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) + + /* + * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2). + */ +-#define EEPROM_TXMIXER_GAIN_BG 0x0024 + #define EEPROM_TXMIXER_GAIN_BG_VAL FIELD16(0x0007) + + /* + * EEPROM RSSI A offset + */ +-#define EEPROM_RSSI_A 0x0025 + #define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) + #define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) + + /* + * EEPROM RSSI A2 offset + */ +-#define EEPROM_RSSI_A2 0x0026 + #define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) + #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) + + /* + * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2). + */ +-#define EEPROM_TXMIXER_GAIN_A 0x0026 + #define EEPROM_TXMIXER_GAIN_A_VAL FIELD16(0x0007) + + /* + * EEPROM EIRP Maximum TX power values(unit: dbm) + */ +-#define EEPROM_EIRP_MAX_TX_POWER 0x0027 + #define EEPROM_EIRP_MAX_TX_POWER_2GHZ FIELD16(0x00ff) + #define EEPROM_EIRP_MAX_TX_POWER_5GHZ FIELD16(0xff00) + +@@ -2383,7 +2578,6 @@ struct mac_iveiv_entry { + * TYPE: 1: Plus the delta value, 0: minus the delta value + * ENABLE: enable tx power compensation for 40BW + */ +-#define EEPROM_TXPOWER_DELTA 0x0028 + #define EEPROM_TXPOWER_DELTA_VALUE_2G FIELD16(0x003f) + #define EEPROM_TXPOWER_DELTA_TYPE_2G FIELD16(0x0040) + #define EEPROM_TXPOWER_DELTA_ENABLE_2G FIELD16(0x0080) +@@ -2394,8 +2588,6 @@ struct mac_iveiv_entry { + /* + * EEPROM TXPOWER 802.11BG + */ +-#define EEPROM_TXPOWER_BG1 0x0029 +-#define EEPROM_TXPOWER_BG2 0x0030 + #define EEPROM_TXPOWER_BG_SIZE 7 + #define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) + #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) +@@ -2407,7 +2599,6 @@ struct mac_iveiv_entry { + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -3) + */ +-#define EEPROM_TSSI_BOUND_BG1 0x0037 + #define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00) + +@@ -2418,7 +2609,6 @@ struct mac_iveiv_entry { + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -1) + */ +-#define EEPROM_TSSI_BOUND_BG2 0x0038 + #define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00) + +@@ -2428,7 +2618,6 @@ struct mac_iveiv_entry { + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 1) + */ +-#define EEPROM_TSSI_BOUND_BG3 0x0039 + #define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00) + +@@ -2439,7 +2628,6 @@ struct mac_iveiv_entry { + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 3) + */ +-#define EEPROM_TSSI_BOUND_BG4 0x003a + #define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00) + +@@ -2449,19 +2637,20 @@ struct mac_iveiv_entry { + * increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +-#define EEPROM_TSSI_BOUND_BG5 0x003b + #define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00) + + /* + * EEPROM TXPOWER 802.11A + */ +-#define EEPROM_TXPOWER_A1 0x003c +-#define EEPROM_TXPOWER_A2 0x0053 + #define EEPROM_TXPOWER_A_SIZE 6 + #define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) + #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) + ++/* EEPROM_TXPOWER_{A,G} fields for RT3593 */ ++#define EEPROM_TXPOWER_ALC FIELD8(0x1f) ++#define EEPROM_TXPOWER_FINE_CTRL FIELD8(0xe0) ++ + /* + * EEPROM temperature compensation boundaries 802.11A + * MINUS4: If the actual TSSI is below this boundary, tx power needs to be +@@ -2469,7 +2658,6 @@ struct mac_iveiv_entry { + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -3) + */ +-#define EEPROM_TSSI_BOUND_A1 0x006a + #define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00) + +@@ -2480,7 +2668,6 @@ struct mac_iveiv_entry { + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -1) + */ +-#define EEPROM_TSSI_BOUND_A2 0x006b + #define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00) + +@@ -2490,7 +2677,6 @@ struct mac_iveiv_entry { + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 1) + */ +-#define EEPROM_TSSI_BOUND_A3 0x006c + #define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00) + +@@ -2501,7 +2687,6 @@ struct mac_iveiv_entry { + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 3) + */ +-#define EEPROM_TSSI_BOUND_A4 0x006d + #define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00) + +@@ -2511,14 +2696,12 @@ struct mac_iveiv_entry { + * increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +-#define EEPROM_TSSI_BOUND_A5 0x006e + #define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff) + #define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00) + + /* + * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode + */ +-#define EEPROM_TXPOWER_BYRATE 0x006f + #define EEPROM_TXPOWER_BYRATE_SIZE 9 + + #define EEPROM_TXPOWER_BYRATE_RATE0 FIELD16(0x000f) +@@ -2529,11 +2712,14 @@ struct mac_iveiv_entry { + /* + * EEPROM BBP. + */ +-#define EEPROM_BBP_START 0x0078 + #define EEPROM_BBP_SIZE 16 + #define EEPROM_BBP_VALUE FIELD16(0x00ff) + #define EEPROM_BBP_REG_ID FIELD16(0xff00) + ++/* EEPROM_EXT_LNA2 */ ++#define EEPROM_EXT_LNA2_A1 FIELD16(0x00ff) ++#define EEPROM_EXT_LNA2_A2 FIELD16(0xff00) ++ + /* + * EEPROM IQ Calibration, unlike other entries those are byte addresses. + */ +@@ -2610,6 +2796,7 @@ struct mac_iveiv_entry { + #define MCU_RADAR 0x60 + #define MCU_BOOT_SIGNAL 0x72 + #define MCU_ANT_SELECT 0X73 ++#define MCU_FREQ_OFFSET 0x74 + #define MCU_BBP_SIGNAL 0x80 + #define MCU_POWER_SAVE 0x83 + #define MCU_BAND_SELECT 0x91 +@@ -2630,6 +2817,7 @@ struct mac_iveiv_entry { + #define TXWI_DESC_SIZE_5WORDS (5 * sizeof(__le32)) + + #define RXWI_DESC_SIZE_4WORDS (4 * sizeof(__le32)) ++#define RXWI_DESC_SIZE_5WORDS (5 * sizeof(__le32)) + #define RXWI_DESC_SIZE_6WORDS (6 * sizeof(__le32)) + + /* +@@ -2750,18 +2938,15 @@ struct mac_iveiv_entry { + #define MAX_A_TXPOWER 15 + #define DEFAULT_TXPOWER 5 + ++#define MIN_A_TXPOWER_3593 0 ++#define MAX_A_TXPOWER_3593 31 ++ + #define TXPOWER_G_FROM_DEV(__txpower) \ + ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +-#define TXPOWER_G_TO_DEV(__txpower) \ +- clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) +- + #define TXPOWER_A_FROM_DEV(__txpower) \ + ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +-#define TXPOWER_A_TO_DEV(__txpower) \ +- clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) +- + /* + * Board's maximun TX power limitation + */ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -221,6 +221,157 @@ static void rt2800_rf_write(struct rt2x0 + mutex_unlock(&rt2x00dev->csr_mutex); + } + ++static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { ++ [EEPROM_CHIP_ID] = 0x0000, ++ [EEPROM_VERSION] = 0x0001, ++ [EEPROM_MAC_ADDR_0] = 0x0002, ++ [EEPROM_MAC_ADDR_1] = 0x0003, ++ [EEPROM_MAC_ADDR_2] = 0x0004, ++ [EEPROM_NIC_CONF0] = 0x001a, ++ [EEPROM_NIC_CONF1] = 0x001b, ++ [EEPROM_FREQ] = 0x001d, ++ [EEPROM_LED_AG_CONF] = 0x001e, ++ [EEPROM_LED_ACT_CONF] = 0x001f, ++ [EEPROM_LED_POLARITY] = 0x0020, ++ [EEPROM_NIC_CONF2] = 0x0021, ++ [EEPROM_LNA] = 0x0022, ++ [EEPROM_RSSI_BG] = 0x0023, ++ [EEPROM_RSSI_BG2] = 0x0024, ++ [EEPROM_TXMIXER_GAIN_BG] = 0x0024, /* overlaps with RSSI_BG2 */ ++ [EEPROM_RSSI_A] = 0x0025, ++ [EEPROM_RSSI_A2] = 0x0026, ++ [EEPROM_TXMIXER_GAIN_A] = 0x0026, /* overlaps with RSSI_A2 */ ++ [EEPROM_EIRP_MAX_TX_POWER] = 0x0027, ++ [EEPROM_TXPOWER_DELTA] = 0x0028, ++ [EEPROM_TXPOWER_BG1] = 0x0029, ++ [EEPROM_TXPOWER_BG2] = 0x0030, ++ [EEPROM_TSSI_BOUND_BG1] = 0x0037, ++ [EEPROM_TSSI_BOUND_BG2] = 0x0038, ++ [EEPROM_TSSI_BOUND_BG3] = 0x0039, ++ [EEPROM_TSSI_BOUND_BG4] = 0x003a, ++ [EEPROM_TSSI_BOUND_BG5] = 0x003b, ++ [EEPROM_TXPOWER_A1] = 0x003c, ++ [EEPROM_TXPOWER_A2] = 0x0053, ++ [EEPROM_TSSI_BOUND_A1] = 0x006a, ++ [EEPROM_TSSI_BOUND_A2] = 0x006b, ++ [EEPROM_TSSI_BOUND_A3] = 0x006c, ++ [EEPROM_TSSI_BOUND_A4] = 0x006d, ++ [EEPROM_TSSI_BOUND_A5] = 0x006e, ++ [EEPROM_TXPOWER_BYRATE] = 0x006f, ++ [EEPROM_BBP_START] = 0x0078, ++}; ++ ++static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { ++ [EEPROM_CHIP_ID] = 0x0000, ++ [EEPROM_VERSION] = 0x0001, ++ [EEPROM_MAC_ADDR_0] = 0x0002, ++ [EEPROM_MAC_ADDR_1] = 0x0003, ++ [EEPROM_MAC_ADDR_2] = 0x0004, ++ [EEPROM_NIC_CONF0] = 0x001a, ++ [EEPROM_NIC_CONF1] = 0x001b, ++ [EEPROM_NIC_CONF2] = 0x001c, ++ [EEPROM_EIRP_MAX_TX_POWER] = 0x0020, ++ [EEPROM_FREQ] = 0x0022, ++ [EEPROM_LED_AG_CONF] = 0x0023, ++ [EEPROM_LED_ACT_CONF] = 0x0024, ++ [EEPROM_LED_POLARITY] = 0x0025, ++ [EEPROM_LNA] = 0x0026, ++ [EEPROM_EXT_LNA2] = 0x0027, ++ [EEPROM_RSSI_BG] = 0x0028, ++ [EEPROM_TXPOWER_DELTA] = 0x0028, /* Overlaps with RSSI_BG */ ++ [EEPROM_RSSI_BG2] = 0x0029, ++ [EEPROM_TXMIXER_GAIN_BG] = 0x0029, /* Overlaps with RSSI_BG2 */ ++ [EEPROM_RSSI_A] = 0x002a, ++ [EEPROM_RSSI_A2] = 0x002b, ++ [EEPROM_TXMIXER_GAIN_A] = 0x002b, /* Overlaps with RSSI_A2 */ ++ [EEPROM_TXPOWER_BG1] = 0x0030, ++ [EEPROM_TXPOWER_BG2] = 0x0037, ++ [EEPROM_EXT_TXPOWER_BG3] = 0x003e, ++ [EEPROM_TSSI_BOUND_BG1] = 0x0045, ++ [EEPROM_TSSI_BOUND_BG2] = 0x0046, ++ [EEPROM_TSSI_BOUND_BG3] = 0x0047, ++ [EEPROM_TSSI_BOUND_BG4] = 0x0048, ++ [EEPROM_TSSI_BOUND_BG5] = 0x0049, ++ [EEPROM_TXPOWER_A1] = 0x004b, ++ [EEPROM_TXPOWER_A2] = 0x0065, ++ [EEPROM_EXT_TXPOWER_A3] = 0x007f, ++ [EEPROM_TSSI_BOUND_A1] = 0x009a, ++ [EEPROM_TSSI_BOUND_A2] = 0x009b, ++ [EEPROM_TSSI_BOUND_A3] = 0x009c, ++ [EEPROM_TSSI_BOUND_A4] = 0x009d, ++ [EEPROM_TSSI_BOUND_A5] = 0x009e, ++ [EEPROM_TXPOWER_BYRATE] = 0x00a0, ++}; ++ ++static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, ++ const enum rt2800_eeprom_word word) ++{ ++ const unsigned int *map; ++ unsigned int index; ++ ++ if (WARN_ONCE(word >= EEPROM_WORD_COUNT, ++ "%s: invalid EEPROM word %d\n", ++ wiphy_name(rt2x00dev->hw->wiphy), word)) ++ return 0; ++ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ map = rt2800_eeprom_map_ext; ++ else ++ map = rt2800_eeprom_map; ++ ++ index = map[word]; ++ ++ /* Index 0 is valid only for EEPROM_CHIP_ID. ++ * Otherwise it means that the offset of the ++ * given word is not initialized in the map, ++ * or that the field is not usable on the ++ * actual chipset. ++ */ ++ WARN_ONCE(word != EEPROM_CHIP_ID && index == 0, ++ "%s: invalid access of EEPROM word %d\n", ++ wiphy_name(rt2x00dev->hw->wiphy), word); ++ ++ return index; ++} ++ ++static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev, ++ const enum rt2800_eeprom_word word) ++{ ++ unsigned int index; ++ ++ index = rt2800_eeprom_word_index(rt2x00dev, word); ++ return rt2x00_eeprom_addr(rt2x00dev, index); ++} ++ ++static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev, ++ const enum rt2800_eeprom_word word, u16 *data) ++{ ++ unsigned int index; ++ ++ index = rt2800_eeprom_word_index(rt2x00dev, word); ++ rt2x00_eeprom_read(rt2x00dev, index, data); ++} ++ ++static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, ++ const enum rt2800_eeprom_word word, u16 data) ++{ ++ unsigned int index; ++ ++ index = rt2800_eeprom_word_index(rt2x00dev, word); ++ rt2x00_eeprom_write(rt2x00dev, index, data); ++} ++ ++static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, ++ const enum rt2800_eeprom_word array, ++ unsigned int offset, ++ u16 *data) ++{ ++ unsigned int index; ++ ++ index = rt2800_eeprom_word_index(rt2x00dev, array); ++ rt2x00_eeprom_read(rt2x00dev, index + offset, data); ++} ++ + static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) + { + u32 reg; +@@ -370,6 +521,29 @@ void rt2800_disable_wpdma(struct rt2x00_ + } + EXPORT_SYMBOL_GPL(rt2800_disable_wpdma); + ++void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, ++ unsigned short *txwi_size, ++ unsigned short *rxwi_size) ++{ ++ switch (rt2x00dev->chip.rt) { ++ case RT3593: ++ *txwi_size = TXWI_DESC_SIZE_4WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_5WORDS; ++ break; ++ ++ case RT5592: ++ *txwi_size = TXWI_DESC_SIZE_5WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_6WORDS; ++ break; ++ ++ default: ++ *txwi_size = TXWI_DESC_SIZE_4WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_4WORDS; ++ break; ++ } ++} ++EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size); ++ + static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) + { + u16 fw_crc; +@@ -609,16 +783,16 @@ static int rt2800_agc_to_rssi(struct rt2 + u8 offset2; + + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); + offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); + offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2); + } else { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); + offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0); + offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1); +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2); + } + +@@ -766,6 +940,18 @@ void rt2800_txdone_entry(struct queue_en + } + EXPORT_SYMBOL_GPL(rt2800_txdone_entry); + ++static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, ++ unsigned int index) ++{ ++ return HW_BEACON_BASE(index); ++} ++ ++static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev, ++ unsigned int index) ++{ ++ return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index)); ++} ++ + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) + { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +@@ -818,7 +1004,8 @@ void rt2800_write_beacon(struct queue_en + return; + } + +- beacon_base = HW_BEACON_OFFSET(entry->entry_idx); ++ beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); ++ + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); + +@@ -837,10 +1024,13 @@ void rt2800_write_beacon(struct queue_en + EXPORT_SYMBOL_GPL(rt2800_write_beacon); + + static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, +- unsigned int beacon_base) ++ unsigned int index) + { + int i; + const int txwi_desc_size = rt2x00dev->bcn->winfo_size; ++ unsigned int beacon_base; ++ ++ beacon_base = rt2800_hw_beacon_base(rt2x00dev, index); + + /* + * For the Beacon base registers we only need to clear +@@ -867,8 +1057,7 @@ void rt2800_clear_beacon(struct queue_en + /* + * Clear beacon. + */ +- rt2800_clear_beacon_register(rt2x00dev, +- HW_BEACON_OFFSET(entry->entry_idx)); ++ rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx); + + /* + * Enabled beaconing again. +@@ -890,6 +1079,9 @@ const struct rt2x00debug rt2800_rt2x00de + .word_count = CSR_REG_SIZE / sizeof(u32), + }, + .eeprom = { ++ /* NOTE: The local EEPROM access functions can't ++ * be used here, use the generic versions instead. ++ */ + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, + .word_base = EEPROM_BASE, +@@ -1547,7 +1739,7 @@ static void rt2800_config_3572bt_ant(str + led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; + if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || + led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); + if (led_ctrl == 0 || led_ctrl > 0x40) { + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); +@@ -1609,7 +1801,7 @@ void rt2800_config_ant(struct rt2x00_dev + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: +- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); ++ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + } + +@@ -1622,7 +1814,7 @@ void rt2800_config_ant(struct rt2x00_dev + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3352) || + rt2x00_rt(rt2x00dev, RT3390)) { +- rt2x00_eeprom_read(rt2x00dev, ++ rt2800_eeprom_read(rt2x00dev, + EEPROM_NIC_CONF1, &eeprom); + if (rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_ANT_DIVERSITY)) +@@ -1649,6 +1841,13 @@ 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 (ant->rx_chain_num == 1) ++ rt2800_bbp_write(rt2x00dev, 86, 0x00); ++ else ++ rt2800_bbp_write(rt2x00dev, 86, 0x46); ++ } + } + EXPORT_SYMBOL_GPL(rt2800_config_ant); + +@@ -1659,22 +1858,73 @@ static void rt2800_config_lna_gain(struc + short lna_gain; + + if (libconf->rf.channel <= 14) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); + } else if (libconf->rf.channel <= 64) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); +- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); ++ if (rt2x00_rt(rt2x00dev, RT3593)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_EXT_LNA2_A1); ++ } else { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_RSSI_BG2_LNA_A1); ++ } + } else { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); +- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); ++ if (rt2x00_rt(rt2x00dev, RT3593)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_EXT_LNA2_A2); ++ } else { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_RSSI_A2_LNA_A2); ++ } + } + + rt2x00dev->lna_gain = lna_gain; + } + ++#define FREQ_OFFSET_BOUND 0x5f ++ ++static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 freq_offset, prev_freq_offset; ++ u8 rfcsr, prev_rfcsr; ++ ++ freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); ++ freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); ++ ++ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); ++ prev_rfcsr = rfcsr; ++ ++ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); ++ if (rfcsr == prev_rfcsr) ++ return; ++ ++ if (rt2x00_is_usb(rt2x00dev)) { ++ rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, ++ freq_offset, prev_rfcsr); ++ return; ++ } ++ ++ prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); ++ while (prev_freq_offset != freq_offset) { ++ if (prev_freq_offset < freq_offset) ++ prev_freq_offset++; ++ else ++ prev_freq_offset--; ++ ++ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); ++ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); ++ ++ usleep_range(1000, 1500); ++ } ++} ++ + static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, +@@ -1993,22 +2243,306 @@ static void rt2800_config_channel_rf3052 + rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + } + +-#define POWER_BOUND 0x27 +-#define POWER_BOUND_5G 0x2b +-#define FREQ_OFFSET_BOUND 0x5f +- +-static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) ++static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_conf *conf, ++ struct rf_channel *rf, ++ struct channel_info *info) + { ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ u8 txrx_agc_fc; ++ u8 txrx_h20m; + u8 rfcsr; ++ u8 bbp; ++ const bool txbf_enabled = false; /* TODO */ + +- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); +- if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) +- rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); ++ /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */ ++ rt2800_bbp_read(rt2x00dev, 109, &bbp); ++ rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0); ++ rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0); ++ rt2800_bbp_write(rt2x00dev, 109, bbp); ++ ++ rt2800_bbp_read(rt2x00dev, 110, &bbp); ++ rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0); ++ rt2800_bbp_write(rt2x00dev, 110, bbp); ++ ++ if (rf->channel <= 14) { ++ /* Restore BBP 25 & 26 for 2.4 GHz */ ++ rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); ++ rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); ++ } else { ++ /* Hard code BBP 25 & 26 for 5GHz */ ++ ++ /* Enable IQ Phase correction */ ++ rt2800_bbp_write(rt2x00dev, 25, 0x09); ++ /* Setup IQ Phase correction value */ ++ rt2800_bbp_write(rt2x00dev, 26, 0xff); ++ } ++ ++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); ++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf); ++ ++ rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3)); ++ rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1); ++ if (rf->channel <= 14) ++ rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1); + else +- rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); +- rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2); ++ rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr); ++ if (rf->channel <= 14) { ++ rfcsr = 0; ++ rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, ++ info->default_power1 & 0x1f); ++ } else { ++ if (rt2x00_is_usb(rt2x00dev)) ++ rfcsr = 0x40; ++ ++ rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, ++ ((info->default_power1 & 0x18) << 1) | ++ (info->default_power1 & 7)); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 53, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr); ++ if (rf->channel <= 14) { ++ rfcsr = 0; ++ rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, ++ info->default_power2 & 0x1f); ++ } else { ++ if (rt2x00_is_usb(rt2x00dev)) ++ rfcsr = 0x40; ++ ++ rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, ++ ((info->default_power2 & 0x18) << 1) | ++ (info->default_power2 & 7)); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 55, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr); ++ if (rf->channel <= 14) { ++ rfcsr = 0; ++ rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, ++ info->default_power3 & 0x1f); ++ } else { ++ if (rt2x00_is_usb(rt2x00dev)) ++ rfcsr = 0x40; ++ ++ rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, ++ ((info->default_power3 & 0x18) << 1) | ++ (info->default_power3 & 7)); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 54, rfcsr); ++ ++ 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); ++ ++ if (conf_is_ht40(conf)) { ++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, ++ RFCSR24_TX_AGC_FC); ++ txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40, ++ RFCSR24_TX_H20M); ++ } else { ++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20, ++ RFCSR24_TX_AGC_FC); ++ txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20, ++ RFCSR24_TX_H20M); ++ } ++ ++ /* NOTE: the reference driver does not writes the new value ++ * back to RFCSR 32 ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc); ++ ++ if (rf->channel <= 14) ++ rfcsr = 0xa0; ++ else ++ rfcsr = 0x80; ++ rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m); ++ rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m); ++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); ++ ++ /* Band selection */ ++ 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); ++ ++ rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr); ++ if (rf->channel <= 14) ++ rfcsr = 0x3c; ++ else ++ rfcsr = 0x20; ++ rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); ++ if (rf->channel <= 14) ++ rfcsr = 0x1a; ++ else ++ rfcsr = 0x12; ++ rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); ++ if (rf->channel >= 1 && rf->channel <= 14) ++ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); ++ else if (rf->channel >= 36 && rf->channel <= 64) ++ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); ++ else if (rf->channel >= 100 && rf->channel <= 128) ++ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); ++ else ++ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); ++ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); ++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); ++ ++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60); ++ ++ if (rf->channel <= 14) { ++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); ++ } else { ++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd8); ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x23); ++ } ++ ++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1); ++ rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); ++ if (rf->channel <= 14) { ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5); ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3); ++ } else { ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4); ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); ++ if (rf->channel <= 14) ++ rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3); ++ else ++ rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2); ++ ++ if (txbf_enabled) ++ rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1); ++ ++ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0); ++ rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); ++ if (rf->channel <= 14) ++ rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b); ++ else ++ rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f); ++ rt2800_rfcsr_write(rt2x00dev, 57, rfcsr); ++ ++ if (rf->channel <= 14) { ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45); ++ } else { ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05); ++ } ++ ++ /* Initiate VCO calibration */ ++ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); ++ if (rf->channel <= 14) { ++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); ++ } else { ++ rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); ++ ++ if (rf->channel >= 1 && rf->channel <= 14) { ++ rfcsr = 0x23; ++ if (txbf_enabled) ++ rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); ++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); ++ ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); ++ } else if (rf->channel >= 36 && rf->channel <= 64) { ++ rfcsr = 0x36; ++ if (txbf_enabled) ++ rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x36); ++ ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xeb); ++ } else if (rf->channel >= 100 && rf->channel <= 128) { ++ rfcsr = 0x32; ++ if (txbf_enabled) ++ rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); ++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); ++ ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xb3); ++ } else { ++ rfcsr = 0x30; ++ if (txbf_enabled) ++ rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); ++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); ++ ++ rt2800_rfcsr_write(rt2x00dev, 45, 0x9b); ++ } + } + ++#define POWER_BOUND 0x27 ++#define POWER_BOUND_5G 0x2b ++ + static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, +@@ -2563,6 +3097,23 @@ static void rt2800_iq_calibrate(struct r + rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); + } + ++static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, ++ unsigned int channel, ++ char txpower) ++{ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ 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)) ++ return clamp_t(char, txpower, MIN_A_TXPOWER_3593, ++ MAX_A_TXPOWER_3593); ++ else ++ return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); ++} ++ + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, +@@ -2572,13 +3123,14 @@ static void rt2800_config_channel(struct + unsigned int tx_pin; + u8 bbp, rfcsr; + +- if (rf->channel <= 14) { +- info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); +- info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2); +- } else { +- info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1); +- info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2); +- } ++ info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, ++ info->default_power1); ++ info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, ++ info->default_power2); ++ if (rt2x00dev->default_ant.tx_chain_num > 2) ++ info->default_power3 = ++ rt2800_txpower_to_dev(rt2x00dev, rf->channel, ++ info->default_power3); + + switch (rt2x00dev->chip.rf) { + case RF2020: +@@ -2591,6 +3143,9 @@ static void rt2800_config_channel(struct + case RF3052: + rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); + break; ++ case RF3053: ++ rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info); ++ break; + case RF3290: + rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); + break; +@@ -2636,6 +3191,23 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 27, 0x20); + rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); ++ } else if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rf->channel > 14) { ++ /* Disable CCK Packet detection on 5GHz */ ++ rt2800_bbp_write(rt2x00dev, 70, 0x00); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 70, 0x0a); ++ } ++ ++ if (conf_is_ht40(conf)) ++ rt2800_bbp_write(rt2x00dev, 105, 0x04); ++ else ++ rt2800_bbp_write(rt2x00dev, 105, 0x34); ++ ++ 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); ++ rt2800_bbp_write(rt2x00dev, 77, 0x98); + } else { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +@@ -2651,16 +3223,27 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 82, 0x62); + rt2800_bbp_write(rt2x00dev, 75, 0x46); + } else { +- rt2800_bbp_write(rt2x00dev, 82, 0x84); ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ rt2800_bbp_write(rt2x00dev, 82, 0x62); ++ else ++ rt2800_bbp_write(rt2x00dev, 82, 0x84); + rt2800_bbp_write(rt2x00dev, 75, 0x50); + } ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ rt2800_bbp_write(rt2x00dev, 83, 0x8a); + } ++ + } else { + if (rt2x00_rt(rt2x00dev, RT3572)) + rt2800_bbp_write(rt2x00dev, 82, 0x94); ++ else if (rt2x00_rt(rt2x00dev, RT3593)) ++ rt2800_bbp_write(rt2x00dev, 82, 0x82); + else + rt2800_bbp_write(rt2x00dev, 82, 0xf2); + ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ rt2800_bbp_write(rt2x00dev, 83, 0x9a); ++ + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) + rt2800_bbp_write(rt2x00dev, 75, 0x46); + else +@@ -2731,6 +3314,41 @@ static void rt2800_config_channel(struct + if (rt2x00_rt(rt2x00dev, RT3572)) + rt2800_rfcsr_write(rt2x00dev, 8, 0x80); + ++ if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rt2x00_is_usb(rt2x00dev)) { ++ rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); ++ ++ /* Band selection. GPIO #8 controls all paths */ ++ rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); ++ if (rf->channel <= 14) ++ rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); ++ else ++ rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); ++ ++ rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); ++ rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); ++ ++ /* LNA PE control. ++ * GPIO #4 controls PE0 and PE1, ++ * GPIO #7 controls PE2 ++ */ ++ rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); ++ rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); ++ ++ rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); ++ } ++ ++ /* AGC init */ ++ if (rf->channel <= 14) ++ reg = 0x1c + 2 * rt2x00dev->lna_gain; ++ else ++ reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); ++ ++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); ++ ++ usleep_range(1000, 1500); ++ } ++ + if (rt2x00_rt(rt2x00dev, RT5592)) { + rt2800_bbp_write(rt2x00dev, 195, 141); + rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); +@@ -2790,6 +3408,13 @@ static int rt2800_get_gain_calibration_d + int i; + + /* ++ * First check if temperature compensation is supported. ++ */ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC)) ++ return 0; ++ ++ /* + * Read TSSI boundaries for temperature compensation from + * the EEPROM. + * +@@ -2798,62 +3423,62 @@ static int rt2800_get_gain_calibration_d + * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 + */ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); + tssi_bounds[0] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG1_MINUS4); + tssi_bounds[1] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG1_MINUS3); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); + tssi_bounds[2] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG2_MINUS2); + tssi_bounds[3] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG2_MINUS1); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); + tssi_bounds[4] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG3_REF); + tssi_bounds[5] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG3_PLUS1); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); + tssi_bounds[6] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG4_PLUS2); + tssi_bounds[7] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG4_PLUS3); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); + tssi_bounds[8] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG5_PLUS4); + + step = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG5_AGC_STEP); + } else { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); + tssi_bounds[0] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A1_MINUS4); + tssi_bounds[1] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A1_MINUS3); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); + tssi_bounds[2] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A2_MINUS2); + tssi_bounds[3] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A2_MINUS1); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); + tssi_bounds[4] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A3_REF); + tssi_bounds[5] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A3_PLUS1); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); + tssi_bounds[6] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A4_PLUS2); + tssi_bounds[7] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A4_PLUS3); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); + tssi_bounds[8] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A5_PLUS4); + +@@ -2899,7 +3524,7 @@ static int rt2800_get_txpower_bw_comp(st + u8 comp_type; + int comp_value = 0; + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); + + /* + * HT40 compensation not required. +@@ -2966,6 +3591,9 @@ static u8 rt2800_compensate_txpower(stru + u8 eirp_txpower_criterion; + u8 reg_limit; + ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return min_t(u8, txpower, 0xc); ++ + if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { + /* + * Check if eirp txpower exceed txpower_limit. +@@ -2974,12 +3602,12 @@ static u8 rt2800_compensate_txpower(stru + * .11b data rate need add additional 4dbm + * when calculating eirp txpower. + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, +- &eeprom); ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ 1, &eeprom); + criterion = rt2x00_get_field16(eeprom, + EEPROM_TXPOWER_BYRATE_RATE0); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, + &eeprom); + + if (band == IEEE80211_BAND_2GHZ) +@@ -3001,6 +3629,412 @@ static u8 rt2800_compensate_txpower(stru + return min_t(u8, txpower, 0xc); + } + ++ ++enum { ++ TX_PWR_CFG_0_IDX, ++ TX_PWR_CFG_1_IDX, ++ TX_PWR_CFG_2_IDX, ++ TX_PWR_CFG_3_IDX, ++ TX_PWR_CFG_4_IDX, ++ TX_PWR_CFG_5_IDX, ++ TX_PWR_CFG_6_IDX, ++ TX_PWR_CFG_7_IDX, ++ TX_PWR_CFG_8_IDX, ++ TX_PWR_CFG_9_IDX, ++ TX_PWR_CFG_0_EXT_IDX, ++ TX_PWR_CFG_1_EXT_IDX, ++ TX_PWR_CFG_2_EXT_IDX, ++ TX_PWR_CFG_3_EXT_IDX, ++ TX_PWR_CFG_4_EXT_IDX, ++ TX_PWR_CFG_IDX_COUNT, ++}; ++ ++static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_channel *chan, ++ int power_level) ++{ ++ u8 txpower; ++ u16 eeprom; ++ u32 regs[TX_PWR_CFG_IDX_COUNT]; ++ unsigned int offset; ++ enum ieee80211_band band = chan->band; ++ int delta; ++ int i; ++ ++ memset(regs, '\0', sizeof(regs)); ++ ++ /* TODO: adapt TX power reduction from the rt28xx code */ ++ ++ /* calculate temperature compensation delta */ ++ delta = rt2800_get_gain_calibration_delta(rt2x00dev); ++ ++ if (band == IEEE80211_BAND_5GHZ) ++ offset = 16; ++ else ++ offset = 0; ++ ++ if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ++ offset += 8; ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset, &eeprom); ++ ++ /* CCK 1MBS,2MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_CCK1_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_CCK1_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], ++ TX_PWR_CFG_0_EXT_CCK1_CH2, txpower); ++ ++ /* CCK 5.5MBS,11MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_CCK5_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_CCK5_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], ++ TX_PWR_CFG_0_EXT_CCK5_CH2, txpower); ++ ++ /* OFDM 6MBS,9MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_OFDM6_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_OFDM6_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], ++ TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower); ++ ++ /* OFDM 12MBS,18MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_OFDM12_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], ++ TX_PWR_CFG_0_OFDM12_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], ++ TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 1, &eeprom); ++ ++ /* OFDM 24MBS,36MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_OFDM24_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_OFDM24_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], ++ TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower); ++ ++ /* OFDM 48MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_OFDM48_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_OFDM48_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], ++ TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower); ++ ++ /* OFDM 54MBS */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_OFDM54_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_OFDM54_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_OFDM54_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 2, &eeprom); ++ ++ /* MCS 0,1 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_MCS0_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_MCS0_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], ++ TX_PWR_CFG_1_EXT_MCS0_CH2, txpower); ++ ++ /* MCS 2,3 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_MCS2_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], ++ TX_PWR_CFG_1_MCS2_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], ++ TX_PWR_CFG_1_EXT_MCS2_CH2, txpower); ++ ++ /* MCS 4,5 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS4_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS4_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], ++ TX_PWR_CFG_2_EXT_MCS4_CH2, txpower); ++ ++ /* MCS 6 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS6_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS6_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], ++ TX_PWR_CFG_2_EXT_MCS6_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 3, &eeprom); ++ ++ /* MCS 7 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_MCS7_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_MCS7_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], ++ TX_PWR_CFG_7_MCS7_CH2, txpower); ++ ++ /* MCS 8,9 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS8_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS8_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], ++ TX_PWR_CFG_2_EXT_MCS8_CH2, txpower); ++ ++ /* MCS 10,11 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS10_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], ++ TX_PWR_CFG_2_MCS10_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], ++ TX_PWR_CFG_2_EXT_MCS10_CH2, txpower); ++ ++ /* MCS 12,13 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_MCS12_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_MCS12_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], ++ TX_PWR_CFG_3_EXT_MCS12_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 4, &eeprom); ++ ++ /* MCS 14 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_MCS14_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_MCS14_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], ++ TX_PWR_CFG_3_EXT_MCS14_CH2, txpower); ++ ++ /* MCS 15 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS15_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS15_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS15_CH2, txpower); ++ ++ /* MCS 16,17 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS16_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS16_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS16_CH2, txpower); ++ ++ /* MCS 18,19 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS18_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS18_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], ++ TX_PWR_CFG_5_MCS18_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 5, &eeprom); ++ ++ /* MCS 20,21 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS20_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS20_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS20_CH2, txpower); ++ ++ /* MCS 22 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS22_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS22_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], ++ TX_PWR_CFG_6_MCS22_CH2, txpower); ++ ++ /* MCS 23 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS23_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS23_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], ++ TX_PWR_CFG_8_MCS23_CH2, txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 6, &eeprom); ++ ++ /* STBC, MCS 0,1 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_STBC0_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_STBC0_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], ++ TX_PWR_CFG_3_EXT_STBC0_CH2, txpower); ++ ++ /* STBC, MCS 2,3 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_STBC2_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], ++ TX_PWR_CFG_3_STBC2_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], ++ TX_PWR_CFG_3_EXT_STBC2_CH2, txpower); ++ ++ /* STBC, MCS 4,5 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0, ++ txpower); ++ ++ /* STBC, MCS 6 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2, ++ txpower); ++ ++ /* read the next four txpower values */ ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ offset + 7, &eeprom); ++ ++ /* STBC, MCS 7 */ ++ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); ++ txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, ++ txpower, delta); ++ rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], ++ TX_PWR_CFG_9_STBC7_CH0, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], ++ TX_PWR_CFG_9_STBC7_CH1, txpower); ++ rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], ++ TX_PWR_CFG_9_STBC7_CH2, txpower); ++ ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]); ++ ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT, ++ regs[TX_PWR_CFG_0_EXT_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT, ++ regs[TX_PWR_CFG_1_EXT_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT, ++ regs[TX_PWR_CFG_2_EXT_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT, ++ regs[TX_PWR_CFG_3_EXT_IDX]); ++ rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT, ++ regs[TX_PWR_CFG_4_EXT_IDX]); ++ ++ for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++) ++ rt2x00_dbg(rt2x00dev, ++ "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n", ++ (band == IEEE80211_BAND_5GHZ) ? '5' : '2', ++ (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ? ++ '4' : '2', ++ (i > TX_PWR_CFG_9_IDX) ? ++ (i - TX_PWR_CFG_9_IDX - 1) : i, ++ (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "", ++ (unsigned long) regs[i]); ++} ++ + /* + * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and + * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, +@@ -3010,9 +4044,9 @@ static u8 rt2800_compensate_txpower(stru + * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to + * current conditions (i.e. band, bandwidth, temperature, user settings). + */ +-static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, +- struct ieee80211_channel *chan, +- int power_level) ++static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_channel *chan, ++ int power_level) + { + u8 txpower, r1; + u16 eeprom; +@@ -3080,8 +4114,8 @@ static void rt2800_config_txpower(struct + rt2800_register_read(rt2x00dev, offset, ®); + + /* read the next four txpower values */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, +- &eeprom); ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ i, &eeprom); + + is_rate_b = i ? 0 : 1; + /* +@@ -3129,8 +4163,8 @@ static void rt2800_config_txpower(struct + rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); + + /* read the next four txpower values */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, +- &eeprom); ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, ++ i + 1, &eeprom); + + is_rate_b = 0; + /* +@@ -3184,6 +4218,16 @@ static void rt2800_config_txpower(struct + } + } + ++static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_channel *chan, ++ int power_level) ++{ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); ++ else ++ rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); ++} ++ + void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) + { + rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan, +@@ -3219,6 +4263,7 @@ void rt2800_vco_calibration(struct rt2x0 + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + break; ++ case RF3053: + case RF3290: + case RF5360: + case RF5370: +@@ -3442,17 +4487,25 @@ static int rt2800_init_registers(struct + return ret; + + rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); +- rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ +- rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ +- rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ +- rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ ++ rt2x00_set_field32(®, BCN_OFFSET0_BCN0, ++ rt2800_get_beacon_offset(rt2x00dev, 0)); ++ rt2x00_set_field32(®, BCN_OFFSET0_BCN1, ++ rt2800_get_beacon_offset(rt2x00dev, 1)); ++ rt2x00_set_field32(®, BCN_OFFSET0_BCN2, ++ rt2800_get_beacon_offset(rt2x00dev, 2)); ++ rt2x00_set_field32(®, BCN_OFFSET0_BCN3, ++ rt2800_get_beacon_offset(rt2x00dev, 3)); + rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg); + + rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); +- rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ +- rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ +- rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ +- rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ ++ rt2x00_set_field32(®, BCN_OFFSET1_BCN4, ++ rt2800_get_beacon_offset(rt2x00dev, 4)); ++ rt2x00_set_field32(®, BCN_OFFSET1_BCN5, ++ rt2800_get_beacon_offset(rt2x00dev, 5)); ++ rt2x00_set_field32(®, BCN_OFFSET1_BCN6, ++ rt2800_get_beacon_offset(rt2x00dev, 6)); ++ rt2x00_set_field32(®, BCN_OFFSET1_BCN7, ++ rt2800_get_beacon_offset(rt2x00dev, 7)); + rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg); + + rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); +@@ -3528,7 +4581,8 @@ static int rt2800_init_registers(struct + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, ++ &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x0000002c); +@@ -3559,6 +4613,23 @@ static int rt2800_init_registers(struct + } else if (rt2x00_rt(rt2x00dev, RT3572)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); ++ } else if (rt2x00_rt(rt2x00dev, RT3593)) { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); ++ if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, ++ &eeprom); ++ if (rt2x00_get_field16(eeprom, ++ EEPROM_NIC_CONF1_DAC_TEST)) ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, ++ 0x0000001f); ++ else ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, ++ 0x0000000f); ++ } else { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, ++ 0x00000000); ++ } + } else if (rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || + rt2x00_rt(rt2x00dev, RT5592)) { +@@ -3786,14 +4857,8 @@ static int rt2800_init_registers(struct + /* + * Clear all beacons + */ +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6); +- rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7); ++ for (i = 0; i < 8; i++) ++ rt2800_clear_beacon_register(rt2x00dev, i); + + if (rt2x00_is_usb(rt2x00dev)) { + rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); +@@ -3989,7 +5054,7 @@ static void rt2800_disable_unused_dac_ad + u8 value; + + rt2800_bbp_read(rt2x00dev, 138, &value); +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) + value |= 0x20; + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) +@@ -4332,6 +5397,22 @@ static void rt2800_init_bbp_3572(struct + rt2800_disable_unused_dac_adc(rt2x00dev); + } + ++static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_init_bbp_early(rt2x00dev); ++ ++ rt2800_bbp_write(rt2x00dev, 79, 0x13); ++ rt2800_bbp_write(rt2x00dev, 80, 0x05); ++ rt2800_bbp_write(rt2x00dev, 81, 0x33); ++ rt2800_bbp_write(rt2x00dev, 137, 0x0f); ++ ++ rt2800_bbp_write(rt2x00dev, 84, 0x19); ++ ++ /* Enable DC filter */ ++ if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E)) ++ rt2800_bbp_write(rt2x00dev, 103, 0xc0); ++} ++ + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) + { + int ant, div_mode; +@@ -4402,7 +5483,7 @@ static void rt2800_init_bbp_53xx(struct + + rt2800_disable_unused_dac_adc(rt2x00dev); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + div_mode = rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_ANT_DIVERSITY); + ant = (div_mode == 3) ? 1 : 0; +@@ -4488,7 +5569,7 @@ static void rt2800_init_bbp_5592(struct + + rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); + ant = (div_mode == 3) ? 1 : 0; + rt2800_bbp_read(rt2x00dev, 152, &value); +@@ -4547,6 +5628,9 @@ static void rt2800_init_bbp(struct rt2x0 + case RT3572: + rt2800_init_bbp_3572(rt2x00dev); + break; ++ case RT3593: ++ rt2800_init_bbp_3593(rt2x00dev); ++ return; + case RT5390: + case RT5392: + rt2800_init_bbp_53xx(rt2x00dev); +@@ -4557,7 +5641,8 @@ static void rt2800_init_bbp(struct rt2x0 + } + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); ++ rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i, ++ &eeprom); + + if (eeprom != 0xffff && eeprom != 0x0000) { + reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); +@@ -4728,7 +5813,7 @@ static void rt2800_normal_mode_setup_3xx + if (rt2x00_rt(rt2x00dev, RT3090)) { + /* Turn off unused DAC1 and ADC1 to reduce power consumption */ + rt2800_bbp_read(rt2x00dev, 138, &bbp); +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) + rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +@@ -4771,6 +5856,42 @@ static void rt2800_normal_mode_setup_3xx + } + } + ++static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ u8 rfcsr; ++ u8 tx_gain; ++ ++ rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0); ++ rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); ++ tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g, ++ RFCSR17_TXMIXER_GAIN); ++ rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain); ++ rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); ++ rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0); ++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); ++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); ++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); ++ ++ /* TODO: enable stream mode */ ++} ++ + static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev) + { + u8 reg; +@@ -4778,7 +5899,7 @@ static void rt2800_normal_mode_setup_5xx + + /* Turn off unused DAC1 and ADC1 to reduce power consumption */ + rt2800_bbp_read(rt2x00dev, 138, ®); +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) + rt2x00_set_field8(®, BBP138_RX_ADC1, 0); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +@@ -4884,7 +6005,8 @@ static void rt2800_init_rfcsr_30xx(struc + rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, ++ &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); + else +@@ -5152,6 +6274,136 @@ static void rt2800_init_rfcsr_3572(struc + rt2800_normal_mode_setup_3xxx(rt2x00dev); + } + ++static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 bbp; ++ bool txbf_enabled = false; /* FIXME */ ++ ++ rt2800_bbp_read(rt2x00dev, 105, &bbp); ++ if (rt2x00dev->default_ant.rx_chain_num == 1) ++ rt2x00_set_field8(&bbp, BBP105_MLD, 0); ++ else ++ rt2x00_set_field8(&bbp, BBP105_MLD, 1); ++ rt2800_bbp_write(rt2x00dev, 105, bbp); ++ ++ rt2800_bbp4_mac_if_ctrl(rt2x00dev); ++ ++ rt2800_bbp_write(rt2x00dev, 92, 0x02); ++ rt2800_bbp_write(rt2x00dev, 82, 0x82); ++ rt2800_bbp_write(rt2x00dev, 106, 0x05); ++ rt2800_bbp_write(rt2x00dev, 104, 0x92); ++ rt2800_bbp_write(rt2x00dev, 88, 0x90); ++ rt2800_bbp_write(rt2x00dev, 148, 0xc8); ++ rt2800_bbp_write(rt2x00dev, 47, 0x48); ++ rt2800_bbp_write(rt2x00dev, 120, 0x50); ++ ++ if (txbf_enabled) ++ rt2800_bbp_write(rt2x00dev, 163, 0xbd); ++ else ++ rt2800_bbp_write(rt2x00dev, 163, 0x9d); ++ ++ /* SNR mapping */ ++ rt2800_bbp_write(rt2x00dev, 142, 6); ++ rt2800_bbp_write(rt2x00dev, 143, 160); ++ rt2800_bbp_write(rt2x00dev, 142, 7); ++ rt2800_bbp_write(rt2x00dev, 143, 161); ++ rt2800_bbp_write(rt2x00dev, 142, 8); ++ rt2800_bbp_write(rt2x00dev, 143, 162); ++ ++ /* ADC/DAC control */ ++ rt2800_bbp_write(rt2x00dev, 31, 0x08); ++ ++ /* RX AGC energy lower bound in log2 */ ++ rt2800_bbp_write(rt2x00dev, 68, 0x0b); ++ ++ /* FIXME: BBP 105 owerwrite? */ ++ rt2800_bbp_write(rt2x00dev, 105, 0x04); ++ ++} ++ ++static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ u32 reg; ++ u8 rfcsr; ++ ++ /* Disable GPIO #4 and #7 function for LAN PE control */ ++ rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); ++ rt2x00_set_field32(®, GPIO_SWITCH_4, 0); ++ rt2x00_set_field32(®, GPIO_SWITCH_7, 0); ++ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); ++ ++ /* Initialize default register values */ ++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 3, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); ++ rt2800_rfcsr_write(rt2x00dev, 9, 0x02); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x4e); ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x78); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0x3b); ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); ++ rt2800_rfcsr_write(rt2x00dev, 35, 0xe0); ++ rt2800_rfcsr_write(rt2x00dev, 38, 0x86); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x23); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0xd3); ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); ++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60); ++ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); ++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86); ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x75); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45); ++ rt2800_rfcsr_write(rt2x00dev, 53, 0x18); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0x18); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x18); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); ++ ++ /* Initiate calibration */ ++ /* TODO: use rt2800_rf_init_calibration ? */ ++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); ++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); ++ ++ rt2800_adjust_freq_offset(rt2x00dev); ++ ++ rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1); ++ rt2800_rfcsr_write(rt2x00dev, 18, rfcsr); ++ ++ rt2800_register_read(rt2x00dev, LDO_CFG0, ®); ++ rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); ++ rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); ++ rt2800_register_write(rt2x00dev, LDO_CFG0, reg); ++ usleep_range(1000, 1500); ++ rt2800_register_read(rt2x00dev, LDO_CFG0, ®); ++ rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); ++ rt2800_register_write(rt2x00dev, LDO_CFG0, reg); ++ ++ /* Set initial values for RX filter calibration */ ++ drv_data->calibration_bw20 = 0x1f; ++ drv_data->calibration_bw40 = 0x2f; ++ ++ /* Save BBP 25 & 26 values for later use in channel switching */ ++ rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); ++ rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); ++ ++ rt2800_led_open_drain_enable(rt2x00dev); ++ rt2800_normal_mode_setup_3593(rt2x00dev); ++ ++ rt3593_post_bbp_init(rt2x00dev); ++ ++ /* TODO: enable stream mode support */ ++} ++ + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +@@ -5380,6 +6632,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3572: + rt2800_init_rfcsr_3572(rt2x00dev); + break; ++ case RT3593: ++ rt2800_init_rfcsr_3593(rt2x00dev); ++ break; + case RT5390: + rt2800_init_rfcsr_5390(rt2x00dev); + break; +@@ -5456,15 +6711,15 @@ int rt2800_enable_radio(struct rt2x00_de + /* + * Initialize LED control + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff, + word & 0xff, (word >> 8) & 0xff); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff, + word & 0xff, (word >> 8) & 0xff); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff, + word & 0xff, (word >> 8) & 0xff); + +@@ -5560,6 +6815,34 @@ int rt2800_read_eeprom_efuse(struct rt2x + } + EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); + ++static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev) ++{ ++ u16 word; ++ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return 0; ++ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); ++ if ((word & 0x00ff) != 0x00ff) ++ return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); ++ ++ return 0; ++} ++ ++static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) ++{ ++ u16 word; ++ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return 0; ++ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); ++ if ((word & 0x00ff) != 0x00ff) ++ return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); ++ ++ return 0; ++} ++ + static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) + { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +@@ -5578,18 +6861,18 @@ static int rt2800_validate_eeprom(struct + /* + * Start validation of the data that has been read. + */ +- mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); ++ mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); + if (!is_valid_ether_addr(mac)) { + eth_random_addr(mac); + rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac); + } + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); + } else if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2872)) { +@@ -5598,10 +6881,10 @@ static int rt2800_validate_eeprom(struct + */ + if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + } + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); +@@ -5618,24 +6901,24 @@ static int rt2800_validate_eeprom(struct + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); + rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); + } + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); + if ((word & 0x00ff) == 0x00ff) { + rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); + rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word); + } + if ((word & 0xff00) == 0xff00) { + rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, + LED_MODE_TXRX_ACTIVITY); + rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); + rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word); + } + +@@ -5644,56 +6927,61 @@ static int rt2800_validate_eeprom(struct + * lna0 as correct value. Note that EEPROM_LNA + * is never validated. + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word); + default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); +- if ((word & 0x00ff) != 0x00ff) { +- drv_data->txmixer_gain_24g = +- rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); +- } else { +- drv_data->txmixer_gain_24g = 0; +- } ++ drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); ++ 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_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, +- default_lna_gain); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); +- +- rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); +- if ((word & 0x00ff) != 0x00ff) { +- drv_data->txmixer_gain_5g = +- rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); +- } else { +- drv_data->txmixer_gain_5g = 0; ++ if (!rt2x00_rt(rt2x00dev, RT3593)) { ++ 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, ++ default_lna_gain); + } ++ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); ++ ++ drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); ++ 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_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, +- default_lna_gain); +- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); ++ if (!rt2x00_rt(rt2x00dev, RT3593)) { ++ 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, ++ default_lna_gain); ++ } ++ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); ++ ++ if (rt2x00_rt(rt2x00dev, RT3593)) { ++ 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) ++ rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, ++ default_lna_gain); ++ if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 || ++ rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff) ++ rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, ++ default_lna_gain); ++ rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word); ++ } + + return 0; + } +@@ -5707,7 +6995,7 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Read EEPROM word for configuration. + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + + /* + * Identify RF chipset by EEPROM value +@@ -5717,7 +7005,7 @@ static int rt2800_init_eeprom(struct rt2 + if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) +- rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +@@ -5731,6 +7019,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3021: + case RF3022: + case RF3052: ++ case RF3053: + case RF3290: + case RF3320: + case RF3322: +@@ -5757,7 +7046,7 @@ static int rt2800_init_eeprom(struct rt2 + rt2x00dev->default_ant.rx_chain_num = + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + + if (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3090) || +@@ -5810,7 +7099,7 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Read frequency offset and RF programming sequence. + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + + /* +@@ -5827,7 +7116,7 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Check if support EIRP tx power limit feature. + */ +- rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); + + if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < + EIRP_MAX_TX_POWER_LIMIT) +@@ -6109,12 +7398,79 @@ static const struct rf_channel rf_vals_5 + {196, 83, 0, 12, 1}, + }; + ++static const struct rf_channel rf_vals_3053[] = { ++ /* Channel, N, R, K */ ++ {1, 241, 2, 2}, ++ {2, 241, 2, 7}, ++ {3, 242, 2, 2}, ++ {4, 242, 2, 7}, ++ {5, 243, 2, 2}, ++ {6, 243, 2, 7}, ++ {7, 244, 2, 2}, ++ {8, 244, 2, 7}, ++ {9, 245, 2, 2}, ++ {10, 245, 2, 7}, ++ {11, 246, 2, 2}, ++ {12, 246, 2, 7}, ++ {13, 247, 2, 2}, ++ {14, 248, 2, 4}, ++ ++ {36, 0x56, 0, 4}, ++ {38, 0x56, 0, 6}, ++ {40, 0x56, 0, 8}, ++ {44, 0x57, 0, 0}, ++ {46, 0x57, 0, 2}, ++ {48, 0x57, 0, 4}, ++ {52, 0x57, 0, 8}, ++ {54, 0x57, 0, 10}, ++ {56, 0x58, 0, 0}, ++ {60, 0x58, 0, 4}, ++ {62, 0x58, 0, 6}, ++ {64, 0x58, 0, 8}, ++ ++ {100, 0x5B, 0, 8}, ++ {102, 0x5B, 0, 10}, ++ {104, 0x5C, 0, 0}, ++ {108, 0x5C, 0, 4}, ++ {110, 0x5C, 0, 6}, ++ {112, 0x5C, 0, 8}, ++ ++ /* NOTE: Channel 114 has been removed intentionally. ++ * The EEPROM contains no TX power values for that, ++ * and it is disabled in the vendor driver as well. ++ */ ++ ++ {116, 0x5D, 0, 0}, ++ {118, 0x5D, 0, 2}, ++ {120, 0x5D, 0, 4}, ++ {124, 0x5D, 0, 8}, ++ {126, 0x5D, 0, 10}, ++ {128, 0x5E, 0, 0}, ++ {132, 0x5E, 0, 4}, ++ {134, 0x5E, 0, 6}, ++ {136, 0x5E, 0, 8}, ++ {140, 0x5F, 0, 0}, ++ ++ {149, 0x5F, 0, 9}, ++ {151, 0x5F, 0, 11}, ++ {153, 0x60, 0, 1}, ++ {157, 0x60, 0, 5}, ++ {159, 0x60, 0, 7}, ++ {161, 0x60, 0, 9}, ++ {165, 0x61, 0, 1}, ++ {167, 0x61, 0, 3}, ++ {169, 0x61, 0, 5}, ++ {171, 0x61, 0, 7}, ++ {173, 0x61, 0, 9}, ++}; ++ + static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; + struct channel_info *info; + char *default_power1; + char *default_power2; ++ char *default_power3; + unsigned int i; + u16 eeprom; + u32 reg; +@@ -6149,7 +7505,7 @@ static int rt2800_probe_hw_mode(struct r + + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, +- rt2x00_eeprom_addr(rt2x00dev, ++ rt2800_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); + + /* +@@ -6165,7 +7521,7 @@ static int rt2800_probe_hw_mode(struct r + rt2x00dev->hw->max_report_rates = 7; + rt2x00dev->hw->max_rate_tries = 1; + +- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + + /* + * Initialize hw_mode information. +@@ -6200,6 +7556,10 @@ static int rt2800_probe_hw_mode(struct r + spec->supported_bands |= SUPPORT_BAND_5GHZ; + spec->num_channels = ARRAY_SIZE(rf_vals_3x); + spec->channels = rf_vals_3x; ++ } else if (rt2x00_rf(rt2x00dev, RF3053)) { ++ spec->supported_bands |= SUPPORT_BAND_5GHZ; ++ spec->num_channels = ARRAY_SIZE(rf_vals_3053); ++ spec->channels = rf_vals_3053; + } else if (rt2x00_rf(rt2x00dev, RF5592)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; + +@@ -6265,21 +7625,40 @@ static int rt2800_probe_hw_mode(struct r + + spec->channels_info = info; + +- default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); +- default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); ++ default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); ++ default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); ++ ++ if (rt2x00dev->default_ant.tx_chain_num > 2) ++ default_power3 = rt2800_eeprom_addr(rt2x00dev, ++ EEPROM_EXT_TXPOWER_BG3); ++ else ++ default_power3 = NULL; + + for (i = 0; i < 14; i++) { + info[i].default_power1 = default_power1[i]; + info[i].default_power2 = default_power2[i]; ++ if (default_power3) ++ info[i].default_power3 = default_power3[i]; + } + + if (spec->num_channels > 14) { +- default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); +- default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); ++ default_power1 = rt2800_eeprom_addr(rt2x00dev, ++ EEPROM_TXPOWER_A1); ++ default_power2 = rt2800_eeprom_addr(rt2x00dev, ++ EEPROM_TXPOWER_A2); ++ ++ if (rt2x00dev->default_ant.tx_chain_num > 2) ++ default_power3 = ++ rt2800_eeprom_addr(rt2x00dev, ++ EEPROM_EXT_TXPOWER_A3); ++ else ++ default_power3 = NULL; + + for (i = 14; i < spec->num_channels; i++) { + info[i].default_power1 = default_power1[i - 14]; + info[i].default_power2 = default_power2[i - 14]; ++ if (default_power3) ++ info[i].default_power3 = default_power3[i - 14]; + } + } + +@@ -6290,6 +7669,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3022: + case RF3320: + case RF3052: ++ case RF3053: + case RF3290: + case RF5360: + case RF5370: +@@ -6328,6 +7708,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3352: + case RT3390: + case RT3572: ++ case RT3593: + case RT5390: + case RT5392: + case RT5592: +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -226,4 +226,8 @@ int rt2800_get_survey(struct ieee80211_h + struct survey_info *survey); + void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); + ++void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, ++ unsigned short *txwi_size, ++ unsigned short *rxwi_size); ++ + #endif /* RT2800LIB_H */ +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -507,9 +507,13 @@ static int rt2800pci_init_registers(stru + rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + + if (rt2x00_is_pcie(rt2x00dev) && +- (rt2x00_rt(rt2x00dev, RT3572) || ++ (rt2x00_rt(rt2x00dev, RT3090) || ++ rt2x00_rt(rt2x00dev, RT3390) || ++ rt2x00_rt(rt2x00dev, RT3572) || ++ rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT5390) || +- rt2x00_rt(rt2x00dev, RT5392))) { ++ rt2x00_rt(rt2x00dev, RT5392) || ++ rt2x00_rt(rt2x00dev, RT5592))) { + rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); + rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); + rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +@@ -1189,12 +1193,17 @@ static const struct rt2x00lib_ops rt2800 + + static void rt2800pci_queue_init(struct data_queue *queue) + { ++ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; ++ unsigned short txwi_size, rxwi_size; ++ ++ rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); ++ + switch (queue->qid) { + case QID_RX: + queue->limit = 128; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = RXD_DESC_SIZE; +- queue->winfo_size = RXWI_DESC_SIZE_4WORDS; ++ queue->winfo_size = rxwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + +@@ -1205,7 +1214,7 @@ static void rt2800pci_queue_init(struct + queue->limit = 64; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = TXD_DESC_SIZE; +- queue->winfo_size = TXWI_DESC_SIZE_4WORDS; ++ queue->winfo_size = txwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + +@@ -1213,7 +1222,7 @@ static void rt2800pci_queue_init(struct + queue->limit = 8; + queue->data_size = 0; /* No DMA required for beacons */ + queue->desc_size = TXD_DESC_SIZE; +- queue->winfo_size = TXWI_DESC_SIZE_4WORDS; ++ queue->winfo_size = txwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -854,13 +854,7 @@ static void rt2800usb_queue_init(struct + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + unsigned short txwi_size, rxwi_size; + +- if (rt2x00_rt(rt2x00dev, RT5592)) { +- txwi_size = TXWI_DESC_SIZE_5WORDS; +- rxwi_size = RXWI_DESC_SIZE_6WORDS; +- } else { +- txwi_size = TXWI_DESC_SIZE_4WORDS; +- rxwi_size = RXWI_DESC_SIZE_4WORDS; +- } ++ rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); + + switch (queue->qid) { + case QID_RX: +@@ -1194,6 +1188,40 @@ static struct usb_device_id rt2800usb_de + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0284) }, + #endif ++#ifdef CPTCFG_RT2800USB_RT3573 ++ /* AirLive */ ++ { USB_DEVICE(0x1b75, 0x7733) }, ++ /* ASUS */ ++ { USB_DEVICE(0x0b05, 0x17bc) }, ++ { USB_DEVICE(0x0b05, 0x17ad) }, ++ /* Belkin */ ++ { USB_DEVICE(0x050d, 0x1103) }, ++ /* Cameo */ ++ { USB_DEVICE(0x148f, 0xf301) }, ++ /* Edimax */ ++ { USB_DEVICE(0x7392, 0x7733) }, ++ /* Hawking */ ++ { USB_DEVICE(0x0e66, 0x0020) }, ++ { USB_DEVICE(0x0e66, 0x0021) }, ++ /* I-O DATA */ ++ { USB_DEVICE(0x04bb, 0x094e) }, ++ /* Linksys */ ++ { USB_DEVICE(0x13b1, 0x003b) }, ++ /* Logitec */ ++ { USB_DEVICE(0x0789, 0x016b) }, ++ /* NETGEAR */ ++ { USB_DEVICE(0x0846, 0x9012) }, ++ { USB_DEVICE(0x0846, 0x9019) }, ++ /* Planex */ ++ { USB_DEVICE(0x2019, 0xed19) }, ++ /* Ralink */ ++ { USB_DEVICE(0x148f, 0x3573) }, ++ /* Sitecom */ ++ { USB_DEVICE(0x0df6, 0x0067) }, ++ { USB_DEVICE(0x0df6, 0x006a) }, ++ /* ZyXEL */ ++ { USB_DEVICE(0x0586, 0x3421) }, ++#endif + #ifdef CPTCFG_RT2800USB_RT53XX + /* Arcadyan */ + { USB_DEVICE(0x043e, 0x7a12) }, +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -211,6 +211,7 @@ struct channel_info { + short max_power; + short default_power1; + short default_power2; ++ short default_power3; + }; + + /* diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch index f47c1a5321..b86724153a 100644 --- a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch @@ -101,7 +101,7 @@ +} --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -549,6 +549,7 @@ struct rt2x00lib_ops { +@@ -550,6 +550,7 @@ struct rt2x00lib_ops { const u8 *data, const size_t len); int (*load_firmware) (struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len); @@ -109,7 +109,7 @@ /* * Device initialization/deinitialization handlers. -@@ -705,6 +706,7 @@ enum rt2x00_capability_flags { +@@ -706,6 +707,7 @@ enum rt2x00_capability_flags { REQUIRE_SW_SEQNO, REQUIRE_HT_TX_DESC, REQUIRE_PS_AUTOWAKE, @@ -117,7 +117,7 @@ /* * Capabilities -@@ -974,6 +976,11 @@ struct rt2x00_dev { +@@ -975,6 +977,11 @@ struct rt2x00_dev { const struct firmware *fw; /* @@ -164,7 +164,7 @@ select RT2X00_LIB_CRYPTO depends on CRC_CCITT depends on EEPROM_93CX6 -@@ -238,6 +239,9 @@ config RT2X00_LIB_FIRMWARE +@@ -244,6 +245,9 @@ config RT2X00_LIB_FIRMWARE config RT2X00_LIB_CRYPTO boolean @@ -186,7 +186,7 @@ obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -90,25 +90,11 @@ static void rt2800pci_mcu_status(struct +@@ -90,25 +90,11 @@ static void rt2800pci_mcu_status(struct rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } @@ -234,7 +234,7 @@ * Initialization functions. */ static bool rt2800pci_get_entry_state(struct queue_entry *entry) -@@ -1156,6 +1156,7 @@ static const struct rt2x00lib_ops rt2800 +@@ -1160,6 +1160,7 @@ static const struct rt2x00lib_ops rt2800 .get_firmware_name = rt2800pci_get_firmware_name, .check_firmware = rt2800_check_firmware, .load_firmware = rt2800_load_firmware, diff --git a/package/kernel/mac80211/patches/605-rt2x00-pci-eeprom.patch b/package/kernel/mac80211/patches/605-rt2x00-pci-eeprom.patch index bcbb435c1d..5e187c7e77 100644 --- a/package/kernel/mac80211/patches/605-rt2x00-pci-eeprom.patch +++ b/package/kernel/mac80211/patches/605-rt2x00-pci-eeprom.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -90,7 +90,7 @@ static void rt2800pci_mcu_status(struct +@@ -90,7 +90,7 @@ static void rt2800pci_mcu_status(struct rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } @@ -9,7 +9,7 @@ { memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE); return 0; -@@ -1093,8 +1093,9 @@ static int rt2800pci_read_eeprom(struct +@@ -1097,8 +1097,9 @@ static int rt2800pci_read_eeprom(struct { int retval; diff --git a/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch index 5e6e27de98..d9820be0d5 100644 --- a/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -37,7 +37,7 @@ num_rates += 4; --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -414,6 +414,7 @@ struct hw_mode_spec { +@@ -415,6 +415,7 @@ struct hw_mode_spec { unsigned int supported_bands; #define SUPPORT_BAND_2GHZ 0x00000001 #define SUPPORT_BAND_5GHZ 0x00000002 diff --git a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch index 0695b893b5..278df72b2d 100644 --- a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch +++ b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch @@ -31,7 +31,7 @@ { --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -1326,6 +1326,7 @@ static inline void rt2x00debug_dump_fram +@@ -1327,6 +1327,7 @@ static inline void rt2x00debug_dump_fram */ u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif); diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch index 15083d4847..122cd11932 100644 --- a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -2631,15 +2631,18 @@ static void rt2800_config_channel(struct +@@ -3186,11 +3186,17 @@ static void rt2800_config_channel(struct /* * Change BBP settings */ @@ -15,6 +15,17 @@ rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 86, 0x38); + rt2800_bbp_write(rt2x00dev, 83, 0x6a); + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rf->channel > 14) { + /* Disable CCK Packet detection on 5GHz */ +@@ -3204,14 +3210,8 @@ static void rt2800_config_channel(struct + else + rt2800_bbp_write(rt2x00dev, 105, 0x34); + +- 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); + rt2800_bbp_write(rt2x00dev, 77, 0x98); } else { - rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); @@ -22,7 +33,7 @@ rt2800_bbp_write(rt2x00dev, 86, 0); } -@@ -4971,6 +4974,12 @@ static void rt2800_init_rfcsr_3290(struc +@@ -6086,6 +6086,12 @@ static void rt2800_init_rfcsr_3290(struc static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) { @@ -35,7 +46,7 @@ rt2800_rf_init_calibration(rt2x00dev, 30); rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); -@@ -5006,15 +5015,30 @@ static void rt2800_init_rfcsr_3352(struc +@@ -6121,15 +6127,30 @@ static void rt2800_init_rfcsr_3352(struc rt2800_rfcsr_write(rt2x00dev, 31, 0x80); rt2800_rfcsr_write(rt2x00dev, 32, 0x80); rt2800_rfcsr_write(rt2x00dev, 33, 0x00); @@ -69,7 +80,7 @@ rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); -@@ -5022,15 +5046,20 @@ static void rt2800_init_rfcsr_3352(struc +@@ -6137,15 +6158,20 @@ static void rt2800_init_rfcsr_3352(struc rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); rt2800_rfcsr_write(rt2x00dev, 48, 0x14); rt2800_rfcsr_write(rt2x00dev, 49, 0x00); @@ -99,15 +110,15 @@ rt2800_rfcsr_write(rt2x00dev, 59, 0x00); rt2800_rfcsr_write(rt2x00dev, 60, 0x00); rt2800_rfcsr_write(rt2x00dev, 61, 0x00); -@@ -5715,6 +5744,7 @@ static int rt2800_init_eeprom(struct rt2 +@@ -6996,6 +7022,7 @@ static int rt2800_init_eeprom(struct rt2 * RT53xx: defined in "EEPROM_CHIP_ID" field */ if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) - rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); -@@ -5804,7 +5834,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +@@ -7086,7 +7113,8 @@ static int rt2800_init_eeprom(struct rt2 /* * Detect if this device has Bluetooth co-existence. */ @@ -117,14 +128,14 @@ __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); /* -@@ -5833,6 +5864,22 @@ static int rt2800_init_eeprom(struct rt2 +@@ -7115,6 +7143,22 @@ static int rt2800_init_eeprom(struct rt2 EIRP_MAX_TX_POWER_LIMIT) __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + /* + * Detect if device uses internal or external PA + */ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + + if (rt2x00_rt(rt2x00dev, RT3352)) { + if (!rt2x00_get_field16(eeprom, @@ -142,8 +153,8 @@ --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h -@@ -2153,6 +2153,12 @@ struct mac_iveiv_entry { - #define RFCSR31_RX_CALIB FIELD8(0x7f) +@@ -2299,6 +2299,12 @@ struct mac_iveiv_entry { + #define RFCSR36_RF_BS FIELD8(0x80) /* + * RFCSR 34: @@ -155,7 +166,7 @@ * RFCSR 38: */ #define RFCSR38_RX_LO1_EN FIELD8(0x20) -@@ -2163,6 +2169,18 @@ struct mac_iveiv_entry { +@@ -2310,6 +2316,18 @@ struct mac_iveiv_entry { #define RFCSR39_RX_LO2_EN FIELD8(0x80) /* @@ -174,25 +185,25 @@ * RFCSR 49: */ #define RFCSR49_TX FIELD8(0x3f) -@@ -2172,6 +2190,8 @@ struct mac_iveiv_entry { +@@ -2322,6 +2340,8 @@ struct mac_iveiv_entry { * RFCSR 50: */ #define RFCSR50_TX FIELD8(0x3f) +#define RFCSR50_TX0_EXT_PA FIELD8(0x02) +#define RFCSR50_TX1_EXT_PA FIELD8(0x10) #define RFCSR50_EP FIELD8(0xc0) - - /* -@@ -2260,6 +2280,8 @@ struct mac_iveiv_entry { + /* bits for RT3593 */ + #define RFCSR50_TX_LO1_EN FIELD8(0x20) +@@ -2469,6 +2489,8 @@ enum rt2800_eeprom_word { * INTERNAL_TX_ALC: 0: disable, 1: enable * BT_COEXIST: 0: disable, 1: enable * DAC_TEST: 0: disable, 1: enable + * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352) + * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352) */ - #define EEPROM_NIC_CONF1 0x001b #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) -@@ -2277,6 +2299,8 @@ struct mac_iveiv_entry { + #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) +@@ -2485,6 +2507,8 @@ enum rt2800_eeprom_word { #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) @@ -203,7 +214,7 @@ * EEPROM frequency --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -726,6 +726,8 @@ enum rt2x00_capability_flags { +@@ -727,6 +727,8 @@ enum rt2x00_capability_flags { CAPABILITY_DOUBLE_ANTENNA, CAPABILITY_BT_COEXIST, CAPABILITY_VCO_RECALIBRATION, diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch index 4d30ae88b7..d3a7c96d8e 100644 --- a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch @@ -1,7 +1,7 @@ --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -6156,6 +6156,27 @@ static const struct rf_channel rf_vals_5 - {196, 83, 0, 12, 1}, +@@ -7501,6 +7501,27 @@ static const struct rf_channel rf_vals_3 + {173, 0x61, 0, 9}, }; +/* @@ -28,7 +28,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -6235,7 +6256,6 @@ static int rt2800_probe_hw_mode(struct r +@@ -7581,7 +7602,6 @@ static int rt2800_probe_hw_mode(struct r rt2x00_rf(rt2x00dev, RF3022) || rt2x00_rf(rt2x00dev, RF3290) || rt2x00_rf(rt2x00dev, RF3320) || @@ -36,7 +36,7 @@ rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || -@@ -6243,6 +6263,12 @@ static int rt2800_probe_hw_mode(struct r +@@ -7589,6 +7609,12 @@ static int rt2800_probe_hw_mode(struct r rt2x00_rf(rt2x00dev, RF5392)) { spec->num_channels = 14; spec->channels = rf_vals_3x; @@ -49,7 +49,7 @@ } else if (rt2x00_rf(rt2x00dev, RF3052)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_3x); -@@ -6390,6 +6416,19 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -7761,6 +7787,19 @@ static int rt2800_probe_rt(struct rt2x00 return 0; } @@ -69,7 +69,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; -@@ -6419,6 +6458,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r +@@ -7790,6 +7829,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); /* @@ -87,7 +87,7 @@ retval = rt2800_probe_hw_mode(rt2x00dev); --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -409,6 +409,7 @@ static inline struct rt2x00_intf* vif_to +@@ -410,6 +410,7 @@ static inline struct rt2x00_intf* vif_to * @channels: Device/chipset specific channel values (See &struct rf_channel). * @channels_info: Additional information for channels (See &struct channel_info). * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). @@ -95,7 +95,7 @@ */ struct hw_mode_spec { unsigned int supported_bands; -@@ -425,6 +426,7 @@ struct hw_mode_spec { +@@ -426,6 +427,7 @@ struct hw_mode_spec { const struct channel_info *channels_info; struct ieee80211_sta_ht_cap ht; diff --git a/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch index 81125a96c2..4c4ae204b7 100644 --- a/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +++ b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -1309,11 +1309,18 @@ static int rt2800soc_probe(struct platfo +@@ -1318,11 +1318,18 @@ static int rt2800soc_probe(struct platfo return rt2x00soc_probe(pdev, &rt2800pci_ops); } diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch index e705a2ae01..48093516d5 100644 --- a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch +++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -6418,13 +6419,14 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -7789,13 +7790,14 @@ static int rt2800_probe_rt(struct rt2x00 int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) { diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch index ac308afaf4..0ee98df5db 100644 --- a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch +++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch @@ -10,7 +10,7 @@ #define RF5372 0x5372 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -2141,6 +2141,15 @@ static void rt2800_config_channel_rf53xx +@@ -2675,6 +2675,15 @@ static void rt2800_config_channel_rf53xx if (rf->channel <= 14) { int idx = rf->channel-1; @@ -26,7 +26,7 @@ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { /* r55/r59 value array of channel 1~14 */ -@@ -2598,6 +2607,7 @@ static void rt2800_config_channel(struct +@@ -3153,6 +3162,7 @@ static void rt2800_config_channel(struct case RF3322: rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); break; @@ -34,7 +34,7 @@ case RF5360: case RF5370: case RF5372: -@@ -2614,6 +2624,7 @@ static void rt2800_config_channel(struct +@@ -3169,6 +3179,7 @@ static void rt2800_config_channel(struct if (rt2x00_rf(rt2x00dev, RF3290) || rt2x00_rf(rt2x00dev, RF3322) || @@ -42,7 +42,7 @@ rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || -@@ -2778,7 +2789,8 @@ static void rt2800_config_channel(struct +@@ -3393,7 +3404,8 @@ static void rt2800_config_channel(struct /* * Clear update flag */ @@ -52,15 +52,15 @@ rt2800_bbp_read(rt2x00dev, 49, &bbp); rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); rt2800_bbp_write(rt2x00dev, 49, bbp); -@@ -3224,6 +3236,7 @@ void rt2800_vco_calibration(struct rt2x0 - rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +@@ -4259,6 +4271,7 @@ void rt2800_vco_calibration(struct rt2x0 break; + case RF3053: case RF3290: + case RF5350: case RF5360: case RF5370: case RF5372: -@@ -3569,6 +3582,8 @@ static int rt2800_init_registers(struct +@@ -4630,6 +4643,8 @@ static int rt2800_init_registers(struct rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); @@ -69,7 +69,7 @@ } else { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); -@@ -4216,9 +4231,13 @@ static void rt2800_init_bbp_3352(struct +@@ -5271,9 +5286,13 @@ static void rt2800_init_bbp_3352(struct rt2800_bbp_write(rt2x00dev, 82, 0x62); @@ -86,7 +86,7 @@ rt2800_bbp_write(rt2x00dev, 86, 0x38); -@@ -4232,9 +4251,13 @@ static void rt2800_init_bbp_3352(struct +@@ -5287,9 +5306,13 @@ static void rt2800_init_bbp_3352(struct rt2800_bbp_write(rt2x00dev, 104, 0x92); @@ -103,7 +103,7 @@ rt2800_bbp_write(rt2x00dev, 120, 0x50); -@@ -4259,6 +4282,13 @@ static void rt2800_init_bbp_3352(struct +@@ -5314,6 +5337,13 @@ static void rt2800_init_bbp_3352(struct rt2800_bbp_write(rt2x00dev, 143, 0xa2); rt2800_bbp_write(rt2x00dev, 148, 0xc8); @@ -117,7 +117,7 @@ } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) -@@ -4543,6 +4573,7 @@ static void rt2800_init_bbp(struct rt2x0 +@@ -5614,6 +5644,7 @@ static void rt2800_init_bbp(struct rt2x0 rt2800_init_bbp_3290(rt2x00dev); break; case RT3352: @@ -125,8 +125,8 @@ rt2800_init_bbp_3352(rt2x00dev); break; case RT3390: -@@ -5182,6 +5213,76 @@ static void rt2800_init_rfcsr_3572(struc - rt2800_normal_mode_setup_3xxx(rt2x00dev); +@@ -6424,6 +6455,76 @@ static void rt2800_init_rfcsr_3593(struc + /* TODO: enable stream mode support */ } +static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev) @@ -202,9 +202,9 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) { rt2800_rf_init_calibration(rt2x00dev, 2); -@@ -5410,6 +5511,9 @@ static void rt2800_init_rfcsr(struct rt2 - case RT3572: - rt2800_init_rfcsr_3572(rt2x00dev); +@@ -6655,6 +6756,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3593: + rt2800_init_rfcsr_3593(rt2x00dev); break; + case RT5350: + rt2800_init_rfcsr_5350(rt2x00dev); @@ -212,9 +212,9 @@ case RT5390: rt2800_init_rfcsr_5390(rt2x00dev); break; -@@ -5621,6 +5725,12 @@ static int rt2800_validate_eeprom(struct +@@ -6894,6 +6998,12 @@ static int rt2800_validate_eeprom(struct rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1); @@ -225,16 +225,16 @@ } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872)) { /* -@@ -5749,6 +5859,8 @@ static int rt2800_init_eeprom(struct rt2 +@@ -7027,6 +7137,8 @@ static int rt2800_init_eeprom(struct rt2 rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) - rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + else if (rt2x00_rt(rt2x00dev, RT5350)) + rf = RF5350; else rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); -@@ -5765,6 +5877,7 @@ static int rt2800_init_eeprom(struct rt2 +@@ -7044,6 +7156,7 @@ static int rt2800_init_eeprom(struct rt2 case RF3290: case RF3320: case RF3322: @@ -242,7 +242,7 @@ case RF5360: case RF5370: case RF5372: -@@ -6264,7 +6377,8 @@ static int rt2800_probe_hw_mode(struct r +@@ -7610,7 +7723,8 @@ static int rt2800_probe_hw_mode(struct r rt2x00_rf(rt2x00dev, RF5392)) { spec->num_channels = 14; spec->channels = rf_vals_3x; @@ -252,18 +252,18 @@ spec->num_channels = 14; if (spec->clk_is_20mhz) spec->channels = rf_vals_xtal20mhz_3x; -@@ -6365,6 +6479,7 @@ static int rt2800_probe_hw_mode(struct r - case RF3320: +@@ -7735,6 +7849,7 @@ static int rt2800_probe_hw_mode(struct r case RF3052: + case RF3053: case RF3290: + case RF5350: case RF5360: case RF5370: case RF5372: -@@ -6402,6 +6517,7 @@ static int rt2800_probe_rt(struct rt2x00 - case RT3352: +@@ -7773,6 +7888,7 @@ static int rt2800_probe_rt(struct rt2x00 case RT3390: case RT3572: + case RT3593: + case RT5350: case RT5390: case RT5392: diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch index 03f4ddd11b..0787cc352f 100644 --- a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -5966,6 +5967,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -7245,6 +7246,17 @@ static int rt2800_init_eeprom(struct rt2 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);