rt2x00 : RT3290 chip support v4
authorWoody Hung <Woody.Hung@mediatek.com>
Wed, 13 Jun 2012 07:01:16 +0000 (15:01 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 20 Jun 2012 18:41:49 +0000 (14:41 -0400)
This patch support the new chipset rt3290 wifi implementation in rt2x00.
It initailize the related mac, bbp and rf register in startup phase.
And this patch modify the efuse read/write method for the different efuse data offset of rt3290.

Signed-off-by: Woody Hung <Woody.Hung@mediatek.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800pci.h
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00pci.c

index 299c3879582da14e12ca00d7f11184da8c61bed7..c7548da6573df87e0bf8017cf1da763efc1bc698 100644 (file)
@@ -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
index 1ca88cdc6eced82ec9d84e460c0398c4c3e4f50f..e252e9bafd0e2776075a8159d74e4f9180b87e83 100644 (file)
@@ -68,6 +68,7 @@
 #define RF3320                         0x000b
 #define RF3322                         0x000c
 #define RF3053                         0x000d
+#define RF3290                         0x3290
 #define RF5360                         0x5360
 #define RF5370                         0x5370
 #define RF5372                         0x5372
  * 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.
 #define E2PROM_CSR_LOAD_STATUS         FIELD32(0x00000040)
 #define E2PROM_CSR_RELOAD              FIELD32(0x00000080)
 
+/*
+ * CMB_CTRL_CFG
+ */
+#define CMB_CTRL               0x0020
+#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)
+
+/*
+ * EFUSE_CSR_3290: RT3290 EEPROM
+ */
+#define EFUSE_CTRL_3290                        0x0024
+
+/*
+ * EFUSE_DATA3 of 3290
+ */
+#define EFUSE_DATA3_3290               0x0028
+
+/*
+ * EFUSE_DATA2 of 3290
+ */
+#define EFUSE_DATA2_3290               0x002c
+
+/*
+ * EFUSE_DATA1 of 3290
+ */
+#define EFUSE_DATA1_3290               0x0030
+
+/*
+ * EFUSE_DATA0 of 3290
+ */
+#define EFUSE_DATA0_3290               0x0034
+
+/*
+ * OSC_CTRL_CFG
+ * Ring oscillator configuration
+ */
+#define OSC_CTRL               0x0038
+#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)
+
+/*
+ * COEX_CFG_0
+ */
+#define COEX_CFG0                      0x0040
+#define COEX_CFG_ANT           FIELD32(0xff000000)
+/*
+ * COEX_CFG_1
+ */
+#define COEX_CFG1                      0x0044
+
+/*
+ * COEX_CFG_2
+ */
+#define COEX_CFG2                      0x0048
+#define BT_COEX_CFG1           FIELD32(0xff000000)
+#define BT_COEX_CFG0           FIELD32(0x00ff0000)
+#define WL_COEX_CFG1           FIELD32(0x0000ff00)
+#define WL_COEX_CFG0           FIELD32(0x000000ff)
+/*
+ * PLL_CTRL_CFG
+ * PLL configuration register
+ */
+#define PLL_CTRL               0x0050
+#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)
+
+
+/*
+ * WLAN_CTRL_CFG
+ * RT3290 wlan configuration
+ */
+#define WLAN_FUN_CTRL                  0x0080
+#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)
+
 /*
  * AUX_CTRL: Aux/PCI-E related configuration
  */
@@ -1763,9 +1914,11 @@ struct mac_iveiv_entry {
 /*
  * BBP 3: RX Antenna
  */
-#define BBP3_RX_ADC                            FIELD8(0x03)
+#define BBP3_RX_ADC                    FIELD8(0x03)
 #define BBP3_RX_ANTENNA                        FIELD8(0x18)
 #define BBP3_HT40_MINUS                        FIELD8(0x20)
+#define BBP3_ADC_MODE_SWITCH           FIELD8(0x40)
+#define BBP3_ADC_INIT_MODE             FIELD8(0x80)
 
 /*
  * BBP 4: Bandwidth
@@ -1774,6 +1927,14 @@ struct mac_iveiv_entry {
 #define BBP4_BANDWIDTH                 FIELD8(0x18)
 #define BBP4_MAC_IF_CTRL               FIELD8(0x40)
 
+/*
+ * BBP 47: Bandwidth
+ */
+#define BBP47_TSSI_REPORT_SEL          FIELD8(0x03)
+#define BBP47_TSSI_UPDATE_REQ          FIELD8(0x04)
+#define BBP47_TSSI_TSSI_MODE           FIELD8(0x18)
+#define BBP47_TSSI_ADC6                        FIELD8(0x80)
+
 /*
  * BBP 109
  */
@@ -1916,6 +2077,16 @@ struct mac_iveiv_entry {
 #define RFCSR27_R3                     FIELD8(0x30)
 #define RFCSR27_R4                     FIELD8(0x40)
 
+/*
+ * RFCSR 29:
+ */
+#define RFCSR29_ADC6_TEST              FIELD8(0x01)
+#define RFCSR29_ADC6_INT_TEST          FIELD8(0x02)
+#define RFCSR29_RSSI_RESET             FIELD8(0x04)
+#define RFCSR29_RSSI_ON                        FIELD8(0x08)
+#define RFCSR29_RSSI_RIP_CTRL          FIELD8(0x30)
+#define RFCSR29_RSSI_GAIN              FIELD8(0xc0)
+
 /*
  * RFCSR 30:
  */
index 4d3747c3010b987134199dabf09d0815f269987e..068276ee8affd07605c2b02f82e0d9314aff7a1f 100644 (file)
@@ -354,16 +354,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
         * of 4kb. Certain USB chipsets however require different firmware,
         * which Ralink only provides attached to the original firmware
         * file. Thus for USB devices, firmware files have a length
-        * which is a multiple of 4kb.
+        * which is a multiple of 4kb. The firmware for rt3290 chip also
+        * have a length which is a multiple of 4kb.
         */
-       if (rt2x00_is_usb(rt2x00dev)) {
+       if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))
                fw_len = 4096;
-               multiple = true;
-       } else {
+       else
                fw_len = 8192;
-               multiple = true;
-       }
 
+       multiple = true;
        /*
         * Validate the firmware length
         */
@@ -415,7 +414,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
                return -EBUSY;
 
        if (rt2x00_is_pci(rt2x00dev)) {
-               if (rt2x00_rt(rt2x00dev, RT3572) ||
+               if (rt2x00_rt(rt2x00dev, RT3290) ||
+                   rt2x00_rt(rt2x00dev, RT3572) ||
                    rt2x00_rt(rt2x00dev, RT5390) ||
                    rt2x00_rt(rt2x00dev, RT5392)) {
                        rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
@@ -851,8 +851,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
-       return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+       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);
+       }
 }
 EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
 
@@ -1935,9 +1940,54 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
+#define RT3290_POWER_BOUND     0x27
+#define RT3290_FREQ_OFFSET_BOUND       0x5f
 #define RT5390_POWER_BOUND     0x27
 #define RT5390_FREQ_OFFSET_BOUND       0x5f
 
+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 > RT3290_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) {
+               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);
+       }
+}
+
 static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
                                         struct ieee80211_conf *conf,
                                         struct rf_channel *rf,
@@ -2036,15 +2086,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
                        }
                }
        }
-
-       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,
@@ -2054,7 +2095,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
        unsigned int tx_pin;
-       u8 bbp;
+       u8 bbp, rfcsr;
 
        if (rf->channel <= 14) {
                info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
@@ -2075,6 +2116,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        case RF3052:
                rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
                break;
+       case RF3290:
+               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+               break;
        case RF5360:
        case RF5370:
        case RF5372:
@@ -2086,6 +2130,22 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
        }
 
+       if (rt2x00_rf(rt2x00dev, RF3290) ||
+           rt2x00_rf(rt2x00dev, RF5360) ||
+           rt2x00_rf(rt2x00dev, RF5370) ||
+           rt2x00_rf(rt2x00dev, RF5372) ||
+           rt2x00_rf(rt2x00dev, RF5390) ||
+           rt2x00_rf(rt2x00dev, RF5392)) {
+               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);
+       }
+
        /*
         * Change BBP settings
         */
@@ -2566,6 +2626,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
                rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
                rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
                break;
+       case RF3290:
        case RF5360:
        case RF5370:
        case RF5372:
@@ -2701,6 +2762,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
                if (rt2x00_rt(rt2x00dev, RT3070) ||
                    rt2x00_rt(rt2x00dev, RT3071) ||
                    rt2x00_rt(rt2x00dev, RT3090) ||
+                   rt2x00_rt(rt2x00dev, RT3290) ||
                    rt2x00_rt(rt2x00dev, RT3390) ||
                    rt2x00_rt(rt2x00dev, RT5390) ||
                    rt2x00_rt(rt2x00dev, RT5392))
@@ -2797,10 +2859,54 @@ 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)) {
+               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, 3);
+                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
+               }
+
+               rt2800_register_read(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);
+               rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
+               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
+
+               rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
+               rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
+               rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
+               rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
+               rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
+               rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
+
+               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, RT3290) ||
            rt2x00_rt(rt2x00dev, RT3390)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+
+               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) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
@@ -3209,14 +3315,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
                     rt2800_wait_bbp_ready(rt2x00dev)))
                return -EACCES;
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392)) {
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_bbp_read(rt2x00dev, 4, &value);
                rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
                rt2800_bbp_write(rt2x00dev, 4, value);
        }
 
        if (rt2800_is_305x_soc(rt2x00dev) ||
+           rt2x00_rt(rt2x00dev, RT3290) ||
            rt2x00_rt(rt2x00dev, RT3572) ||
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392))
@@ -3225,20 +3333,26 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt2800_bbp_write(rt2x00dev, 65, 0x2c);
        rt2800_bbp_write(rt2x00dev, 66, 0x38);
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                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)) {
+       } else if (rt2x00_rt(rt2x00dev, RT3290) ||
+                  rt2x00_rt(rt2x00dev, RT5390) ||
+                  rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_bbp_write(rt2x00dev, 69, 0x12);
                rt2800_bbp_write(rt2x00dev, 73, 0x13);
                rt2800_bbp_write(rt2x00dev, 75, 0x46);
                rt2800_bbp_write(rt2x00dev, 76, 0x28);
-               rt2800_bbp_write(rt2x00dev, 77, 0x59);
+
+               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);
                rt2800_bbp_write(rt2x00dev, 73, 0x10);
@@ -3263,23 +3377,33 @@ 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))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 83, 0x7a);
        else
                rt2800_bbp_write(rt2x00dev, 83, 0x6a);
 
        if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
                rt2800_bbp_write(rt2x00dev, 84, 0x19);
-       else if (rt2x00_rt(rt2x00dev, RT5390) ||
-                        rt2x00_rt(rt2x00dev, RT5392))
+       else if (rt2x00_rt(rt2x00dev, RT3290) ||
+                    rt2x00_rt(rt2x00dev, RT5390) ||
+                    rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 84, 0x9a);
        else
                rt2800_bbp_write(rt2x00dev, 84, 0x99);
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 86, 0x38);
        else
                rt2800_bbp_write(rt2x00dev, 86, 0x00);
@@ -3289,8 +3413,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 
        rt2800_bbp_write(rt2x00dev, 91, 0x04);
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 92, 0x02);
        else
                rt2800_bbp_write(rt2x00dev, 92, 0x00);
@@ -3304,6 +3429,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
            rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
            rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
            rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+           rt2x00_rt(rt2x00dev, RT3290) ||
            rt2x00_rt(rt2x00dev, RT3572) ||
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392) ||
@@ -3312,27 +3438,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
        else
                rt2800_bbp_write(rt2x00dev, 103, 0x00);
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 104, 0x92);
 
        if (rt2800_is_305x_soc(rt2x00dev))
                rt2800_bbp_write(rt2x00dev, 105, 0x01);
+       else if (rt2x00_rt(rt2x00dev, RT3290))
+               rt2800_bbp_write(rt2x00dev, 105, 0x1c);
        else if (rt2x00_rt(rt2x00dev, RT5390) ||
                         rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 105, 0x3c);
        else
                rt2800_bbp_write(rt2x00dev, 105, 0x05);
 
-       if (rt2x00_rt(rt2x00dev, RT5390))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390))
                rt2800_bbp_write(rt2x00dev, 106, 0x03);
        else if (rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 106, 0x12);
        else
                rt2800_bbp_write(rt2x00dev, 106, 0x35);
 
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392))
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
                rt2800_bbp_write(rt2x00dev, 128, 0x12);
 
        if (rt2x00_rt(rt2x00dev, RT5392)) {
@@ -3357,6 +3488,29 @@ 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, BBP47_TSSI_ADC6, 1);
+               rt2800_bbp_write(rt2x00dev, 47, value);
+
+               /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
+               rt2800_bbp_read(rt2x00dev, 3, &value);
+               rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
+               rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
+               rt2800_bbp_write(rt2x00dev, 3, value);
+       }
+
        if (rt2x00_rt(rt2x00dev, RT5390) ||
                rt2x00_rt(rt2x00dev, RT5392)) {
                int ant, div_mode;
@@ -3489,6 +3643,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
        if (!rt2x00_rt(rt2x00dev, RT3070) &&
            !rt2x00_rt(rt2x00dev, RT3071) &&
            !rt2x00_rt(rt2x00dev, RT3090) &&
+           !rt2x00_rt(rt2x00dev, RT3290) &&
            !rt2x00_rt(rt2x00dev, RT3390) &&
            !rt2x00_rt(rt2x00dev, RT3572) &&
            !rt2x00_rt(rt2x00dev, RT5390) &&
@@ -3499,8 +3654,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
        /*
         * Init RF calibration.
         */
-       if (rt2x00_rt(rt2x00dev, RT5390) ||
-               rt2x00_rt(rt2x00dev, RT5392)) {
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
                rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
                rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
@@ -3538,6 +3694,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
                rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
                rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
                rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+       } 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);
        } else if (rt2x00_rt(rt2x00dev, RT3390)) {
                rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
                rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
@@ -3946,6 +4149,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
                rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
        }
 
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
+               rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+       }
+
        if (rt2x00_rt(rt2x00dev, RT5390) ||
                rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
@@ -4052,9 +4261,14 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
 int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
+       u16 efuse_ctrl_reg;
 
-       rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               efuse_ctrl_reg = EFUSE_CTRL_3290;
+       else
+               efuse_ctrl_reg = EFUSE_CTRL;
 
+       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
        return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
 }
 EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -4062,27 +4276,44 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
 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;
+
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               efuse_ctrl_reg = EFUSE_CTRL_3290;
+               efuse_data0_reg = EFUSE_DATA0_3290;
+               efuse_data1_reg = EFUSE_DATA1_3290;
+               efuse_data2_reg = EFUSE_DATA2_3290;
+               efuse_data3_reg = EFUSE_DATA3_3290;
+       } else {
+               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;
+       }
        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);
@@ -4244,9 +4475,14 @@ 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
         */
-       rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-       if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
-               rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+       else
+               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+
+       if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 ||
+           rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
+           rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
                rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
        else
                value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
@@ -4261,6 +4497,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        case RT3070:
        case RT3071:
        case RT3090:
+       case RT3290:
        case RT3390:
        case RT3572:
        case RT5390:
@@ -4281,6 +4518,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        case RF3021:
        case RF3022:
        case RF3052:
+       case RF3290:
        case RF3320:
        case RF5360:
        case RF5370:
@@ -4597,6 +4835,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                   rt2x00_rf(rt2x00dev, RF2020) ||
                   rt2x00_rf(rt2x00dev, RF3021) ||
                   rt2x00_rf(rt2x00dev, RF3022) ||
+                  rt2x00_rf(rt2x00dev, RF3290) ||
                   rt2x00_rf(rt2x00dev, RF3320) ||
                   rt2x00_rf(rt2x00dev, RF5360) ||
                   rt2x00_rf(rt2x00dev, RF5370) ||
@@ -4685,6 +4924,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        case RF3022:
        case RF3320:
        case RF3052:
+       case RF3290:
        case RF5360:
        case RF5370:
        case RF5372:
index 206158b674268403aa46d237da3a81981a9b4bdd..dd436125fe3d3a175e18f3dffc5f73d0ba49f1a0 100644 (file)
@@ -280,7 +280,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
  */
 static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 {
-       return FIRMWARE_RT2860;
+       /*
+        * Chip rt3290 use specific 4KB firmware named rt3290.bin.
+        */
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               return FIRMWARE_RT3290;
+       else
+               return FIRMWARE_RT2860;
 }
 
 static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
@@ -974,6 +980,66 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        return rt2800_validate_eeprom(rt2x00dev);
 }
 
+static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       int i, count;
+
+       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+       if ((rt2x00_get_field32(reg, WLAN_EN) == 1))
+               return 0;
+
+       rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
+       rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
+       rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
+       rt2x00_set_field32(&reg, WLAN_EN, 1);
+       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+
+       udelay(REGISTER_BUSY_DELAY);
+
+       count = 0;
+       do {
+               /*
+                * Check PLL_LD & XTAL_RDY.
+                */
+               for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+                       rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+                       if ((rt2x00_get_field32(reg, PLL_LD) == 1) &&
+                               (rt2x00_get_field32(reg, XTAL_RDY) == 1))
+                                       break;
+                       udelay(REGISTER_BUSY_DELAY);
+               }
+
+               if (i >= REGISTER_BUSY_COUNT) {
+
+                       if (count >= 10)
+                               return -EIO;
+
+                       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);
+                       count++;
+               } else {
+                       count = 0;
+               }
+
+               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
+               rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
+               rt2x00_set_field32(&reg, WLAN_RESET, 1);
+               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+               udelay(10);
+               rt2x00_set_field32(&reg, WLAN_RESET, 0);
+               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+               udelay(10);
+               rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);
+       } while (count != 0);
+
+       return 0;
+}
 static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
@@ -996,6 +1062,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan
+        * clk for rt3290. That avoid the MCU fail in start phase.
+        */
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               retval = rt2800_enable_wlan_rt3290(rt2x00dev);
+
+               if (retval)
+                       return retval;
+       }
+
        /*
         * This device has multiple filters for control frames
         * and has a separate filter for PS Poll frames.
@@ -1175,6 +1252,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
        { PCI_DEVICE(0x1432, 0x7768) },
        { PCI_DEVICE(0x1462, 0x891a) },
        { PCI_DEVICE(0x1a3b, 0x1059) },
+#ifdef CONFIG_RT2800PCI_RT3290
+       { PCI_DEVICE(0x1814, 0x3290) },
+#endif
 #ifdef CONFIG_RT2800PCI_RT33XX
        { PCI_DEVICE(0x1814, 0x3390) },
 #endif
index 70e050d904c853c81973942d9526cbc7dc41635d..ab22a087c50dba15cf67b3ff237f8915bc8e2996 100644 (file)
@@ -47,6 +47,7 @@
  * 8051 firmware image.
  */
 #define FIRMWARE_RT2860                        "rt2860.bin"
+#define FIRMWARE_RT3290                        "rt3290.bin"
 #define FIRMWARE_IMAGE_BASE            0x2000
 
 /*
index 8f754025b06ead9b9a2c9d5be62d5d19b871690f..8afb546c2b2d3b1741be167969e7c04dcefb0239 100644 (file)
@@ -187,6 +187,7 @@ struct rt2x00_chip {
 #define RT3070         0x3070
 #define RT3071         0x3071
 #define RT3090         0x3090  /* 2.4GHz PCIe */
+#define RT3290         0x3290
 #define RT3390         0x3390
 #define RT3572         0x3572
 #define RT3593         0x3593
index 0a4653a92cab059f1dcfc18d6304c754df168fb6..a0c8caef3b0a8f3616a4dd4a71e6eebeb3b939ae 100644 (file)
@@ -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 chip;
 
        retval = pci_enable_device(pci_dev);
        if (retval) {
@@ -305,6 +306,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
        if (retval)
                goto exit_free_device;
 
+       /*
+        * Because rt3290 chip use different efuse offset to read efuse data.
+        * So before read efuse it need to indicate it is the
+        * rt3290 or not.
+        */
+       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
+       rt2x00dev->chip.rt = chip;
+
        retval = rt2x00lib_probe_dev(rt2x00dev);
        if (retval)
                goto exit_free_reg;