diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 381 | 
1 files changed, 287 insertions, 94 deletions
| diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2a6aa85cc6c9..ef67f6786a84 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -401,7 +401,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  		return -EBUSY;  	if (rt2x00_is_pci(rt2x00dev)) { -		if (rt2x00_rt(rt2x00dev, RT5390)) { +		if (rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT5390)) {  			rt2800_register_read(rt2x00dev, AUX_CTRL, ®);  			rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);  			rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); @@ -600,49 +601,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,  }  EXPORT_SYMBOL_GPL(rt2800_process_rxwi); -static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) -{ -	__le32 *txwi; -	u32 word; -	int wcid, ack, pid; -	int tx_wcid, tx_ack, tx_pid; - -	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); -	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); -	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - -	/* -	 * This frames has returned with an IO error, -	 * so the status report is not intended for this -	 * frame. -	 */ -	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { -		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); -		return false; -	} - -	/* -	 * Validate if this TX status report is intended for -	 * this entry by comparing the WCID/ACK/PID fields. -	 */ -	txwi = rt2800_drv_get_txwi(entry); - -	rt2x00_desc_read(txwi, 1, &word); -	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); -	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); -	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); - -	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { -		WARNING(entry->queue->rt2x00dev, -			"TX status report missed for queue %d entry %d\n", -		entry->queue->qid, entry->entry_idx); -		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); -		return false; -	} - -	return true; -} -  void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -725,45 +683,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  }  EXPORT_SYMBOL_GPL(rt2800_txdone_entry); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; -	struct queue_entry *entry; -	u32 reg; -	u8 qid; - -	while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { - -		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus -		 * qid is guaranteed to be one of the TX QIDs -		 */ -		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); -		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); -		if (unlikely(!queue)) { -			WARNING(rt2x00dev, "Got TX status for an unavailable " -					   "queue %u, dropping\n", qid); -			continue; -		} - -		/* -		 * Inside each queue, we process each entry in a chronological -		 * order. We first check that the queue is not empty. -		 */ -		entry = NULL; -		while (!rt2x00queue_empty(queue)) { -			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (rt2800_txdone_entry_check(entry, reg)) -				break; -		} - -		if (!entry || rt2x00queue_empty(queue)) -			break; - -		rt2800_txdone_entry(entry, reg); -	} -} -EXPORT_SYMBOL_GPL(rt2800_txdone); -  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -784,8 +703,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  	/*  	 * Add space for the TXWI in front of the skb.  	 */ -	skb_push(entry->skb, TXWI_DESC_SIZE); -	memset(entry->skb, 0, TXWI_DESC_SIZE); +	memset(skb_push(entry->skb, TXWI_DESC_SIZE), 0, TXWI_DESC_SIZE);  	/*  	 * Register descriptor details in skb frame descriptor. @@ -1355,7 +1273,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,  			gf20_rate = gf40_rate = 0x0003;  		}  		break; -	}; +	}  	/* check for STAs not supporting greenfield mode */  	if (any_sta_nongf) @@ -1433,6 +1351,40 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,  }  EXPORT_SYMBOL_GPL(rt2800_config_erp); +static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u16 eeprom; +	u8 led_ctrl, led_g_mode, led_r_mode; + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 1); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 1); +	} else { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 0); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 0); +	} +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_register_read(rt2x00dev, LED_CFG, ®); +	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0; +	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; +	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || +	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { +		rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); +		if (led_ctrl == 0 || led_ctrl > 0x40) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode); +			rt2800_register_write(rt2x00dev, LED_CFG, reg); +		} else { +			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff, +					   (led_g_mode << 2) | led_r_mode, 1); +		} +	} +} +  static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,  				     enum antenna ant)  { @@ -1463,6 +1415,10 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  	rt2800_bbp_read(rt2x00dev, 1, &r1);  	rt2800_bbp_read(rt2x00dev, 3, &r3); +	if (rt2x00_rt(rt2x00dev, RT3572) && +	    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +		rt2800_config_3572bt_ant(rt2x00dev); +  	/*  	 * Configure the TX antenna.  	 */ @@ -1471,7 +1427,11 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); +		else +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	case 3:  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); @@ -1496,7 +1456,15 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { +			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, +				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); +			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B); +		} else { +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		}  		break;  	case 3:  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); @@ -1630,6 +1598,161 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);  } +static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; +	u32 reg; + +	if (rf->channel <= 14) { +		rt2800_bbp_write(rt2x00dev, 25, 0x15); +		rt2800_bbp_write(rt2x00dev, 26, 0x85); +	} else { +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		rt2800_bbp_write(rt2x00dev, 26, 0xff); +	} + +	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2); +	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { +		if (rf->channel <= 14) { +			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		} +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +			break; +		} + +		switch (rt2x00dev->default_ant.rx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +			break; +		} +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); +	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 24, +			      rt2x00dev->calibration[conf_is_ht40(conf)]); +	rt2800_rfcsr_write(rt2x00dev, 31, +			      rt2x00dev->calibration[conf_is_ht40(conf)]); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 7, 0x14); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x43); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x7a); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		if (rf->channel <= 64) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +		} else if (rf->channel <= 128) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x74); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} else { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x72); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} +		rt2800_rfcsr_write(rt2x00dev, 26, 0x87); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); +	} + +	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT7, 0); +	if (rf->channel <= 14) +		rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 1); +	else +		rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 0); +	rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +}  #define RT5390_POWER_BOUND     0x27  #define RT5390_FREQ_OFFSET_BOUND       0x5f @@ -1748,9 +1871,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	    rt2x00_rf(rt2x00dev, RF3020) ||  	    rt2x00_rf(rt2x00dev, RF3021) ||  	    rt2x00_rf(rt2x00dev, RF3022) || -	    rt2x00_rf(rt2x00dev, RF3052) ||  	    rt2x00_rf(rt2x00dev, RF3320))  		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +	else if (rt2x00_rf(rt2x00dev, RF3052)) +		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);  	else if (rt2x00_rf(rt2x00dev, RF5370) ||  		 rt2x00_rf(rt2x00dev, RF5390))  		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); @@ -1777,7 +1901,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  			}  		}  	} else { -		rt2800_bbp_write(rt2x00dev, 82, 0xf2); +		if (rt2x00_rt(rt2x00dev, RT3572)) +			rt2800_bbp_write(rt2x00dev, 82, 0x94); +		else +			rt2800_bbp_write(rt2x00dev, 82, 0xf2);  		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))  			rt2800_bbp_write(rt2x00dev, 75, 0x46); @@ -1791,12 +1918,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);  	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0); +  	tx_pin = 0;  	/* Turn on unused PA or LNA when not using 1T or 1R */  	if (rt2x00dev->default_ant.tx_chain_num == 2) { -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, +				   rf->channel <= 14);  	}  	/* Turn on unused PA or LNA when not using 1T or 1R */ @@ -1809,11 +1941,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); +	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +	else +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, +				   rf->channel <= 14);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);  	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0x80); +  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));  	rt2800_bbp_write(rt2x00dev, 4, bbp); @@ -2413,6 +2552,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);  		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);  	} else if (rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -2799,6 +2941,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	}  	if (rt2800_is_305x_soc(rt2x00dev) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390))  		rt2800_bbp_write(rt2x00dev, 31, 0x08); @@ -2828,6 +2971,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	    rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) ||  	    rt2x00_rt(rt2x00dev, RT3390) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_bbp_write(rt2x00dev, 79, 0x13);  		rt2800_bbp_write(rt2x00dev, 80, 0x05); @@ -2868,6 +3012,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, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390) ||  	    rt2800_is_305x_soc(rt2x00dev))  		rt2800_bbp_write(rt2x00dev, 103, 0xc0); @@ -2895,6 +3040,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	if (rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) ||  	    rt2x00_rt(rt2x00dev, RT3390) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_bbp_read(rt2x00dev, 138, &value); @@ -3031,6 +3177,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rt(rt2x00dev, RT3071) &&  	    !rt2x00_rt(rt2x00dev, RT3090) &&  	    !rt2x00_rt(rt2x00dev, RT3390) && +	    !rt2x00_rt(rt2x00dev, RT3572) &&  	    !rt2x00_rt(rt2x00dev, RT5390) &&  	    !rt2800_is_305x_soc(rt2x00dev))  		return 0; @@ -3109,6 +3256,38 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);  		rt2800_rfcsr_write(rt2x00dev, 30, 0x20);  		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_write(rt2x00dev, 0, 0x70); +		rt2800_rfcsr_write(rt2x00dev, 1, 0x81); +		rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 3, 0x02); +		rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 5, 0x05); +		rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 12, 0x70); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x65); +		rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 18, 0xac); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); +		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); +		rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +		rt2800_rfcsr_write(rt2x00dev, 30, 0x09); +		rt2800_rfcsr_write(rt2x00dev, 31, 0x10);  	} else if (rt2800_is_305x_soc(rt2x00dev)) {  		rt2800_rfcsr_write(rt2x00dev, 0, 0x50);  		rt2800_rfcsr_write(rt2x00dev, 1, 0x01); @@ -3258,6 +3437,19 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);  		rt2x00_set_field32(®, GPIO_SWITCH_5, 0);  		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +		msleep(1); +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  	}  	/* @@ -3270,7 +3462,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);  	} else if (rt2x00_rt(rt2x00dev, RT3071) ||  		   rt2x00_rt(rt2x00dev, RT3090) || -		   rt2x00_rt(rt2x00dev, RT3390)) { +		   rt2x00_rt(rt2x00dev, RT3390) || +		   rt2x00_rt(rt2x00dev, RT3572)) {  		rt2x00dev->calibration[0] =  			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);  		rt2x00dev->calibration[1] = | 
