All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] rt2x00 : RT3290 chip support v4
@ 2012-06-13 10:13 Xose Vazquez Perez
  2012-06-18  9:16 ` [rt2x00-users] " Matt Chen
  0 siblings, 1 reply; 7+ messages in thread
From: Xose Vazquez Perez @ 2012-06-13 10:13 UTC (permalink / raw)
  To: linux-wireless, users, Woody.Hung

Woody Hung wrote:

> --- 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"

There is no rt3290 fw in linux-firmware [1]
Please, send it ASAP.

[1] http://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.git

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

* Re: [rt2x00-users] [PATCH] rt2x00 : RT3290 chip support v4
  2012-06-13 10:13 [PATCH] rt2x00 : RT3290 chip support v4 Xose Vazquez Perez
@ 2012-06-18  9:16 ` Matt Chen
  2012-06-18 16:22   ` Woody Hung (洪秋竹)
  0 siblings, 1 reply; 7+ messages in thread
From: Matt Chen @ 2012-06-18  9:16 UTC (permalink / raw)
  To: Xose Vazquez Perez; +Cc: linux-wireless, users, Woody.Hung

2012/6/13 Xose Vazquez Perez <xose.vazquez@gmail.com>:
> Woody Hung wrote:
>
>> --- 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"
>
>
> There is no rt3290 fw in linux-firmware [1]
> Please, send it ASAP.
Indeed, I found the firmware is only in
http://www.ralink.com.tw/en/04_support/support.php?sn=501, RT3290 PCIe
driver tar ball.

Hi Woody,
Please send the firmware to the linux-firmware ASAP. :)

> [1] http://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.git
>
>
> _______________________________________________
> users mailing list
> users@rt2x00.serialmonkey.com
> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com
>



-- 
Thank you.

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

* RE: [rt2x00-users] [PATCH] rt2x00 : RT3290 chip support v4
  2012-06-18  9:16 ` [rt2x00-users] " Matt Chen
@ 2012-06-18 16:22   ` Woody Hung (洪秋竹)
  2012-06-19  3:28     ` Matt Chen
  0 siblings, 1 reply; 7+ messages in thread
From: Woody Hung (洪秋竹) @ 2012-06-18 16:22 UTC (permalink / raw)
  To: Matt Chen, Xose Vazquez Perez; +Cc: linux-wireless, users

RGVhciBBbGw6DQoNCglJIGhhdmUgc2VuZCBpdCB0byB0aGUgaHR0cDovL2dpdC5rZXJuZWwub3Jn
Lz9wPWxpbnV4L2tlcm5lbC9naXQvZmlybXdhcmUvbGludXgtZmlybXdhcmUuZ2l0Lg0KCUFuZCBp
dCBoYXZlIGJlZW4gYXBwbGllZCAzIGRheXMgYWdvLg0KCVBsZWFzZSBzZWUgdGhlIHNob3J0IGxv
ZyAicnQyODAwcGNpOkZpcm13YXJlIHVwZGF0ZSB2MSIuDQoJRG8gSSBtaXNzIHNvbWV0aGluZyBv
ciBzb21lIHJ1bGUgSSBuZWVkIHRvIGZvbGxvdz8/Pw0KDQpCUiwNCldvb2R5IEh1bmcNCi0tLS0t
T3JpZ2luYWwgTWVzc2FnZS0tLS0tDQpGcm9tOiBNYXR0IENoZW4gW21haWx0bzptYWNoZW5Ac3Vz
ZS5jb21dIA0KU2VudDogTW9uZGF5LCBKdW5lIDE4LCAyMDEyIDU6MTcgUE0NClRvOiBYb3NlIFZh
enF1ZXogUGVyZXoNCkNjOiBsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmc7IHVzZXJzQHJ0
MngwMC5zZXJpYWxtb25rZXkuY29tOyBXb29keSBIdW5nICjmtKrnp4vnq7kpDQpTdWJqZWN0OiBS
ZTogW3J0MngwMC11c2Vyc10gW1BBVENIXSBydDJ4MDAgOiBSVDMyOTAgY2hpcCBzdXBwb3J0IHY0
DQoNCjIwMTIvNi8xMyBYb3NlIFZhenF1ZXogUGVyZXogPHhvc2UudmF6cXVlekBnbWFpbC5jb20+
Og0KPiBXb29keSBIdW5nIHdyb3RlOg0KPg0KPj4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
cnQyeDAwL3J0MjgwMHBjaS5oDQo+PiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAv
cnQyODAwcGNpLmgNCj4+IEBAIC00Nyw2ICs0Nyw3IEBADQo+PiDCoCogODA1MSBmaXJtd2FyZSBp
bWFnZS4NCj4+IMKgKi8NCj4+IMKgI2RlZmluZSBGSVJNV0FSRV9SVDI4NjAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAicnQyODYwLmJpbiINCj4+ICsjZGVmaW5lIEZJUk1XQVJF
X1JUMzI5MCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCJydDMyOTAuYmluIg0K
Pg0KPg0KPiBUaGVyZSBpcyBubyBydDMyOTAgZncgaW4gbGludXgtZmlybXdhcmUgWzFdIFBsZWFz
ZSwgc2VuZCBpdCBBU0FQLg0KSW5kZWVkLCBJIGZvdW5kIHRoZSBmaXJtd2FyZSBpcyBvbmx5IGlu
DQpodHRwOi8vd3d3LnJhbGluay5jb20udHcvZW4vMDRfc3VwcG9ydC9zdXBwb3J0LnBocD9zbj01
MDEsIFJUMzI5MCBQQ0llIGRyaXZlciB0YXIgYmFsbC4NCg0KSGkgV29vZHksDQpQbGVhc2Ugc2Vu
ZCB0aGUgZmlybXdhcmUgdG8gdGhlIGxpbnV4LWZpcm13YXJlIEFTQVAuIDopDQoNCj4gWzFdIA0K
PiBodHRwOi8vZ2l0Lmtlcm5lbC5vcmcvP3A9bGludXgva2VybmVsL2dpdC9maXJtd2FyZS9saW51
eC1maXJtd2FyZS5naXQNCj4NCj4NCj4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX18NCj4gdXNlcnMgbWFpbGluZyBsaXN0DQo+IHVzZXJzQHJ0MngwMC5zZXJp
YWxtb25rZXkuY29tDQo+IGh0dHA6Ly9ydDJ4MDAuc2VyaWFsbW9ua2V5LmNvbS9tYWlsbWFuL2xp
c3RpbmZvL3VzZXJzX3J0MngwMC5zZXJpYWxtb24NCj4ga2V5LmNvbQ0KPg0KDQoNCg0KLS0NClRo
YW5rIHlvdS4NCgoqKioqKioqKioqKioqIEVtYWlsIENvbmZpZGVudGlhbGl0eSBOb3RpY2UgKioq
KioqKioqKioqKioqKioqKioNClRoZSBpbmZvcm1hdGlvbiBjb250YWluZWQgaW4gdGhpcyBlLW1h
aWwgbWVzc2FnZSAoaW5jbHVkaW5nIGFueSANCmF0dGFjaG1lbnRzKSBtYXkgYmUgY29uZmlkZW50
aWFsLCBwcm9wcmlldGFyeSwgcHJpdmlsZWdlZCwgb3Igb3RoZXJ3aXNlDQpleGVtcHQgZnJvbSBk
aXNjbG9zdXJlIHVuZGVyIGFwcGxpY2FibGUgbGF3cy4gSXQgaXMgaW50ZW5kZWQgdG8gYmUgDQpj
b252ZXllZCBvbmx5IHRvIHRoZSBkZXNpZ25hdGVkIHJlY2lwaWVudChzKS4gQW55IHVzZSwgZGlz
c2VtaW5hdGlvbiwgDQpkaXN0cmlidXRpb24sIHByaW50aW5nLCByZXRhaW5pbmcgb3IgY29weWlu
ZyBvZiB0aGlzIGUtbWFpbCAoaW5jbHVkaW5nIGl0cyANCmF0dGFjaG1lbnRzKSBieSB1bmludGVu
ZGVkIHJlY2lwaWVudChzKSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkIGFuZCBtYXkgDQpiZSB1bmxh
d2Z1bC4gSWYgeW91IGFyZSBub3QgYW4gaW50ZW5kZWQgcmVjaXBpZW50IG9mIHRoaXMgZS1tYWls
LCBvciBiZWxpZXZlIA0KdGhhdCB5b3UgaGF2ZSByZWNlaXZlZCB0aGlzIGUtbWFpbCBpbiBlcnJv
ciwgcGxlYXNlIG5vdGlmeSB0aGUgc2VuZGVyIA0KaW1tZWRpYXRlbHkgKGJ5IHJlcGx5aW5nIHRv
IHRoaXMgZS1tYWlsKSwgZGVsZXRlIGFueSBhbmQgYWxsIGNvcGllcyBvZiANCnRoaXMgZS1tYWls
IChpbmNsdWRpbmcgYW55IGF0dGFjaG1lbnRzKSBmcm9tIHlvdXIgc3lzdGVtLCBhbmQgZG8gbm90
DQpkaXNjbG9zZSB0aGUgY29udGVudCBvZiB0aGlzIGUtbWFpbCB0byBhbnkgb3RoZXIgcGVyc29u
LiBUaGFuayB5b3Uh


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

* Re: [rt2x00-users] [PATCH] rt2x00 : RT3290 chip support v4
  2012-06-18 16:22   ` Woody Hung (洪秋竹)
@ 2012-06-19  3:28     ` Matt Chen
  0 siblings, 0 replies; 7+ messages in thread
From: Matt Chen @ 2012-06-19  3:28 UTC (permalink / raw)
  To: Woody Hung (洪秋竹)
  Cc: Xose Vazquez Perez, linux-wireless, users

Hi Woody,

2012/6/19 Woody Hung (洪秋竹) <woody.hung@mediatek.com>:
> Dear All:
>
>        I have send it to the http://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.git.
>        And it have been applied 3 days ago.
>        Please see the short log "rt2800pci:Firmware update v1".
>        Do I miss something or some rule I need to follow???
I see. I found it in the
http://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.git.
I tested this patch and firmware, it works fine to me here. :)
> BR,
> Woody Hung
> -----Original Message-----
> From: Matt Chen [mailto:machen@suse.com]
> Sent: Monday, June 18, 2012 5:17 PM
> To: Xose Vazquez Perez
> Cc: linux-wireless@vger.kernel.org; users@rt2x00.serialmonkey.com; Woody Hung (洪秋竹)
> Subject: Re: [rt2x00-users] [PATCH] rt2x00 : RT3290 chip support v4
>
> 2012/6/13 Xose Vazquez Perez <xose.vazquez@gmail.com>:
>> Woody Hung wrote:
>>
>>> --- 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"
>>
>>
>> There is no rt3290 fw in linux-firmware [1] Please, send it ASAP.
> Indeed, I found the firmware is only in
> http://www.ralink.com.tw/en/04_support/support.php?sn=501, RT3290 PCIe driver tar ball.
>
> Hi Woody,
> Please send the firmware to the linux-firmware ASAP. :)
>
>> [1]
>> http://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.git
>>
>>
>> _______________________________________________
>> users mailing list
>> users@rt2x00.serialmonkey.com
>> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmon
>> key.com
>>
>
>
>
> --
> Thank you.
>


-- 
Thank you.

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

* Re: [PATCH] rt2x00 : RT3290 chip support v4
  2012-06-22  7:45 ` Helmut Schaa
@ 2012-06-22 11:18   ` Gertjan van Wingerde
  0 siblings, 0 replies; 7+ messages in thread
From: Gertjan van Wingerde @ 2012-06-22 11:18 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Woody Hung, linville, linux-wireless, users

On 06/22/12 09:45, Helmut Schaa wrote:
> Hi Woody,
> 
> sorry for reviweing this so late but haven't found time before :/
> Please find my comments inlined in the patch.
> 
> Helmut

Hi Helmut, Woody,

I noticed that John has already applied this v4 of the patch to his
tree, probably due to us (the maintainers) being very slow on reviewing it.

Therefore I suggest that any changes that are the result of Helmut's
comments are submitted as incremental patches on top of John's latest tree.

---
Gertjan


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

* Re: [PATCH] rt2x00 : RT3290 chip support v4
  2012-06-13  7:01 Woody Hung
@ 2012-06-22  7:45 ` Helmut Schaa
  2012-06-22 11:18   ` Gertjan van Wingerde
  0 siblings, 1 reply; 7+ messages in thread
From: Helmut Schaa @ 2012-06-22  7:45 UTC (permalink / raw)
  To: Woody Hung; +Cc: linville, linux-wireless, users

Hi Woody,

sorry for reviweing this so late but haven't found time before :/
Please find my comments inlined in the patch.

Helmut

On Wed, Jun 13, 2012 at 9:01 AM, Woody Hung <Woody.Hung@mediatek.com> wrote:
> 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>
> ---
>  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)

Nitpicking: Could use a newline here.

> +/*
> + * 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)

This change has nothing to do with 3290 support, so please keep the code as is.

>  #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;

The "multiple" variable seems superfluous now and could be removed
completely but
in general your cleanup seems unrelated to the introduction of RT3290
support and should
go in via its own patch.

>        /*
>         * 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

Any reason why we cannot reuse the existing defines as they seem to be equal?
Maybe we could just remove the prefix?

> +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);

What has this todo with RT3290 support? Won't it cause problems on 53xx devices?
If it's a fix for 5xxx devices it should be in a separate patch.

>  }
>
>  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);
> +       }
> +

Same here, since this affects more then just the 3290 devices it should go in
on its own with a clear commit message why this is needed.

>        /*
>         * 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) {

You could just drop the "== 1" part.

> +                       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)) {

You could just drop the "== 1" part.

> +                       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);

Mind to introduce a register define for 0x58 and the according fields?

> +                       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
>
> --
> 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] 7+ messages in thread

* [PATCH] rt2x00 : RT3290 chip support v4
@ 2012-06-13  7:01 Woody Hung
  2012-06-22  7:45 ` Helmut Schaa
  0 siblings, 1 reply; 7+ messages in thread
From: Woody Hung @ 2012-06-13  7:01 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, users, Woody Hung

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>
---
 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


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

end of thread, other threads:[~2012-06-22 11:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-13 10:13 [PATCH] rt2x00 : RT3290 chip support v4 Xose Vazquez Perez
2012-06-18  9:16 ` [rt2x00-users] " Matt Chen
2012-06-18 16:22   ` Woody Hung (洪秋竹)
2012-06-19  3:28     ` Matt Chen
  -- strict thread matches above, loose matches on Subject: below --
2012-06-13  7:01 Woody Hung
2012-06-22  7:45 ` Helmut Schaa
2012-06-22 11:18   ` Gertjan van Wingerde

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.