rt2x00: Fix radio off hang issue for PCIE interface
PATCH 1/2 rt2x00: Fix radio off hang issue for PCIE interface
From: RA-Jay Hung <[email protected]>
PCI/PCIE radio off behavior is different from SOC/USB.
They mainly use MCU command to disable DMA, TX/RX and enter power saving mode.
Signed-off-by RA-Jay Hung <[email protected]>
Signed-off-by Ivo van Doorn <[email protected]>
--- drivers/net/wireless/rt2x00/rt2800lib.c | 6 ----- drivers/net/wireless/rt2x00/rt2800pci.c | 36 ++++++++---------------------- 2 files changed, 10 insertions(+), 32 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +0 -6
@@ -2810,10 +2810,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)rt2800_register_read (rt2x00dev,WPDMA_GLO_CFG , ®);rt2x00_set_field32 (®,WPDMA_GLO_CFG_ENABLE_TX_DMA ,0 ); -rt2x00_set_field32 (®,WPDMA_GLO_CFG_TX_DMA_BUSY ,0 );rt2x00_set_field32 (®,WPDMA_GLO_CFG_ENABLE_RX_DMA ,0 ); -rt2x00_set_field32 (®,WPDMA_GLO_CFG_RX_DMA_BUSY ,0 ); -rt2x00_set_field32 (®,WPDMA_GLO_CFG_TX_WRITEBACK_DONE ,1 );rt2800_register_write (rt2x00dev,WPDMA_GLO_CFG , reg);/* Wait for DMA, ignore error */
@@ -2823,9 +2820,6 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)rt2x00_set_field32 (®,MAC_SYS_CTRL_ENABLE_TX ,0 );rt2x00_set_field32 (®,MAC_SYS_CTRL_ENABLE_RX ,0 );rt2800_register_write (rt2x00dev,MAC_SYS_CTRL , reg); - -rt2800_register_write (rt2x00dev,PWR_PIN_CFG ,0 ); -rt2800_register_write (rt2x00dev,TX_PIN_CFG ,0 ); }EXPORT_SYMBOL_GPL (rt2800_disable_radio);
drivers/net/wireless/rt2x00/rt2800pci.c +10 -26
@@ -475,39 +475,23 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)static void rt2800pci_disable_radio (struct rt2x00_dev *rt2x00dev) { -u32 reg; - -rt2800_disable_radio (rt2x00dev); - -rt2800_register_write (rt2x00dev,PBF_SYS_CTRL ,0x00001280 ); - -rt2800_register_read (rt2x00dev,WPDMA_RST_IDX , ®); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX0 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX1 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX2 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX3 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX4 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DTX_IDX5 ,1 ); -rt2x00_set_field32 (®,WPDMA_RST_IDX_DRX_IDX0 ,1 ); -rt2800_register_write (rt2x00dev,WPDMA_RST_IDX , reg); - -rt2800_register_write (rt2x00dev,PBF_SYS_CTRL ,0x00000e1f ); -rt2800_register_write (rt2x00dev,PBF_SYS_CTRL ,0x00000e00 ); +if (rt2x00_is_soc (rt2x00dev)) { +rt2800_disable_radio (rt2x00dev); +rt2800_register_write (rt2x00dev,PWR_PIN_CFG ,0 ); +rt2800_register_write (rt2x00dev,TX_PIN_CFG ,0 ); + } }static int rt2800pci_set_state (struct rt2x00_dev *rt2x00dev,enum dev_state state) { -/* -* Always put the device to sleep (even when we intend to wakeup!) -* if the device is booting and wasn't asleep it will return -* failure when attempting to wakeup. -*/ -rt2800_mcu_request (rt2x00dev,MCU_SLEEP ,0xff ,0xff ,2 ); -if (state ==STATE_AWAKE ) { -rt2800_mcu_request (rt2x00dev,MCU_WAKEUP ,TOKEN_WAKUP ,0 ,0 ); +rt2800_mcu_request (rt2x00dev,MCU_WAKEUP ,TOKEN_WAKUP ,0 ,0x02 );rt2800pci_mcu_status (rt2x00dev,TOKEN_WAKUP ); + }else if (state ==STATE_SLEEP ) { +rt2800_register_write (rt2x00dev,H2M_MAILBOX_STATUS ,0xffffffff ); +rt2800_register_write (rt2x00dev,H2M_MAILBOX_CID ,0xffffffff ); +rt2800_mcu_request (rt2x00dev,MCU_SLEEP ,0x01 ,0xff ,0x01 ); }return 0 ;
Signature · 1 line
1.7.2.3
PATCH 2/2 rt2x00: Fix and fine-tune rf registers for RT3070/RT3071/RT3090
From: RA-Jay Hung <[email protected]>
Basically fix and fine-tune RT3070/RT3071/RT3090 chip RF initial value when call rt2800_init_rfcsr
Signed-off-by RA-Jay Hung <[email protected]>
Signed-off-by Ivo van Doorn <[email protected]>
--- drivers/net/wireless/rt2x00/rt2800.h | 6 ++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 25 +++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2800.h +6 -0
@@ -1805,6 +1805,12 @@ struct mac_iveiv_entry {#define RFCSR30_RF_CALIBRATION FIELD8(0x80)/* +* RFCSR 31: +*/ +#define RFCSR31_RX_AGC_FC FIELD8(0x1f) +#define RFCSR31_RX_H20M FIELD8(0x20) + +/* * RF registers */
drivers/net/wireless/rt2x00/rt2800lib.c +17 -8
@@ -2436,6 +2436,10 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,rt2x00_set_field8 (&bbp,BBP4_BANDWIDTH ,2 * bw40);rt2800_bbp_write (rt2x00dev,4 , bbp); +rt2800_rfcsr_read (rt2x00dev,31 , &rfcsr); +rt2x00_set_field8 (&rfcsr,RFCSR31_RX_H20M , bw40); +rt2800_rfcsr_write (rt2x00dev,31 , rfcsr); +rt2800_rfcsr_read (rt2x00dev,22 , &rfcsr);rt2x00_set_field8 (&rfcsr,RFCSR22_BASEBAND_LOOPBACK ,1 );rt2800_rfcsr_write (rt2x00dev,22 , rfcsr);
@@ -2510,7 +2514,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)rt2800_rfcsr_write (rt2x00dev,4 ,0x40 );rt2800_rfcsr_write (rt2x00dev,5 ,0x03 );rt2800_rfcsr_write (rt2x00dev,6 ,0x02 ); -rt2800_rfcsr_write (rt2x00dev,7 ,0x70 ); +rt2800_rfcsr_write (rt2x00dev,7 ,0x60 );rt2800_rfcsr_write (rt2x00dev,9 ,0x0f );rt2800_rfcsr_write (rt2x00dev,10 ,0x41 );rt2800_rfcsr_write (rt2x00dev,11 ,0x21 );
@@ -2602,12 +2606,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)rt2800_register_write (rt2x00dev,LDO_CFG0 , reg); }else if (rt2x00_rt (rt2x00dev,RT3071 ) ||rt2x00_rt (rt2x00dev,RT3090 )) { +rt2800_rfcsr_write (rt2x00dev,31 ,0x14 ); +rt2800_rfcsr_read (rt2x00dev,6 , &rfcsr);rt2x00_set_field8 (&rfcsr,RFCSR6_R2 ,1 );rt2800_rfcsr_write (rt2x00dev,6 , rfcsr); -rt2800_rfcsr_write (rt2x00dev,31 ,0x14 ); -rt2800_register_read (rt2x00dev,LDO_CFG0 , ®);rt2x00_set_field32 (®,LDO_CFG0_BGSEL ,1 ); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -2619,6 +2623,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)rt2x00_set_field32 (®,LDO_CFG0_LDO_CORE_VLEVEL ,0 ); }rt2800_register_write (rt2x00dev,LDO_CFG0 , reg); + +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,RT3390 )) {rt2800_register_read (rt2x00dev,GPIO_SWITCH , ®);rt2x00_set_field32 (®,GPIO_SWITCH_5 ,0 );
@@ -2670,10 +2678,11 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)rt2800_rfcsr_read (rt2x00dev,17 , &rfcsr);rt2x00_set_field8 (&rfcsr,RFCSR17_TX_LO1_EN ,0 ); -if (rt2x00_rt_rev_lt (rt2x00dev,RT3071 ,REV_RT3071E ) || +if (rt2x00_rt (rt2x00dev,RT3070 ) || +rt2x00_rt_rev_lt (rt2x00dev,RT3071 ,REV_RT3071E ) ||rt2x00_rt_rev_lt (rt2x00dev,RT3090 ,REV_RT3090E ) ||rt2x00_rt_rev_lt (rt2x00dev,RT3390 ,REV_RT3390E )) { -if (test_bit (CONFIG_EXTERNAL_LNA_BG , &rt2x00dev->flags)) +if (!test_bit (CONFIG_EXTERNAL_LNA_BG , &rt2x00dev->flags))rt2x00_set_field8 (&rfcsr,RFCSR17_R ,1 ); }rt2x00_eeprom_read (rt2x00dev,EEPROM_TXMIXER_GAIN_BG , &eeprom);
@@ -2686,6 +2695,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)if (rt2x00_rt (rt2x00dev,RT3090 )) {rt2800_bbp_read (rt2x00dev,138 , &bbp); +/* Turn off unused DAC1 and ADC1 to reduce power consumption */ rt2x00_eeprom_read (rt2x00dev,EEPROM_NIC_CONF0 , &eeprom);if (rt2x00_get_field16 (eeprom,EEPROM_NIC_CONF0_RXPATH ) ==1 )rt2x00_set_field8 (&bbp,BBP138_RX_ADC1 ,0 );
@@ -2719,10 +2729,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)rt2800_rfcsr_write (rt2x00dev,21 , rfcsr); } -if (rt2x00_rt (rt2x00dev,RT3070 ) ||rt2x00_rt (rt2x00dev,RT3071 )) { +if (rt2x00_rt (rt2x00dev,RT3070 )) {rt2800_rfcsr_read (rt2x00dev,27 , &rfcsr); -if (rt2x00_rt_rev_lt (rt2x00dev,RT3070 ,REV_RT3070F ) || -rt2x00_rt_rev_lt (rt2x00dev,RT3071 ,REV_RT3071E )) +if (rt2x00_rt_rev_lt (rt2x00dev,RT3070 ,REV_RT3070F ))rt2x00_set_field8 (&rfcsr,RFCSR27_R1 ,3 );else rt2x00_set_field8 (&rfcsr,RFCSR27_R1 ,0 );
Signature · 1 line
1.7.2.3