Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] rt2x00 : RT3290 chip support
@ 2012-04-27  2:22 Woody Hung
  2012-04-27  7:40 ` Helmut Schaa
  2012-05-11 12:05 ` Gertjan van Wingerde
  0 siblings, 2 replies; 5+ messages in thread
From: Woody Hung @ 2012-04-27  2:22 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, jay.hung, pohsun.yang, dennis.lee, Woody Hung

This support RT3290 chip

Signed-off-by: Woody Hung <Woody.Hung@mediatek.com>
---
 drivers/net/wireless/rt2x00/Kconfig     |    8 +
 drivers/net/wireless/rt2x00/rt2800.h    |  120 +++++++++-
 drivers/net/wireless/rt2x00/rt2800lib.c |  395 ++++++++++++++++++++++++++++--
 drivers/net/wireless/rt2x00/rt2800lib.h |    3 +-
 drivers/net/wireless/rt2x00/rt2800pci.c |   12 +
 drivers/net/wireless/rt2x00/rt2800pci.h |    3 +
 drivers/net/wireless/rt2x00/rt2x00.h    |    3 +-
 drivers/net/wireless/rt2x00/rt2x00pci.c |    6 +
 8 files changed, 520 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 299c387..c7548da 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
          rt2800pci driver.
          Supported chips: RT5390
 
+config RT2800PCI_RT3290
+       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       default y
+       ---help---
+         This adds support for rt3290 wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT3290
 endif
 
 config RT2500USB
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index d91f4f6..39b1685 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -70,7 +70,7 @@
 #define RF5370				0x5370
 #define RF5372				0x5372
 #define RF5390				0x5390
-
+#define RF3290				0x3290
 /*
  * Chipset revisions.
  */
@@ -112,6 +112,12 @@
  * Registers.
  */
 
+
+/*
+ * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
+ */
+#define MAC_CSR0_3290				0x0000
+
 /*
  * E2PROM_CSR: PCI EEPROM control register.
  * RELOAD: Write 1 to reload eeprom content.
@@ -305,6 +311,118 @@
 #define GPIO_CTRL_CFG_GPIOD_BIT7	FIELD32(0x00008000)
 
 /*
+ * WLAN_CTRL_CFG
+ */
+#define WLAN_FUN_CTRL			0x80
+#define WLAN_EN				FIELD32(0x00000001)
+#define WLAN_CLK_EN			FIELD32(0x00000002)
+#define WLAN_RSV1			FIELD32(0x00000004)
+#define WLAN_RESET			FIELD32(0x00000008)
+#define PCIE_APP0_CLK_REQ		FIELD32(0x00000010)
+#define FRC_WL_ANT_SET			FIELD32(0x00000020)
+#define INV_TR_SW0			FIELD32(0x00000040)
+#define WLAN_GPIO_IN_BIT0		FIELD32(0x00000100)
+#define WLAN_GPIO_IN_BIT1		FIELD32(0x00000200)
+#define WLAN_GPIO_IN_BIT2		FIELD32(0x00000400)
+#define WLAN_GPIO_IN_BIT3		FIELD32(0x00000800)
+#define WLAN_GPIO_IN_BIT4		FIELD32(0x00001000)
+#define WLAN_GPIO_IN_BIT5		FIELD32(0x00002000)
+#define WLAN_GPIO_IN_BIT6		FIELD32(0x00004000)
+#define WLAN_GPIO_IN_BIT7		FIELD32(0x00008000)
+#define WLAN_GPIO_IN_BIT_ALL		FIELD32(0x0000ff00)
+#define WLAN_GPIO_OUT_BIT0		FIELD32(0x00010000)
+#define WLAN_GPIO_OUT_BIT1		FIELD32(0x00020000)
+#define WLAN_GPIO_OUT_BIT2		FIELD32(0x00040000)
+#define WLAN_GPIO_OUT_BIT3		FIELD32(0x00050000)
+#define WLAN_GPIO_OUT_BIT4		FIELD32(0x00100000)
+#define WLAN_GPIO_OUT_BIT5		FIELD32(0x00200000)
+#define WLAN_GPIO_OUT_BIT6		FIELD32(0x00400000)
+#define WLAN_GPIO_OUT_BIT7		FIELD32(0x00800000)
+#define WLAN_GPIO_OUT_BIT_ALL		FIELD32(0x00ff0000)
+#define WLAN_GPIO_OUT_OE_BIT0		FIELD32(0x01000000)
+#define WLAN_GPIO_OUT_OE_BIT1		FIELD32(0x02000000)
+#define WLAN_GPIO_OUT_OE_BIT2		FIELD32(0x04000000)
+#define WLAN_GPIO_OUT_OE_BIT3		FIELD32(0x08000000)
+#define WLAN_GPIO_OUT_OE_BIT4		FIELD32(0x10000000)
+#define WLAN_GPIO_OUT_OE_BIT5		FIELD32(0x20000000)
+#define WLAN_GPIO_OUT_OE_BIT6		FIELD32(0x40000000)
+#define WLAN_GPIO_OUT_OE_BIT7		FIELD32(0x80000000)
+#define WLAN_GPIO_OUT_OE_BIT_ALL	FIELD32(0xff000000)
+
+/*
+ * CMB_CTRL_CFG
+ */
+#define CMB_CTRL		0x20
+#define AUX_OPT_BIT0		FIELD32(0x00000001)
+#define AUX_OPT_BIT1		FIELD32(0x00000002)
+#define AUX_OPT_BIT2		FIELD32(0x00000004)
+#define AUX_OPT_BIT3		FIELD32(0x00000008)
+#define AUX_OPT_BIT4		FIELD32(0x00000010)
+#define AUX_OPT_BIT5		FIELD32(0x00000020)
+#define AUX_OPT_BIT6		FIELD32(0x00000040)
+#define AUX_OPT_BIT7		FIELD32(0x00000080)
+#define AUX_OPT_BIT8		FIELD32(0x00000100)
+#define AUX_OPT_BIT9		FIELD32(0x00000200)
+#define AUX_OPT_BIT10		FIELD32(0x00000400)
+#define AUX_OPT_BIT11		FIELD32(0x00000800)
+#define AUX_OPT_BIT12		FIELD32(0x00001000)
+#define AUX_OPT_BIT13		FIELD32(0x00002000)
+#define AUX_OPT_BIT14		FIELD32(0x00004000)
+#define AUX_OPT_BIT15		FIELD32(0x00008000)
+#define LDO25_LEVEL		FIELD32(0x00030000)
+#define LDO25_LARGEA		FIELD32(0x00040000)
+#define LDO25_FRC_ON		FIELD32(0x00080000)
+#define CMB_RSV			FIELD32(0x00300000)
+#define XTAL_RDY		FIELD32(0x00400000)
+#define PLL_LD			FIELD32(0x00800000)
+#define LDO_CORE_LEVEL		FIELD32(0x0F000000)
+#define LDO_BGSEL		FIELD32(0x30000000)
+#define LDO3_EN			FIELD32(0x40000000)
+#define LDO0_EN			FIELD32(0x80000000)
+
+/*
+ * OSC_CTRL_CFG
+ */
+#define OSC_CTRL		0x38
+#define OSC_REF_CYCLE		FIELD32(0x00001fff)
+#define OSC_RSV			FIELD32(0x0000e000)
+#define OSC_CAL_CNT		FIELD32(0x0fff0000)
+#define OSC_CAL_ACK		FIELD32(0x10000000)
+#define OSC_CLK_32K_VLD		FIELD32(0x20000000)
+#define OSC_CAL_REQ		FIELD32(0x40000000)
+#define OSC_ROSC_EN		FIELD32(0x80000000)
+
+/*
+ * PLL_CTRL_CFG
+ */
+#define PLL_CTRL		0x50
+#define PLL_RESERVED_INPUT1	FIELD32(0x000000ff)
+#define PLL_RESERVED_INPUT2	FIELD32(0x0000ff00)
+#define PLL_CONTROL		FIELD32(0x00070000)
+#define PLL_LPF_R1		FIELD32(0x00080000)
+#define PLL_LPF_C1_CTRL	FIELD32(0x00300000)
+#define PLL_LPF_C2_CTRL	FIELD32(0x00c00000)
+#define PLL_CP_CURRENT_CTRL	FIELD32(0x03000000)
+#define PLL_PFD_DELAY_CTRL	FIELD32(0x0c000000)
+#define PLL_LOCK_CTRL		FIELD32(0x70000000)
+#define PLL_VBGBK_EN		FIELD32(0x80000000)
+
+/*
+ * COEX_CFG_0
+ */
+#define COEX_CFG0			0x40
+
+/*
+ * COEX_CFG_1
+ */
+#define COEX_CFG1			0x44
+
+/*
+ * COEX_CFG_2
+ */
+#define COEX_CFG2			0x48
+
+/*
  * MCU_CMD_CFG
  */
 #define MCU_CMD_CFG			0x022c
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 1cd16b4..7753791 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
 		multiple = true;
 	} else {
 		fw_len = 8192;
+
+		if (rt2x00_rt(rt2x00dev, RT3290))
+			fw_len = 4096;
+
 		multiple = true;
 	}
 
@@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00_is_pci(rt2x00dev)) {
 		if (rt2x00_rt(rt2x00dev, RT3572) ||
 		    rt2x00_rt(rt2x00dev, RT5390) ||
-		    rt2x00_rt(rt2x00dev, RT5392)) {
+		    rt2x00_rt(rt2x00dev, RT5392) ||
+		    rt2x00_rt(rt2x00dev, RT3290)) {
 			rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
 			rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
 			rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
 
+	if (rt2x00_rt(rt2x00dev, RT3290)) {
+		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+		return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
+	} else
 	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
 	return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
 }
@@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
 
 #define RT5390_POWER_BOUND     0x27
 #define RT5390_FREQ_OFFSET_BOUND       0x5f
-
+#define RT3290_POWER_BOUND     0x27
+#define RT3290_FREQ_OFFSET_BOUND       0x5f
 static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 					 struct ieee80211_conf *conf,
 					 struct rf_channel *rf,
@@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
 }
 
+
+static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr;
+
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+	if (info->default_power1 > RT5390_POWER_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
+				  RT3290_FREQ_OFFSET_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+	if (rf->channel <= 14) {
+		rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+		rfcsr &= ~0xF8;
+		rfcsr |= (0x1f << 3);
+		rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
+		rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+		rfcsr &= ~0xF8;
+		rfcsr |= (0x1f << 3);
+		rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+		if (rf->channel == 6)
+			rt2800_bbp_write(rt2x00dev, 68, 0x0c);
+		else
+			rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+		if (rf->channel >= 1 && rf->channel <= 6)
+			rt2800_bbp_write(rt2x00dev, 59, 0x0f);
+		else if (rf->channel >= 7 && rf->channel <= 11)
+			rt2800_bbp_write(rt2x00dev, 59, 0x0e);
+		else if (rf->channel >= 12 && rf->channel <= 14)
+			rt2800_bbp_write(rt2x00dev, 59, 0x0d);
+	}
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+}
 static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				  struct ieee80211_conf *conf,
 				  struct rf_channel *rf,
@@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	case RF5390:
 		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
 		break;
+	case RF3290:
+		rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+		break;
 	default:
 		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
 	}
@@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
 	case RF5370:
 	case RF5372:
 	case RF5390:
+	case RF3290:
 		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
 		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
@@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
 		    rt2x00_rt(rt2x00dev, RT3090) ||
 		    rt2x00_rt(rt2x00dev, RT3390) ||
 		    rt2x00_rt(rt2x00dev, RT5390) ||
-		    rt2x00_rt(rt2x00dev, RT5392))
+		    rt2x00_rt(rt2x00dev, RT5392) ||
+		    rt2x00_rt(rt2x00dev, RT3290))
 			return 0x1c + (2 * rt2x00dev->lna_gain);
 		else
 			return 0x2e + rt2x00dev->lna_gain;
@@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
 	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
 
+	if (rt2x00_rt(rt2x00dev, RT3290)) {
+		rt2800pci_3290_enable_wlan(rt2x00dev);
+		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+		if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
+			rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
+			rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+		}
+
+		rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+		if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
+			rt2x00_set_field32(&reg, LDO0_EN, 1);
+			rt2x00_set_field32(&reg, LDO_BGSEL, 1);
+			rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
+		}
+
+		rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+		rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+		rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+		rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+		rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
+		rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
+		rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+		rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+		reg &= ~(0xFF000000);
+		reg |= 0x5E000000;
+		rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
+		rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
+		rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+		rt2x00_set_field32(&reg, PLL_CONTROL, 1);
+		rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
+	}
+
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
-	    rt2x00_rt(rt2x00dev, RT3390)) {
+	    rt2x00_rt(rt2x00dev, RT3390) ||
+		rt2x00_rt(rt2x00dev, RT3290)) {
+
+		if (rt2x00_rt(rt2x00dev, RT3290))
+			rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+				0x00000404);
+		else
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
 		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		return -EACCES;
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392)) {
+		rt2x00_rt(rt2x00dev, RT5392)	||
+		rt2x00_rt(rt2x00dev, RT3290)) {
 		rt2800_bbp_read(rt2x00dev, 4, &value);
 		rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
 		rt2800_bbp_write(rt2x00dev, 4, value);
@@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	if (rt2800_is_305x_soc(rt2x00dev) ||
 	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390) ||
-	    rt2x00_rt(rt2x00dev, RT5392))
+	    rt2x00_rt(rt2x00dev, RT5392) ||
+	    rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 31, 0x08);
 
 	rt2800_bbp_write(rt2x00dev, 65, 0x2c);
 	rt2800_bbp_write(rt2x00dev, 66, 0x38);
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 68, 0x0b);
 
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
 		rt2800_bbp_write(rt2x00dev, 69, 0x16);
 		rt2800_bbp_write(rt2x00dev, 73, 0x12);
 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
-			   rt2x00_rt(rt2x00dev, RT5392)) {
+			rt2x00_rt(rt2x00dev, RT5392) ||
+			rt2x00_rt(rt2x00dev, RT3290)) {
 		rt2800_bbp_write(rt2x00dev, 69, 0x12);
 		rt2800_bbp_write(rt2x00dev, 73, 0x13);
 		rt2800_bbp_write(rt2x00dev, 75, 0x46);
 		rt2800_bbp_write(rt2x00dev, 76, 0x28);
+
+		if (rt2x00_rt(rt2x00dev, RT3290))
+			rt2800_bbp_write(rt2x00dev, 77, 0x58);
+		else
 		rt2800_bbp_write(rt2x00dev, 77, 0x59);
 	} else {
 		rt2800_bbp_write(rt2x00dev, 69, 0x12);
@@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 81, 0x37);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT3290)) {
+		rt2800_bbp_write(rt2x00dev, 74, 0x0b);
+		rt2800_bbp_write(rt2x00dev, 79, 0x18);
+		rt2800_bbp_write(rt2x00dev, 80, 0x09);
+		rt2800_bbp_write(rt2x00dev, 81, 0x33);
+	}
+
 	rt2800_bbp_write(rt2x00dev, 82, 0x62);
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 83, 0x7a);
 	else
 		rt2800_bbp_write(rt2x00dev, 83, 0x6a);
@@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
 		rt2800_bbp_write(rt2x00dev, 84, 0x19);
 	else if (rt2x00_rt(rt2x00dev, RT5390) ||
-			 rt2x00_rt(rt2x00dev, RT5392))
+			rt2x00_rt(rt2x00dev, RT5392) ||
+			rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 84, 0x9a);
 	else
 		rt2800_bbp_write(rt2x00dev, 84, 0x99);
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 86, 0x38);
 	else
 		rt2800_bbp_write(rt2x00dev, 86, 0x00);
@@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	rt2800_bbp_write(rt2x00dev, 91, 0x04);
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 92, 0x02);
 	else
 		rt2800_bbp_write(rt2x00dev, 92, 0x00);
@@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2x00_rt(rt2x00dev, RT5392) ||
+	    rt2x00_rt(rt2x00dev, RT3290) ||
 	    rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 	else
 		rt2800_bbp_write(rt2x00dev, 103, 0x00);
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 104, 0x92);
 
 	if (rt2800_is_305x_soc(rt2x00dev))
@@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	else if (rt2x00_rt(rt2x00dev, RT5390) ||
 			 rt2x00_rt(rt2x00dev, RT5392))
 		rt2800_bbp_write(rt2x00dev, 105, 0x3c);
+	else if (rt2x00_rt(rt2x00dev, RT3290))
+		rt2800_bbp_write(rt2x00dev, 105, 0x1c);
 	else
 		rt2800_bbp_write(rt2x00dev, 105, 0x05);
 
-	if (rt2x00_rt(rt2x00dev, RT5390))
+	if (rt2x00_rt(rt2x00dev, RT5390) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 106, 0x03);
 	else if (rt2x00_rt(rt2x00dev, RT5392))
 		rt2800_bbp_write(rt2x00dev, 106, 0x12);
@@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 106, 0x35);
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290))
 		rt2800_bbp_write(rt2x00dev, 128, 0x12);
 
 	if (rt2x00_rt(rt2x00dev, RT5392)) {
@@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 138, value);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT3290)) {
+		rt2800_bbp_write(rt2x00dev, 67, 0x24);
+		rt2800_bbp_write(rt2x00dev, 143, 0x04);
+		rt2800_bbp_write(rt2x00dev, 142, 0x99);
+		rt2800_bbp_write(rt2x00dev, 150, 0x30);
+		rt2800_bbp_write(rt2x00dev, 151, 0x2e);
+		rt2800_bbp_write(rt2x00dev, 152, 0x20);
+		rt2800_bbp_write(rt2x00dev, 153, 0x34);
+		rt2800_bbp_write(rt2x00dev, 154, 0x40);
+		rt2800_bbp_write(rt2x00dev, 155, 0x3b);
+		rt2800_bbp_write(rt2x00dev, 253, 0x04);
+
+		rt2800_bbp_read(rt2x00dev, 47, &value);
+		rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
+		rt2800_bbp_write(rt2x00dev, 47, value);
+
+		rt2800_bbp_read(rt2x00dev, 3, &value);
+		value &= (~0xc0);
+		value |= 0xc0;
+		rt2800_bbp_write(rt2x00dev, 3, value);
+	}
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
 		rt2x00_rt(rt2x00dev, RT5392)) {
 		int ant, div_mode;
@@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rt(rt2x00dev, RT3572) &&
 	    !rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2x00_rt(rt2x00dev, RT5392) &&
+	    !rt2x00_rt(rt2x00dev, RT3290) &&
 	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
 
@@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	 * Init RF calibration.
 	 */
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-		rt2x00_rt(rt2x00dev, RT5392)) {
+		rt2x00_rt(rt2x00dev, RT5392) ||
+		rt2x00_rt(rt2x00dev, RT3290)) {
 		rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
 		rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
@@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 			rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
 			rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
 			rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+	} else if (rt2x00_rt(rt2x00dev, RT3290)) {
+			rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+			rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+			rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+			rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+			rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+			rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
+			rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+			rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+			rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+			rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+			rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+			rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
+			rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
+			rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+			rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+			rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+			rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+			rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+			rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+			rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+			rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
+			rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+			rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+			rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+			rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+			rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+			rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+			rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+			rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
+			rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+			rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+			rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+			rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+			rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+			rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
+			rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+			rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+			rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+			rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+			rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
+			rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+			rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+			rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
+			rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+			rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
 	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT3290)) {
+		rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+		rfcsr = ((rfcsr & ~0xc0) | 0xc0);
+		rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+	}
+
 	return 0;
 }
 
@@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
 int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
+	u16 efuse_ctrl_reg;
+	efuse_ctrl_reg = EFUSE_CTRL;
 
-	rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+	if (rt2x00dev->chip.mac_version == 0x3290)
+		efuse_ctrl_reg = 0x24;
 
+	rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
 	return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
 }
 EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
 {
 	u32 reg;
 
+	u16 efuse_ctrl_reg;
+	u16 efuse_data0_reg;
+	u16 efuse_data1_reg;
+	u16 efuse_data2_reg;
+	u16 efuse_data3_reg;
+
+	efuse_ctrl_reg = EFUSE_CTRL;
+	efuse_data0_reg = EFUSE_DATA0;
+	efuse_data1_reg = EFUSE_DATA1;
+	efuse_data2_reg = EFUSE_DATA2;
+	efuse_data3_reg = EFUSE_DATA3;
+
+	if (rt2x00dev->chip.mac_version == 0x3290) {
+		efuse_ctrl_reg = 0x24;
+		efuse_data3_reg = 0x28;
+		efuse_data2_reg = efuse_data3_reg + 4;
+		efuse_data1_reg = efuse_data2_reg + 4;
+		efuse_data0_reg = efuse_data1_reg + 4;
+	}
 	mutex_lock(&rt2x00dev->csr_mutex);
 
-	rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
+	rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
 	rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
 	rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
 	rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
-	rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
+	rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
 
 	/* Wait until the EEPROM has been loaded */
-	rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
-
+	rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
 	/* Apparently the data is read from end to start */
-	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
+	rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
 	/* The returned value is in CPU order, but eeprom is le */
 	*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
-	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
+	rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
 	*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
-	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
+	rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
 	*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
-	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
+	rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
 	*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
 
 	mutex_unlock(&rt2x00dev->csr_mutex);
@@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
 	 * RT53xx: defined in "EEPROM_CHIP_ID" field
 	 */
+	if (rt2x00dev->chip.mac_version == 0x3290)
+		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+	else
 	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
 	if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
-		rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
+		rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
+		rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
 	else
 		value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
@@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RT3572:
 	case RT5390:
 	case RT5392:
+	case RT3290:
 		break;
 	default:
 		ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
@@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RF5370:
 	case RF5372:
 	case RF5390:
+	case RF3290:
 		break;
 	default:
 		ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
@@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		   rt2x00_rf(rt2x00dev, RF3320) ||
 		   rt2x00_rf(rt2x00dev, RF5370) ||
 		   rt2x00_rf(rt2x00dev, RF5372) ||
-		   rt2x00_rf(rt2x00dev, RF5390)) {
+		   rt2x00_rf(rt2x00dev, RF5390) ||
+		   rt2x00_rf(rt2x00dev, RF3290)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals_3x;
 	} else if (rt2x00_rf(rt2x00dev, RF3052)) {
@@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	case RF5370:
 	case RF5372:
 	case RF5390:
+	case RF3290:
 		__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
 		break;
 	}
@@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 }
 EXPORT_SYMBOL_GPL(rt2800_get_survey);
 
+int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
+{
+	u32 wlanfunctrl;
+	u32 glocfg;
+	u32 cmbctrl;
+	u8 index;
+	int i;
+
+	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
+	rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
+	rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
+	if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
+		return 0;
+
+	rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
+	rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
+	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
+	udelay(REGISTER_BUSY_DELAY);
+
+	index = 0;
+	cmbctrl = 0;
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
+		if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
+			(rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
+			break;
+		udelay(REGISTER_BUSY_DELAY);
+	}
+
+	if (index >= REGISTER_BUSY_COUNT) {
+		rt2800_register_write(rt2x00dev, 0x58, 0x018);
+		udelay(REGISTER_BUSY_DELAY);
+		rt2800_register_write(rt2x00dev, 0x58, 0x418);
+		udelay(REGISTER_BUSY_DELAY);
+		rt2800_register_write(rt2x00dev, 0x58, 0x618);
+		udelay(REGISTER_BUSY_DELAY);
+	} else {
+		rt2800_register_read(rt2x00dev,
+			WPDMA_GLO_CFG, &glocfg);
+	}
+	rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
+	rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
+
+	rt2800_register_write(rt2x00dev,
+		WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
+	udelay(REGISTER_BUSY_DELAY);
+	rt2800_register_write(rt2x00dev,
+		WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
+	udelay(2);
+	rt2800_register_write(rt2x00dev,
+		INT_SOURCE_CSR, 0x7fffffff);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
+
+int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
+{
+	u32 wlanfunctrl;
+	u32 glocfg;
+	u32 reg;
+	int i;
+
+	/* Change Interrupt bitmask. */
+	rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
+	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
+	rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
+
+	/* wait RX DMA idle */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
+		if ((rt2x00_get_field32(glocfg,
+			WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
+			(glocfg == 0xFFFFFFFF))
+			break;
+		udelay(REGISTER_BUSY_DELAY);
+	}
+
+	if (i >= REGISTER_BUSY_COUNT) {
+		rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
+		rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+		return 0;
+		}
+
+	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
+	rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
+	rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
+	rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
+	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
+	udelay(REGISTER_BUSY_DELAY);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
 MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION("Ralink RT2800 library");
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 18a0b67..22d7cbb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
-
+int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
+int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
 #endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 931331d..9251f2d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
  */
 static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 {
+
+	if (rt2x00_rt(rt2x00dev, RT3290))
+		return FIRMWARE_RT3290;
+
 	return FIRMWARE_RT2860;
 }
 
@@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 		rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
 		rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
 	}
+
+	if (rt2x00_rt(rt2x00dev, RT3290))
+		rt2800pci_3290_disable_wlan(rt2x00dev);
 }
 
 static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 */
 	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
 
+	if (rt2x00_rf(rt2x00dev, RF3290))
+		rt2800pci_3290_enable_wlan(rt2x00dev);
 	return 0;
 }
 
@@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
 	{ PCI_DEVICE(0x1814, 0x539a) },
 	{ PCI_DEVICE(0x1814, 0x539f) },
 #endif
+#ifdef CONFIG_RT2800PCI_RT3290
+	{ PCI_DEVICE(0x1814, 0x3290) },
+#endif
 	{ 0, }
 };
 #endif /* CONFIG_PCI */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index 70e050d..dd043c7 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -49,6 +49,9 @@
 #define FIRMWARE_RT2860			"rt2860.bin"
 #define FIRMWARE_IMAGE_BASE		0x2000
 
+
+#define FIRMWARE_RT3290			"rt3290.bin"
+
 /*
  * DMA descriptor defines.
  */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index ca36ccc..ee770e7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -193,10 +193,11 @@ struct rt2x00_chip {
 #define RT3883		0x3883	/* WSOC */
 #define RT5390		0x5390  /* 2.4GHz */
 #define RT5392		0x5392  /* 2.4GHz */
+#define RT3290		0x3290
 
 	u16 rf;
 	u16 rev;
-
+	u16 mac_version;
 	enum rt2x00_chip_intf intf;
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 0a4653a..9bbd9a3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
+	u16 device_id;
 
 	retval = pci_enable_device(pci_dev);
 	if (retval) {
@@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 	if (retval)
 		goto exit_free_device;
 
+
+	pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
+	if (device_id == 0x3290)
+		rt2x00dev->chip.mac_version = 0x3290;
+
 	retval = rt2x00lib_probe_dev(rt2x00dev);
 	if (retval)
 		goto exit_free_reg;
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] rt2x00 : RT3290 chip support
  2012-04-27  2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung
@ 2012-04-27  7:40 ` Helmut Schaa
  2012-05-02 18:13   ` John W. Linville
  2012-05-11 12:05 ` Gertjan van Wingerde
  1 sibling, 1 reply; 5+ messages in thread
From: Helmut Schaa @ 2012-04-27  7:40 UTC (permalink / raw)
  To: Woody Hung
  Cc: linville, linux-wireless, jay.hung, pohsun.yang, dennis.lee,
	Ivo Van Doorn, Gertjan van Wingerde

Hi Woody,

A bit more verbose patch description would be highly appreciated. Also
see some inline
comments about the patch itself. However, I only had a quick look, so
expect a few more
comments from others too ...

Also, please always check your patch by running scripts/checkpatch.pl from your
kernel tree onto it.

Helmut

On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <Woody.Hung@mediatek.com> wrote:
> This support RT3290 chip
>
> Signed-off-by: Woody Hung <Woody.Hung@mediatek.com>
> ---
>  drivers/net/wireless/rt2x00/Kconfig     |    8 +
>  drivers/net/wireless/rt2x00/rt2800.h    |  120 +++++++++-
>  drivers/net/wireless/rt2x00/rt2800lib.c |  395 ++++++++++++++++++++++++++++--
>  drivers/net/wireless/rt2x00/rt2800lib.h |    3 +-
>  drivers/net/wireless/rt2x00/rt2800pci.c |   12 +
>  drivers/net/wireless/rt2x00/rt2800pci.h |    3 +
>  drivers/net/wireless/rt2x00/rt2x00.h    |    3 +-
>  drivers/net/wireless/rt2x00/rt2x00pci.c |    6 +
>  8 files changed, 520 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> index 299c387..c7548da 100644
> --- a/drivers/net/wireless/rt2x00/Kconfig
> +++ b/drivers/net/wireless/rt2x00/Kconfig
> @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
>          rt2800pci driver.
>          Supported chips: RT5390
>
> +config RT2800PCI_RT3290
> +       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> +       depends on EXPERIMENTAL
> +       default y
> +       ---help---
> +         This adds support for rt3290 wireless chipset family to the
> +         rt2800pci driver.
> +         Supported chips: RT3290
>  endif
>
>  config RT2500USB
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index d91f4f6..39b1685 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -70,7 +70,7 @@
>  #define RF5370                         0x5370
>  #define RF5372                         0x5372
>  #define RF5390                         0x5390
> -
> +#define RF3290                         0x3290

There's no need to remove the emty line here.

>  /*
>  * Chipset revisions.
>  */
> @@ -112,6 +112,12 @@
>  * Registers.
>  */
>
> +
> +/*
> + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> + */
> +#define MAC_CSR0_3290                          0x0000
> +

This should be moved to the other MAC register definitions.
Is this register only valid on 3290 chipsets?

>  /*
>  * E2PROM_CSR: PCI EEPROM control register.
>  * RELOAD: Write 1 to reload eeprom content.
> @@ -305,6 +311,118 @@
>  #define GPIO_CTRL_CFG_GPIOD_BIT7       FIELD32(0x00008000)
>
>  /*
> + * WLAN_CTRL_CFG
> + */
> +#define WLAN_FUN_CTRL                  0x80
> +#define WLAN_EN                                FIELD32(0x00000001)
> +#define WLAN_CLK_EN                    FIELD32(0x00000002)
> +#define WLAN_RSV1                      FIELD32(0x00000004)
> +#define WLAN_RESET                     FIELD32(0x00000008)
> +#define PCIE_APP0_CLK_REQ              FIELD32(0x00000010)
> +#define FRC_WL_ANT_SET                 FIELD32(0x00000020)
> +#define INV_TR_SW0                     FIELD32(0x00000040)
> +#define WLAN_GPIO_IN_BIT0              FIELD32(0x00000100)
> +#define WLAN_GPIO_IN_BIT1              FIELD32(0x00000200)
> +#define WLAN_GPIO_IN_BIT2              FIELD32(0x00000400)
> +#define WLAN_GPIO_IN_BIT3              FIELD32(0x00000800)
> +#define WLAN_GPIO_IN_BIT4              FIELD32(0x00001000)
> +#define WLAN_GPIO_IN_BIT5              FIELD32(0x00002000)
> +#define WLAN_GPIO_IN_BIT6              FIELD32(0x00004000)
> +#define WLAN_GPIO_IN_BIT7              FIELD32(0x00008000)
> +#define WLAN_GPIO_IN_BIT_ALL           FIELD32(0x0000ff00)
> +#define WLAN_GPIO_OUT_BIT0             FIELD32(0x00010000)
> +#define WLAN_GPIO_OUT_BIT1             FIELD32(0x00020000)
> +#define WLAN_GPIO_OUT_BIT2             FIELD32(0x00040000)
> +#define WLAN_GPIO_OUT_BIT3             FIELD32(0x00050000)
> +#define WLAN_GPIO_OUT_BIT4             FIELD32(0x00100000)
> +#define WLAN_GPIO_OUT_BIT5             FIELD32(0x00200000)
> +#define WLAN_GPIO_OUT_BIT6             FIELD32(0x00400000)
> +#define WLAN_GPIO_OUT_BIT7             FIELD32(0x00800000)
> +#define WLAN_GPIO_OUT_BIT_ALL          FIELD32(0x00ff0000)
> +#define WLAN_GPIO_OUT_OE_BIT0          FIELD32(0x01000000)
> +#define WLAN_GPIO_OUT_OE_BIT1          FIELD32(0x02000000)
> +#define WLAN_GPIO_OUT_OE_BIT2          FIELD32(0x04000000)
> +#define WLAN_GPIO_OUT_OE_BIT3          FIELD32(0x08000000)
> +#define WLAN_GPIO_OUT_OE_BIT4          FIELD32(0x10000000)
> +#define WLAN_GPIO_OUT_OE_BIT5          FIELD32(0x20000000)
> +#define WLAN_GPIO_OUT_OE_BIT6          FIELD32(0x40000000)
> +#define WLAN_GPIO_OUT_OE_BIT7          FIELD32(0x80000000)
> +#define WLAN_GPIO_OUT_OE_BIT_ALL       FIELD32(0xff000000)
> +
> +/*
> + * CMB_CTRL_CFG
> + */
> +#define CMB_CTRL               0x20
> +#define AUX_OPT_BIT0           FIELD32(0x00000001)
> +#define AUX_OPT_BIT1           FIELD32(0x00000002)
> +#define AUX_OPT_BIT2           FIELD32(0x00000004)
> +#define AUX_OPT_BIT3           FIELD32(0x00000008)
> +#define AUX_OPT_BIT4           FIELD32(0x00000010)
> +#define AUX_OPT_BIT5           FIELD32(0x00000020)
> +#define AUX_OPT_BIT6           FIELD32(0x00000040)
> +#define AUX_OPT_BIT7           FIELD32(0x00000080)
> +#define AUX_OPT_BIT8           FIELD32(0x00000100)
> +#define AUX_OPT_BIT9           FIELD32(0x00000200)
> +#define AUX_OPT_BIT10          FIELD32(0x00000400)
> +#define AUX_OPT_BIT11          FIELD32(0x00000800)
> +#define AUX_OPT_BIT12          FIELD32(0x00001000)
> +#define AUX_OPT_BIT13          FIELD32(0x00002000)
> +#define AUX_OPT_BIT14          FIELD32(0x00004000)
> +#define AUX_OPT_BIT15          FIELD32(0x00008000)
> +#define LDO25_LEVEL            FIELD32(0x00030000)
> +#define LDO25_LARGEA           FIELD32(0x00040000)
> +#define LDO25_FRC_ON           FIELD32(0x00080000)
> +#define CMB_RSV                        FIELD32(0x00300000)
> +#define XTAL_RDY               FIELD32(0x00400000)
> +#define PLL_LD                 FIELD32(0x00800000)
> +#define LDO_CORE_LEVEL         FIELD32(0x0F000000)
> +#define LDO_BGSEL              FIELD32(0x30000000)
> +#define LDO3_EN                        FIELD32(0x40000000)
> +#define LDO0_EN                        FIELD32(0x80000000)
> +
> +/*
> + * OSC_CTRL_CFG
> + */
> +#define OSC_CTRL               0x38
> +#define OSC_REF_CYCLE          FIELD32(0x00001fff)
> +#define OSC_RSV                        FIELD32(0x0000e000)
> +#define OSC_CAL_CNT            FIELD32(0x0fff0000)
> +#define OSC_CAL_ACK            FIELD32(0x10000000)
> +#define OSC_CLK_32K_VLD                FIELD32(0x20000000)
> +#define OSC_CAL_REQ            FIELD32(0x40000000)
> +#define OSC_ROSC_EN            FIELD32(0x80000000)
> +
> +/*
> + * PLL_CTRL_CFG
> + */
> +#define PLL_CTRL               0x50
> +#define PLL_RESERVED_INPUT1    FIELD32(0x000000ff)
> +#define PLL_RESERVED_INPUT2    FIELD32(0x0000ff00)
> +#define PLL_CONTROL            FIELD32(0x00070000)
> +#define PLL_LPF_R1             FIELD32(0x00080000)
> +#define PLL_LPF_C1_CTRL        FIELD32(0x00300000)
> +#define PLL_LPF_C2_CTRL        FIELD32(0x00c00000)
> +#define PLL_CP_CURRENT_CTRL    FIELD32(0x03000000)
> +#define PLL_PFD_DELAY_CTRL     FIELD32(0x0c000000)
> +#define PLL_LOCK_CTRL          FIELD32(0x70000000)
> +#define PLL_VBGBK_EN           FIELD32(0x80000000)
> +
> +/*
> + * COEX_CFG_0
> + */
> +#define COEX_CFG0                      0x40
> +
> +/*
> + * COEX_CFG_1
> + */
> +#define COEX_CFG1                      0x44
> +
> +/*
> + * COEX_CFG_2
> + */
> +#define COEX_CFG2                      0x48
> +
> +/*
>  * MCU_CMD_CFG
>  */
>  #define MCU_CMD_CFG                    0x022c
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 1cd16b4..7753791 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
>                multiple = true;
>        } else {
>                fw_len = 8192;
> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       fw_len = 4096;
> +
>                multiple = true;
>        }
>
> @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
>        if (rt2x00_is_pci(rt2x00dev)) {
>                if (rt2x00_rt(rt2x00dev, RT3572) ||
>                    rt2x00_rt(rt2x00dev, RT5390) ||
> -                   rt2x00_rt(rt2x00dev, RT5392)) {
> +                   rt2x00_rt(rt2x00dev, RT5392) ||
> +                   rt2x00_rt(rt2x00dev, RT3290)) {
>                        rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
>                        rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
>                        rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
> @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
>  {
>        u32 reg;
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> +               return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> +       } else
>        rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);

This looks awkward, either you have to use correct indention here
or drop the else completely.

>        return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
>  }
> @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
>
>  #define RT5390_POWER_BOUND     0x27
>  #define RT5390_FREQ_OFFSET_BOUND       0x5f
> -

This empty line can stay.

> +#define RT3290_POWER_BOUND     0x27
> +#define RT3290_FREQ_OFFSET_BOUND       0x5f

Might be worth to add another empty line here.

>  static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
>                                         struct ieee80211_conf *conf,
>                                         struct rf_channel *rf,
> @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
>        rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
>  }
>
> +
> +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> +                                        struct ieee80211_conf *conf,
> +                                        struct rf_channel *rf,
> +                                        struct channel_info *info)
> +{
> +       u8 rfcsr;
> +
> +       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> +       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> +       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> +       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> +       if (info->default_power1 > RT5390_POWER_BOUND)
> +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> +       else
> +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> +       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> +       if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> +                                 RT3290_FREQ_OFFSET_BOUND);
> +       else
> +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> +       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> +
> +       if (rf->channel <= 14) {
> +               rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> +               rfcsr &= ~0xF8;
> +               rfcsr |= (0x1f << 3);
> +               rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> +               rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> +               rfcsr &= ~0xF8;
> +               rfcsr |= (0x1f << 3);
> +               rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
> +
> +               if (rf->channel == 6)
> +                       rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> +               else
> +                       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> +
> +               if (rf->channel >= 1 && rf->channel <= 6)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> +               else if (rf->channel >= 7 && rf->channel <= 11)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> +               else if (rf->channel >= 12 && rf->channel <= 14)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> +       }
> +
> +       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> +       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> +       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> +}

This function could really use a few comments.

>  static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>                                  struct ieee80211_conf *conf,
>                                  struct rf_channel *rf,
> @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>        case RF5390:
>                rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
>                break;
> +       case RF3290:
> +               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> +               break;
>        default:
>                rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
>        }
> @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
>                rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
>                rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
>                    rt2x00_rt(rt2x00dev, RT3090) ||
>                    rt2x00_rt(rt2x00dev, RT3390) ||
>                    rt2x00_rt(rt2x00dev, RT5390) ||
> -                   rt2x00_rt(rt2x00dev, RT5392))
> +                   rt2x00_rt(rt2x00dev, RT5392) ||
> +                   rt2x00_rt(rt2x00dev, RT3290))
>                        return 0x1c + (2 * rt2x00dev->lna_gain);
>                else
>                        return 0x2e + rt2x00dev->lna_gain;
> @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
>        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
>        rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800pci_3290_enable_wlan(rt2x00dev);

Calling a rt2800pci function from within rt2800lib doesn't look correct. Maybe
use a new callback function for that?

> +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> +               if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> +                       rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> +                       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> +               }
> +
> +               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> +               if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> +                       rt2x00_set_field32(&reg, LDO0_EN, 1);
> +                       rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> +                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> +               }
> +
> +               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> +               rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> +               rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> +               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> +               reg &= ~(0xFF000000);
> +               reg |= 0x5E000000;
> +               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> +               rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> +               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> +               rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> +               rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> +       }
> +
>        if (rt2x00_rt(rt2x00dev, RT3071) ||
>            rt2x00_rt(rt2x00dev, RT3090) ||
> -           rt2x00_rt(rt2x00dev, RT3390)) {
> +           rt2x00_rt(rt2x00dev, RT3390) ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {

Indention looks strange here.

> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> +                               0x00000404);
> +               else
>                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);

Indention again.

>                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
>                if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                return -EACCES;
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392)) {
> +               rt2x00_rt(rt2x00dev, RT5392)    ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_bbp_read(rt2x00dev, 4, &value);
>                rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
>                rt2800_bbp_write(rt2x00dev, 4, value);
> @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        if (rt2800_is_305x_soc(rt2x00dev) ||
>            rt2x00_rt(rt2x00dev, RT3572) ||
>            rt2x00_rt(rt2x00dev, RT5390) ||
> -           rt2x00_rt(rt2x00dev, RT5392))
> +           rt2x00_rt(rt2x00dev, RT5392) ||
> +           rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 31, 0x08);
>
>        rt2800_bbp_write(rt2x00dev, 65, 0x2c);
>        rt2800_bbp_write(rt2x00dev, 66, 0x38);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 68, 0x0b);
>
>        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
>                rt2800_bbp_write(rt2x00dev, 69, 0x16);
>                rt2800_bbp_write(rt2x00dev, 73, 0x12);
>        } else if (rt2x00_rt(rt2x00dev, RT5390) ||
> -                          rt2x00_rt(rt2x00dev, RT5392)) {
> +                       rt2x00_rt(rt2x00dev, RT5392) ||
> +                       rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_bbp_write(rt2x00dev, 69, 0x12);
>                rt2800_bbp_write(rt2x00dev, 73, 0x13);
>                rt2800_bbp_write(rt2x00dev, 75, 0x46);
>                rt2800_bbp_write(rt2x00dev, 76, 0x28);
> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       rt2800_bbp_write(rt2x00dev, 77, 0x58);
> +               else
>                rt2800_bbp_write(rt2x00dev, 77, 0x59);

Indention.

>        } else {
>                rt2800_bbp_write(rt2x00dev, 69, 0x12);
> @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 81, 0x37);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> +               rt2800_bbp_write(rt2x00dev, 79, 0x18);
> +               rt2800_bbp_write(rt2x00dev, 80, 0x09);
> +               rt2800_bbp_write(rt2x00dev, 81, 0x33);
> +       }
> +
>        rt2800_bbp_write(rt2x00dev, 82, 0x62);
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 83, 0x7a);
>        else
>                rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
>                rt2800_bbp_write(rt2x00dev, 84, 0x19);
>        else if (rt2x00_rt(rt2x00dev, RT5390) ||
> -                        rt2x00_rt(rt2x00dev, RT5392))
> +                       rt2x00_rt(rt2x00dev, RT5392) ||
> +                       rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 84, 0x9a);
>        else
>                rt2800_bbp_write(rt2x00dev, 84, 0x99);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 86, 0x38);
>        else
>                rt2800_bbp_write(rt2x00dev, 86, 0x00);
> @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        rt2800_bbp_write(rt2x00dev, 91, 0x04);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 92, 0x02);
>        else
>                rt2800_bbp_write(rt2x00dev, 92, 0x00);
> @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>            rt2x00_rt(rt2x00dev, RT3572) ||
>            rt2x00_rt(rt2x00dev, RT5390) ||
>            rt2x00_rt(rt2x00dev, RT5392) ||
> +           rt2x00_rt(rt2x00dev, RT3290) ||
>            rt2800_is_305x_soc(rt2x00dev))
>                rt2800_bbp_write(rt2x00dev, 103, 0xc0);
>        else
>                rt2800_bbp_write(rt2x00dev, 103, 0x00);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 104, 0x92);
>
>        if (rt2800_is_305x_soc(rt2x00dev))
> @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        else if (rt2x00_rt(rt2x00dev, RT5390) ||
>                         rt2x00_rt(rt2x00dev, RT5392))
>                rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> +       else if (rt2x00_rt(rt2x00dev, RT3290))
> +               rt2800_bbp_write(rt2x00dev, 105, 0x1c);
>        else
>                rt2800_bbp_write(rt2x00dev, 105, 0x05);
>
> -       if (rt2x00_rt(rt2x00dev, RT5390))
> +       if (rt2x00_rt(rt2x00dev, RT5390) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 106, 0x03);
>        else if (rt2x00_rt(rt2x00dev, RT5392))
>                rt2800_bbp_write(rt2x00dev, 106, 0x12);
> @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 106, 0x35);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 128, 0x12);
>
>        if (rt2x00_rt(rt2x00dev, RT5392)) {
> @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 138, value);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_bbp_write(rt2x00dev, 67, 0x24);
> +               rt2800_bbp_write(rt2x00dev, 143, 0x04);
> +               rt2800_bbp_write(rt2x00dev, 142, 0x99);
> +               rt2800_bbp_write(rt2x00dev, 150, 0x30);
> +               rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> +               rt2800_bbp_write(rt2x00dev, 152, 0x20);
> +               rt2800_bbp_write(rt2x00dev, 153, 0x34);
> +               rt2800_bbp_write(rt2x00dev, 154, 0x40);
> +               rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> +               rt2800_bbp_write(rt2x00dev, 253, 0x04);
> +
> +               rt2800_bbp_read(rt2x00dev, 47, &value);
> +               rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> +               rt2800_bbp_write(rt2x00dev, 47, value);
> +
> +               rt2800_bbp_read(rt2x00dev, 3, &value);
> +               value &= (~0xc0);
> +               value |= 0xc0;
> +               rt2800_bbp_write(rt2x00dev, 3, value);
> +       }
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
>                rt2x00_rt(rt2x00dev, RT5392)) {
>                int ant, div_mode;
> @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>            !rt2x00_rt(rt2x00dev, RT3572) &&
>            !rt2x00_rt(rt2x00dev, RT5390) &&
>            !rt2x00_rt(rt2x00dev, RT5392) &&
> +           !rt2x00_rt(rt2x00dev, RT3290) &&
>            !rt2800_is_305x_soc(rt2x00dev))
>                return 0;
>
> @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>         * Init RF calibration.
>         */
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392)) {
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
>                rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
>                rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>                        rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
>                        rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
>                        rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> +       } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> +                       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> +                       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> +                       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> +                       rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> +                       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> +                       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> +                       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> +                       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> +                       rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> +                       rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> +                       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> +                       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> +                       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> +                       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> +                       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> +                       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> +                       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> +                       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> +                       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> +                       rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> +                       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> +                       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> +                       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> +                       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> +                       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> +                       rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> +                       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> +                       rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> +                       rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> +                       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> +                       rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
>        }
>
>        if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>                rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> +               rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> +               rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> +       }
> +
>        return 0;
>  }
>
> @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
>  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
>  {
>        u32 reg;
> +       u16 efuse_ctrl_reg;
> +       efuse_ctrl_reg = EFUSE_CTRL;
>
> -       rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> +       if (rt2x00dev->chip.mac_version == 0x3290)
> +               efuse_ctrl_reg = 0x24;

This shouldn't be hardcoded. Please add a define to rt2800.h.

>
> +       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
>        return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
>  }
>  EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
> @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
>  {
>        u32 reg;
>
> +       u16 efuse_ctrl_reg;
> +       u16 efuse_data0_reg;
> +       u16 efuse_data1_reg;
> +       u16 efuse_data2_reg;
> +       u16 efuse_data3_reg;
> +
> +       efuse_ctrl_reg = EFUSE_CTRL;
> +       efuse_data0_reg = EFUSE_DATA0;
> +       efuse_data1_reg = EFUSE_DATA1;
> +       efuse_data2_reg = EFUSE_DATA2;
> +       efuse_data3_reg = EFUSE_DATA3;
> +
> +       if (rt2x00dev->chip.mac_version == 0x3290) {
> +               efuse_ctrl_reg = 0x24;
> +               efuse_data3_reg = 0x28;
> +               efuse_data2_reg = efuse_data3_reg + 4;
> +               efuse_data1_reg = efuse_data2_reg + 4;
> +               efuse_data0_reg = efuse_data1_reg + 4;
> +       }

Same here, the register offsets would make sense as defines.

>        mutex_lock(&rt2x00dev->csr_mutex);
>
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> -       rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> +       rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
>
>        /* Wait until the EEPROM has been loaded */
> -       rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> -
> +       rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
>        /* Apparently the data is read from end to start */
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
>        /* The returned value is in CPU order, but eeprom is le */
>        *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
>
>        mutex_unlock(&rt2x00dev->csr_mutex);
> @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>         * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
>         * RT53xx: defined in "EEPROM_CHIP_ID" field
>         */
> +       if (rt2x00dev->chip.mac_version == 0x3290)
> +               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> +       else
>        rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);

Indention.

>        if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> -               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
>                rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
>        else
>                value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>        case RT3572:
>        case RT5390:
>        case RT5392:
> +       case RT3290:
>                break;
>        default:
>                ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                break;
>        default:
>                ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>                   rt2x00_rf(rt2x00dev, RF3320) ||
>                   rt2x00_rf(rt2x00dev, RF5370) ||
>                   rt2x00_rf(rt2x00dev, RF5372) ||
> -                  rt2x00_rf(rt2x00dev, RF5390)) {
> +                  rt2x00_rf(rt2x00dev, RF5390) ||
> +                  rt2x00_rf(rt2x00dev, RF3290)) {
>                spec->num_channels = 14;
>                spec->channels = rf_vals_3x;
>        } else if (rt2x00_rf(rt2x00dev, RF3052)) {
> @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
>                break;
>        }
> @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
>  }
>  EXPORT_SYMBOL_GPL(rt2800_get_survey);
>
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)

rt2800pci functions should live in rt2800pci.c, not in rt2800lib.c.

> +{
> +       u32 wlanfunctrl;
> +       u32 glocfg;
> +       u32 cmbctrl;
> +       u8 index;
> +       int i;
> +
> +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> +       rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> +       if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> +               return 0;
> +
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> +       udelay(REGISTER_BUSY_DELAY);
> +
> +       index = 0;
> +       cmbctrl = 0;
> +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> +               rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> +               if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> +                       (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> +                       break;
> +               udelay(REGISTER_BUSY_DELAY);
> +       }
> +
> +       if (index >= REGISTER_BUSY_COUNT) {
> +               rt2800_register_write(rt2x00dev, 0x58, 0x018);
> +               udelay(REGISTER_BUSY_DELAY);
> +               rt2800_register_write(rt2x00dev, 0x58, 0x418);
> +               udelay(REGISTER_BUSY_DELAY);
> +               rt2800_register_write(rt2x00dev, 0x58, 0x618);
> +               udelay(REGISTER_BUSY_DELAY);
> +       } else {
> +               rt2800_register_read(rt2x00dev,
> +                       WPDMA_GLO_CFG, &glocfg);
> +       }
> +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> +
> +       rt2800_register_write(rt2x00dev,
> +               WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> +       udelay(REGISTER_BUSY_DELAY);
> +       rt2800_register_write(rt2x00dev,
> +               WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> +       udelay(2);
> +       rt2800_register_write(rt2x00dev,
> +               INT_SOURCE_CSR, 0x7fffffff);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> +
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> +       u32 wlanfunctrl;
> +       u32 glocfg;
> +       u32 reg;
> +       int i;
> +
> +       /* Change Interrupt bitmask. */
> +       rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> +       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> +       rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> +       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> +
> +       /* wait RX DMA idle */
> +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> +               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> +               if ((rt2x00_get_field32(glocfg,
> +                       WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> +                       (glocfg == 0xFFFFFFFF))
> +                       break;
> +               udelay(REGISTER_BUSY_DELAY);
> +       }
> +
> +       if (i >= REGISTER_BUSY_COUNT) {
> +               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> +               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> +               return 0;
> +               }
> +
> +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> +       udelay(REGISTER_BUSY_DELAY);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
>  MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
>  MODULE_VERSION(DRV_VERSION);
>  MODULE_DESCRIPTION("Ralink RT2800 library");
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> index 18a0b67..22d7cbb 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>  int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
>                      struct survey_info *survey);
>  void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> -
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
>  #endif /* RT2800LIB_H */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 931331d..9251f2d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
>  */
>  static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
>  {
> +
> +       if (rt2x00_rt(rt2x00dev, RT3290))
> +               return FIRMWARE_RT3290;
> +
>        return FIRMWARE_RT2860;
>  }
>
> @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
>                rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
>                rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
>        }
> +
> +       if (rt2x00_rt(rt2x00dev, RT3290))
> +               rt2800pci_3290_disable_wlan(rt2x00dev);
>  }
>
>  static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
>         */
>        rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
>
> +       if (rt2x00_rf(rt2x00dev, RF3290))
> +               rt2800pci_3290_enable_wlan(rt2x00dev);
>        return 0;
>  }
>
> @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
>        { PCI_DEVICE(0x1814, 0x539a) },
>        { PCI_DEVICE(0x1814, 0x539f) },
>  #endif
> +#ifdef CONFIG_RT2800PCI_RT3290
> +       { PCI_DEVICE(0x1814, 0x3290) },
> +#endif
>        { 0, }
>  };
>  #endif /* CONFIG_PCI */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> index 70e050d..dd043c7 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> @@ -49,6 +49,9 @@
>  #define FIRMWARE_RT2860                        "rt2860.bin"
>  #define FIRMWARE_IMAGE_BASE            0x2000
>
> +
> +#define FIRMWARE_RT3290                        "rt3290.bin"
> +
>  /*
>  * DMA descriptor defines.
>  */
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index ca36ccc..ee770e7 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -193,10 +193,11 @@ struct rt2x00_chip {
>  #define RT3883         0x3883  /* WSOC */
>  #define RT5390         0x5390  /* 2.4GHz */
>  #define RT5392         0x5392  /* 2.4GHz */
> +#define RT3290         0x3290
>
>        u16 rf;
>        u16 rev;
> -
> +       u16 mac_version;
>        enum rt2x00_chip_intf intf;
>  };
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index 0a4653a..9bbd9a3 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
>        struct ieee80211_hw *hw;
>        struct rt2x00_dev *rt2x00dev;
>        int retval;
> +       u16 device_id;
>
>        retval = pci_enable_device(pci_dev);
>        if (retval) {
> @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
>        if (retval)
>                goto exit_free_device;
>
> +
> +       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> +       if (device_id == 0x3290)
> +               rt2x00dev->chip.mac_version = 0x3290;
> +
>        retval = rt2x00lib_probe_dev(rt2x00dev);
>        if (retval)
>                goto exit_free_reg;
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rt2x00 : RT3290 chip support
  2012-04-27  7:40 ` Helmut Schaa
@ 2012-05-02 18:13   ` John W. Linville
  2012-05-03  1:07     ` Woody Hung (洪秋竹)
  0 siblings, 1 reply; 5+ messages in thread
From: John W. Linville @ 2012-05-02 18:13 UTC (permalink / raw)
  To: Helmut Schaa
  Cc: Woody Hung, linux-wireless, jay.hung, pohsun.yang, dennis.lee,
	Ivo Van Doorn, Gertjan van Wingerde

Please respond to Helmut's commentary...

On Fri, Apr 27, 2012 at 09:40:28AM +0200, Helmut Schaa wrote:
> Hi Woody,
> 
> A bit more verbose patch description would be highly appreciated. Also
> see some inline
> comments about the patch itself. However, I only had a quick look, so
> expect a few more
> comments from others too ...
> 
> Also, please always check your patch by running scripts/checkpatch.pl from your
> kernel tree onto it.
> 
> Helmut
> 
> On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <Woody.Hung@mediatek.com> wrote:
> > This support RT3290 chip
> >
> > Signed-off-by: Woody Hung <Woody.Hung@mediatek.com>
> > ---
> >  drivers/net/wireless/rt2x00/Kconfig     |    8 +
> >  drivers/net/wireless/rt2x00/rt2800.h    |  120 +++++++++-
> >  drivers/net/wireless/rt2x00/rt2800lib.c |  395 ++++++++++++++++++++++++++++--
> >  drivers/net/wireless/rt2x00/rt2800lib.h |    3 +-
> >  drivers/net/wireless/rt2x00/rt2800pci.c |   12 +
> >  drivers/net/wireless/rt2x00/rt2800pci.h |    3 +
> >  drivers/net/wireless/rt2x00/rt2x00.h    |    3 +-
> >  drivers/net/wireless/rt2x00/rt2x00pci.c |    6 +
> >  8 files changed, 520 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> > index 299c387..c7548da 100644
> > --- a/drivers/net/wireless/rt2x00/Kconfig
> > +++ b/drivers/net/wireless/rt2x00/Kconfig
> > @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
> >          rt2800pci driver.
> >          Supported chips: RT5390
> >
> > +config RT2800PCI_RT3290
> > +       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> > +       depends on EXPERIMENTAL
> > +       default y
> > +       ---help---
> > +         This adds support for rt3290 wireless chipset family to the
> > +         rt2800pci driver.
> > +         Supported chips: RT3290
> >  endif
> >
> >  config RT2500USB
> > diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> > index d91f4f6..39b1685 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800.h
> > @@ -70,7 +70,7 @@
> >  #define RF5370                         0x5370
> >  #define RF5372                         0x5372
> >  #define RF5390                         0x5390
> > -
> > +#define RF3290                         0x3290
> 
> There's no need to remove the emty line here.
> 
> >  /*
> >  * Chipset revisions.
> >  */
> > @@ -112,6 +112,12 @@
> >  * Registers.
> >  */
> >
> > +
> > +/*
> > + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> > + */
> > +#define MAC_CSR0_3290                          0x0000
> > +
> 
> This should be moved to the other MAC register definitions.
> Is this register only valid on 3290 chipsets?
> 
> >  /*
> >  * E2PROM_CSR: PCI EEPROM control register.
> >  * RELOAD: Write 1 to reload eeprom content.
> > @@ -305,6 +311,118 @@
> >  #define GPIO_CTRL_CFG_GPIOD_BIT7       FIELD32(0x00008000)
> >
> >  /*
> > + * WLAN_CTRL_CFG
> > + */
> > +#define WLAN_FUN_CTRL                  0x80
> > +#define WLAN_EN                                FIELD32(0x00000001)
> > +#define WLAN_CLK_EN                    FIELD32(0x00000002)
> > +#define WLAN_RSV1                      FIELD32(0x00000004)
> > +#define WLAN_RESET                     FIELD32(0x00000008)
> > +#define PCIE_APP0_CLK_REQ              FIELD32(0x00000010)
> > +#define FRC_WL_ANT_SET                 FIELD32(0x00000020)
> > +#define INV_TR_SW0                     FIELD32(0x00000040)
> > +#define WLAN_GPIO_IN_BIT0              FIELD32(0x00000100)
> > +#define WLAN_GPIO_IN_BIT1              FIELD32(0x00000200)
> > +#define WLAN_GPIO_IN_BIT2              FIELD32(0x00000400)
> > +#define WLAN_GPIO_IN_BIT3              FIELD32(0x00000800)
> > +#define WLAN_GPIO_IN_BIT4              FIELD32(0x00001000)
> > +#define WLAN_GPIO_IN_BIT5              FIELD32(0x00002000)
> > +#define WLAN_GPIO_IN_BIT6              FIELD32(0x00004000)
> > +#define WLAN_GPIO_IN_BIT7              FIELD32(0x00008000)
> > +#define WLAN_GPIO_IN_BIT_ALL           FIELD32(0x0000ff00)
> > +#define WLAN_GPIO_OUT_BIT0             FIELD32(0x00010000)
> > +#define WLAN_GPIO_OUT_BIT1             FIELD32(0x00020000)
> > +#define WLAN_GPIO_OUT_BIT2             FIELD32(0x00040000)
> > +#define WLAN_GPIO_OUT_BIT3             FIELD32(0x00050000)
> > +#define WLAN_GPIO_OUT_BIT4             FIELD32(0x00100000)
> > +#define WLAN_GPIO_OUT_BIT5             FIELD32(0x00200000)
> > +#define WLAN_GPIO_OUT_BIT6             FIELD32(0x00400000)
> > +#define WLAN_GPIO_OUT_BIT7             FIELD32(0x00800000)
> > +#define WLAN_GPIO_OUT_BIT_ALL          FIELD32(0x00ff0000)
> > +#define WLAN_GPIO_OUT_OE_BIT0          FIELD32(0x01000000)
> > +#define WLAN_GPIO_OUT_OE_BIT1          FIELD32(0x02000000)
> > +#define WLAN_GPIO_OUT_OE_BIT2          FIELD32(0x04000000)
> > +#define WLAN_GPIO_OUT_OE_BIT3          FIELD32(0x08000000)
> > +#define WLAN_GPIO_OUT_OE_BIT4          FIELD32(0x10000000)
> > +#define WLAN_GPIO_OUT_OE_BIT5          FIELD32(0x20000000)
> > +#define WLAN_GPIO_OUT_OE_BIT6          FIELD32(0x40000000)
> > +#define WLAN_GPIO_OUT_OE_BIT7          FIELD32(0x80000000)
> > +#define WLAN_GPIO_OUT_OE_BIT_ALL       FIELD32(0xff000000)
> > +
> > +/*
> > + * CMB_CTRL_CFG
> > + */
> > +#define CMB_CTRL               0x20
> > +#define AUX_OPT_BIT0           FIELD32(0x00000001)
> > +#define AUX_OPT_BIT1           FIELD32(0x00000002)
> > +#define AUX_OPT_BIT2           FIELD32(0x00000004)
> > +#define AUX_OPT_BIT3           FIELD32(0x00000008)
> > +#define AUX_OPT_BIT4           FIELD32(0x00000010)
> > +#define AUX_OPT_BIT5           FIELD32(0x00000020)
> > +#define AUX_OPT_BIT6           FIELD32(0x00000040)
> > +#define AUX_OPT_BIT7           FIELD32(0x00000080)
> > +#define AUX_OPT_BIT8           FIELD32(0x00000100)
> > +#define AUX_OPT_BIT9           FIELD32(0x00000200)
> > +#define AUX_OPT_BIT10          FIELD32(0x00000400)
> > +#define AUX_OPT_BIT11          FIELD32(0x00000800)
> > +#define AUX_OPT_BIT12          FIELD32(0x00001000)
> > +#define AUX_OPT_BIT13          FIELD32(0x00002000)
> > +#define AUX_OPT_BIT14          FIELD32(0x00004000)
> > +#define AUX_OPT_BIT15          FIELD32(0x00008000)
> > +#define LDO25_LEVEL            FIELD32(0x00030000)
> > +#define LDO25_LARGEA           FIELD32(0x00040000)
> > +#define LDO25_FRC_ON           FIELD32(0x00080000)
> > +#define CMB_RSV                        FIELD32(0x00300000)
> > +#define XTAL_RDY               FIELD32(0x00400000)
> > +#define PLL_LD                 FIELD32(0x00800000)
> > +#define LDO_CORE_LEVEL         FIELD32(0x0F000000)
> > +#define LDO_BGSEL              FIELD32(0x30000000)
> > +#define LDO3_EN                        FIELD32(0x40000000)
> > +#define LDO0_EN                        FIELD32(0x80000000)
> > +
> > +/*
> > + * OSC_CTRL_CFG
> > + */
> > +#define OSC_CTRL               0x38
> > +#define OSC_REF_CYCLE          FIELD32(0x00001fff)
> > +#define OSC_RSV                        FIELD32(0x0000e000)
> > +#define OSC_CAL_CNT            FIELD32(0x0fff0000)
> > +#define OSC_CAL_ACK            FIELD32(0x10000000)
> > +#define OSC_CLK_32K_VLD                FIELD32(0x20000000)
> > +#define OSC_CAL_REQ            FIELD32(0x40000000)
> > +#define OSC_ROSC_EN            FIELD32(0x80000000)
> > +
> > +/*
> > + * PLL_CTRL_CFG
> > + */
> > +#define PLL_CTRL               0x50
> > +#define PLL_RESERVED_INPUT1    FIELD32(0x000000ff)
> > +#define PLL_RESERVED_INPUT2    FIELD32(0x0000ff00)
> > +#define PLL_CONTROL            FIELD32(0x00070000)
> > +#define PLL_LPF_R1             FIELD32(0x00080000)
> > +#define PLL_LPF_C1_CTRL        FIELD32(0x00300000)
> > +#define PLL_LPF_C2_CTRL        FIELD32(0x00c00000)
> > +#define PLL_CP_CURRENT_CTRL    FIELD32(0x03000000)
> > +#define PLL_PFD_DELAY_CTRL     FIELD32(0x0c000000)
> > +#define PLL_LOCK_CTRL          FIELD32(0x70000000)
> > +#define PLL_VBGBK_EN           FIELD32(0x80000000)
> > +
> > +/*
> > + * COEX_CFG_0
> > + */
> > +#define COEX_CFG0                      0x40
> > +
> > +/*
> > + * COEX_CFG_1
> > + */
> > +#define COEX_CFG1                      0x44
> > +
> > +/*
> > + * COEX_CFG_2
> > + */
> > +#define COEX_CFG2                      0x48
> > +
> > +/*
> >  * MCU_CMD_CFG
> >  */
> >  #define MCU_CMD_CFG                    0x022c
> > diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> > index 1cd16b4..7753791 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> > +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> > @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
> >                multiple = true;
> >        } else {
> >                fw_len = 8192;
> > +
> > +               if (rt2x00_rt(rt2x00dev, RT3290))
> > +                       fw_len = 4096;
> > +
> >                multiple = true;
> >        }
> >
> > @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
> >        if (rt2x00_is_pci(rt2x00dev)) {
> >                if (rt2x00_rt(rt2x00dev, RT3572) ||
> >                    rt2x00_rt(rt2x00dev, RT5390) ||
> > -                   rt2x00_rt(rt2x00dev, RT5392)) {
> > +                   rt2x00_rt(rt2x00dev, RT5392) ||
> > +                   rt2x00_rt(rt2x00dev, RT3290)) {
> >                        rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
> >                        rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
> >                        rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
> > @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
> >  {
> >        u32 reg;
> >
> > +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> > +               return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> > +       } else
> >        rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
> 
> This looks awkward, either you have to use correct indention here
> or drop the else completely.
> 
> >        return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
> >  }
> > @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
> >
> >  #define RT5390_POWER_BOUND     0x27
> >  #define RT5390_FREQ_OFFSET_BOUND       0x5f
> > -
> 
> This empty line can stay.
> 
> > +#define RT3290_POWER_BOUND     0x27
> > +#define RT3290_FREQ_OFFSET_BOUND       0x5f
> 
> Might be worth to add another empty line here.
> 
> >  static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> >                                         struct ieee80211_conf *conf,
> >                                         struct rf_channel *rf,
> > @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> >        rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> >  }
> >
> > +
> > +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> > +                                        struct ieee80211_conf *conf,
> > +                                        struct rf_channel *rf,
> > +                                        struct channel_info *info)
> > +{
> > +       u8 rfcsr;
> > +
> > +       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> > +       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> > +       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> > +       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> > +       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> > +
> > +       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> > +       if (info->default_power1 > RT5390_POWER_BOUND)
> > +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> > +       else
> > +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> > +       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> > +
> > +       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> > +       if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> > +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> > +                                 RT3290_FREQ_OFFSET_BOUND);
> > +       else
> > +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> > +       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> > +
> > +       if (rf->channel <= 14) {
> > +               rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> > +               rfcsr &= ~0xF8;
> > +               rfcsr |= (0x1f << 3);
> > +               rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> > +               rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> > +               rfcsr &= ~0xF8;
> > +               rfcsr |= (0x1f << 3);
> > +               rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
> > +
> > +               if (rf->channel == 6)
> > +                       rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> > +               else
> > +                       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> > +
> > +               if (rf->channel >= 1 && rf->channel <= 6)
> > +                       rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> > +               else if (rf->channel >= 7 && rf->channel <= 11)
> > +                       rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> > +               else if (rf->channel >= 12 && rf->channel <= 14)
> > +                       rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> > +       }
> > +
> > +       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> > +       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> > +       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> > +       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> > +
> > +       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> > +       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> > +       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> > +}
> 
> This function could really use a few comments.
> 
> >  static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> >                                  struct ieee80211_conf *conf,
> >                                  struct rf_channel *rf,
> > @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> >        case RF5390:
> >                rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
> >                break;
> > +       case RF3290:
> > +               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> > +               break;
> >        default:
> >                rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
> >        }
> > @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
> >        case RF5370:
> >        case RF5372:
> >        case RF5390:
> > +       case RF3290:
> >                rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> >                rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> >                rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> > @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
> >                    rt2x00_rt(rt2x00dev, RT3090) ||
> >                    rt2x00_rt(rt2x00dev, RT3390) ||
> >                    rt2x00_rt(rt2x00dev, RT5390) ||
> > -                   rt2x00_rt(rt2x00dev, RT5392))
> > +                   rt2x00_rt(rt2x00dev, RT5392) ||
> > +                   rt2x00_rt(rt2x00dev, RT3290))
> >                        return 0x1c + (2 * rt2x00dev->lna_gain);
> >                else
> >                        return 0x2e + rt2x00dev->lna_gain;
> > @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
> >        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
> >        rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
> >
> > +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +               rt2800pci_3290_enable_wlan(rt2x00dev);
> 
> Calling a rt2800pci function from within rt2800lib doesn't look correct. Maybe
> use a new callback function for that?
> 
> > +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> > +               if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> > +                       rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> > +                       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> > +               }
> > +
> > +               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> > +               if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> > +                       rt2x00_set_field32(&reg, LDO0_EN, 1);
> > +                       rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> > +                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> > +               }
> > +
> > +               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> > +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> > +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> > +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> > +               rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> > +               rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> > +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> > +               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> > +               reg &= ~(0xFF000000);
> > +               reg |= 0x5E000000;
> > +               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> > +               rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> > +               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> > +               rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> > +               rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> > +       }
> > +
> >        if (rt2x00_rt(rt2x00dev, RT3071) ||
> >            rt2x00_rt(rt2x00dev, RT3090) ||
> > -           rt2x00_rt(rt2x00dev, RT3390)) {
> > +           rt2x00_rt(rt2x00dev, RT3390) ||
> > +               rt2x00_rt(rt2x00dev, RT3290)) {
> 
> Indention looks strange here.
> 
> > +
> > +               if (rt2x00_rt(rt2x00dev, RT3290))
> > +                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> > +                               0x00000404);
> > +               else
> >                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
> 
> Indention again.
> 
> >                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
> >                if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> > @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >                return -EACCES;
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392)) {
> > +               rt2x00_rt(rt2x00dev, RT5392)    ||
> > +               rt2x00_rt(rt2x00dev, RT3290)) {
> >                rt2800_bbp_read(rt2x00dev, 4, &value);
> >                rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
> >                rt2800_bbp_write(rt2x00dev, 4, value);
> > @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >        if (rt2800_is_305x_soc(rt2x00dev) ||
> >            rt2x00_rt(rt2x00dev, RT3572) ||
> >            rt2x00_rt(rt2x00dev, RT5390) ||
> > -           rt2x00_rt(rt2x00dev, RT5392))
> > +           rt2x00_rt(rt2x00dev, RT5392) ||
> > +           rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 31, 0x08);
> >
> >        rt2800_bbp_write(rt2x00dev, 65, 0x2c);
> >        rt2800_bbp_write(rt2x00dev, 66, 0x38);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> >
> >        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
> >                rt2800_bbp_write(rt2x00dev, 69, 0x16);
> >                rt2800_bbp_write(rt2x00dev, 73, 0x12);
> >        } else if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -                          rt2x00_rt(rt2x00dev, RT5392)) {
> > +                       rt2x00_rt(rt2x00dev, RT5392) ||
> > +                       rt2x00_rt(rt2x00dev, RT3290)) {
> >                rt2800_bbp_write(rt2x00dev, 69, 0x12);
> >                rt2800_bbp_write(rt2x00dev, 73, 0x13);
> >                rt2800_bbp_write(rt2x00dev, 75, 0x46);
> >                rt2800_bbp_write(rt2x00dev, 76, 0x28);
> > +
> > +               if (rt2x00_rt(rt2x00dev, RT3290))
> > +                       rt2800_bbp_write(rt2x00dev, 77, 0x58);
> > +               else
> >                rt2800_bbp_write(rt2x00dev, 77, 0x59);
> 
> Indention.
> 
> >        } else {
> >                rt2800_bbp_write(rt2x00dev, 69, 0x12);
> > @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >                rt2800_bbp_write(rt2x00dev, 81, 0x37);
> >        }
> >
> > +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +               rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> > +               rt2800_bbp_write(rt2x00dev, 79, 0x18);
> > +               rt2800_bbp_write(rt2x00dev, 80, 0x09);
> > +               rt2800_bbp_write(rt2x00dev, 81, 0x33);
> > +       }
> > +
> >        rt2800_bbp_write(rt2x00dev, 82, 0x62);
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 83, 0x7a);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> > @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
> >                rt2800_bbp_write(rt2x00dev, 84, 0x19);
> >        else if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -                        rt2x00_rt(rt2x00dev, RT5392))
> > +                       rt2x00_rt(rt2x00dev, RT5392) ||
> > +                       rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 84, 0x9a);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 84, 0x99);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 86, 0x38);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 86, 0x00);
> > @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >        rt2800_bbp_write(rt2x00dev, 91, 0x04);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 92, 0x02);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 92, 0x00);
> > @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >            rt2x00_rt(rt2x00dev, RT3572) ||
> >            rt2x00_rt(rt2x00dev, RT5390) ||
> >            rt2x00_rt(rt2x00dev, RT5392) ||
> > +           rt2x00_rt(rt2x00dev, RT3290) ||
> >            rt2800_is_305x_soc(rt2x00dev))
> >                rt2800_bbp_write(rt2x00dev, 103, 0xc0);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 103, 0x00);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 104, 0x92);
> >
> >        if (rt2800_is_305x_soc(rt2x00dev))
> > @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >        else if (rt2x00_rt(rt2x00dev, RT5390) ||
> >                         rt2x00_rt(rt2x00dev, RT5392))
> >                rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> > +       else if (rt2x00_rt(rt2x00dev, RT3290))
> > +               rt2800_bbp_write(rt2x00dev, 105, 0x1c);
> >        else
> >                rt2800_bbp_write(rt2x00dev, 105, 0x05);
> >
> > -       if (rt2x00_rt(rt2x00dev, RT5390))
> > +       if (rt2x00_rt(rt2x00dev, RT5390) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 106, 0x03);
> >        else if (rt2x00_rt(rt2x00dev, RT5392))
> >                rt2800_bbp_write(rt2x00dev, 106, 0x12);
> > @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >                rt2800_bbp_write(rt2x00dev, 106, 0x35);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392))
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290))
> >                rt2800_bbp_write(rt2x00dev, 128, 0x12);
> >
> >        if (rt2x00_rt(rt2x00dev, RT5392)) {
> > @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> >                rt2800_bbp_write(rt2x00dev, 138, value);
> >        }
> >
> > +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +               rt2800_bbp_write(rt2x00dev, 67, 0x24);
> > +               rt2800_bbp_write(rt2x00dev, 143, 0x04);
> > +               rt2800_bbp_write(rt2x00dev, 142, 0x99);
> > +               rt2800_bbp_write(rt2x00dev, 150, 0x30);
> > +               rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> > +               rt2800_bbp_write(rt2x00dev, 152, 0x20);
> > +               rt2800_bbp_write(rt2x00dev, 153, 0x34);
> > +               rt2800_bbp_write(rt2x00dev, 154, 0x40);
> > +               rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> > +               rt2800_bbp_write(rt2x00dev, 253, 0x04);
> > +
> > +               rt2800_bbp_read(rt2x00dev, 47, &value);
> > +               rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> > +               rt2800_bbp_write(rt2x00dev, 47, value);
> > +
> > +               rt2800_bbp_read(rt2x00dev, 3, &value);
> > +               value &= (~0xc0);
> > +               value |= 0xc0;
> > +               rt2800_bbp_write(rt2x00dev, 3, value);
> > +       }
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> >                rt2x00_rt(rt2x00dev, RT5392)) {
> >                int ant, div_mode;
> > @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> >            !rt2x00_rt(rt2x00dev, RT3572) &&
> >            !rt2x00_rt(rt2x00dev, RT5390) &&
> >            !rt2x00_rt(rt2x00dev, RT5392) &&
> > +           !rt2x00_rt(rt2x00dev, RT3290) &&
> >            !rt2800_is_305x_soc(rt2x00dev))
> >                return 0;
> >
> > @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> >         * Init RF calibration.
> >         */
> >        if (rt2x00_rt(rt2x00dev, RT5390) ||
> > -               rt2x00_rt(rt2x00dev, RT5392)) {
> > +               rt2x00_rt(rt2x00dev, RT5392) ||
> > +               rt2x00_rt(rt2x00dev, RT3290)) {
> >                rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
> >                rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
> >                rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> > @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> >                        rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
> >                        rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
> >                        rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> > +       } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +                       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> > +                       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> > +                       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> > +                       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> > +                       rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> > +                       rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> > +                       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> > +                       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> > +                       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> > +                       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> > +                       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> > +                       rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> > +                       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> > +                       rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> > +                       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> > +                       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> > +                       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> > +                       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> > +                       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> > +                       rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> > +                       rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> > +                       rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> > +                       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> > +                       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> > +                       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> > +                       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> > +                       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> > +                       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> > +                       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> > +                       rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> > +                       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> > +                       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> > +                       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> > +                       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> > +                       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> > +                       rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> > +                       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> > +                       rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> > +                       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> > +                       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> > +                       rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> > +                       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> > +                       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> > +                       rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> > +                       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> > +                       rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
> >        }
> >
> >        if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> > @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> >                rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> >        }
> >
> > +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> > +               rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> > +               rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> > +               rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> > +       }
> > +
> >        return 0;
> >  }
> >
> > @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
> >  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
> >  {
> >        u32 reg;
> > +       u16 efuse_ctrl_reg;
> > +       efuse_ctrl_reg = EFUSE_CTRL;
> >
> > -       rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> > +       if (rt2x00dev->chip.mac_version == 0x3290)
> > +               efuse_ctrl_reg = 0x24;
> 
> This shouldn't be hardcoded. Please add a define to rt2800.h.
> 
> >
> > +       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
> >        return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
> >  }
> >  EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
> > @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
> >  {
> >        u32 reg;
> >
> > +       u16 efuse_ctrl_reg;
> > +       u16 efuse_data0_reg;
> > +       u16 efuse_data1_reg;
> > +       u16 efuse_data2_reg;
> > +       u16 efuse_data3_reg;
> > +
> > +       efuse_ctrl_reg = EFUSE_CTRL;
> > +       efuse_data0_reg = EFUSE_DATA0;
> > +       efuse_data1_reg = EFUSE_DATA1;
> > +       efuse_data2_reg = EFUSE_DATA2;
> > +       efuse_data3_reg = EFUSE_DATA3;
> > +
> > +       if (rt2x00dev->chip.mac_version == 0x3290) {
> > +               efuse_ctrl_reg = 0x24;
> > +               efuse_data3_reg = 0x28;
> > +               efuse_data2_reg = efuse_data3_reg + 4;
> > +               efuse_data1_reg = efuse_data2_reg + 4;
> > +               efuse_data0_reg = efuse_data1_reg + 4;
> > +       }
> 
> Same here, the register offsets would make sense as defines.
> 
> >        mutex_lock(&rt2x00dev->csr_mutex);
> >
> > -       rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> > +       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
> >        rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
> >        rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
> >        rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> > -       rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> > +       rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
> >
> >        /* Wait until the EEPROM has been loaded */
> > -       rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> > -
> > +       rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
> >        /* Apparently the data is read from end to start */
> > -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> > +       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
> >        /* The returned value is in CPU order, but eeprom is le */
> >        *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> > -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> > +       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
> >        *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> > -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> > +       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
> >        *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> > -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> > +       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
> >        *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
> >
> >        mutex_unlock(&rt2x00dev->csr_mutex);
> > @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> >         * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
> >         * RT53xx: defined in "EEPROM_CHIP_ID" field
> >         */
> > +       if (rt2x00dev->chip.mac_version == 0x3290)
> > +               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> > +       else
> >        rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
> 
> Indention.
> 
> >        if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> > -               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> > +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> > +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
> >                rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
> >        else
> >                value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> > @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> >        case RT3572:
> >        case RT5390:
> >        case RT5392:
> > +       case RT3290:
> >                break;
> >        default:
> >                ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> > @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> >        case RF5370:
> >        case RF5372:
> >        case RF5390:
> > +       case RF3290:
> >                break;
> >        default:
> >                ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> > @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> >                   rt2x00_rf(rt2x00dev, RF3320) ||
> >                   rt2x00_rf(rt2x00dev, RF5370) ||
> >                   rt2x00_rf(rt2x00dev, RF5372) ||
> > -                  rt2x00_rf(rt2x00dev, RF5390)) {
> > +                  rt2x00_rf(rt2x00dev, RF5390) ||
> > +                  rt2x00_rf(rt2x00dev, RF3290)) {
> >                spec->num_channels = 14;
> >                spec->channels = rf_vals_3x;
> >        } else if (rt2x00_rf(rt2x00dev, RF3052)) {
> > @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> >        case RF5370:
> >        case RF5372:
> >        case RF5390:
> > +       case RF3290:
> >                __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
> >                break;
> >        }
> > @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> >  }
> >  EXPORT_SYMBOL_GPL(rt2800_get_survey);
> >
> > +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
> 
> rt2800pci functions should live in rt2800pci.c, not in rt2800lib.c.
> 
> > +{
> > +       u32 wlanfunctrl;
> > +       u32 glocfg;
> > +       u32 cmbctrl;
> > +       u8 index;
> > +       int i;
> > +
> > +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> > +       rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> > +       if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> > +               return 0;
> > +
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> > +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> > +       udelay(REGISTER_BUSY_DELAY);
> > +
> > +       index = 0;
> > +       cmbctrl = 0;
> > +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> > +               rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> > +               if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> > +                       (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> > +                       break;
> > +               udelay(REGISTER_BUSY_DELAY);
> > +       }
> > +
> > +       if (index >= REGISTER_BUSY_COUNT) {
> > +               rt2800_register_write(rt2x00dev, 0x58, 0x018);
> > +               udelay(REGISTER_BUSY_DELAY);
> > +               rt2800_register_write(rt2x00dev, 0x58, 0x418);
> > +               udelay(REGISTER_BUSY_DELAY);
> > +               rt2800_register_write(rt2x00dev, 0x58, 0x618);
> > +               udelay(REGISTER_BUSY_DELAY);
> > +       } else {
> > +               rt2800_register_read(rt2x00dev,
> > +                       WPDMA_GLO_CFG, &glocfg);
> > +       }
> > +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> > +
> > +       rt2800_register_write(rt2x00dev,
> > +               WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> > +       udelay(REGISTER_BUSY_DELAY);
> > +       rt2800_register_write(rt2x00dev,
> > +               WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> > +       udelay(2);
> > +       rt2800_register_write(rt2x00dev,
> > +               INT_SOURCE_CSR, 0x7fffffff);
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> > +
> > +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> > +{
> > +       u32 wlanfunctrl;
> > +       u32 glocfg;
> > +       u32 reg;
> > +       int i;
> > +
> > +       /* Change Interrupt bitmask. */
> > +       rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> > +       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> > +       rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> > +       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> > +
> > +       /* wait RX DMA idle */
> > +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> > +               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> > +               if ((rt2x00_get_field32(glocfg,
> > +                       WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> > +                       (glocfg == 0xFFFFFFFF))
> > +                       break;
> > +               udelay(REGISTER_BUSY_DELAY);
> > +       }
> > +
> > +       if (i >= REGISTER_BUSY_COUNT) {
> > +               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> > +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> > +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> > +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> > +               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> > +               return 0;
> > +               }
> > +
> > +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> > +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> > +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> > +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> > +       udelay(REGISTER_BUSY_DELAY);
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
> >  MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
> >  MODULE_VERSION(DRV_VERSION);
> >  MODULE_DESCRIPTION("Ralink RT2800 library");
> > diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> > index 18a0b67..22d7cbb 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> > @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> >  int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> >                      struct survey_info *survey);
> >  void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> > -
> > +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> > +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
> >  #endif /* RT2800LIB_H */
> > diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> > index 931331d..9251f2d 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> > +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> > @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
> >  */
> >  static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
> >  {
> > +
> > +       if (rt2x00_rt(rt2x00dev, RT3290))
> > +               return FIRMWARE_RT3290;
> > +
> >        return FIRMWARE_RT2860;
> >  }
> >
> > @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> >                rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
> >                rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
> >        }
> > +
> > +       if (rt2x00_rt(rt2x00dev, RT3290))
> > +               rt2800pci_3290_disable_wlan(rt2x00dev);
> >  }
> >
> >  static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> > @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
> >         */
> >        rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
> >
> > +       if (rt2x00_rf(rt2x00dev, RF3290))
> > +               rt2800pci_3290_enable_wlan(rt2x00dev);
> >        return 0;
> >  }
> >
> > @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
> >        { PCI_DEVICE(0x1814, 0x539a) },
> >        { PCI_DEVICE(0x1814, 0x539f) },
> >  #endif
> > +#ifdef CONFIG_RT2800PCI_RT3290
> > +       { PCI_DEVICE(0x1814, 0x3290) },
> > +#endif
> >        { 0, }
> >  };
> >  #endif /* CONFIG_PCI */
> > diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> > index 70e050d..dd043c7 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> > @@ -49,6 +49,9 @@
> >  #define FIRMWARE_RT2860                        "rt2860.bin"
> >  #define FIRMWARE_IMAGE_BASE            0x2000
> >
> > +
> > +#define FIRMWARE_RT3290                        "rt3290.bin"
> > +
> >  /*
> >  * DMA descriptor defines.
> >  */
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> > index ca36ccc..ee770e7 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00.h
> > +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> > @@ -193,10 +193,11 @@ struct rt2x00_chip {
> >  #define RT3883         0x3883  /* WSOC */
> >  #define RT5390         0x5390  /* 2.4GHz */
> >  #define RT5392         0x5392  /* 2.4GHz */
> > +#define RT3290         0x3290
> >
> >        u16 rf;
> >        u16 rev;
> > -
> > +       u16 mac_version;
> >        enum rt2x00_chip_intf intf;
> >  };
> >
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > index 0a4653a..9bbd9a3 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> >        struct ieee80211_hw *hw;
> >        struct rt2x00_dev *rt2x00dev;
> >        int retval;
> > +       u16 device_id;
> >
> >        retval = pci_enable_device(pci_dev);
> >        if (retval) {
> > @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> >        if (retval)
> >                goto exit_free_device;
> >
> > +
> > +       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> > +       if (device_id == 0x3290)
> > +               rt2x00dev->chip.mac_version = 0x3290;
> > +
> >        retval = rt2x00lib_probe_dev(rt2x00dev);
> >        if (retval)
> >                goto exit_free_reg;
> > --
> > 1.7.5.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH] rt2x00 : RT3290 chip support
  2012-05-02 18:13   ` John W. Linville
@ 2012-05-03  1:07     ` Woody Hung (洪秋竹)
  0 siblings, 0 replies; 5+ messages in thread
From: Woody Hung (洪秋竹) @ 2012-05-03  1:07 UTC (permalink / raw)
  To: John W. Linville, Helmut Schaa
  Cc: linux-wireless@vger.kernel.org,
	Jay Hung (洪偉傑),
	Pohsun Yang (楊伯勳),
	Dennis Lee (李明達), Ivo Van Doorn,
	Gertjan van Wingerde

R290IGl0LCBJIHdpbGwgcmUtd3JpdGUgaXR+fn4NCg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0t
LS0NCkZyb206IEpvaG4gVy4gTGludmlsbGUgW21haWx0bzpsaW52aWxsZUB0dXhkcml2ZXIuY29t
XQ0KU2VudDogVGh1cnNkYXksIE1heSAwMywgMjAxMiAyOjEzIEFNDQpUbzogSGVsbXV0IFNjaGFh
DQpDYzogV29vZHkgSHVuZyAo5rSq56eL56u5KTsgbGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwu
b3JnOyBKYXkgSHVuZyAo5rSq5YGJ5YKRKTsgUG9oc3VuIFlhbmcgKOaliuS8r+WLsyk7IERlbm5p
cyBMZWUgKOadjuaYjumBlCk7IEl2byBWYW4gRG9vcm47IEdlcnRqYW4gdmFuIFdpbmdlcmRlDQpT
dWJqZWN0OiBSZTogW1BBVENIXSBydDJ4MDAgOiBSVDMyOTAgY2hpcCBzdXBwb3J0DQoNClBsZWFz
ZSByZXNwb25kIHRvIEhlbG11dCdzIGNvbW1lbnRhcnkuLi4NCg0KT24gRnJpLCBBcHIgMjcsIDIw
MTIgYXQgMDk6NDA6MjhBTSArMDIwMCwgSGVsbXV0IFNjaGFhIHdyb3RlOg0KPiBIaSBXb29keSwN
Cj4NCj4gQSBiaXQgbW9yZSB2ZXJib3NlIHBhdGNoIGRlc2NyaXB0aW9uIHdvdWxkIGJlIGhpZ2hs
eSBhcHByZWNpYXRlZC4gQWxzbw0KPiBzZWUgc29tZSBpbmxpbmUgY29tbWVudHMgYWJvdXQgdGhl
IHBhdGNoIGl0c2VsZi4gSG93ZXZlciwgSSBvbmx5IGhhZCBhDQo+IHF1aWNrIGxvb2ssIHNvIGV4
cGVjdCBhIGZldyBtb3JlIGNvbW1lbnRzIGZyb20gb3RoZXJzIHRvbyAuLi4NCj4NCj4gQWxzbywg
cGxlYXNlIGFsd2F5cyBjaGVjayB5b3VyIHBhdGNoIGJ5IHJ1bm5pbmcgc2NyaXB0cy9jaGVja3Bh
dGNoLnBsDQo+IGZyb20geW91ciBrZXJuZWwgdHJlZSBvbnRvIGl0Lg0KPg0KPiBIZWxtdXQNCj4N
Cj4gT24gRnJpLCBBcHIgMjcsIDIwMTIgYXQgNDoyMiBBTSwgV29vZHkgSHVuZyA8V29vZHkuSHVu
Z0BtZWRpYXRlay5jb20+IHdyb3RlOg0KPiA+IFRoaXMgc3VwcG9ydCBSVDMyOTAgY2hpcA0KPiA+
DQo+ID4gU2lnbmVkLW9mZi1ieTogV29vZHkgSHVuZyA8V29vZHkuSHVuZ0BtZWRpYXRlay5jb20+
DQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnICAgICB8
ICAgIDggKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwLmggICAgfCAg
MTIwICsrKysrKysrKy0NCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMGxp
Yi5jIHwgIDM5NQ0KPiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKystLQ0KPiA+ICBkcml2
ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwbGliLmggfCAgICAzICstDQo+ID4gIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuYyB8ICAgMTIgKw0KPiA+ICBkcml2ZXJz
L25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNpLmggfCAgICAzICsNCj4gPiAgZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMC5oICAgIHwgICAgMyArLQ0KPiA+ICBkcml2ZXJzL25l
dC93aXJlbGVzcy9ydDJ4MDAvcnQyeDAwcGNpLmMgfCAgICA2ICsNCj4gPiAgOCBmaWxlcyBjaGFu
Z2VkLCA1MjAgaW5zZXJ0aW9ucygrKSwgMzAgZGVsZXRpb25zKC0pDQo+ID4NCj4gPiBkaWZmIC0t
Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL0tjb25maWcNCj4gPiBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnDQo+ID4gaW5kZXggMjk5YzM4Ny4uYzc1NDhkYSAx
MDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvS2NvbmZpZw0KPiA+
ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnDQo+ID4gQEAgLTk5LDYg
Kzk5LDE0IEBAIGNvbmZpZyBSVDI4MDBQQ0lfUlQ1M1hYDQo+ID4gICAgICAgICAgcnQyODAwcGNp
IGRyaXZlci4NCj4gPiAgICAgICAgICBTdXBwb3J0ZWQgY2hpcHM6IFJUNTM5MA0KPiA+DQo+ID4g
K2NvbmZpZyBSVDI4MDBQQ0lfUlQzMjkwDQo+ID4gKyAgICAgICBib29sICJydDI4MDBwY2kgLSBJ
bmNsdWRlIHN1cHBvcnQgZm9yIHJ0MzI5MCBkZXZpY2VzIChFWFBFUklNRU5UQUwpIg0KPiA+ICsg
ICAgICAgZGVwZW5kcyBvbiBFWFBFUklNRU5UQUwNCj4gPiArICAgICAgIGRlZmF1bHQgeQ0KPiA+
ICsgICAgICAgLS0taGVscC0tLQ0KPiA+ICsgICAgICAgICBUaGlzIGFkZHMgc3VwcG9ydCBmb3Ig
cnQzMjkwIHdpcmVsZXNzIGNoaXBzZXQgZmFtaWx5IHRvDQo+ID4gK3RoZQ0KPiA+ICsgICAgICAg
ICBydDI4MDBwY2kgZHJpdmVyLg0KPiA+ICsgICAgICAgICBTdXBwb3J0ZWQgY2hpcHM6IFJUMzI5
MA0KPiA+ICBlbmRpZg0KPiA+DQo+ID4gIGNvbmZpZyBSVDI1MDBVU0INCj4gPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMC5oDQo+ID4gYi9kcml2ZXJzL25l
dC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwLmgNCj4gPiBpbmRleCBkOTFmNGY2Li4zOWIxNjg1IDEw
MDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDAuaA0KPiA+
ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDAuaA0KPiA+IEBAIC03MCw3
ICs3MCw3IEBADQo+ID4gICNkZWZpbmUgUkY1MzcwICAgICAgICAgICAgICAgICAgICAgICAgIDB4
NTM3MA0KPiA+ICAjZGVmaW5lIFJGNTM3MiAgICAgICAgICAgICAgICAgICAgICAgICAweDUzNzIN
Cj4gPiAgI2RlZmluZSBSRjUzOTAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1MzkwDQo+ID4g
LQ0KPiA+ICsjZGVmaW5lIFJGMzI5MCAgICAgICAgICAgICAgICAgICAgICAgICAweDMyOTANCj4N
Cj4gVGhlcmUncyBubyBuZWVkIHRvIHJlbW92ZSB0aGUgZW10eSBsaW5lIGhlcmUuDQo+DQo+ID4g
IC8qDQo+ID4gICogQ2hpcHNldCByZXZpc2lvbnMuDQo+ID4gICovDQo+ID4gQEAgLTExMiw2ICsx
MTIsMTIgQEANCj4gPiAgKiBSZWdpc3RlcnMuDQo+ID4gICovDQo+ID4NCj4gPiArDQo+ID4gKy8q
DQo+ID4gKyAqIE1BQ19DU1IwXzMyOTA6IE1BQ19DU1IwIGZvciBydDMyOTAgdG8gaWRlbnRpdHkg
TUFDIHZlcnNpb24gbnVtYmVyLg0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBNQUNfQ1NSMF8zMjkw
ICAgICAgICAgICAgICAgICAgICAgICAgICAweDAwMDANCj4gPiArDQo+DQo+IFRoaXMgc2hvdWxk
IGJlIG1vdmVkIHRvIHRoZSBvdGhlciBNQUMgcmVnaXN0ZXIgZGVmaW5pdGlvbnMuDQo+IElzIHRo
aXMgcmVnaXN0ZXIgb25seSB2YWxpZCBvbiAzMjkwIGNoaXBzZXRzPw0KPg0KPiA+ICAvKg0KPiA+
ICAqIEUyUFJPTV9DU1I6IFBDSSBFRVBST00gY29udHJvbCByZWdpc3Rlci4NCj4gPiAgKiBSRUxP
QUQ6IFdyaXRlIDEgdG8gcmVsb2FkIGVlcHJvbSBjb250ZW50Lg0KPiA+IEBAIC0zMDUsNiArMzEx
LDExOCBAQA0KPiA+ICAjZGVmaW5lIEdQSU9fQ1RSTF9DRkdfR1BJT0RfQklUNyAgICAgICBGSUVM
RDMyKDB4MDAwMDgwMDApDQo+ID4NCj4gPiAgLyoNCj4gPiArICogV0xBTl9DVFJMX0NGRw0KPiA+
ICsgKi8NCj4gPiArI2RlZmluZSBXTEFOX0ZVTl9DVFJMICAgICAgICAgICAgICAgICAgMHg4MCAj
ZGVmaW5lIFdMQU5fRU4NCj4gPiArRklFTEQzMigweDAwMDAwMDAxKSAjZGVmaW5lIFdMQU5fQ0xL
X0VODQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAwMikgI2RlZmluZSBXTEFOX1JTVjENCj4gPiArRklF
TEQzMigweDAwMDAwMDA0KSAjZGVmaW5lIFdMQU5fUkVTRVQNCj4gPiArRklFTEQzMigweDAwMDAw
MDA4KSAjZGVmaW5lIFBDSUVfQVBQMF9DTEtfUkVRDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAxMCkg
I2RlZmluZSBGUkNfV0xfQU5UX1NFVA0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwMjApICNkZWZpbmUg
SU5WX1RSX1NXMA0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwNDApICNkZWZpbmUgV0xBTl9HUElPX0lO
X0JJVDANCj4gPiArRklFTEQzMigweDAwMDAwMTAwKSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQx
DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDIwMCkgI2RlZmluZSBXTEFOX0dQSU9fSU5fQklUMg0KPiA+
ICtGSUVMRDMyKDB4MDAwMDA0MDApICNkZWZpbmUgV0xBTl9HUElPX0lOX0JJVDMNCj4gPiArRklF
TEQzMigweDAwMDAwODAwKSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQ0DQo+ID4gK0ZJRUxEMzIo
MHgwMDAwMTAwMCkgI2RlZmluZSBXTEFOX0dQSU9fSU5fQklUNQ0KPiA+ICtGSUVMRDMyKDB4MDAw
MDIwMDApICNkZWZpbmUgV0xBTl9HUElPX0lOX0JJVDYNCj4gPiArRklFTEQzMigweDAwMDA0MDAw
KSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQ3DQo+ID4gK0ZJRUxEMzIoMHgwMDAwODAwMCkgI2Rl
ZmluZSBXTEFOX0dQSU9fSU5fQklUX0FMTA0KPiA+ICtGSUVMRDMyKDB4MDAwMGZmMDApICNkZWZp
bmUgV0xBTl9HUElPX09VVF9CSVQwDQo+ID4gK0ZJRUxEMzIoMHgwMDAxMDAwMCkgI2RlZmluZSBX
TEFOX0dQSU9fT1VUX0JJVDENCj4gPiArRklFTEQzMigweDAwMDIwMDAwKSAjZGVmaW5lIFdMQU5f
R1BJT19PVVRfQklUMg0KPiA+ICtGSUVMRDMyKDB4MDAwNDAwMDApICNkZWZpbmUgV0xBTl9HUElP
X09VVF9CSVQzDQo+ID4gK0ZJRUxEMzIoMHgwMDA1MDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VU
X0JJVDQNCj4gPiArRklFTEQzMigweDAwMTAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfQklU
NQ0KPiA+ICtGSUVMRDMyKDB4MDAyMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9CSVQ2DQo+
ID4gK0ZJRUxEMzIoMHgwMDQwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX0JJVDcNCj4gPiAr
RklFTEQzMigweDAwODAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfQklUX0FMTA0KPiA+ICtG
SUVMRDMyKDB4MDBmZjAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQwDQo+ID4gK0ZJ
RUxEMzIoMHgwMTAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDENCj4gPiArRklF
TEQzMigweDAyMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUMg0KPiA+ICtGSUVM
RDMyKDB4MDQwMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQzDQo+ID4gK0ZJRUxE
MzIoMHgwODAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDQNCj4gPiArRklFTEQz
MigweDEwMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUNQ0KPiA+ICtGSUVMRDMy
KDB4MjAwMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQ2DQo+ID4gK0ZJRUxEMzIo
MHg0MDAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDcNCj4gPiArRklFTEQzMigw
eDgwMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUX0FMTA0KPiA+ICtGSUVMRDMy
KDB4ZmYwMDAwMDApDQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBDTUJfQ1RSTF9DRkcNCj4gPiAr
ICovDQo+ID4gKyNkZWZpbmUgQ01CX0NUUkwgICAgICAgICAgICAgICAweDIwICNkZWZpbmUgQVVY
X09QVF9CSVQwDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAwMSkgI2RlZmluZSBBVVhfT1BUX0JJVDEN
Cj4gPiArRklFTEQzMigweDAwMDAwMDAyKSAjZGVmaW5lIEFVWF9PUFRfQklUMg0KPiA+ICtGSUVM
RDMyKDB4MDAwMDAwMDQpICNkZWZpbmUgQVVYX09QVF9CSVQzDQo+ID4gK0ZJRUxEMzIoMHgwMDAw
MDAwOCkgI2RlZmluZSBBVVhfT1BUX0JJVDQNCj4gPiArRklFTEQzMigweDAwMDAwMDEwKSAjZGVm
aW5lIEFVWF9PUFRfQklUNQ0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwMjApICNkZWZpbmUgQVVYX09Q
VF9CSVQ2DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDA0MCkgI2RlZmluZSBBVVhfT1BUX0JJVDcNCj4g
PiArRklFTEQzMigweDAwMDAwMDgwKSAjZGVmaW5lIEFVWF9PUFRfQklUOA0KPiA+ICtGSUVMRDMy
KDB4MDAwMDAxMDApICNkZWZpbmUgQVVYX09QVF9CSVQ5DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDIw
MCkgI2RlZmluZSBBVVhfT1BUX0JJVDEwDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDQwMCkgI2RlZmlu
ZSBBVVhfT1BUX0JJVDExDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDgwMCkgI2RlZmluZSBBVVhfT1BU
X0JJVDEyDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMTAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDEzDQo+
ID4gK0ZJRUxEMzIoMHgwMDAwMjAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDE0DQo+ID4gK0ZJRUxE
MzIoMHgwMDAwNDAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDE1DQo+ID4gK0ZJRUxEMzIoMHgwMDAw
ODAwMCkgI2RlZmluZSBMRE8yNV9MRVZFTA0KPiA+ICtGSUVMRDMyKDB4MDAwMzAwMDApICNkZWZp
bmUgTERPMjVfTEFSR0VBDQo+ID4gK0ZJRUxEMzIoMHgwMDA0MDAwMCkgI2RlZmluZSBMRE8yNV9G
UkNfT04NCj4gPiArRklFTEQzMigweDAwMDgwMDAwKSAjZGVmaW5lIENNQl9SU1YNCj4gPiArRklF
TEQzMigweDAwMzAwMDAwKSAjZGVmaW5lIFhUQUxfUkRZDQo+ID4gK0ZJRUxEMzIoMHgwMDQwMDAw
MCkgI2RlZmluZSBQTExfTEQNCj4gPiArRklFTEQzMigweDAwODAwMDAwKSAjZGVmaW5lIExET19D
T1JFX0xFVkVMDQo+ID4gK0ZJRUxEMzIoMHgwRjAwMDAwMCkgI2RlZmluZSBMRE9fQkdTRUwNCj4g
PiArRklFTEQzMigweDMwMDAwMDAwKSAjZGVmaW5lIExETzNfRU4NCj4gPiArRklFTEQzMigweDQw
MDAwMDAwKSAjZGVmaW5lIExETzBfRU4NCj4gPiArRklFTEQzMigweDgwMDAwMDAwKQ0KPiA+ICsN
Cj4gPiArLyoNCj4gPiArICogT1NDX0NUUkxfQ0ZHDQo+ID4gKyAqLw0KPiA+ICsjZGVmaW5lIE9T
Q19DVFJMICAgICAgICAgICAgICAgMHgzOCAjZGVmaW5lIE9TQ19SRUZfQ1lDTEUNCj4gPiArRklF
TEQzMigweDAwMDAxZmZmKSAjZGVmaW5lIE9TQ19SU1YNCj4gPiArRklFTEQzMigweDAwMDBlMDAw
KSAjZGVmaW5lIE9TQ19DQUxfQ05UDQo+ID4gK0ZJRUxEMzIoMHgwZmZmMDAwMCkgI2RlZmluZSBP
U0NfQ0FMX0FDSw0KPiA+ICtGSUVMRDMyKDB4MTAwMDAwMDApICNkZWZpbmUgT1NDX0NMS18zMktf
VkxEDQo+ID4gK0ZJRUxEMzIoMHgyMDAwMDAwMCkgI2RlZmluZSBPU0NfQ0FMX1JFUQ0KPiA+ICtG
SUVMRDMyKDB4NDAwMDAwMDApICNkZWZpbmUgT1NDX1JPU0NfRU4NCj4gPiArRklFTEQzMigweDgw
MDAwMDAwKQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogUExMX0NUUkxfQ0ZHDQo+ID4gKyAqLw0K
PiA+ICsjZGVmaW5lIFBMTF9DVFJMICAgICAgICAgICAgICAgMHg1MCAjZGVmaW5lIFBMTF9SRVNF
UlZFRF9JTlBVVDENCj4gPiArRklFTEQzMigweDAwMDAwMGZmKSAjZGVmaW5lIFBMTF9SRVNFUlZF
RF9JTlBVVDINCj4gPiArRklFTEQzMigweDAwMDBmZjAwKSAjZGVmaW5lIFBMTF9DT05UUk9MDQo+
ID4gK0ZJRUxEMzIoMHgwMDA3MDAwMCkgI2RlZmluZSBQTExfTFBGX1IxDQo+ID4gK0ZJRUxEMzIo
MHgwMDA4MDAwMCkgI2RlZmluZSBQTExfTFBGX0MxX0NUUkwNCj4gPiArRklFTEQzMigweDAwMzAw
MDAwKSAjZGVmaW5lIFBMTF9MUEZfQzJfQ1RSTA0KPiA+ICtGSUVMRDMyKDB4MDBjMDAwMDApICNk
ZWZpbmUgUExMX0NQX0NVUlJFTlRfQ1RSTA0KPiA+ICtGSUVMRDMyKDB4MDMwMDAwMDApICNkZWZp
bmUgUExMX1BGRF9ERUxBWV9DVFJMDQo+ID4gK0ZJRUxEMzIoMHgwYzAwMDAwMCkgI2RlZmluZSBQ
TExfTE9DS19DVFJMDQo+ID4gK0ZJRUxEMzIoMHg3MDAwMDAwMCkgI2RlZmluZSBQTExfVkJHQktf
RU4NCj4gPiArRklFTEQzMigweDgwMDAwMDAwKQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogQ09F
WF9DRkdfMA0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBDT0VYX0NGRzAgICAgICAgICAgICAgICAg
ICAgICAgMHg0MA0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogQ09FWF9DRkdfMQ0KPiA+ICsgKi8N
Cj4gPiArI2RlZmluZSBDT0VYX0NGRzEgICAgICAgICAgICAgICAgICAgICAgMHg0NA0KPiA+ICsN
Cj4gPiArLyoNCj4gPiArICogQ09FWF9DRkdfMg0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBDT0VY
X0NGRzIgICAgICAgICAgICAgICAgICAgICAgMHg0OA0KPiA+ICsNCj4gPiArLyoNCj4gPiAgKiBN
Q1VfQ01EX0NGRw0KPiA+ICAqLw0KPiA+ICAjZGVmaW5lIE1DVV9DTURfQ0ZHICAgICAgICAgICAg
ICAgICAgICAweDAyMmMgZGlmZiAtLWdpdA0KPiA+IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQy
eDAwL3J0MjgwMGxpYi5jDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
bGliLmMNCj4gPiBpbmRleCAxY2QxNmI0Li43NzUzNzkxIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZl
cnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0
L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuYw0KPiA+IEBAIC0zNjEsNiArMzYxLDEwIEBAIGlu
dCBydDI4MDBfY2hlY2tfZmlybXdhcmUoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2
LA0KPiA+ICAgICAgICAgICAgICAgIG11bHRpcGxlID0gdHJ1ZTsNCj4gPiAgICAgICAgfSBlbHNl
IHsNCj4gPiAgICAgICAgICAgICAgICBmd19sZW4gPSA4MTkyOw0KPiA+ICsNCj4gPiArICAgICAg
ICAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgZndfbGVuID0gNDA5NjsNCj4gPiArDQo+ID4gICAgICAgICAgICAgICAg
bXVsdGlwbGUgPSB0cnVlOw0KPiA+ICAgICAgICB9DQo+ID4NCj4gPiBAQCAtNDE3LDcgKzQyMSw4
IEBAIGludCBydDI4MDBfbG9hZF9maXJtd2FyZShzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4
MDBkZXYsDQo+ID4gICAgICAgIGlmIChydDJ4MDBfaXNfcGNpKHJ0MngwMGRldikpIHsNCj4gPiAg
ICAgICAgICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSB8fA0KPiA+ICAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKSB7DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIEFVWF9D
VFJMLA0KPiA+ICZyZWcpOw0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9m
aWVsZDMyKCZyZWcsDQo+ID4gQVVYX0NUUkxfRk9SQ0VfUENJRV9DTEssIDEpOw0KPiA+ICAgICAg
ICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsDQo+ID4gQVVYX0NUUkxf
V0FLRV9QQ0lFX0VOLCAxKTsgQEAgLTg0NCw2ICs4NDksMTAgQEAgaW50DQo+ID4gcnQyODAwX3Jm
a2lsbF9wb2xsKHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gIHsNCj4gPiAgICAg
ICAgdTMyIHJlZzsNCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJU
MzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAw
ZGV2LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAgICAgICAgICAgIHJl
dHVybiBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBXTEFOX0dQSU9fSU5fQklUMCk7DQo+ID4gKyAg
ICAgICB9IGVsc2UNCj4gPiAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBH
UElPX0NUUkxfQ0ZHLCAmcmVnKTsNCj4NCj4gVGhpcyBsb29rcyBhd2t3YXJkLCBlaXRoZXIgeW91
IGhhdmUgdG8gdXNlIGNvcnJlY3QgaW5kZW50aW9uIGhlcmUgb3INCj4gZHJvcCB0aGUgZWxzZSBj
b21wbGV0ZWx5Lg0KPg0KPiA+ICAgICAgICByZXR1cm4gcnQyeDAwX2dldF9maWVsZDMyKHJlZywg
R1BJT19DVFJMX0NGR19CSVQyKTsNCj4gPiAgfQ0KPiA+IEBAIC0xOTMwLDcgKzE5MzksOCBAQCBz
dGF0aWMgdm9pZA0KPiA+IHJ0MjgwMF9jb25maWdfY2hhbm5lbF9yZjMwNTIoc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldiwNCj4gPg0KPiA+ICAjZGVmaW5lIFJUNTM5MF9QT1dFUl9CT1VORCAg
ICAgMHgyNw0KPiA+ICAjZGVmaW5lIFJUNTM5MF9GUkVRX09GRlNFVF9CT1VORCAgICAgICAweDVm
DQo+ID4gLQ0KPg0KPiBUaGlzIGVtcHR5IGxpbmUgY2FuIHN0YXkuDQo+DQo+ID4gKyNkZWZpbmUg
UlQzMjkwX1BPV0VSX0JPVU5EICAgICAweDI3ICNkZWZpbmUNCj4gPiArUlQzMjkwX0ZSRVFfT0ZG
U0VUX0JPVU5EICAgICAgIDB4NWYNCj4NCj4gTWlnaHQgYmUgd29ydGggdG8gYWRkIGFub3RoZXIg
ZW1wdHkgbGluZSBoZXJlLg0KPg0KPiA+ICBzdGF0aWMgdm9pZCBydDI4MDBfY29uZmlnX2NoYW5u
ZWxfcmY1M3h4KHN0cnVjdCBydDJ4MDBfZGV2DQo+ID4gKnJ0MngwMGRldiwNCj4gPiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGllZWU4MDIxMV9jb25mICpj
b25mLA0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qg
cmZfY2hhbm5lbCAqcmYsIEBADQo+ID4gLTIwMjUsNiArMjAzNSw2NyBAQCBzdGF0aWMgdm9pZCBy
dDI4MDBfY29uZmlnX2NoYW5uZWxfcmY1M3h4KHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0Mngw
MGRldiwNCj4gPiAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMywgcmZjc3Ip
Ow0KPiA+ICB9DQo+ID4NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIHJ0MjgwMF9jb25maWdfY2hh
bm5lbF9yZjMyOTAoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiArKnJ0MngwMGRldiwNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBpZWVlODAyMTFfY29u
Zg0KPiA+ICsqY29uZiwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIHN0cnVjdCByZl9jaGFubmVsICpyZiwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIHN0cnVjdCBjaGFubmVsX2luZm8gKmluZm8pDQo+ID4gK3sNCj4gPiAr
ICAgICAgIHU4IHJmY3NyOw0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDgsIHJmLT5yZjEpOw0KPiA+ICsgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgOSwgcmYtPnJmMyk7DQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4
MDBkZXYsIDExLCAmcmZjc3IpOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDgoJnJmY3Ny
LCBSRkNTUjExX1IsIHJmLT5yZjIpOw0KPiA+ICsgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgMTEsIHJmY3NyKTsNCj4gPiArDQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3JfcmVh
ZChydDJ4MDBkZXYsIDQ5LCAmcmZjc3IpOw0KPiA+ICsgICAgICAgaWYgKGluZm8tPmRlZmF1bHRf
cG93ZXIxID4gUlQ1MzkwX1BPV0VSX0JPVU5EKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBf
c2V0X2ZpZWxkOCgmcmZjc3IsIFJGQ1NSNDlfVFgsDQo+ID4gKyBSVDMyOTBfUE9XRVJfQk9VTkQp
Ow0KPiA+ICsgICAgICAgZWxzZQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxk
OCgmcmZjc3IsIFJGQ1NSNDlfVFgsDQo+ID4gKyBpbmZvLT5kZWZhdWx0X3Bvd2VyMSk7DQo+ID4g
KyAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0OSwgcmZjc3IpOw0KPiA+ICsN
Cj4gPiArICAgICAgIHJ0MjgwMF9yZmNzcl9yZWFkKHJ0MngwMGRldiwgMTcsICZyZmNzcik7DQo+
ID4gKyAgICAgICBpZiAocnQyeDAwZGV2LT5mcmVxX29mZnNldCA+IFJUMzI5MF9GUkVRX09GRlNF
VF9CT1VORCkNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDgoJnJmY3NyLCBS
RkNTUjE3X0NPREUsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJUMzI5
MF9GUkVRX09GRlNFVF9CT1VORCk7DQo+ID4gKyAgICAgICBlbHNlDQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MngwMF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IxN19DT0RFLA0KPiA+ICsgcnQyeDAw
ZGV2LT5mcmVxX29mZnNldCk7DQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCAxNywgcmZjc3IpOw0KPiA+ICsNCj4gPiArICAgICAgIGlmIChyZi0+Y2hhbm5lbCA8PSAx
NCkgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4MDBkZXYsIDMy
LCAmcmZjc3IpOw0KPiA+ICsgICAgICAgICAgICAgICByZmNzciAmPSB+MHhGODsNCj4gPiArICAg
ICAgICAgICAgICAgcmZjc3IgfD0gKDB4MWYgPDwgMyk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMyLCByZmNzcik7DQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MjgwMF9yZmNzcl9yZWFkKHJ0MngwMGRldiwgMzEsICZyZmNzcik7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJmY3NyICY9IH4weEY4Ow0KPiA+ICsgICAgICAgICAgICAgICByZmNzciB8PSAo
MHgxZiA8PCAzKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0Mngw
MGRldiwgMzEsIHJmY3NyKTsNCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIGlmIChyZi0+Y2hh
bm5lbCA9PSA2KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCA2OCwgMHgwYyk7DQo+ID4gKyAgICAgICAgICAgICAgIGVsc2UNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNjgsIDB4MGIp
Ow0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJmLT5jaGFubmVsID49IDEgJiYgcmYt
PmNoYW5uZWwgPD0gNikNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dy
aXRlKHJ0MngwMGRldiwgNTksIDB4MGYpOw0KPiA+ICsgICAgICAgICAgICAgICBlbHNlIGlmIChy
Zi0+Y2hhbm5lbCA+PSA3ICYmIHJmLT5jaGFubmVsIDw9IDExKQ0KPiA+ICsgICAgICAgICAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA1OSwgMHgwZSk7DQo+ID4gKyAg
ICAgICAgICAgICAgIGVsc2UgaWYgKHJmLT5jaGFubmVsID49IDEyICYmIHJmLT5jaGFubmVsIDw9
IDE0KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAw
ZGV2LCA1OSwgMHgwZCk7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAgICAgcnQyODAw
X3JmY3NyX3JlYWQocnQyeDAwZGV2LCAzMCwgJnJmY3NyKTsNCj4gPiArICAgICAgIHJ0MngwMF9z
ZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IzMF9UWF9IMjBNLCAwKTsNCj4gPiArICAgICAgIHJ0Mngw
MF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IzMF9SWF9IMjBNLCAwKTsNCj4gPiArICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMwLCByZmNzcik7DQo+ID4gKw0KPiA+ICsgICAg
ICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAwZGV2LCAzLCAmcmZjc3IpOw0KPiA+ICsgICAgICAg
cnQyeDAwX3NldF9maWVsZDgoJnJmY3NyLCBSRkNTUjMwX1JGX0NBTElCUkFUSU9OLCAxKTsNCj4g
PiArICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMsIHJmY3NyKTsgfQ0KPg0K
PiBUaGlzIGZ1bmN0aW9uIGNvdWxkIHJlYWxseSB1c2UgYSBmZXcgY29tbWVudHMuDQo+DQo+ID4g
IHN0YXRpYyB2b2lkIHJ0MjgwMF9jb25maWdfY2hhbm5lbChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2LA0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBpZWVl
ODAyMTFfY29uZiAqY29uZiwNCj4gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBz
dHJ1Y3QgcmZfY2hhbm5lbCAqcmYsIEBAIC0yMDU4LDYNCj4gPiArMjEyOSw5IEBAIHN0YXRpYyB2
b2lkIHJ0MjgwMF9jb25maWdfY2hhbm5lbChzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBk
ZXYsDQo+ID4gICAgICAgIGNhc2UgUkY1MzkwOg0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9j
b25maWdfY2hhbm5lbF9yZjUzeHgocnQyeDAwZGV2LCBjb25mLCByZiwNCj4gPiBpbmZvKTsNCj4g
PiAgICAgICAgICAgICAgICBicmVhazsNCj4gPiArICAgICAgIGNhc2UgUkYzMjkwOg0KPiA+ICsg
ICAgICAgICAgICAgICBydDI4MDBfY29uZmlnX2NoYW5uZWxfcmYzMjkwKHJ0MngwMGRldiwgY29u
ZiwgcmYsDQo+ID4gKyBpbmZvKTsNCj4gPiArICAgICAgICAgICAgICAgYnJlYWs7DQo+ID4gICAg
ICAgIGRlZmF1bHQ6DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2NvbmZpZ19jaGFubmVsX3Jm
Mnh4eChydDJ4MDBkZXYsIGNvbmYsIHJmLA0KPiA+IGluZm8pOw0KPiA+ICAgICAgICB9DQo+ID4g
QEAgLTI1NDUsNiArMjYxOSw3IEBAIHZvaWQgcnQyODAwX3Zjb19jYWxpYnJhdGlvbihzdHJ1Y3Qg
cnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgIGNhc2UgUkY1MzcwOg0KPiA+
ICAgICAgICBjYXNlIFJGNTM3MjoNCj4gPiAgICAgICAgY2FzZSBSRjUzOTA6DQo+ID4gKyAgICAg
ICBjYXNlIFJGMzI5MDoNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4
MDBkZXYsIDMsICZyZmNzcik7DQo+ID4gICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDgo
JnJmY3NyLCBSRkNTUjMwX1JGX0NBTElCUkFUSU9OLCAxKTsNCj4gPiAgICAgICAgICAgICAgICBy
dDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzLCByZmNzcik7IEBAIC0yNjc3LDcNCj4gPiAr
Mjc1Miw4IEBAIHN0YXRpYyB1OCBydDI4MDBfZ2V0X2RlZmF1bHRfdmdjKHN0cnVjdCBydDJ4MDBf
ZGV2DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0
MngwMGRldiwgUlQzMDkwKSB8fA0KPiA+ICAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQy
eDAwZGV2LCBSVDMzOTApIHx8DQo+ID4gICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDB4MWMgKyAo
MiAqIHJ0MngwMGRldi0+bG5hX2dhaW4pOw0KPiA+ICAgICAgICAgICAgICAgIGVsc2UNCj4gPiAg
ICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAweDJlICsgcnQyeDAwZGV2LT5sbmFfZ2Fpbjsg
QEAgLTI3NzEsOQ0KPiA+ICsyODQ3LDQ3IEBAIHN0YXRpYyBpbnQgcnQyODAwX2luaXRfcmVnaXN0
ZXJzKHN0cnVjdCBydDJ4MDBfZGV2DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgcnQyeDAw
X3NldF9maWVsZDMyKCZyZWcsIEJLT0ZGX1NMT1RfQ0ZHX0NDX0RFTEFZX1RJTUUsIDIpOw0KPiA+
ICAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBCS09GRl9TTE9UX0NGRywg
cmVnKTsNCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkp
IHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4ocnQyeDAw
ZGV2KTsNCj4NCj4gQ2FsbGluZyBhIHJ0MjgwMHBjaSBmdW5jdGlvbiBmcm9tIHdpdGhpbiBydDI4
MDBsaWIgZG9lc24ndCBsb29rDQo+IGNvcnJlY3QuIE1heWJlIHVzZSBhIG5ldyBjYWxsYmFjayBm
dW5jdGlvbiBmb3IgdGhhdD8NCj4NCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWQocnQyeDAwZGV2LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAg
ICAgICAgICAgIGlmIChydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBXTEFOX0VOKSA9PSAxKSB7DQo+
ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIFBDSUVf
QVBQMF9DTEtfUkVRLA0KPiA+ICsgMSk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQy
ODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwNCj4gPiArIFdMQU5fRlVOX0NUUkwsIHJlZyk7
DQo+ID4gKyAgICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIHJ0Mjgw
MF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgQ01CX0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAg
ICAgICAgICBpZiAoIShydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBMRE8wX0VOKSA9PSAxKSkgew0K
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmcmVnLCBMRE8w
X0VOLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIo
JnJlZywgTERPX0JHU0VMLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBf
cmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBDTUJfQ1RSTCwNCj4gPiArIHJlZyk7DQo+ID4gKyAg
ICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rl
cl9yZWFkKHJ0MngwMGRldiwgT1NDX0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBy
dDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywgT1NDX1JPU0NfRU4sIDEpOw0KPiA+ICsgICAgICAgICAg
ICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBPU0NfQ1RSTCwgcmVnKTsNCj4g
PiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9TQ19ST1NDX0VOLCAx
KTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9TQ19DQUxf
UkVRLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9T
Q19SRUZfQ1lDTEUsIDB4MjcpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJf
d3JpdGUocnQyeDAwZGV2LCBPU0NfQ1RSTCwgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAgcnQy
ODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBDT0VYX0NGRzAsICZyZWcpOw0KPiA+ICsgICAg
ICAgICAgICAgICByZWcgJj0gfigweEZGMDAwMDAwKTsNCj4gPiArICAgICAgICAgICAgICAgcmVn
IHw9IDB4NUUwMDAwMDA7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0
ZShydDJ4MDBkZXYsIENPRVhfQ0ZHMCwgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAw
X3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwgQ09FWF9DRkcyLA0KPiA+ICsgMHgwMDE3OTM3Rik7
DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgUExM
X0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJnJl
ZywgUExMX0NPTlRST0wsIDEpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJf
d3JpdGUocnQyeDAwZGV2LCBQTExfQ1RSTCwgcmVnKTsNCj4gPiArICAgICAgIH0NCj4gPiArDQo+
ID4gICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMwNzEpIHx8DQo+ID4gICAgICAg
ICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMwOTApIHx8DQo+ID4gLSAgICAgICAgICAgcnQy
eDAwX3J0KHJ0MngwMGRldiwgUlQzMzkwKSkgew0KPiA+ICsgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUMzM5MCkgfHwNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0Mngw
MGRldiwgUlQzMjkwKSkgew0KPg0KPiBJbmRlbnRpb24gbG9va3Mgc3RyYW5nZSBoZXJlLg0KPg0K
PiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5
MCkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0
MngwMGRldiwgVFhfU1dfQ0ZHMCwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IDB4MDAwMDA0MDQpOw0KPiA+ICsgICAgICAgICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAg
ICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwgVFhfU1dfQ0ZHMCwNCj4gPiAweDAw
MDAwNDAwKTsNCj4NCj4gSW5kZW50aW9uIGFnYWluLg0KPg0KPiA+ICAgICAgICAgICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4MDBkZXYsIFRYX1NXX0NGRzEsDQo+ID4gMHgwMDAwMDAw
MCk7DQo+ID4gICAgICAgICAgICAgICAgaWYgKHJ0MngwMF9ydF9yZXZfbHQocnQyeDAwZGV2LCBS
VDMwNzEsIFJFVl9SVDMwNzFFKQ0KPiA+IHx8IEBAIC0zMTg0LDcgKzMyOTgsOCBAQCBzdGF0aWMg
aW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QNCj4gPiBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+
ID4gICAgICAgICAgICAgICAgcmV0dXJuIC1FQUNDRVM7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgcnQyeDAw
X3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkgew0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQo
cnQyeDAwZGV2LCBSVDUzOTIpICAgIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3JlYWQo
cnQyeDAwZGV2LCA0LCAmdmFsdWUpOw0KPiA+ICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmll
bGQ4KCZ2YWx1ZSwgQkJQNF9NQUNfSUZfQ1RSTCwgMSk7DQo+ID4gICAgICAgICAgICAgICAgcnQy
ODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDQsIHZhbHVlKTsgQEAgLTMxOTMsMjUNCj4gPiArMzMw
OCwzMiBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2KQ0KPiA+ICAgICAgICBpZiAocnQyODAwX2lzXzMwNXhfc29jKHJ0MngwMGRldikgfHwN
Cj4gPiAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzU3MikgfHwNCj4gPiAgICAg
ICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICBy
dDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+ICsgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUNTM5MikgfHwNCj4gPiArICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2
LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCAzMSwgMHgwOCk7DQo+ID4NCj4gPiAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYs
IDY1LCAweDJjKTsNCj4gPiAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY2LCAw
eDM4KTsNCj4gPg0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8
fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAgICAgICAg
ICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY4LCAweDBiKTsNCj4gPg0KPiA+ICAg
ICAgICBpZiAocnQyeDAwX3J0X3JldihydDJ4MDBkZXYsIFJUMjg2MCwgUkVWX1JUMjg2MEMpKSB7
DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY5LCAweDE2
KTsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNzMsIDB4
MTIpOw0KPiA+ICAgICAgICB9IGVsc2UgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkg
fHwNCj4gPiAtICAgICAgICAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTIpKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRl
diwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0
MngwMGRldiwgNjksIDB4MTIpOw0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCA3MywgMHgxMyk7DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0
ZShydDJ4MDBkZXYsIDc1LCAweDQ2KTsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dy
aXRlKHJ0MngwMGRldiwgNzYsIDB4MjgpOw0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYg
KHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDc3LCAweDU4KTsNCj4gPiArICAgICAgICAg
ICAgICAgZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCA3NywgMHg1OSk7DQo+DQo+IEluZGVudGlvbi4NCj4NCj4gPiAgICAgICAgfSBlbHNlIHsNCj4g
PiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNjksIDB4MTIpOyBA
QCAtMzIzNyw5DQo+ID4gKzMzNTksMTcgQEAgc3RhdGljIGludCBydDI4MDBfaW5pdF9iYnAoc3Ry
dWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJw
X3dyaXRlKHJ0MngwMGRldiwgODEsIDB4MzcpOw0KPiA+ICAgICAgICB9DQo+ID4NCj4gPiArICAg
ICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA3NCwgMHgwYik7DQo+ID4gKyAgICAgICAg
ICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA3OSwgMHgxOCk7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4MCwgMHgwOSk7DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4MSwgMHgzMyk7DQo+ID4g
KyAgICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwg
ODIsIDB4NjIpOw0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8
fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAgICAgICAg
ICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDgzLCAweDdhKTsNCj4gPiAgICAgICAg
ZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4Mywg
MHg2YSk7IEBAIC0zMjQ3LDEzDQo+ID4gKzMzNzcsMTUgQEAgc3RhdGljIGludCBydDI4MDBfaW5p
dF9iYnAoc3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgaWYgKHJ0Mngw
MF9ydF9yZXYocnQyeDAwZGV2LCBSVDI4NjAsIFJFVl9SVDI4NjBEKSkNCj4gPiAgICAgICAgICAg
ICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgODQsIDB4MTkpOw0KPiA+ICAgICAgICBl
bHNlIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAgICAgICAgICAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAg
ICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAg
ICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDg0LCAweDlhKTsNCj4gPiAg
ICAgICAgZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCA4NCwgMHg5OSk7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJU
NTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1Mzky
KSkNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0K
PiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKQ0KPiA+ICAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4NiwgMHgzOCk7DQo+ID4g
ICAgICAgIGVsc2UNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRl
diwgODYsIDB4MDApOyBAQCAtMzI2NCw3DQo+ID4gKzMzOTYsOCBAQCBzdGF0aWMgaW50IHJ0Mjgw
MF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICBydDI4
MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgOTEsIDB4MDQpOw0KPiA+DQo+ID4gICAgICAgIGlmIChy
dDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAgICAgICAgICAgICAgIHJ0Mngw
MF9ydChydDJ4MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUNTM5MikgfHwNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0Mngw
MGRldiwgUlQzMjkwKSkNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0Mngw
MGRldiwgOTIsIDB4MDIpOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgcnQy
ODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDkyLCAweDAwKTsgQEAgLTMyODEsMTMNCj4gPiArMzQx
NCwxNSBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2KQ0KPiA+ICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSB8fA0K
PiA+ICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+ICAgICAg
ICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgIHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkgfHwNCj4gPiAgICAgICAgICAgIHJ0MjgwMF9pc18z
MDV4X3NvYyhydDJ4MDBkZXYpKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCAxMDMsIDB4YzApOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAg
ICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDEwMywgMHgwMCk7DQo+ID4NCj4gPiAgICAg
ICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAg
ICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiArICAgICAgICAgICAgICAgcnQy
eDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBf
cnQocnQyeDAwZGV2LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3Jp
dGUocnQyeDAwZGV2LCAxMDQsIDB4OTIpOw0KPiA+DQo+ID4gICAgICAgIGlmIChydDI4MDBfaXNf
MzA1eF9zb2MocnQyeDAwZGV2KSkgQEAgLTMyOTUsMTAgKzM0MzAsMTMgQEANCj4gPiBzdGF0aWMg
aW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAg
ICAgICBlbHNlIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gICAgICAg
ICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiAgICAg
ICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA1LCAweDNjKTsNCj4gPiAr
ICAgICAgIGVsc2UgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxMDUsIDB4MWMpOw0KPiA+ICAg
ICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYs
IDEwNSwgMHgwNSk7DQo+ID4NCj4gPiAtICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTApKQ0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwN
Cj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzMjkwKSkNCj4gPiAg
ICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA2LCAweDAzKTsNCj4g
PiAgICAgICAgZWxzZSBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiAgICAg
ICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA2LCAweDEyKTsgQEAgLTMz
MDYsNw0KPiA+ICszNDQ0LDggQEAgc3RhdGljIGludCBydDI4MDBfaW5pdF9iYnAoc3RydWN0IHJ0
MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRl
KHJ0MngwMGRldiwgMTA2LCAweDM1KTsNCj4gPg0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0
MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDUzOTIpKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTIpIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5
MCkpDQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDEyOCwg
MHgxMik7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5Mikp
IHsgQEAgLTMzMzEsNiArMzQ3MCwyNyBAQA0KPiA+IHN0YXRpYyBpbnQgcnQyODAwX2luaXRfYmJw
KHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgICAgICAgICAgcnQyODAw
X2JicF93cml0ZShydDJ4MDBkZXYsIDEzOCwgdmFsdWUpOw0KPiA+ICAgICAgICB9DQo+ID4NCj4g
PiArICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA2NywgMHgyNCk7DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxNDMsIDB4MDQpOw0KPiA+
ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTQyLCAweDk5KTsN
Cj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDE1MCwgMHgz
MCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxNTEs
IDB4MmUpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwg
MTUyLCAweDIwKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBk
ZXYsIDE1MywgMHgzNCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQy
eDAwZGV2LCAxNTQsIDB4NDApOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRl
KHJ0MngwMGRldiwgMTU1LCAweDNiKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93
cml0ZShydDJ4MDBkZXYsIDI1MywgMHgwNCk7DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBy
dDI4MDBfYmJwX3JlYWQocnQyeDAwZGV2LCA0NywgJnZhbHVlKTsNCj4gPiArICAgICAgICAgICAg
ICAgcnQyeDAwX3NldF9maWVsZDgoJnZhbHVlLCBSRkNTUjJfUkVTQ0FMX0VOLCAxKTsNCj4gPiAr
ICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDQ3LCB2YWx1ZSk7DQo+
ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3JlYWQocnQyeDAwZGV2LCAzLCAm
dmFsdWUpOw0KPiA+ICsgICAgICAgICAgICAgICB2YWx1ZSAmPSAofjB4YzApOw0KPiA+ICsgICAg
ICAgICAgICAgICB2YWx1ZSB8PSAweGMwOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJw
X3dyaXRlKHJ0MngwMGRldiwgMywgdmFsdWUpOw0KPiA+ICsgICAgICAgfQ0KPiA+ICAgICAgICBp
ZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+ICAgICAgICAgICAgICAgIHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpIHsNCj4gPiAgICAgICAgICAgICAgICBpbnQgYW50
LCBkaXZfbW9kZTsNCj4gPiBAQCAtMzQ2Nyw2ICszNjI3LDcgQEAgc3RhdGljIGludCBydDI4MDBf
aW5pdF9yZmNzcihzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAg
ICAgICAhcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSAmJg0KPiA+ICAgICAgICAgICAgIXJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgJiYNCj4gPiAgICAgICAgICAgICFydDJ4MDBfcnQo
cnQyeDAwZGV2LCBSVDUzOTIpICYmDQo+ID4gKyAgICAgICAgICAgIXJ0MngwMF9ydChydDJ4MDBk
ZXYsIFJUMzI5MCkgJiYNCj4gPiAgICAgICAgICAgICFydDI4MDBfaXNfMzA1eF9zb2MocnQyeDAw
ZGV2KSkNCj4gPiAgICAgICAgICAgICAgICByZXR1cm4gMDsNCj4gPg0KPiA+IEBAIC0zNDc0LDcg
KzM2MzUsOCBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X3JmY3NyKHN0cnVjdCBydDJ4MDBfZGV2
DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgICogSW5pdCBSRiBjYWxpYnJhdGlvbi4NCj4g
PiAgICAgICAgICovDQo+ID4gICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTAp
IHx8DQo+ID4gLSAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpIHsN
Cj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gICAg
ICAgICAgICAgICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAwZGV2LCAyLCAmcmZjc3IpOw0KPiA+
ICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IyX1JFU0NBTF9F
TiwgMSk7DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwg
MiwgcmZjc3IpOyBAQCAtMzc1Miw2DQo+ID4gKzM5MTQsNTMgQEAgc3RhdGljIGludCBydDI4MDBf
aW5pdF9yZmNzcihzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAg
ICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA2MSwgMHg5MSk7
DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2
LCA2MiwgMHgzOSk7DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3Jp
dGUocnQyeDAwZGV2LCA2MywgMHgwNyk7DQo+ID4gKyAgICAgICB9IGVsc2UgaWYgKHJ0MngwMF9y
dChydDJ4MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4
MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxLCAweDBmKTsNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAyLCAweDgwKTsNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzLCAweDA4
KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCA0LCAweDAwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jf
d3JpdGUocnQyeDAwZGV2LCA2LCAweGEwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBy
dDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA4LCAweGYzKTsNCj4gPiArICAgICAgICAgICAg
ICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA5LCAweDAyKTsNCj4gPiAr
ICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxMCwg
MHg1Myk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgMTEsIDB4NGEpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9y
ZmNzcl93cml0ZShydDJ4MDBkZXYsIDEyLCAweDQ2KTsNCj4gPiArICAgICAgICAgICAgICAgICAg
ICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxMywgMHg5Zik7DQo+ID4gKyAgICAg
ICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMTgsIDB4MDIp
Ow0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBk
ZXYsIDIyLCAweDIwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jf
d3JpdGUocnQyeDAwZGV2LCAyNSwgMHg4Myk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg
cnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMjYsIDB4ODIpOw0KPiA+ICsgICAgICAgICAg
ICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDI3LCAweDA5KTsNCj4g
PiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAy
OSwgMHgxMCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRl
KHJ0MngwMGRldiwgMzAsIDB4MTApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0Mjgw
MF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMxLCAweDgwKTsNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzMiwgMHg4MCk7DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMzMsIDB4
MDApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4
MDBkZXYsIDM0LCAweDA1KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZj
c3Jfd3JpdGUocnQyeDAwZGV2LCAzNSwgMHgxMik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMzYsIDB4MDApOw0KPiA+ICsgICAgICAg
ICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDM4LCAweDg1KTsN
Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2
LCAzOSwgMHgxYik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dy
aXRlKHJ0MngwMGRldiwgNDAsIDB4MGIpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDQxLCAweGJiKTsNCj4gPiArICAgICAgICAgICAg
ICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0MiwgMHhkNSk7DQo+ID4g
KyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNDMs
IDB4N2IpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDQ0LCAweDBlKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBf
cmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0NSwgMHhhMik7DQo+ID4gKyAgICAgICAgICAgICAgICAg
ICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNDYsIDB4NzMpOw0KPiA+ICsgICAg
ICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDQ3LCAweDAw
KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCA0OCwgMHgxMCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3Ny
X3dyaXRlKHJ0MngwMGRldiwgNDksIDB4OTgpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAg
IHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDUyLCAweDM4KTsNCj4gPiArICAgICAgICAg
ICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA1MywgMHgwMCk7DQo+
ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwg
NTQsIDB4NzgpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0
ZShydDJ4MDBkZXYsIDU1LCAweDQzKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4
MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA1NiwgMHgwMik7DQo+ID4gKyAgICAgICAgICAgICAg
ICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNTcsIDB4ODApOw0KPiA+ICsg
ICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDU4LCAw
eDdmKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQy
eDAwZGV2LCA1OSwgMHgwOSk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3Jm
Y3NyX3dyaXRlKHJ0MngwMGRldiwgNjAsIDB4NDUpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAg
ICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDYxLCAweGMxKTsNCj4gPiAgICAgICAg
fQ0KPiA+DQo+ID4gICAgICAgIGlmIChydDJ4MDBfcnRfcmV2X2x0KHJ0MngwMGRldiwgUlQzMDcw
LCBSRVZfUlQzMDcwRikpIHsgQEANCj4gPiAtMzkzNSw2ICs0MTQ0LDEyIEBAIHN0YXRpYyBpbnQg
cnQyODAwX2luaXRfcmZjc3Ioc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+
ICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMwLCByZmNzcik7
DQo+ID4gICAgICAgIH0NCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYs
IFJUMzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAw
ZGV2LCAyOSwgJnJmY3NyKTsNCj4gPiArICAgICAgICAgICAgICAgcmZjc3IgPSAoKHJmY3NyICYg
fjB4YzApIHwgMHhjMCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDI5LCByZmNzcik7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICBy
ZXR1cm4gMDsNCj4gPiAgfQ0KPiA+DQo+ID4gQEAgLTQwMjYsOSArNDI0MSwxMyBAQCBFWFBPUlRf
U1lNQk9MX0dQTChydDI4MDBfZGlzYWJsZV9yYWRpbyk7DQo+ID4gIGludCBydDI4MDBfZWZ1c2Vf
ZGV0ZWN0KHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gIHsNCj4gPiAgICAgICAg
dTMyIHJlZzsNCj4gPiArICAgICAgIHUxNiBlZnVzZV9jdHJsX3JlZzsNCj4gPiArICAgICAgIGVm
dXNlX2N0cmxfcmVnID0gRUZVU0VfQ1RSTDsNCj4gPg0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lz
dGVyX3JlYWQocnQyeDAwZGV2LCBFRlVTRV9DVFJMLCAmcmVnKTsNCj4gPiArICAgICAgIGlmIChy
dDJ4MDBkZXYtPmNoaXAubWFjX3ZlcnNpb24gPT0gMHgzMjkwKQ0KPiA+ICsgICAgICAgICAgICAg
ICBlZnVzZV9jdHJsX3JlZyA9IDB4MjQ7DQo+DQo+IFRoaXMgc2hvdWxkbid0IGJlIGhhcmRjb2Rl
ZC4gUGxlYXNlIGFkZCBhIGRlZmluZSB0byBydDI4MDAuaC4NCj4NCj4gPg0KPiA+ICsgICAgICAg
cnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBlZnVzZV9jdHJsX3JlZywgJnJlZyk7DQo+
ID4gICAgICAgIHJldHVybiBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBFRlVTRV9DVFJMX1BSRVNF
TlQpOw0KPiA+ICB9DQo+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMF9lZnVzZV9kZXRlY3Qp
Ow0KPiA+IEBAIC00MDM3LDI2ICs0MjU2LDQ0IEBAIHN0YXRpYyB2b2lkIHJ0MjgwMF9lZnVzZV9y
ZWFkKHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0MngwMGRldiwgdW5zaWduZWQgaW50IGkpDQo+
ID4gIHsNCj4gPiAgICAgICAgdTMyIHJlZzsNCj4gPg0KPiA+ICsgICAgICAgdTE2IGVmdXNlX2N0
cmxfcmVnOw0KPiA+ICsgICAgICAgdTE2IGVmdXNlX2RhdGEwX3JlZzsNCj4gPiArICAgICAgIHUx
NiBlZnVzZV9kYXRhMV9yZWc7DQo+ID4gKyAgICAgICB1MTYgZWZ1c2VfZGF0YTJfcmVnOw0KPiA+
ICsgICAgICAgdTE2IGVmdXNlX2RhdGEzX3JlZzsNCj4gPiArDQo+ID4gKyAgICAgICBlZnVzZV9j
dHJsX3JlZyA9IEVGVVNFX0NUUkw7DQo+ID4gKyAgICAgICBlZnVzZV9kYXRhMF9yZWcgPSBFRlVT
RV9EQVRBMDsNCj4gPiArICAgICAgIGVmdXNlX2RhdGExX3JlZyA9IEVGVVNFX0RBVEExOw0KPiA+
ICsgICAgICAgZWZ1c2VfZGF0YTJfcmVnID0gRUZVU0VfREFUQTI7DQo+ID4gKyAgICAgICBlZnVz
ZV9kYXRhM19yZWcgPSBFRlVTRV9EQVRBMzsNCj4gPiArDQo+ID4gKyAgICAgICBpZiAocnQyeDAw
ZGV2LT5jaGlwLm1hY192ZXJzaW9uID09IDB4MzI5MCkgew0KPiA+ICsgICAgICAgICAgICAgICBl
ZnVzZV9jdHJsX3JlZyA9IDB4MjQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEzX3Jl
ZyA9IDB4Mjg7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEyX3JlZyA9IGVmdXNlX2Rh
dGEzX3JlZyArIDQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGExX3JlZyA9IGVmdXNl
X2RhdGEyX3JlZyArIDQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEwX3JlZyA9IGVm
dXNlX2RhdGExX3JlZyArIDQ7DQo+ID4gKyAgICAgICB9DQo+DQo+IFNhbWUgaGVyZSwgdGhlIHJl
Z2lzdGVyIG9mZnNldHMgd291bGQgbWFrZSBzZW5zZSBhcyBkZWZpbmVzLg0KPg0KPiA+ICAgICAg
ICBtdXRleF9sb2NrKCZydDJ4MDBkZXYtPmNzcl9tdXRleCk7DQo+ID4NCj4gPiAtICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBFRlVTRV9DVFJMLCAmcmVnKTsNCj4g
PiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVzZV9jdHJs
X3JlZywgJnJlZyk7DQo+ID4gICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmcmVnLCBFRlVTRV9D
VFJMX0FERFJFU1NfSU4sIGkpOw0KPiA+ICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywg
RUZVU0VfQ1RSTF9NT0RFLCAwKTsNCj4gPiAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcs
IEVGVVNFX0NUUkxfS0lDSywgMSk7DQo+ID4gLSAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGVf
bG9jayhydDJ4MDBkZXYsIEVGVVNFX0NUUkwsIHJlZyk7DQo+ID4gKyAgICAgICBydDI4MDBfcmVn
aXN0ZXJfd3JpdGVfbG9jayhydDJ4MDBkZXYsIGVmdXNlX2N0cmxfcmVnLCByZWcpOw0KPiA+DQo+
ID4gICAgICAgIC8qIFdhaXQgdW50aWwgdGhlIEVFUFJPTSBoYXMgYmVlbiBsb2FkZWQgKi8NCj4g
PiAtICAgICAgIHJ0MjgwMF9yZWdidXN5X3JlYWQocnQyeDAwZGV2LCBFRlVTRV9DVFJMLCBFRlVT
RV9DVFJMX0tJQ0ssDQo+ID4gJnJlZyk7DQo+ID4gLQ0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2J1
c3lfcmVhZChydDJ4MDBkZXYsIGVmdXNlX2N0cmxfcmVnLA0KPiA+ICsgRUZVU0VfQ1RSTF9LSUNL
LCAmcmVnKTsNCj4gPiAgICAgICAgLyogQXBwYXJlbnRseSB0aGUgZGF0YSBpcyByZWFkIGZyb20g
ZW5kIHRvIHN0YXJ0ICovDQo+ID4gLSAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZF9sb2NrKHJ0
MngwMGRldiwgRUZVU0VfREFUQTMsICZyZWcpOw0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWRfbG9jayhydDJ4MDBkZXYsIGVmdXNlX2RhdGEzX3JlZywgJnJlZyk7DQo+ID4gICAgICAg
IC8qIFRoZSByZXR1cm5lZCB2YWx1ZSBpcyBpbiBDUFUgb3JkZXIsIGJ1dCBlZXByb20gaXMgbGUg
Ki8NCj4gPiAgICAgICAgKih1MzIgKikmcnQyeDAwZGV2LT5lZXByb21baV0gPSBjcHVfdG9fbGUz
MihyZWcpOw0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWRfbG9jayhydDJ4MDBkZXYs
IEVGVVNFX0RBVEEyLCAmcmVnKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xv
Y2socnQyeDAwZGV2LCBlZnVzZV9kYXRhMl9yZWcsICZyZWcpOw0KPiA+ICAgICAgICAqKHUzMiAq
KSZydDJ4MDBkZXYtPmVlcHJvbVtpICsgMl0gPSBjcHVfdG9fbGUzMihyZWcpOw0KPiA+IC0gICAg
ICAgcnQyODAwX3JlZ2lzdGVyX3JlYWRfbG9jayhydDJ4MDBkZXYsIEVGVVNFX0RBVEExLCAmcmVn
KTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVz
ZV9kYXRhMV9yZWcsICZyZWcpOw0KPiA+ICAgICAgICAqKHUzMiAqKSZydDJ4MDBkZXYtPmVlcHJv
bVtpICsgNF0gPSBjcHVfdG9fbGUzMihyZWcpOw0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWRfbG9jayhydDJ4MDBkZXYsIEVGVVNFX0RBVEEwLCAmcmVnKTsNCj4gPiArICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVzZV9kYXRhMF9yZWcsICZyZWcp
Ow0KPiA+ICAgICAgICAqKHUzMiAqKSZydDJ4MDBkZXYtPmVlcHJvbVtpICsgNl0gPSBjcHVfdG9f
bGUzMihyZWcpOw0KPiA+DQo+ID4gICAgICAgIG11dGV4X3VubG9jaygmcnQyeDAwZGV2LT5jc3Jf
bXV0ZXgpOw0KPiA+IEBAIC00MjE4LDkgKzQ0NTUsMTMgQEAgaW50IHJ0MjgwMF9pbml0X2VlcHJv
bShzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgICAqIFJUMjh4
eC9SVDMweHg6IGRlZmluZWQgaW4gIkVFUFJPTV9OSUNfQ09ORjBfUkZfVFlQRSIgZmllbGQNCj4g
PiAgICAgICAgICogUlQ1M3h4OiBkZWZpbmVkIGluICJFRVBST01fQ0hJUF9JRCIgZmllbGQNCj4g
PiAgICAgICAgICovDQo+ID4gKyAgICAgICBpZiAocnQyeDAwZGV2LT5jaGlwLm1hY192ZXJzaW9u
ID09IDB4MzI5MCkNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQy
eDAwZGV2LCBNQUNfQ1NSMF8zMjkwLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAgICBlbHNlDQo+
ID4gICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgTUFDX0NTUjAsICZyZWcp
Ow0KPg0KPiBJbmRlbnRpb24uDQo+DQo+ID4gICAgICAgIGlmIChydDJ4MDBfZ2V0X2ZpZWxkMzIo
cmVnLCBNQUNfQ1NSMF9DSElQU0VUKSA9PSBSVDUzOTAgfHwNCj4gPiAtICAgICAgICAgICAgICAg
cnQyeDAwX2dldF9maWVsZDMyKHJlZywgTUFDX0NTUjBfQ0hJUFNFVCkgPT0gUlQ1MzkyKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBNQUNfQ1NSMF9DSElQU0VU
KSA9PSBSVDUzOTINCj4gPiArIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9nZXRfZmll
bGQzMihyZWcsIE1BQ19DU1IwX0NISVBTRVQpID09IFJUMzI5MCkNCj4gPiAgICAgICAgICAgICAg
ICBydDJ4MDBfZWVwcm9tX3JlYWQocnQyeDAwZGV2LCBFRVBST01fQ0hJUF9JRCwNCj4gPiAmdmFs
dWUpOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgdmFsdWUgPSBydDJ4MDBf
Z2V0X2ZpZWxkMTYoZWVwcm9tLA0KPiA+IEVFUFJPTV9OSUNfQ09ORjBfUkZfVFlQRSk7IEBAIC00
MjM5LDYgKzQ0ODAsNyBAQCBpbnQNCj4gPiBydDI4MDBfaW5pdF9lZXByb20oc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgY2FzZSBSVDM1NzI6DQo+ID4gICAgICAgIGNh
c2UgUlQ1MzkwOg0KPiA+ICAgICAgICBjYXNlIFJUNTM5MjoNCj4gPiArICAgICAgIGNhc2UgUlQz
MjkwOg0KPiA+ICAgICAgICAgICAgICAgIGJyZWFrOw0KPiA+ICAgICAgICBkZWZhdWx0Og0KPiA+
ICAgICAgICAgICAgICAgIEVSUk9SKHJ0MngwMGRldiwgIkludmFsaWQgUlQgY2hpcHNldCAweCUw
NHgNCj4gPiBkZXRlY3RlZC5cbiIsIHJ0MngwMGRldi0+Y2hpcC5ydCk7IEBAIC00MjU5LDYgKzQ1
MDEsNyBAQCBpbnQNCj4gPiBydDI4MDBfaW5pdF9lZXByb20oc3RydWN0IHJ0MngwMF9kZXYgKnJ0
MngwMGRldikNCj4gPiAgICAgICAgY2FzZSBSRjUzNzA6DQo+ID4gICAgICAgIGNhc2UgUkY1Mzcy
Og0KPiA+ICAgICAgICBjYXNlIFJGNTM5MDoNCj4gPiArICAgICAgIGNhc2UgUkYzMjkwOg0KPiA+
ICAgICAgICAgICAgICAgIGJyZWFrOw0KPiA+ICAgICAgICBkZWZhdWx0Og0KPiA+ICAgICAgICAg
ICAgICAgIEVSUk9SKHJ0MngwMGRldiwgIkludmFsaWQgUkYgY2hpcHNldCAweCUwNHgNCj4gPiBk
ZXRlY3RlZC5cbiIsIEBAIC00NTcyLDcgKzQ4MTUsOCBAQCBpbnQgcnQyODAwX3Byb2JlX2h3X21v
ZGUoc3RydWN0DQo+ID4gcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICAgICAgICAg
ICAgIHJ0MngwMF9yZihydDJ4MDBkZXYsIFJGMzMyMCkgfHwNCj4gPiAgICAgICAgICAgICAgICAg
ICBydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjUzNzApIHx8DQo+ID4gICAgICAgICAgICAgICAgICAg
cnQyeDAwX3JmKHJ0MngwMGRldiwgUkY1MzcyKSB8fA0KPiA+IC0gICAgICAgICAgICAgICAgICBy
dDJ4MDBfcmYocnQyeDAwZGV2LCBSRjUzOTApKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgIHJ0
MngwMF9yZihydDJ4MDBkZXYsIFJGNTM5MCkgfHwNCj4gPiArICAgICAgICAgICAgICAgICAgcnQy
eDAwX3JmKHJ0MngwMGRldiwgUkYzMjkwKSkgew0KPiA+ICAgICAgICAgICAgICAgIHNwZWMtPm51
bV9jaGFubmVscyA9IDE0Ow0KPiA+ICAgICAgICAgICAgICAgIHNwZWMtPmNoYW5uZWxzID0gcmZf
dmFsc18zeDsNCj4gPiAgICAgICAgfSBlbHNlIGlmIChydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjMw
NTIpKSB7IEBAIC00NjU4LDYgKzQ5MDIsNw0KPiA+IEBAIGludCBydDI4MDBfcHJvYmVfaHdfbW9k
ZShzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICBjYXNlIFJGNTM3MDoN
Cj4gPiAgICAgICAgY2FzZSBSRjUzNzI6DQo+ID4gICAgICAgIGNhc2UgUkY1MzkwOg0KPiA+ICsg
ICAgICAgY2FzZSBSRjMyOTA6DQo+ID4gICAgICAgICAgICAgICAgX19zZXRfYml0KENBUEFCSUxJ
VFlfVkNPX1JFQ0FMSUJSQVRJT04sDQo+ID4gJnJ0MngwMGRldi0+Y2FwX2ZsYWdzKTsNCj4gPiAg
ICAgICAgICAgICAgICBicmVhazsNCj4gPiAgICAgICAgfQ0KPiA+IEBAIC00ODg1LDYgKzUxMzAs
MTAyIEBAIGludCBydDI4MDBfZ2V0X3N1cnZleShzdHJ1Y3QgaWVlZTgwMjExX2h3DQo+ID4gKmh3
LCBpbnQgaWR4LA0KPiA+ICB9DQo+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMF9nZXRfc3Vy
dmV5KTsNCj4gPg0KPiA+ICtpbnQgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4oc3RydWN0IHJ0
MngwMF9kZXYgKnJ0MngwMGRldikNCj4NCj4gcnQyODAwcGNpIGZ1bmN0aW9ucyBzaG91bGQgbGl2
ZSBpbiBydDI4MDBwY2kuYywgbm90IGluIHJ0MjgwMGxpYi5jLg0KPg0KPiA+ICt7DQo+ID4gKyAg
ICAgICB1MzIgd2xhbmZ1bmN0cmw7DQo+ID4gKyAgICAgICB1MzIgZ2xvY2ZnOw0KPiA+ICsgICAg
ICAgdTMyIGNtYmN0cmw7DQo+ID4gKyAgICAgICB1OCBpbmRleDsNCj4gPiArICAgICAgIGludCBp
Ow0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgV0xB
Tl9GVU5fQ1RSTCwNCj4gPiArICZ3bGFuZnVuY3RybCk7DQo+ID4gKyAgICAgICBydDJ4MDBfc2V0
X2ZpZWxkMzIoJndsYW5mdW5jdHJsLCBXTEFOX0dQSU9fT1VUX09FX0JJVF9BTEwsDQo+ID4gKyAw
eGZmKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0cmwsIEZSQ19X
TF9BTlRfU0VULCAxKTsNCj4gPiArICAgICAgIGlmICgocnQyeDAwX2dldF9maWVsZDMyKHdsYW5m
dW5jdHJsLCBXTEFOX0VOKSA9PSAxKSkNCj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIDA7DQo+
ID4gKw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgV0xBTl9D
TEtfRU4sIDApOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwg
V0xBTl9FTiwgMSk7DQo+ID4gKyAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2
LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgd2xhbmZ1bmN0cmwpOw0KPiA+ICsgICAgICAgdWRlbGF5
KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsNCj4gPiArICAgICAgIGluZGV4ID0gMDsNCj4g
PiArICAgICAgIGNtYmN0cmwgPSAwOw0KPiA+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IFJFR0lT
VEVSX0JVU1lfQ09VTlQ7IGkrKykgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0
ZXJfcmVhZChydDJ4MDBkZXYsIENNQl9DVFJMLCAmY21iY3RybCk7DQo+ID4gKyAgICAgICAgICAg
ICAgIGlmICgocnQyeDAwX2dldF9maWVsZDMyKGNtYmN0cmwsIFBMTF9MRCkgPT0gMSkgJiYNCj4g
PiArICAgICAgICAgICAgICAgICAgICAgICAocnQyeDAwX2dldF9maWVsZDMyKGNtYmN0cmwsIFhU
QUxfUkRZKSA9PQ0KPiA+ICsgMSkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7
DQo+ID4gKyAgICAgICAgICAgICAgIHVkZWxheShSRUdJU1RFUl9CVVNZX0RFTEFZKTsNCj4gPiAr
ICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICBpZiAoaW5kZXggPj0gUkVHSVNURVJfQlVTWV9D
T1VOVCkgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAw
ZGV2LCAweDU4LCAweDAxOCk7DQo+ID4gKyAgICAgICAgICAgICAgIHVkZWxheShSRUdJU1RFUl9C
VVNZX0RFTEFZKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0
MngwMGRldiwgMHg1OCwgMHg0MTgpOw0KPiA+ICsgICAgICAgICAgICAgICB1ZGVsYXkoUkVHSVNU
RVJfQlVTWV9ERUxBWSk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0
ZShydDJ4MDBkZXYsIDB4NTgsIDB4NjE4KTsNCj4gPiArICAgICAgICAgICAgICAgdWRlbGF5KFJF
R0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAg
ICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LA0KPiA+ICsgICAgICAgICAgICAg
ICAgICAgICAgIFdQRE1BX0dMT19DRkcsICZnbG9jZmcpOw0KPiA+ICsgICAgICAgfQ0KPiA+ICsg
ICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgUENJRV9BUFAwX0NMS19SRVEs
IDApOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgV0xBTl9D
TEtfRU4sIDEpOw0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsDQo+ID4gKyAgICAgICAgICAgICAgIFdMQU5fRlVOX0NUUkwsICh3bGFuZnVuY3RybCB8
IDB4OCkpOw0KPiA+ICsgICAgICAgdWRlbGF5KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsg
ICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwNCj4gPiArICAgICAgICAgICAg
ICAgV0xBTl9GVU5fQ1RSTCwgKHdsYW5mdW5jdHJsICY9ICh+MHg4KSkpOw0KPiA+ICsgICAgICAg
dWRlbGF5KDIpOw0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwN
Cj4gPiArICAgICAgICAgICAgICAgSU5UX1NPVVJDRV9DU1IsIDB4N2ZmZmZmZmYpOw0KPiA+ICsg
ICAgICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJPTF9HUEwocnQyODAwcGNp
XzMyOTBfZW5hYmxlX3dsYW4pOw0KPiA+ICsNCj4gPiAraW50IHJ0MjgwMHBjaV8zMjkwX2Rpc2Fi
bGVfd2xhbihzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KSB7DQo+ID4gKyAgICAgICB1MzIg
d2xhbmZ1bmN0cmw7DQo+ID4gKyAgICAgICB1MzIgZ2xvY2ZnOw0KPiA+ICsgICAgICAgdTMyIHJl
ZzsNCj4gPiArICAgICAgIGludCBpOw0KPiA+ICsNCj4gPiArICAgICAgIC8qIENoYW5nZSBJbnRl
cnJ1cHQgYml0bWFzay4gKi8NCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsIElOVF9NQVNLX0NTUiwgMHgwKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9y
ZWFkKHJ0MngwMGRldiwgV1BETUFfR0xPX0NGRywgJmdsb2NmZyk7DQo+ID4gKyAgICAgICBydDJ4
MDBfc2V0X2ZpZWxkMzIoJmdsb2NmZywgV1BETUFfR0xPX0NGR19FTkFCTEVfUlhfRE1BLCAwKTsN
Cj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4MDBkZXYsIFdQRE1BX0dMT19D
RkcsIGdsb2NmZyk7DQo+ID4gKw0KPiA+ICsgICAgICAgLyogd2FpdCBSWCBETUEgaWRsZSAqLw0K
PiA+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IFJFR0lTVEVSX0JVU1lfQ09VTlQ7IGkrKykgew0K
PiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIFdQRE1B
X0dMT19DRkcsDQo+ID4gKyAmZ2xvY2ZnKTsNCj4gPiArICAgICAgICAgICAgICAgaWYgKChydDJ4
MDBfZ2V0X2ZpZWxkMzIoZ2xvY2ZnLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIFdQRE1B
X0dMT19DRkdfUlhfRE1BX0JVU1kpID09IDApIHx8DQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgKGdsb2NmZyA9PSAweEZGRkZGRkZGKSkNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBi
cmVhazsNCj4gPiArICAgICAgICAgICAgICAgdWRlbGF5KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0K
PiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIGlmIChpID49IFJFR0lTVEVSX0JVU1lf
Q09VTlQpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAw
ZGV2LCBBVVRPV0FLRVVQX0NGRywNCj4gPiArICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBy
dDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywNCj4gPiArIEFVVE9XQUtFVVBfQ0ZHX0FVVE9fTEVBRF9U
SU1FLCAwKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsDQo+
ID4gKyBBVVRPV0FLRVVQX0NGR19UQkNOX0JFRk9SRV9XQUtFLCAwKTsNCj4gPiArICAgICAgICAg
ICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIEFVVE9XQUtFVVBfQ0ZHX0FVVE9XQUtFLA0K
PiA+ICsgMCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsIEFVVE9XQUtFVVBfQ0ZHLA0KPiA+ICsgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAg
cmV0dXJuIDA7DQo+ID4gKyAgICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICBydDI4
MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIFdMQU5fRlVOX0NUUkwsDQo+ID4gKyZ3bGFuZnVu
Y3RybCk7DQo+ID4gKyAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJndsYW5mdW5jdHJsLCBXTEFO
X0VOLCAwKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0cmwsIFdM
QU5fQ0xLX0VOLCAwKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0
cmwsIFBDSUVfQVBQMF9DTEtfUkVRLCAwKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93
cml0ZShydDJ4MDBkZXYsIFdMQU5fRlVOX0NUUkwsDQo+ID4gK3dsYW5mdW5jdHJsKTsNCj4gPiAr
ICAgICAgIHVkZWxheShSRUdJU1RFUl9CVVNZX0RFTEFZKTsNCj4gPiArICAgICAgIHJldHVybiAw
Ow0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMHBjaV8zMjkwX2Rpc2FibGVf
d2xhbik7DQo+ID4gIE1PRFVMRV9BVVRIT1IoRFJWX1BST0pFQ1QgIiwgQmFydGxvbWllaiBab2xu
aWVya2lld2ljeiIpOw0KPiA+ICBNT0RVTEVfVkVSU0lPTihEUlZfVkVSU0lPTik7DQo+ID4gIE1P
RFVMRV9ERVNDUklQVElPTigiUmFsaW5rIFJUMjgwMCBsaWJyYXJ5Iik7IGRpZmYgLS1naXQNCj4g
PiBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuaA0KPiA+IGIvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMGxpYi5oDQo+ID4gaW5kZXggMThhMGI2Ny4uMjJk
N2NiYiAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
bGliLmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwbGliLmgN
Cj4gPiBAQCAtMjA5LDUgKzIwOSw2IEBAIGludCBydDI4MDBfYW1wZHVfYWN0aW9uKHN0cnVjdCBp
ZWVlODAyMTFfaHcgKmh3LA0KPiA+IHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQo+ID4gIGlu
dCBydDI4MDBfZ2V0X3N1cnZleShzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywgaW50IGlkeCwNCj4g
PiAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgc3VydmV5X2luZm8gKnN1cnZleSk7DQo+ID4g
IHZvaWQgcnQyODAwX2Rpc2FibGVfd3BkbWEoc3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldik7
DQo+ID4gLQ0KPiA+ICtpbnQgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4oc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldik7IGludA0KPiA+ICtydDI4MDBwY2lfMzI5MF9kaXNhYmxlX3dsYW4o
c3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldik7DQo+ID4gICNlbmRpZiAvKiBSVDI4MDBMSUJf
SCAqLw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
cGNpLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuYw0KPiA+
IGluZGV4IDkzMTMzMWQuLjkyNTFmMmQgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2ly
ZWxlc3MvcnQyeDAwL3J0MjgwMHBjaS5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
cnQyeDAwL3J0MjgwMHBjaS5jDQo+ID4gQEAgLTI4MCw2ICsyODAsMTAgQEAgc3RhdGljIHZvaWQg
cnQyODAwcGNpX3N0b3BfcXVldWUoc3RydWN0DQo+ID4gZGF0YV9xdWV1ZSAqcXVldWUpDQo+ID4g
ICovDQo+ID4gIHN0YXRpYyBjaGFyICpydDI4MDBwY2lfZ2V0X2Zpcm13YXJlX25hbWUoc3RydWN0
IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+ICB7DQo+ID4gKw0KPiA+ICsgICAgICAg
aWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAgICAgICAgIHJl
dHVybiBGSVJNV0FSRV9SVDMyOTA7DQo+ID4gKw0KPiA+ICAgICAgICByZXR1cm4gRklSTVdBUkVf
UlQyODYwOw0KPiA+ICB9DQo+ID4NCj4gPiBAQCAtNTM2LDYgKzU0MCw5IEBAIHN0YXRpYyB2b2lk
IHJ0MjgwMHBjaV9kaXNhYmxlX3JhZGlvKHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0MngwMGRl
dikNCj4gPiAgICAgICAgICAgICAgICBydDJ4MDBwY2lfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2
LCBQV1JfUElOX0NGRywgMCk7DQo+ID4gICAgICAgICAgICAgICAgcnQyeDAwcGNpX3JlZ2lzdGVy
X3dyaXRlKHJ0MngwMGRldiwgVFhfUElOX0NGRywgMCk7DQo+ID4gICAgICAgIH0NCj4gPiArDQo+
ID4gKyAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzMjkwKSkNCj4gPiArICAgICAg
ICAgICAgICAgcnQyODAwcGNpXzMyOTBfZGlzYWJsZV93bGFuKHJ0MngwMGRldik7DQo+ID4gIH0N
Cj4gPg0KPiA+ICBzdGF0aWMgaW50IHJ0MjgwMHBjaV9zZXRfc3RhdGUoc3RydWN0IHJ0MngwMF9k
ZXYgKnJ0MngwMGRldiwgQEANCj4gPiAtMTAyOCw2ICsxMDM1LDggQEAgc3RhdGljIGludCBydDI4
MDBwY2lfcHJvYmVfaHcoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+ICAg
ICAgICAgKi8NCj4gPiAgICAgICAgcnQyeDAwZGV2LT5yc3NpX29mZnNldCA9IERFRkFVTFRfUlNT
SV9PRkZTRVQ7DQo+ID4NCj4gPiArICAgICAgIGlmIChydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjMy
OTApKQ0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBwY2lfMzI5MF9lbmFibGVfd2xhbihydDJ4
MDBkZXYpOw0KPiA+ICAgICAgICByZXR1cm4gMDsNCj4gPiAgfQ0KPiA+DQo+ID4gQEAgLTExOTQs
NiArMTIwMyw5IEBAIHN0YXRpYw0KPiA+IERFRklORV9QQ0lfREVWSUNFX1RBQkxFKHJ0MjgwMHBj
aV9kZXZpY2VfdGFibGUpID0gew0KPiA+ICAgICAgICB7IFBDSV9ERVZJQ0UoMHgxODE0LCAweDUz
OWEpIH0sDQo+ID4gICAgICAgIHsgUENJX0RFVklDRSgweDE4MTQsIDB4NTM5ZikgfSwNCj4gPiAg
I2VuZGlmDQo+ID4gKyNpZmRlZiBDT05GSUdfUlQyODAwUENJX1JUMzI5MA0KPiA+ICsgICAgICAg
eyBQQ0lfREVWSUNFKDB4MTgxNCwgMHgzMjkwKSB9LCAjZW5kaWYNCj4gPiAgICAgICAgeyAwLCB9
DQo+ID4gIH07DQo+ID4gICNlbmRpZiAvKiBDT05GSUdfUENJICovDQo+ID4gZGlmZiAtLWdpdCBh
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuaA0KPiA+IGIvZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMHBjaS5oDQo+ID4gaW5kZXggNzBlMDUwZC4uZGQwNDNj
NyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNp
LmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNpLmgNCj4g
PiBAQCAtNDksNiArNDksOSBAQA0KPiA+ICAjZGVmaW5lIEZJUk1XQVJFX1JUMjg2MCAgICAgICAg
ICAgICAgICAgICAgICAgICJydDI4NjAuYmluIg0KPiA+ICAjZGVmaW5lIEZJUk1XQVJFX0lNQUdF
X0JBU0UgICAgICAgICAgICAweDIwMDANCj4gPg0KPiA+ICsNCj4gPiArI2RlZmluZSBGSVJNV0FS
RV9SVDMyOTAgICAgICAgICAgICAgICAgICAgICAgICAicnQzMjkwLmJpbiINCj4gPiArDQo+ID4g
IC8qDQo+ID4gICogRE1BIGRlc2NyaXB0b3IgZGVmaW5lcy4NCj4gPiAgKi8NCj4gPiBkaWZmIC0t
Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMC5oDQo+ID4gYi9kcml2ZXJz
L25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyeDAwLmgNCj4gPiBpbmRleCBjYTM2Y2NjLi5lZTc3MGU3
IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4MDAuaA0K
PiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4MDAuaA0KPiA+IEBAIC0x
OTMsMTAgKzE5MywxMSBAQCBzdHJ1Y3QgcnQyeDAwX2NoaXAgew0KPiA+ICAjZGVmaW5lIFJUMzg4
MyAgICAgICAgIDB4Mzg4MyAgLyogV1NPQyAqLw0KPiA+ICAjZGVmaW5lIFJUNTM5MCAgICAgICAg
IDB4NTM5MCAgLyogMi40R0h6ICovDQo+ID4gICNkZWZpbmUgUlQ1MzkyICAgICAgICAgMHg1Mzky
ICAvKiAyLjRHSHogKi8NCj4gPiArI2RlZmluZSBSVDMyOTAgICAgICAgICAweDMyOTANCj4gPg0K
PiA+ICAgICAgICB1MTYgcmY7DQo+ID4gICAgICAgIHUxNiByZXY7DQo+ID4gLQ0KPiA+ICsgICAg
ICAgdTE2IG1hY192ZXJzaW9uOw0KPiA+ICAgICAgICBlbnVtIHJ0MngwMF9jaGlwX2ludGYgaW50
ZjsNCj4gPiAgfTsNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9y
dDJ4MDAvcnQyeDAwcGNpLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4
MDBwY2kuYw0KPiA+IGluZGV4IDBhNDY1M2EuLjliYmQ5YTMgMTAwNjQ0DQo+ID4gLS0tIGEvZHJp
dmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMHBjaS5jDQo+ID4gKysrIGIvZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMHBjaS5jDQo+ID4gQEAgLTI1Niw2ICsyNTYsNyBAQCBp
bnQgcnQyeDAwcGNpX3Byb2JlKHN0cnVjdCBwY2lfZGV2ICpwY2lfZGV2LA0KPiA+IGNvbnN0IHN0
cnVjdCBydDJ4MDBfb3BzICpvcHMpDQo+ID4gICAgICAgIHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3
Ow0KPiA+ICAgICAgICBzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2Ow0KPiA+ICAgICAgICBp
bnQgcmV0dmFsOw0KPiA+ICsgICAgICAgdTE2IGRldmljZV9pZDsNCj4gPg0KPiA+ICAgICAgICBy
ZXR2YWwgPSBwY2lfZW5hYmxlX2RldmljZShwY2lfZGV2KTsNCj4gPiAgICAgICAgaWYgKHJldHZh
bCkgew0KPiA+IEBAIC0zMDUsNiArMzA2LDExIEBAIGludCBydDJ4MDBwY2lfcHJvYmUoc3RydWN0
IHBjaV9kZXYgKnBjaV9kZXYsDQo+ID4gY29uc3Qgc3RydWN0IHJ0MngwMF9vcHMgKm9wcykNCj4g
PiAgICAgICAgaWYgKHJldHZhbCkNCj4gPiAgICAgICAgICAgICAgICBnb3RvIGV4aXRfZnJlZV9k
ZXZpY2U7DQo+ID4NCj4gPiArDQo+ID4gKyAgICAgICBwY2lfcmVhZF9jb25maWdfd29yZChwY2lf
ZGV2LCBQQ0lfREVWSUNFX0lELCAmZGV2aWNlX2lkKTsNCj4gPiArICAgICAgIGlmIChkZXZpY2Vf
aWQgPT0gMHgzMjkwKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBkZXYtPmNoaXAubWFjX3Zl
cnNpb24gPSAweDMyOTA7DQo+ID4gKw0KPiA+ICAgICAgICByZXR2YWwgPSBydDJ4MDBsaWJfcHJv
YmVfZGV2KHJ0MngwMGRldik7DQo+ID4gICAgICAgIGlmIChyZXR2YWwpDQo+ID4gICAgICAgICAg
ICAgICAgZ290byBleGl0X2ZyZWVfcmVnOw0KPiA+IC0tDQo+ID4gMS43LjUuNA0KPiA+DQo+ID4g
LS0NCj4gPiBUbyB1bnN1YnNjcmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5z
dWJzY3JpYmUNCj4gPiBsaW51eC13aXJlbGVzcyIgaW4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRv
DQo+ID4gbWFqb3Jkb21vQHZnZXIua2VybmVsLm9yZyBNb3JlIG1ham9yZG9tbyBpbmZvIGF0DQo+
ID4gaHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW5mby5odG1sDQo+DQoNCi0tDQpK
b2huIFcuIExpbnZpbGxlICAgICAgICAgICAgICAgIFNvbWVkYXkgdGhlIHdvcmxkIHdpbGwgbmVl
ZCBhIGhlcm8sIGFuZCB5b3UNCmxpbnZpbGxlQHR1eGRyaXZlci5jb20gICAgICAgICAgICAgICAg
ICBtaWdodCBiZSBhbGwgd2UgaGF2ZS4gIEJlIHJlYWR5Lg0KCioqKioqKioqKioqKiogRW1haWwg
Q29uZmlkZW50aWFsaXR5IE5vdGljZSAqKioqKioqKioqKioqKioqKioqKg0KVGhlIGluZm9ybWF0
aW9uIGNvbnRhaW5lZCBpbiB0aGlzIGUtbWFpbCBtZXNzYWdlIChpbmNsdWRpbmcgYW55IA0KYXR0
YWNobWVudHMpIG1heSBiZSBjb25maWRlbnRpYWwsIHByb3ByaWV0YXJ5LCBwcml2aWxlZ2VkLCBv
ciBvdGhlcndpc2UNCmV4ZW1wdCBmcm9tIGRpc2Nsb3N1cmUgdW5kZXIgYXBwbGljYWJsZSBsYXdz
LiBJdCBpcyBpbnRlbmRlZCB0byBiZSANCmNvbnZleWVkIG9ubHkgdG8gdGhlIGRlc2lnbmF0ZWQg
cmVjaXBpZW50KHMpLiBBbnkgdXNlLCBkaXNzZW1pbmF0aW9uLCANCmRpc3RyaWJ1dGlvbiwgcHJp
bnRpbmcsIHJldGFpbmluZyBvciBjb3B5aW5nIG9mIHRoaXMgZS1tYWlsIChpbmNsdWRpbmcgaXRz
IA0KYXR0YWNobWVudHMpIGJ5IHVuaW50ZW5kZWQgcmVjaXBpZW50KHMpIGlzIHN0cmljdGx5IHBy
b2hpYml0ZWQgYW5kIG1heSANCmJlIHVubGF3ZnVsLiBJZiB5b3UgYXJlIG5vdCBhbiBpbnRlbmRl
ZCByZWNpcGllbnQgb2YgdGhpcyBlLW1haWwsIG9yIGJlbGlldmUgDQp0aGF0IHlvdSBoYXZlIHJl
Y2VpdmVkIHRoaXMgZS1tYWlsIGluIGVycm9yLCBwbGVhc2Ugbm90aWZ5IHRoZSBzZW5kZXIgDQpp
bW1lZGlhdGVseSAoYnkgcmVwbHlpbmcgdG8gdGhpcyBlLW1haWwpLCBkZWxldGUgYW55IGFuZCBh
bGwgY29waWVzIG9mIA0KdGhpcyBlLW1haWwgKGluY2x1ZGluZyBhbnkgYXR0YWNobWVudHMpIGZy
b20geW91ciBzeXN0ZW0sIGFuZCBkbyBub3QNCmRpc2Nsb3NlIHRoZSBjb250ZW50IG9mIHRoaXMg
ZS1tYWlsIHRvIGFueSBvdGhlciBwZXJzb24uIFRoYW5rIHlvdSE=


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rt2x00 : RT3290 chip support
  2012-04-27  2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung
  2012-04-27  7:40 ` Helmut Schaa
@ 2012-05-11 12:05 ` Gertjan van Wingerde
  1 sibling, 0 replies; 5+ messages in thread
From: Gertjan van Wingerde @ 2012-05-11 12:05 UTC (permalink / raw)
  To: Woody Hung; +Cc: linville, linux-wireless, jay.hung, pohsun.yang, dennis.lee

Hi Woody,

On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <Woody.Hung@mediatek.com> wrote:
> This support RT3290 chip
>
> Signed-off-by: Woody Hung <Woody.Hung@mediatek.com>

I'm sorry for the late review. I couldn't find time sooner to look at this.

See further down for a number of comments to your patch.

> ---
>  drivers/net/wireless/rt2x00/Kconfig     |    8 +
>  drivers/net/wireless/rt2x00/rt2800.h    |  120 +++++++++-
>  drivers/net/wireless/rt2x00/rt2800lib.c |  395 ++++++++++++++++++++++++++++--
>  drivers/net/wireless/rt2x00/rt2800lib.h |    3 +-
>  drivers/net/wireless/rt2x00/rt2800pci.c |   12 +
>  drivers/net/wireless/rt2x00/rt2800pci.h |    3 +
>  drivers/net/wireless/rt2x00/rt2x00.h    |    3 +-
>  drivers/net/wireless/rt2x00/rt2x00pci.c |    6 +
>  8 files changed, 520 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> index 299c387..c7548da 100644
> --- a/drivers/net/wireless/rt2x00/Kconfig
> +++ b/drivers/net/wireless/rt2x00/Kconfig
> @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
>          rt2800pci driver.
>          Supported chips: RT5390
>
> +config RT2800PCI_RT3290
> +       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> +       depends on EXPERIMENTAL
> +       default y
> +       ---help---
> +         This adds support for rt3290 wireless chipset family to the
> +         rt2800pci driver.
> +         Supported chips: RT3290
>  endif
>
>  config RT2500USB
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index d91f4f6..39b1685 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -70,7 +70,7 @@
>  #define RF5370                         0x5370
>  #define RF5372                         0x5372
>  #define RF5390                         0x5390
> -
> +#define RF3290                         0x3290
>  /*
>  * Chipset revisions.
>  */

Please add the define in the right numerical order. It just looks
nicer when things are in numerical order.

> @@ -112,6 +112,12 @@
>  * Registers.
>  */
>
> +
> +/*
> + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> + */
> +#define MAC_CSR0_3290                          0x0000
> +
>  /*
>  * E2PROM_CSR: PCI EEPROM control register.
>  * RELOAD: Write 1 to reload eeprom content.
> @@ -305,6 +311,118 @@
>  #define GPIO_CTRL_CFG_GPIOD_BIT7       FIELD32(0x00008000)
>
>  /*
> + * WLAN_CTRL_CFG
> + */
> +#define WLAN_FUN_CTRL                  0x80
> +#define WLAN_EN                                FIELD32(0x00000001)
> +#define WLAN_CLK_EN                    FIELD32(0x00000002)
> +#define WLAN_RSV1                      FIELD32(0x00000004)
> +#define WLAN_RESET                     FIELD32(0x00000008)
> +#define PCIE_APP0_CLK_REQ              FIELD32(0x00000010)
> +#define FRC_WL_ANT_SET                 FIELD32(0x00000020)
> +#define INV_TR_SW0                     FIELD32(0x00000040)
> +#define WLAN_GPIO_IN_BIT0              FIELD32(0x00000100)
> +#define WLAN_GPIO_IN_BIT1              FIELD32(0x00000200)
> +#define WLAN_GPIO_IN_BIT2              FIELD32(0x00000400)
> +#define WLAN_GPIO_IN_BIT3              FIELD32(0x00000800)
> +#define WLAN_GPIO_IN_BIT4              FIELD32(0x00001000)
> +#define WLAN_GPIO_IN_BIT5              FIELD32(0x00002000)
> +#define WLAN_GPIO_IN_BIT6              FIELD32(0x00004000)
> +#define WLAN_GPIO_IN_BIT7              FIELD32(0x00008000)
> +#define WLAN_GPIO_IN_BIT_ALL           FIELD32(0x0000ff00)
> +#define WLAN_GPIO_OUT_BIT0             FIELD32(0x00010000)
> +#define WLAN_GPIO_OUT_BIT1             FIELD32(0x00020000)
> +#define WLAN_GPIO_OUT_BIT2             FIELD32(0x00040000)
> +#define WLAN_GPIO_OUT_BIT3             FIELD32(0x00050000)
> +#define WLAN_GPIO_OUT_BIT4             FIELD32(0x00100000)
> +#define WLAN_GPIO_OUT_BIT5             FIELD32(0x00200000)
> +#define WLAN_GPIO_OUT_BIT6             FIELD32(0x00400000)
> +#define WLAN_GPIO_OUT_BIT7             FIELD32(0x00800000)
> +#define WLAN_GPIO_OUT_BIT_ALL          FIELD32(0x00ff0000)
> +#define WLAN_GPIO_OUT_OE_BIT0          FIELD32(0x01000000)
> +#define WLAN_GPIO_OUT_OE_BIT1          FIELD32(0x02000000)
> +#define WLAN_GPIO_OUT_OE_BIT2          FIELD32(0x04000000)
> +#define WLAN_GPIO_OUT_OE_BIT3          FIELD32(0x08000000)
> +#define WLAN_GPIO_OUT_OE_BIT4          FIELD32(0x10000000)
> +#define WLAN_GPIO_OUT_OE_BIT5          FIELD32(0x20000000)
> +#define WLAN_GPIO_OUT_OE_BIT6          FIELD32(0x40000000)
> +#define WLAN_GPIO_OUT_OE_BIT7          FIELD32(0x80000000)
> +#define WLAN_GPIO_OUT_OE_BIT_ALL       FIELD32(0xff000000)
> +
> +/*
> + * CMB_CTRL_CFG
> + */
> +#define CMB_CTRL               0x20
> +#define AUX_OPT_BIT0           FIELD32(0x00000001)
> +#define AUX_OPT_BIT1           FIELD32(0x00000002)
> +#define AUX_OPT_BIT2           FIELD32(0x00000004)
> +#define AUX_OPT_BIT3           FIELD32(0x00000008)
> +#define AUX_OPT_BIT4           FIELD32(0x00000010)
> +#define AUX_OPT_BIT5           FIELD32(0x00000020)
> +#define AUX_OPT_BIT6           FIELD32(0x00000040)
> +#define AUX_OPT_BIT7           FIELD32(0x00000080)
> +#define AUX_OPT_BIT8           FIELD32(0x00000100)
> +#define AUX_OPT_BIT9           FIELD32(0x00000200)
> +#define AUX_OPT_BIT10          FIELD32(0x00000400)
> +#define AUX_OPT_BIT11          FIELD32(0x00000800)
> +#define AUX_OPT_BIT12          FIELD32(0x00001000)
> +#define AUX_OPT_BIT13          FIELD32(0x00002000)
> +#define AUX_OPT_BIT14          FIELD32(0x00004000)
> +#define AUX_OPT_BIT15          FIELD32(0x00008000)
> +#define LDO25_LEVEL            FIELD32(0x00030000)
> +#define LDO25_LARGEA           FIELD32(0x00040000)
> +#define LDO25_FRC_ON           FIELD32(0x00080000)
> +#define CMB_RSV                        FIELD32(0x00300000)
> +#define XTAL_RDY               FIELD32(0x00400000)
> +#define PLL_LD                 FIELD32(0x00800000)
> +#define LDO_CORE_LEVEL         FIELD32(0x0F000000)
> +#define LDO_BGSEL              FIELD32(0x30000000)
> +#define LDO3_EN                        FIELD32(0x40000000)
> +#define LDO0_EN                        FIELD32(0x80000000)
> +
> +/*
> + * OSC_CTRL_CFG
> + */
> +#define OSC_CTRL               0x38
> +#define OSC_REF_CYCLE          FIELD32(0x00001fff)
> +#define OSC_RSV                        FIELD32(0x0000e000)
> +#define OSC_CAL_CNT            FIELD32(0x0fff0000)
> +#define OSC_CAL_ACK            FIELD32(0x10000000)
> +#define OSC_CLK_32K_VLD                FIELD32(0x20000000)
> +#define OSC_CAL_REQ            FIELD32(0x40000000)
> +#define OSC_ROSC_EN            FIELD32(0x80000000)
> +
> +/*
> + * PLL_CTRL_CFG
> + */
> +#define PLL_CTRL               0x50
> +#define PLL_RESERVED_INPUT1    FIELD32(0x000000ff)
> +#define PLL_RESERVED_INPUT2    FIELD32(0x0000ff00)
> +#define PLL_CONTROL            FIELD32(0x00070000)
> +#define PLL_LPF_R1             FIELD32(0x00080000)
> +#define PLL_LPF_C1_CTRL        FIELD32(0x00300000)
> +#define PLL_LPF_C2_CTRL        FIELD32(0x00c00000)
> +#define PLL_CP_CURRENT_CTRL    FIELD32(0x03000000)
> +#define PLL_PFD_DELAY_CTRL     FIELD32(0x0c000000)
> +#define PLL_LOCK_CTRL          FIELD32(0x70000000)
> +#define PLL_VBGBK_EN           FIELD32(0x80000000)
> +
> +/*
> + * COEX_CFG_0
> + */
> +#define COEX_CFG0                      0x40
> +
> +/*
> + * COEX_CFG_1
> + */
> +#define COEX_CFG1                      0x44
> +
> +/*
> + * COEX_CFG_2
> + */
> +#define COEX_CFG2                      0x48
> +
> +/*
>  * MCU_CMD_CFG
>  */
>  #define MCU_CMD_CFG                    0x022c
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 1cd16b4..7753791 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
>                multiple = true;
>        } else {
>                fw_len = 8192;
> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       fw_len = 4096;
> +
>                multiple = true;
>        }
>

It would look better to create an else-branch for the fw_len = 8192
assignment. Now it looks odd with overwriting the earlier given value.

> @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
>        if (rt2x00_is_pci(rt2x00dev)) {
>                if (rt2x00_rt(rt2x00dev, RT3572) ||
>                    rt2x00_rt(rt2x00dev, RT5390) ||
> -                   rt2x00_rt(rt2x00dev, RT5392)) {
> +                   rt2x00_rt(rt2x00dev, RT5392) ||
> +                   rt2x00_rt(rt2x00dev, RT3290)) {
>                        rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
>                        rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
>                        rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);

I will just mention this once, but this applies for the whole patch:
Please include the condition in the correct numerical order. It just
makes it easier to look through the code if the RT chipset checks are
in numerical order.

> @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
>  {
>        u32 reg;
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> +               return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> +       } else
>        rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
>        return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
>  }

This looks fishy, as I think both the register_read and the return
statement need to be part of the else branch. Technically the code
still behaves correctly, but it just looks fishy.

> @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
>
>  #define RT5390_POWER_BOUND     0x27
>  #define RT5390_FREQ_OFFSET_BOUND       0x5f
> -
> +#define RT3290_POWER_BOUND     0x27
> +#define RT3290_FREQ_OFFSET_BOUND       0x5f
>  static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
>                                         struct ieee80211_conf *conf,
>                                         struct rf_channel *rf,

No need to remove the empty line. Also, if these values are the same
as for the RT5390 defines, can we combine these in a more generically
named set of defines?

> @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
>        rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
>  }
>
> +
> +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> +                                        struct ieee80211_conf *conf,
> +                                        struct rf_channel *rf,
> +                                        struct channel_info *info)
> +{
> +       u8 rfcsr;
> +
> +       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> +       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> +       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> +       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> +       if (info->default_power1 > RT5390_POWER_BOUND)
> +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> +       else
> +               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> +       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> +       if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> +                                 RT3290_FREQ_OFFSET_BOUND);
> +       else
> +               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> +       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> +
> +       if (rf->channel <= 14) {
> +               rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> +               rfcsr &= ~0xF8;
> +               rfcsr |= (0x1f << 3);
> +               rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> +               rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> +               rfcsr &= ~0xF8;
> +               rfcsr |= (0x1f << 3);
> +               rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);

Can we create some defines for this RFCSR so that we don't have to do
this bit manipulation magic? That would make the code more readable
and better understandable.

> +
> +               if (rf->channel == 6)
> +                       rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> +               else
> +                       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> +
> +               if (rf->channel >= 1 && rf->channel <= 6)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> +               else if (rf->channel >= 7 && rf->channel <= 11)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> +               else if (rf->channel >= 12 && rf->channel <= 14)
> +                       rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> +       }
> +
> +       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> +       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> +
> +       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> +       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> +       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> +}
>  static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>                                  struct ieee80211_conf *conf,
>                                  struct rf_channel *rf,

There is quite a bit of overlap with the already existing
rt2800_config_channel_rf53xx function. Is it possible to share more
code between the two?

> @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>        case RF5390:
>                rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
>                break;
> +       case RF3290:
> +               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> +               break;
>        default:
>                rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
>        }

Again, please put the case in the correct numerical order.

> @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
>                rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
>                rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
>                    rt2x00_rt(rt2x00dev, RT3090) ||
>                    rt2x00_rt(rt2x00dev, RT3390) ||
>                    rt2x00_rt(rt2x00dev, RT5390) ||
> -                   rt2x00_rt(rt2x00dev, RT5392))
> +                   rt2x00_rt(rt2x00dev, RT5392) ||
> +                   rt2x00_rt(rt2x00dev, RT3290))
>                        return 0x1c + (2 * rt2x00dev->lna_gain);
>                else
>                        return 0x2e + rt2x00dev->lna_gain;
> @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
>        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
>        rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800pci_3290_enable_wlan(rt2x00dev);
> +               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> +               if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> +                       rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> +                       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> +               }
> +
> +               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> +               if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> +                       rt2x00_set_field32(&reg, LDO0_EN, 1);
> +                       rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> +                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> +               }
> +
> +               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> +               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> +               rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> +               rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> +               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> +               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> +               reg &= ~(0xFF000000);
> +               reg |= 0x5E000000;
> +               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> +               rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> +               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> +               rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> +               rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> +       }
> +
>        if (rt2x00_rt(rt2x00dev, RT3071) ||
>            rt2x00_rt(rt2x00dev, RT3090) ||
> -           rt2x00_rt(rt2x00dev, RT3390)) {
> +           rt2x00_rt(rt2x00dev, RT3390) ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {
> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> +                               0x00000404);
> +               else
>                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
>                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
>                if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                return -EACCES;
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392)) {
> +               rt2x00_rt(rt2x00dev, RT5392)    ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_bbp_read(rt2x00dev, 4, &value);
>                rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
>                rt2800_bbp_write(rt2x00dev, 4, value);
> @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        if (rt2800_is_305x_soc(rt2x00dev) ||
>            rt2x00_rt(rt2x00dev, RT3572) ||
>            rt2x00_rt(rt2x00dev, RT5390) ||
> -           rt2x00_rt(rt2x00dev, RT5392))
> +           rt2x00_rt(rt2x00dev, RT5392) ||
> +           rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 31, 0x08);
>
>        rt2800_bbp_write(rt2x00dev, 65, 0x2c);
>        rt2800_bbp_write(rt2x00dev, 66, 0x38);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 68, 0x0b);
>
>        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
>                rt2800_bbp_write(rt2x00dev, 69, 0x16);
>                rt2800_bbp_write(rt2x00dev, 73, 0x12);
>        } else if (rt2x00_rt(rt2x00dev, RT5390) ||
> -                          rt2x00_rt(rt2x00dev, RT5392)) {
> +                       rt2x00_rt(rt2x00dev, RT5392) ||
> +                       rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_bbp_write(rt2x00dev, 69, 0x12);
>                rt2800_bbp_write(rt2x00dev, 73, 0x13);
>                rt2800_bbp_write(rt2x00dev, 75, 0x46);
>                rt2800_bbp_write(rt2x00dev, 76, 0x28);
> +
> +               if (rt2x00_rt(rt2x00dev, RT3290))
> +                       rt2800_bbp_write(rt2x00dev, 77, 0x58);
> +               else
>                rt2800_bbp_write(rt2x00dev, 77, 0x59);
>        } else {
>                rt2800_bbp_write(rt2x00dev, 69, 0x12);

Please adjust the indentation of the else branch. You can't just
insert the else and leave the code that is now in the else branch at
its old indentation level.

> @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 81, 0x37);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> +               rt2800_bbp_write(rt2x00dev, 79, 0x18);
> +               rt2800_bbp_write(rt2x00dev, 80, 0x09);
> +               rt2800_bbp_write(rt2x00dev, 81, 0x33);
> +       }
> +
>        rt2800_bbp_write(rt2x00dev, 82, 0x62);
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 83, 0x7a);
>        else
>                rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
>                rt2800_bbp_write(rt2x00dev, 84, 0x19);
>        else if (rt2x00_rt(rt2x00dev, RT5390) ||
> -                        rt2x00_rt(rt2x00dev, RT5392))
> +                       rt2x00_rt(rt2x00dev, RT5392) ||
> +                       rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 84, 0x9a);
>        else
>                rt2800_bbp_write(rt2x00dev, 84, 0x99);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 86, 0x38);
>        else
>                rt2800_bbp_write(rt2x00dev, 86, 0x00);
> @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        rt2800_bbp_write(rt2x00dev, 91, 0x04);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 92, 0x02);
>        else
>                rt2800_bbp_write(rt2x00dev, 92, 0x00);
> @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>            rt2x00_rt(rt2x00dev, RT3572) ||
>            rt2x00_rt(rt2x00dev, RT5390) ||
>            rt2x00_rt(rt2x00dev, RT5392) ||
> +           rt2x00_rt(rt2x00dev, RT3290) ||
>            rt2800_is_305x_soc(rt2x00dev))
>                rt2800_bbp_write(rt2x00dev, 103, 0xc0);
>        else
>                rt2800_bbp_write(rt2x00dev, 103, 0x00);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 104, 0x92);
>
>        if (rt2800_is_305x_soc(rt2x00dev))
> @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>        else if (rt2x00_rt(rt2x00dev, RT5390) ||
>                         rt2x00_rt(rt2x00dev, RT5392))
>                rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> +       else if (rt2x00_rt(rt2x00dev, RT3290))
> +               rt2800_bbp_write(rt2x00dev, 105, 0x1c);
>        else
>                rt2800_bbp_write(rt2x00dev, 105, 0x05);
>
> -       if (rt2x00_rt(rt2x00dev, RT5390))
> +       if (rt2x00_rt(rt2x00dev, RT5390) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 106, 0x03);
>        else if (rt2x00_rt(rt2x00dev, RT5392))
>                rt2800_bbp_write(rt2x00dev, 106, 0x12);
> @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 106, 0x35);
>
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392))
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290))
>                rt2800_bbp_write(rt2x00dev, 128, 0x12);
>
>        if (rt2x00_rt(rt2x00dev, RT5392)) {
> @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
>                rt2800_bbp_write(rt2x00dev, 138, value);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_bbp_write(rt2x00dev, 67, 0x24);
> +               rt2800_bbp_write(rt2x00dev, 143, 0x04);
> +               rt2800_bbp_write(rt2x00dev, 142, 0x99);
> +               rt2800_bbp_write(rt2x00dev, 150, 0x30);
> +               rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> +               rt2800_bbp_write(rt2x00dev, 152, 0x20);
> +               rt2800_bbp_write(rt2x00dev, 153, 0x34);
> +               rt2800_bbp_write(rt2x00dev, 154, 0x40);
> +               rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> +               rt2800_bbp_write(rt2x00dev, 253, 0x04);
> +
> +               rt2800_bbp_read(rt2x00dev, 47, &value);
> +               rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> +               rt2800_bbp_write(rt2x00dev, 47, value);
> +
> +               rt2800_bbp_read(rt2x00dev, 3, &value);
> +               value &= (~0xc0);
> +               value |= 0xc0;
> +               rt2800_bbp_write(rt2x00dev, 3, value);
> +       }

Again, please introduce some define so that we do not have to do this
bit manipulation magic.

>        if (rt2x00_rt(rt2x00dev, RT5390) ||
>                rt2x00_rt(rt2x00dev, RT5392)) {
>                int ant, div_mode;
> @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>            !rt2x00_rt(rt2x00dev, RT3572) &&
>            !rt2x00_rt(rt2x00dev, RT5390) &&
>            !rt2x00_rt(rt2x00dev, RT5392) &&
> +           !rt2x00_rt(rt2x00dev, RT3290) &&
>            !rt2800_is_305x_soc(rt2x00dev))
>                return 0;
>
> @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>         * Init RF calibration.
>         */
>        if (rt2x00_rt(rt2x00dev, RT5390) ||
> -               rt2x00_rt(rt2x00dev, RT5392)) {
> +               rt2x00_rt(rt2x00dev, RT5392) ||
> +               rt2x00_rt(rt2x00dev, RT3290)) {
>                rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
>                rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
>                rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>                        rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
>                        rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
>                        rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> +       } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> +                       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> +                       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> +                       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> +                       rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> +                       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> +                       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> +                       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> +                       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> +                       rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> +                       rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> +                       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> +                       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> +                       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> +                       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> +                       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> +                       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> +                       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> +                       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> +                       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> +                       rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> +                       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> +                       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> +                       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> +                       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> +                       rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> +                       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> +                       rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> +                       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> +                       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> +                       rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> +                       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> +                       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> +                       rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> +                       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> +                       rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
>        }
>
>        if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
>                rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
>        }
>
> +       if (rt2x00_rt(rt2x00dev, RT3290)) {
> +               rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> +               rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> +               rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> +       }
> +
>        return 0;
>  }

More bit manipulation magic.

>
> @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
>  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
>  {
>        u32 reg;
> +       u16 efuse_ctrl_reg;
> +       efuse_ctrl_reg = EFUSE_CTRL;
>
> -       rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> +       if (rt2x00dev->chip.mac_version == 0x3290)
> +               efuse_ctrl_reg = 0x24;
>
> +       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
>        return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
>  }
>  EXPORT_SYMBOL_GPL(rt2800_efuse_detect);

Can you explain why we need the chip.mac_version check here instead of
just doing a check for rt2x00_rt(rt2x00dev, RT3290)?
That way we would not have to add this mac_version field.

> @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
>  {
>        u32 reg;
>
> +       u16 efuse_ctrl_reg;
> +       u16 efuse_data0_reg;
> +       u16 efuse_data1_reg;
> +       u16 efuse_data2_reg;
> +       u16 efuse_data3_reg;
> +
> +       efuse_ctrl_reg = EFUSE_CTRL;
> +       efuse_data0_reg = EFUSE_DATA0;
> +       efuse_data1_reg = EFUSE_DATA1;
> +       efuse_data2_reg = EFUSE_DATA2;
> +       efuse_data3_reg = EFUSE_DATA3;
> +
> +       if (rt2x00dev->chip.mac_version == 0x3290) {
> +               efuse_ctrl_reg = 0x24;
> +               efuse_data3_reg = 0x28;
> +               efuse_data2_reg = efuse_data3_reg + 4;
> +               efuse_data1_reg = efuse_data2_reg + 4;
> +               efuse_data0_reg = efuse_data1_reg + 4;
> +       }
>        mutex_lock(&rt2x00dev->csr_mutex);
>
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
>        rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> -       rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> +       rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
>
>        /* Wait until the EEPROM has been loaded */
> -       rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> -
> +       rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
>        /* Apparently the data is read from end to start */
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
>        /* The returned value is in CPU order, but eeprom is le */
>        *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> -       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> +       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
>        *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
>
>        mutex_unlock(&rt2x00dev->csr_mutex);
> @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>         * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
>         * RT53xx: defined in "EEPROM_CHIP_ID" field
>         */
> +       if (rt2x00dev->chip.mac_version == 0x3290)
> +               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> +       else
>        rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
>        if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> -               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> +               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
>                rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
>        else
>                value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>        case RT3572:
>        case RT5390:
>        case RT5392:
> +       case RT3290:
>                break;
>        default:
>                ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                break;
>        default:
>                ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>                   rt2x00_rf(rt2x00dev, RF3320) ||
>                   rt2x00_rf(rt2x00dev, RF5370) ||
>                   rt2x00_rf(rt2x00dev, RF5372) ||
> -                  rt2x00_rf(rt2x00dev, RF5390)) {
> +                  rt2x00_rf(rt2x00dev, RF5390) ||
> +                  rt2x00_rf(rt2x00dev, RF3290)) {
>                spec->num_channels = 14;
>                spec->channels = rf_vals_3x;
>        } else if (rt2x00_rf(rt2x00dev, RF3052)) {
> @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>        case RF5370:
>        case RF5372:
>        case RF5390:
> +       case RF3290:
>                __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
>                break;
>        }
> @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
>  }
>  EXPORT_SYMBOL_GPL(rt2800_get_survey);
>
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> +       u32 wlanfunctrl;
> +       u32 glocfg;
> +       u32 cmbctrl;
> +       u8 index;
> +       int i;
> +
> +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> +       rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> +       if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> +               return 0;
> +
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> +       udelay(REGISTER_BUSY_DELAY);
> +
> +       index = 0;
> +       cmbctrl = 0;
> +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> +               rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> +               if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> +                       (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> +                       break;
> +               udelay(REGISTER_BUSY_DELAY);
> +       }
> +
> +       if (index >= REGISTER_BUSY_COUNT) {
> +               rt2800_register_write(rt2x00dev, 0x58, 0x018);
> +               udelay(REGISTER_BUSY_DELAY);
> +               rt2800_register_write(rt2x00dev, 0x58, 0x418);
> +               udelay(REGISTER_BUSY_DELAY);
> +               rt2800_register_write(rt2x00dev, 0x58, 0x618);
> +               udelay(REGISTER_BUSY_DELAY);
> +       } else {
> +               rt2800_register_read(rt2x00dev,
> +                       WPDMA_GLO_CFG, &glocfg);
> +       }
> +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> +
> +       rt2800_register_write(rt2x00dev,
> +               WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> +       udelay(REGISTER_BUSY_DELAY);
> +       rt2800_register_write(rt2x00dev,
> +               WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> +       udelay(2);
> +       rt2800_register_write(rt2x00dev,
> +               INT_SOURCE_CSR, 0x7fffffff);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> +
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> +       u32 wlanfunctrl;
> +       u32 glocfg;
> +       u32 reg;
> +       int i;
> +
> +       /* Change Interrupt bitmask. */
> +       rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> +       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> +       rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> +       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> +
> +       /* wait RX DMA idle */
> +       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> +               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> +               if ((rt2x00_get_field32(glocfg,
> +                       WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> +                       (glocfg == 0xFFFFFFFF))
> +                       break;
> +               udelay(REGISTER_BUSY_DELAY);
> +       }
> +
> +       if (i >= REGISTER_BUSY_COUNT) {
> +               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> +               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> +               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> +               return 0;
> +               }
> +
> +       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> +       rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> +       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> +       udelay(REGISTER_BUSY_DELAY);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);

These two functions seems to be pci specific, shouldn't they be in
rt2800pci.c then?


>  MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
>  MODULE_VERSION(DRV_VERSION);
>  MODULE_DESCRIPTION("Ralink RT2800 library");
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> index 18a0b67..22d7cbb 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>  int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
>                      struct survey_info *survey);
>  void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> -
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
>  #endif /* RT2800LIB_H */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 931331d..9251f2d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
>  */
>  static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
>  {
> +
> +       if (rt2x00_rt(rt2x00dev, RT3290))
> +               return FIRMWARE_RT3290;
> +
>        return FIRMWARE_RT2860;
>  }
>

OK. Since this is a different firmware file, I assume you will be
submitting this firmware to the linux-firmware repository, right?

> @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
>                rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
>                rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
>        }
> +
> +       if (rt2x00_rt(rt2x00dev, RT3290))
> +               rt2800pci_3290_disable_wlan(rt2x00dev);
>  }
>
>  static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
>         */
>        rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
>
> +       if (rt2x00_rf(rt2x00dev, RF3290))
> +               rt2800pci_3290_enable_wlan(rt2x00dev);
>        return 0;
>  }
>
> @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
>        { PCI_DEVICE(0x1814, 0x539a) },
>        { PCI_DEVICE(0x1814, 0x539f) },
>  #endif
> +#ifdef CONFIG_RT2800PCI_RT3290
> +       { PCI_DEVICE(0x1814, 0x3290) },
> +#endif
>        { 0, }
>  };

Numerical order, please.

>  #endif /* CONFIG_PCI */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> index 70e050d..dd043c7 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> @@ -49,6 +49,9 @@
>  #define FIRMWARE_RT2860                        "rt2860.bin"
>  #define FIRMWARE_IMAGE_BASE            0x2000
>
> +
> +#define FIRMWARE_RT3290                        "rt3290.bin"
> +
>  /*
>  * DMA descriptor defines.
>  */

Please move the define next to the order firmware filename definition.

> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index ca36ccc..ee770e7 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -193,10 +193,11 @@ struct rt2x00_chip {
>  #define RT3883         0x3883  /* WSOC */
>  #define RT5390         0x5390  /* 2.4GHz */
>  #define RT5392         0x5392  /* 2.4GHz */
> +#define RT3290         0x3290
>
>        u16 rf;
>        u16 rev;
> -
> +       u16 mac_version;
>        enum rt2x00_chip_intf intf;
>  };
>

As mentioned before, please explain why this new field is needed.

> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index 0a4653a..9bbd9a3 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
>        struct ieee80211_hw *hw;
>        struct rt2x00_dev *rt2x00dev;
>        int retval;
> +       u16 device_id;
>
>        retval = pci_enable_device(pci_dev);
>        if (retval) {
> @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
>        if (retval)
>                goto exit_free_device;
>
> +
> +       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> +       if (device_id == 0x3290)
> +               rt2x00dev->chip.mac_version = 0x3290;
> +
>        retval = rt2x00lib_probe_dev(rt2x00dev);
>        if (retval)
>                goto exit_free_reg;
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
---
Gertjan

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-05-11 12:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-27  2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung
2012-04-27  7:40 ` Helmut Schaa
2012-05-02 18:13   ` John W. Linville
2012-05-03  1:07     ` Woody Hung (洪秋竹)
2012-05-11 12:05 ` Gertjan van Wingerde

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox