Tested-by: Matt Chen <machen@xxxxxxx> 2012/6/13 Woody Hung <Woody.Hung@xxxxxxxxxxxx>: > This patch support the new chipset rt3290 wifi implementation in rt2x00. > It initailize the related mac, bbp and rf register in startup phase. > And this patch modify the efuse read/write method for the different efuse data offset of rt3290. > > Signed-off-by: Woody Hung <Woody.Hung@xxxxxxxxxxxx> > --- > drivers/net/wireless/rt2x00/Kconfig | 8 + > drivers/net/wireless/rt2x00/rt2800.h | 173 +++++++++++++++- > drivers/net/wireless/rt2x00/rt2800lib.c | 350 ++++++++++++++++++++++++++----- > drivers/net/wireless/rt2x00/rt2800pci.c | 82 +++++++- > drivers/net/wireless/rt2x00/rt2800pci.h | 1 + > drivers/net/wireless/rt2x00/rt2x00.h | 1 + > drivers/net/wireless/rt2x00/rt2x00pci.c | 9 + > 7 files changed, 567 insertions(+), 57 deletions(-) > > diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig > index 299c387..c7548da 100644 > --- a/drivers/net/wireless/rt2x00/Kconfig > +++ b/drivers/net/wireless/rt2x00/Kconfig > @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX > rt2800pci driver. > Supported chips: RT5390 > > +config RT2800PCI_RT3290 > + bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)" > + depends on EXPERIMENTAL > + default y > + ---help--- > + This adds support for rt3290 wireless chipset family to the > + rt2800pci driver. > + Supported chips: RT3290 > endif > > config RT2500USB > diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h > index 1ca88cd..e252e9b 100644 > --- a/drivers/net/wireless/rt2x00/rt2800.h > +++ b/drivers/net/wireless/rt2x00/rt2800.h > @@ -68,6 +68,7 @@ > #define RF3320 0x000b > #define RF3322 0x000c > #define RF3053 0x000d > +#define RF3290 0x3290 > #define RF5360 0x5360 > #define RF5370 0x5370 > #define RF5372 0x5372 > @@ -117,6 +118,12 @@ > * Registers. > */ > > + > +/* > + * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. > + */ > +#define MAC_CSR0_3290 0x0000 > + > /* > * E2PROM_CSR: PCI EEPROM control register. > * RELOAD: Write 1 to reload eeprom content. > @@ -133,6 +140,150 @@ > #define E2PROM_CSR_RELOAD FIELD32(0x00000080) > > /* > + * CMB_CTRL_CFG > + */ > +#define CMB_CTRL 0x0020 > +#define AUX_OPT_BIT0 FIELD32(0x00000001) > +#define AUX_OPT_BIT1 FIELD32(0x00000002) > +#define AUX_OPT_BIT2 FIELD32(0x00000004) > +#define AUX_OPT_BIT3 FIELD32(0x00000008) > +#define AUX_OPT_BIT4 FIELD32(0x00000010) > +#define AUX_OPT_BIT5 FIELD32(0x00000020) > +#define AUX_OPT_BIT6 FIELD32(0x00000040) > +#define AUX_OPT_BIT7 FIELD32(0x00000080) > +#define AUX_OPT_BIT8 FIELD32(0x00000100) > +#define AUX_OPT_BIT9 FIELD32(0x00000200) > +#define AUX_OPT_BIT10 FIELD32(0x00000400) > +#define AUX_OPT_BIT11 FIELD32(0x00000800) > +#define AUX_OPT_BIT12 FIELD32(0x00001000) > +#define AUX_OPT_BIT13 FIELD32(0x00002000) > +#define AUX_OPT_BIT14 FIELD32(0x00004000) > +#define AUX_OPT_BIT15 FIELD32(0x00008000) > +#define LDO25_LEVEL FIELD32(0x00030000) > +#define LDO25_LARGEA FIELD32(0x00040000) > +#define LDO25_FRC_ON FIELD32(0x00080000) > +#define CMB_RSV FIELD32(0x00300000) > +#define XTAL_RDY FIELD32(0x00400000) > +#define PLL_LD FIELD32(0x00800000) > +#define LDO_CORE_LEVEL FIELD32(0x0F000000) > +#define LDO_BGSEL FIELD32(0x30000000) > +#define LDO3_EN FIELD32(0x40000000) > +#define LDO0_EN FIELD32(0x80000000) > + > +/* > + * EFUSE_CSR_3290: RT3290 EEPROM > + */ > +#define EFUSE_CTRL_3290 0x0024 > + > +/* > + * EFUSE_DATA3 of 3290 > + */ > +#define EFUSE_DATA3_3290 0x0028 > + > +/* > + * EFUSE_DATA2 of 3290 > + */ > +#define EFUSE_DATA2_3290 0x002c > + > +/* > + * EFUSE_DATA1 of 3290 > + */ > +#define EFUSE_DATA1_3290 0x0030 > + > +/* > + * EFUSE_DATA0 of 3290 > + */ > +#define EFUSE_DATA0_3290 0x0034 > + > +/* > + * OSC_CTRL_CFG > + * Ring oscillator configuration > + */ > +#define OSC_CTRL 0x0038 > +#define OSC_REF_CYCLE FIELD32(0x00001fff) > +#define OSC_RSV FIELD32(0x0000e000) > +#define OSC_CAL_CNT FIELD32(0x0fff0000) > +#define OSC_CAL_ACK FIELD32(0x10000000) > +#define OSC_CLK_32K_VLD FIELD32(0x20000000) > +#define OSC_CAL_REQ FIELD32(0x40000000) > +#define OSC_ROSC_EN FIELD32(0x80000000) > + > +/* > + * COEX_CFG_0 > + */ > +#define COEX_CFG0 0x0040 > +#define COEX_CFG_ANT FIELD32(0xff000000) > +/* > + * COEX_CFG_1 > + */ > +#define COEX_CFG1 0x0044 > + > +/* > + * COEX_CFG_2 > + */ > +#define COEX_CFG2 0x0048 > +#define BT_COEX_CFG1 FIELD32(0xff000000) > +#define BT_COEX_CFG0 FIELD32(0x00ff0000) > +#define WL_COEX_CFG1 FIELD32(0x0000ff00) > +#define WL_COEX_CFG0 FIELD32(0x000000ff) > +/* > + * PLL_CTRL_CFG > + * PLL configuration register > + */ > +#define PLL_CTRL 0x0050 > +#define PLL_RESERVED_INPUT1 FIELD32(0x000000ff) > +#define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) > +#define PLL_CONTROL FIELD32(0x00070000) > +#define PLL_LPF_R1 FIELD32(0x00080000) > +#define PLL_LPF_C1_CTRL FIELD32(0x00300000) > +#define PLL_LPF_C2_CTRL FIELD32(0x00c00000) > +#define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) > +#define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) > +#define PLL_LOCK_CTRL FIELD32(0x70000000) > +#define PLL_VBGBK_EN FIELD32(0x80000000) > + > + > +/* > + * WLAN_CTRL_CFG > + * RT3290 wlan configuration > + */ > +#define WLAN_FUN_CTRL 0x0080 > +#define WLAN_EN FIELD32(0x00000001) > +#define WLAN_CLK_EN FIELD32(0x00000002) > +#define WLAN_RSV1 FIELD32(0x00000004) > +#define WLAN_RESET FIELD32(0x00000008) > +#define PCIE_APP0_CLK_REQ FIELD32(0x00000010) > +#define FRC_WL_ANT_SET FIELD32(0x00000020) > +#define INV_TR_SW0 FIELD32(0x00000040) > +#define WLAN_GPIO_IN_BIT0 FIELD32(0x00000100) > +#define WLAN_GPIO_IN_BIT1 FIELD32(0x00000200) > +#define WLAN_GPIO_IN_BIT2 FIELD32(0x00000400) > +#define WLAN_GPIO_IN_BIT3 FIELD32(0x00000800) > +#define WLAN_GPIO_IN_BIT4 FIELD32(0x00001000) > +#define WLAN_GPIO_IN_BIT5 FIELD32(0x00002000) > +#define WLAN_GPIO_IN_BIT6 FIELD32(0x00004000) > +#define WLAN_GPIO_IN_BIT7 FIELD32(0x00008000) > +#define WLAN_GPIO_IN_BIT_ALL FIELD32(0x0000ff00) > +#define WLAN_GPIO_OUT_BIT0 FIELD32(0x00010000) > +#define WLAN_GPIO_OUT_BIT1 FIELD32(0x00020000) > +#define WLAN_GPIO_OUT_BIT2 FIELD32(0x00040000) > +#define WLAN_GPIO_OUT_BIT3 FIELD32(0x00050000) > +#define WLAN_GPIO_OUT_BIT4 FIELD32(0x00100000) > +#define WLAN_GPIO_OUT_BIT5 FIELD32(0x00200000) > +#define WLAN_GPIO_OUT_BIT6 FIELD32(0x00400000) > +#define WLAN_GPIO_OUT_BIT7 FIELD32(0x00800000) > +#define WLAN_GPIO_OUT_BIT_ALL FIELD32(0x00ff0000) > +#define WLAN_GPIO_OUT_OE_BIT0 FIELD32(0x01000000) > +#define WLAN_GPIO_OUT_OE_BIT1 FIELD32(0x02000000) > +#define WLAN_GPIO_OUT_OE_BIT2 FIELD32(0x04000000) > +#define WLAN_GPIO_OUT_OE_BIT3 FIELD32(0x08000000) > +#define WLAN_GPIO_OUT_OE_BIT4 FIELD32(0x10000000) > +#define WLAN_GPIO_OUT_OE_BIT5 FIELD32(0x20000000) > +#define WLAN_GPIO_OUT_OE_BIT6 FIELD32(0x40000000) > +#define WLAN_GPIO_OUT_OE_BIT7 FIELD32(0x80000000) > +#define WLAN_GPIO_OUT_OE_BIT_ALL FIELD32(0xff000000) > + > +/* > * AUX_CTRL: Aux/PCI-E related configuration > */ > #define AUX_CTRL 0x10c > @@ -1763,9 +1914,11 @@ struct mac_iveiv_entry { > /* > * BBP 3: RX Antenna > */ > -#define BBP3_RX_ADC FIELD8(0x03) > +#define BBP3_RX_ADC FIELD8(0x03) > #define BBP3_RX_ANTENNA FIELD8(0x18) > #define BBP3_HT40_MINUS FIELD8(0x20) > +#define BBP3_ADC_MODE_SWITCH FIELD8(0x40) > +#define BBP3_ADC_INIT_MODE FIELD8(0x80) > > /* > * BBP 4: Bandwidth > @@ -1775,6 +1928,14 @@ struct mac_iveiv_entry { > #define BBP4_MAC_IF_CTRL FIELD8(0x40) > > /* > + * BBP 47: Bandwidth > + */ > +#define BBP47_TSSI_REPORT_SEL FIELD8(0x03) > +#define BBP47_TSSI_UPDATE_REQ FIELD8(0x04) > +#define BBP47_TSSI_TSSI_MODE FIELD8(0x18) > +#define BBP47_TSSI_ADC6 FIELD8(0x80) > + > +/* > * BBP 109 > */ > #define BBP109_TX0_POWER FIELD8(0x0f) > @@ -1917,6 +2078,16 @@ struct mac_iveiv_entry { > #define RFCSR27_R4 FIELD8(0x40) > > /* > + * RFCSR 29: > + */ > +#define RFCSR29_ADC6_TEST FIELD8(0x01) > +#define RFCSR29_ADC6_INT_TEST FIELD8(0x02) > +#define RFCSR29_RSSI_RESET FIELD8(0x04) > +#define RFCSR29_RSSI_ON FIELD8(0x08) > +#define RFCSR29_RSSI_RIP_CTRL FIELD8(0x30) > +#define RFCSR29_RSSI_GAIN FIELD8(0xc0) > + > +/* > * RFCSR 30: > */ > #define RFCSR30_TX_H20M FIELD8(0x02) > diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c > index 4d3747c..068276e 100644 > --- a/drivers/net/wireless/rt2x00/rt2800lib.c > +++ b/drivers/net/wireless/rt2x00/rt2800lib.c > @@ -354,16 +354,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, > * of 4kb. Certain USB chipsets however require different firmware, > * which Ralink only provides attached to the original firmware > * file. Thus for USB devices, firmware files have a length > - * which is a multiple of 4kb. > + * which is a multiple of 4kb. The firmware for rt3290 chip also > + * have a length which is a multiple of 4kb. > */ > - if (rt2x00_is_usb(rt2x00dev)) { > + if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290)) > fw_len = 4096; > - multiple = true; > - } else { > + else > fw_len = 8192; > - multiple = true; > - } > > + multiple = true; > /* > * Validate the firmware length > */ > @@ -415,7 +414,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, > return -EBUSY; > > if (rt2x00_is_pci(rt2x00dev)) { > - if (rt2x00_rt(rt2x00dev, RT3572) || > + if (rt2x00_rt(rt2x00dev, RT3290) || > + rt2x00_rt(rt2x00dev, RT3572) || > rt2x00_rt(rt2x00dev, RT5390) || > rt2x00_rt(rt2x00dev, RT5392)) { > rt2800_register_read(rt2x00dev, AUX_CTRL, ®); > @@ -851,8 +851,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev) > { > u32 reg; > > - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); > - return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); > + if (rt2x00_rt(rt2x00dev, RT3290)) { > + rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); > + return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); > + } else { > + rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); > + 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(®, 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, ®); > + if (rt2x00_get_field32(reg, WLAN_EN) == 1) { > + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); > + if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { > + rt2x00_set_field32(®, LDO0_EN, 1); > + rt2x00_set_field32(®, LDO_BGSEL, 3); > + rt2800_register_write(rt2x00dev, CMB_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, OSC_CTRL, ®); > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > + rt2x00_set_field32(®, OSC_CAL_REQ, 1); > + rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > + > + rt2800_register_read(rt2x00dev, COEX_CFG0, ®); > + rt2x00_set_field32(®, COEX_CFG_ANT, 0x5e); > + rt2800_register_write(rt2x00dev, COEX_CFG0, reg); > + > + rt2800_register_read(rt2x00dev, COEX_CFG2, ®); > + rt2x00_set_field32(®, BT_COEX_CFG1, 0x00); > + rt2x00_set_field32(®, BT_COEX_CFG0, 0x17); > + rt2x00_set_field32(®, WL_COEX_CFG1, 0x93); > + rt2x00_set_field32(®, WL_COEX_CFG0, 0x7f); > + rt2800_register_write(rt2x00dev, COEX_CFG2, reg); > + > + rt2800_register_read(rt2x00dev, PLL_CTRL, ®); > + rt2x00_set_field32(®, 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, ®); > + if (rt2x00_rt(rt2x00dev, RT3290)) > + efuse_ctrl_reg = EFUSE_CTRL_3290; > + else > + efuse_ctrl_reg = EFUSE_CTRL; > > + rt2800_register_read(rt2x00dev, efuse_ctrl_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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); > rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); > rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); > rt2x00_set_field32(®, 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, ®); > - > + rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); > /* Apparently the data is read from end to start */ > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data3_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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data0_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, ®); > - 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, ®); > + else > + rt2800_register_read(rt2x00dev, MAC_CSR0, ®); > + > + 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, ®); > + if ((rt2x00_get_field32(reg, WLAN_EN) == 1)) > + return 0; > + > + rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); > + rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); > + rt2x00_set_field32(®, WLAN_CLK_EN, 0); > + rt2x00_set_field32(®, 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, ®); > + 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, ®); > + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); > + rt2x00_set_field32(®, WLAN_CLK_EN, 1); > + rt2x00_set_field32(®, WLAN_RESET, 1); > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > + udelay(10); > + rt2x00_set_field32(®, WLAN_RESET, 0); > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > + udelay(10); > + rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); > + } while (count != 0); > + > + return 0; > +} > static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) > { > int retval; > @@ -997,6 +1063,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) > return retval; > > /* > + * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan > + * clk for rt3290. That avoid the MCU fail in start phase. > + */ > + if (rt2x00_rt(rt2x00dev, RT3290)) { > + retval = rt2800_enable_wlan_rt3290(rt2x00dev); > + > + if (retval) > + return retval; > + } > + > + /* > * This device has multiple filters for control frames > * and has a separate filter for PS Poll frames. > */ > @@ -1175,6 +1252,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { > { PCI_DEVICE(0x1432, 0x7768) }, > { PCI_DEVICE(0x1462, 0x891a) }, > { PCI_DEVICE(0x1a3b, 0x1059) }, > +#ifdef CONFIG_RT2800PCI_RT3290 > + { PCI_DEVICE(0x1814, 0x3290) }, > +#endif > #ifdef CONFIG_RT2800PCI_RT33XX > { PCI_DEVICE(0x1814, 0x3390) }, > #endif > diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h > index 70e050d..ab22a08 100644 > --- a/drivers/net/wireless/rt2x00/rt2800pci.h > +++ b/drivers/net/wireless/rt2x00/rt2800pci.h > @@ -47,6 +47,7 @@ > * 8051 firmware image. > */ > #define FIRMWARE_RT2860 "rt2860.bin" > +#define FIRMWARE_RT3290 "rt3290.bin" > #define FIRMWARE_IMAGE_BASE 0x2000 > > /* > diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h > index 8f75402..8afb546 100644 > --- a/drivers/net/wireless/rt2x00/rt2x00.h > +++ b/drivers/net/wireless/rt2x00/rt2x00.h > @@ -187,6 +187,7 @@ struct rt2x00_chip { > #define RT3070 0x3070 > #define RT3071 0x3071 > #define RT3090 0x3090 /* 2.4GHz PCIe */ > +#define RT3290 0x3290 > #define RT3390 0x3390 > #define RT3572 0x3572 > #define RT3593 0x3593 > diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c > index 0a4653a..a0c8cae 100644 > --- a/drivers/net/wireless/rt2x00/rt2x00pci.c > +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c > @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) > struct ieee80211_hw *hw; > struct rt2x00_dev *rt2x00dev; > int retval; > + u16 chip; > > retval = pci_enable_device(pci_dev); > if (retval) { > @@ -305,6 +306,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) > if (retval) > goto exit_free_device; > > + /* > + * Because rt3290 chip use different efuse offset to read efuse data. > + * So before read efuse it need to indicate it is the > + * rt3290 or not. > + */ > + pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); > + rt2x00dev->chip.rt = chip; > + > retval = rt2x00lib_probe_dev(rt2x00dev); > if (retval) > goto exit_free_reg; > -- > 1.7.5.4 > > > _______________________________________________ > users mailing list > users@xxxxxxxxxxxxxxxxxxxxxxx > http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com > -- Thank you. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html