Search Linux Wireless

Re: [rt2x00-users] [PATCH] rt2x00 : RT3290 chip support v4

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



CC to maintainers.

2012/6/21 Matt Chen <machen@xxxxxxxx>:
> Tested-by: Matt Chen <machen@xxxxxxx>
>
> 2012/6/13 Woody Hung <Woody.Hung@xxxxxxxxxxxx>:
>> 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@xxxxxxxxxxxx>
>> ---
>>  drivers/net/wireless/rt2x00/Kconfig     |    8 +
>>  drivers/net/wireless/rt2x00/rt2800.h    |  173 +++++++++++++++-
>>  drivers/net/wireless/rt2x00/rt2800lib.c |  350 ++++++++++++++++++++++++++-----
>>  drivers/net/wireless/rt2x00/rt2800pci.c |   82 +++++++-
>>  drivers/net/wireless/rt2x00/rt2800pci.h |    1 +
>>  drivers/net/wireless/rt2x00/rt2x00.h    |    1 +
>>  drivers/net/wireless/rt2x00/rt2x00pci.c |    9 +
>>  7 files changed, 567 insertions(+), 57 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 1ca88cd..e252e9b 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800.h
>> +++ b/drivers/net/wireless/rt2x00/rt2800.h
>> @@ -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
>> @@ -117,6 +118,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.
>> @@ -133,6 +140,150 @@
>>  #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
>>  */
>>  #define AUX_CTRL                       0x10c
>> @@ -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
>> @@ -1775,6 +1928,14 @@ struct mac_iveiv_entry {
>>  #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
>>  */
>>  #define BBP109_TX0_POWER               FIELD8(0x0f)
>> @@ -1917,6 +2078,16 @@ struct mac_iveiv_entry {
>>  #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:
>>  */
>>  #define RFCSR30_TX_H20M                        FIELD8(0x02)
>> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
>> index 4d3747c..068276e 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
>> @@ -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:
>> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
>> index 206158b..dd43612 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
>> @@ -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;
>> @@ -997,6 +1063,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
>>                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
>> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
>> index 70e050d..ab22a08 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800pci.h
>> +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
>> @@ -47,6 +47,7 @@
>>  * 8051 firmware image.
>>  */
>>  #define FIRMWARE_RT2860                        "rt2860.bin"
>> +#define FIRMWARE_RT3290                        "rt3290.bin"
>>  #define FIRMWARE_IMAGE_BASE            0x2000
>>
>>  /*
>> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
>> index 8f75402..8afb546 100644
>> --- a/drivers/net/wireless/rt2x00/rt2x00.h
>> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
>> @@ -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
>> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
>> index 0a4653a..a0c8cae 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 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;
>> --
>> 1.7.5.4
>>
>>
>> _______________________________________________
>> users mailing list
>> users@xxxxxxxxxxxxxxxxxxxxxxx
>> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com
>>
>
>
>
> --
> Thank you.



-- 
Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux