CFLAGS_trace.o := -I$(src)
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
-@@ -319,14 +319,7 @@ void _ath_dbg(struct ath_common *common,
+@@ -321,14 +321,7 @@ void _ath_dbg(struct ath_common *common,
#endif /* CPTCFG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */
--- /dev/null
+From 186f2432741f6d28d86ff723ac7830446affddfc Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 5 Aug 2023 17:17:28 +0800
+Subject: wifi: rt2x00: correct MAC_SYS_CTRL register RX mask in R-Calibration
+
+For MAC_SYS_CTRL register, Bit[2] controls MAC_TX_EN and Bit[3]
+controls MAC_RX_EN (Bit index starts from 0). Therefore, 0x08 is
+the correct mask for RX.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB03150B571B67B896A504AC34BC0EA@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -8561,7 +8561,7 @@ static void rt2800_r_calibration(struct
+ rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n");
+
+ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
+- maccfg &= (~0x04);
++ maccfg &= (~0x08);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
+
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX)))
--- /dev/null
+From 821b5192c955144bd2f0aeea6cd153e1aedd16e1 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Fri, 11 Aug 2023 14:34:54 +0800
+Subject: wifi: rt2x00: limit MT7620 TX power based on eeprom calibration
+
+In the vendor driver, the current channel power is queried from
+EEPROM_TXPOWER_BG1 and EEPROM_TXPOWER_BG2. And then the mixed value
+will be written into the low half-word of the TX_ALC_CFG_0 register.
+The high half-word of the TX_ALC_CFG_0 is a fixed value 0x2f2f.
+
+We can't get the accurate TX power. Based on my tests and the new
+MediaTek mt76 driver source code, the real TX power is approximately
+equal to channel_power + (max) rate_power. Usually max rate_power is
+the gain of the OFDM 6M rate, which can be readed from the offset
+EEPROM_TXPOWER_BYRATE +1.
+
+Based on these eeprom values, this patch adds basic TX power control
+for the MT7620 and limits its maximum TX power. This can avoid the
+link speed decrease caused by chip overheating. rt2800_config_alc()
+function has also been renamed to rt2800_config_alc_rt6352() because
+it's only used by RT6352 (MT7620).
+
+Notice:
+It's still need some work to sync the max channel power to the user
+interface. This part is missing from the rt2x00 driver framework. If
+we set the power exceed the calibration value, it won't take effect.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB03159090ED14044215E59FD6BC10A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 57 ++++++++++++++++++--------
+ 1 file changed, 40 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -3865,28 +3865,51 @@ static void rt2800_config_channel_rf7620
+ }
+ }
+
+-static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
+- struct ieee80211_channel *chan,
+- int power_level) {
+- u16 eeprom, target_power, max_power;
++static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_channel *chan,
++ int power_level)
++{
++ int cur_channel = rt2x00dev->rf_channel;
++ u16 eeprom, chan_power, rate_power, target_power;
++ u16 tx_power[2];
++ s8 *power_group[2];
+ u32 mac_sys_ctrl;
+- u32 reg;
++ u32 cnt, reg;
+ u8 bbp;
+
+- /* hardware unit is 0.5dBm, limited to 23.5dBm */
+- power_level *= 2;
+- if (power_level > 0x2f)
+- power_level = 0x2f;
+-
+- max_power = chan->max_power * 2;
+- if (max_power > 0x2f)
+- max_power = 0x2f;
++ if (WARN_ON(cur_channel < 1 || cur_channel > 14))
++ return;
++
++ /* get per chain power, 2 chains in total, unit is 0.5dBm */
++ power_level = (power_level - 3) * 2;
++
++ /* We can't get the accurate TX power. Based on some tests, the real
++ * TX power is approximately equal to channel_power + (max)rate_power.
++ * Usually max rate_power is the gain of the OFDM 6M rate. The antenna
++ * gain and externel PA gain are not included as we are unable to
++ * obtain these values.
++ */
++ rate_power = rt2800_eeprom_read_from_array(rt2x00dev,
++ EEPROM_TXPOWER_BYRATE, 1);
++ rate_power &= 0x3f;
++ power_level -= rate_power;
++ if (power_level < 1)
++ power_level = 1;
++
++ power_group[0] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
++ power_group[1] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
++ for (cnt = 0; cnt < 2; cnt++) {
++ chan_power = power_group[cnt][cur_channel - 1];
++ if (chan_power >= 0x20 || chan_power == 0)
++ chan_power = 0x10;
++ tx_power[cnt] = power_level < chan_power ? power_level : chan_power;
++ }
+
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0);
+- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, power_level);
+- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, power_level);
+- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, max_power);
+- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, max_power);
++ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, tx_power[0]);
++ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, tx_power[1]);
++ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, 0x2f);
++ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, 0x2f);
+
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
+@@ -5268,7 +5291,7 @@ static void rt2800_config_txpower_rt6352
+ rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg);
+
+- rt2800_config_alc(rt2x00dev, chan, power_level);
++ rt2800_config_alc_rt6352(rt2x00dev, chan, power_level);
+
+ /* TODO: temperature compensation code! */
+ }
--- /dev/null
+From 2ecfe6f07e8e6257cad3d3290c5aec2102120041 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 23 Sep 2023 09:01:01 +0800
+Subject: wifi: rt2x00: fix MT7620 low RSSI issue
+
+On Mediatek vendor driver[1], MT7620 (RT6352) uses different RSSI
+base value '-2' compared to the other RT2x00 chips. This patch
+introduces the SoC specific base value to fix the low RSSI value
+reports on MT7620.
+
+[1] Found on MT76x2E_MT7620_LinuxAP_V3.0.4.0_P3 ConvertToRssi().
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB031571CDB146C414A908A66DBCFEA@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -856,6 +856,7 @@ static int rt2800_agc_to_rssi(struct rt2
+ s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+ s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+ s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
++ s8 base_val = rt2x00_rt(rt2x00dev, RT6352) ? -2 : -12;
+ u16 eeprom;
+ u8 offset0;
+ u8 offset1;
+@@ -880,9 +881,9 @@ static int rt2800_agc_to_rssi(struct rt2
+ * If the value in the descriptor is 0, it is considered invalid
+ * and the default (extremely low) rssi value is assumed
+ */
+- rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
+- rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
+- rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
++ rssi0 = (rssi0) ? (base_val - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
++ rssi1 = (rssi1) ? (base_val - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
++ rssi2 = (rssi2) ? (base_val - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
+
+ /*
+ * mac80211 only accepts a single RSSI value. Calculating the
--- /dev/null
+From 69708fbb2c698f262e03360d064c7066e0679953 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 14 Oct 2023 14:55:01 +0800
+Subject: wifi: rt2x00: fix rt2800 watchdog function
+
+The watchdog function is broken on rt2800 series SoCs. This patch
+fixes the incorrect watchdog logic to make it work again.
+
+1. Update current wdt queue index if it's not equal to the previous
+ index. Watchdog compares the current and previous queue index to
+ judge if the queue hung.
+2. Make sure hung_{rx,tx} 'true' status won't be override by the
+ normal queue. Any queue hangs should trigger a reset action.
+3. Clear the watchdog counter of all queues before resetting the
+ hardware. This change may help to avoid the reset loop.
+4. Change hang check function return type to bool as we only need
+ to return two status, yes or no.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB0315BC1D83D31154924F0D39BCD1A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -1237,13 +1237,14 @@ void rt2800_txdone_nostatus(struct rt2x0
+ }
+ EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
+
+-static int rt2800_check_hung(struct data_queue *queue)
++static bool rt2800_check_hung(struct data_queue *queue)
+ {
+ unsigned int cur_idx = rt2800_drv_get_dma_done(queue);
+
+- if (queue->wd_idx != cur_idx)
++ if (queue->wd_idx != cur_idx) {
++ queue->wd_idx = cur_idx;
+ queue->wd_count = 0;
+- else
++ } else
+ queue->wd_count++;
+
+ return queue->wd_count > 16;
+@@ -1280,7 +1281,7 @@ void rt2800_watchdog(struct rt2x00_dev *
+ case QID_MGMT:
+ if (rt2x00queue_empty(queue))
+ continue;
+- hung_tx = rt2800_check_hung(queue);
++ hung_tx = hung_tx || rt2800_check_hung(queue);
+ break;
+ case QID_RX:
+ /* For station mode we should reactive at least
+@@ -1289,7 +1290,7 @@ void rt2800_watchdog(struct rt2x00_dev *
+ */
+ if (rt2x00dev->intf_sta_count == 0)
+ continue;
+- hung_rx = rt2800_check_hung(queue);
++ hung_rx = hung_rx || rt2800_check_hung(queue);
+ break;
+ default:
+ break;
+@@ -1302,8 +1303,12 @@ void rt2800_watchdog(struct rt2x00_dev *
+ if (hung_rx)
+ rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+
+- if (hung_tx || hung_rx)
++ if (hung_tx || hung_rx) {
++ queue_for_each(rt2x00dev, queue)
++ queue->wd_count = 0;
++
+ ieee80211_restart_hw(rt2x00dev->hw);
++ }
+ }
+ EXPORT_SYMBOL_GPL(rt2800_watchdog);
+
--- /dev/null
+From 1ffe76d5ae78553948d67a978acd9945c2f0a175 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Thu, 19 Oct 2023 19:58:56 +0800
+Subject: wifi: rt2x00: improve MT7620 register initialization
+
+1. Do not hard reset the BBP. We can use soft reset instead. This
+ change has some help to the calibration failure issue.
+2. Enable falling back to legacy rate from the HT/RTS rate by
+ setting the HT_FBK_TO_LEGACY register.
+3. Implement MCS rate specific maximum PSDU size. It can improve
+ the transmission quality under the low RSSI condition.
+4. Set BBP_84 register value to 0x19. This is used for extension
+ channel overlapping IOT.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB031553CCD4B7A3B89C85935DBCD4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 18 ++++++++++++++++++
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++
+ drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 3 +++
+ 3 files changed, 45 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -871,6 +871,18 @@
+ #define LED_CFG_LED_POLAR FIELD32(0x40000000)
+
+ /*
++ * AMPDU_MAX_LEN_20M1S: Per MCS max A-MPDU length, 20 MHz, MCS 0-7
++ * AMPDU_MAX_LEN_20M2S: Per MCS max A-MPDU length, 20 MHz, MCS 8-15
++ * AMPDU_MAX_LEN_40M1S: Per MCS max A-MPDU length, 40 MHz, MCS 0-7
++ * AMPDU_MAX_LEN_40M2S: Per MCS max A-MPDU length, 40 MHz, MCS 8-15
++ * Maximum A-MPDU length = 2^(AMPDU_MAX - 5) kilobytes
++ */
++#define AMPDU_MAX_LEN_20M1S 0x1030
++#define AMPDU_MAX_LEN_20M2S 0x1034
++#define AMPDU_MAX_LEN_40M1S 0x1038
++#define AMPDU_MAX_LEN_40M2S 0x103C
++
++/*
+ * AMPDU_BA_WINSIZE: Force BlockAck window size
+ * FORCE_WINSIZE_ENABLE:
+ * 0: Disable forcing of BlockAck window size
+@@ -1545,6 +1557,12 @@
+ */
+ #define EXP_ACK_TIME 0x1380
+
++/*
++ * HT_FBK_TO_LEGACY: Enable/Disable HT/RTS fallback to OFDM/CCK rate
++ * Not available for legacy SoCs
++ */
++#define HT_FBK_TO_LEGACY 0x1384
++
+ /* TX_PWR_CFG_5 */
+ #define TX_PWR_CFG_5 0x1384
+ #define TX_PWR_CFG_5_MCS16_CH0 FIELD32(0x0000000f)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -5851,6 +5851,7 @@ static int rt2800_init_registers(struct
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u32 reg;
+ u16 eeprom;
++ u8 bbp;
+ unsigned int i;
+ int ret;
+
+@@ -5860,6 +5861,19 @@ static int rt2800_init_registers(struct
+ if (ret)
+ return ret;
+
++ if (rt2x00_rt(rt2x00dev, RT6352)) {
++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x01);
++
++ bbp = rt2800_bbp_read(rt2x00dev, 21);
++ bbp |= 0x01;
++ rt2800_bbp_write(rt2x00dev, 21, bbp);
++ bbp = rt2800_bbp_read(rt2x00dev, 21);
++ bbp &= (~0x01);
++ rt2800_bbp_write(rt2x00dev, 21, bbp);
++
++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00);
++ }
++
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+@@ -6013,6 +6027,14 @@ static int rt2800_init_registers(struct
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
+ rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
+ rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
++
++ rt2800_register_write(rt2x00dev, AMPDU_MAX_LEN_20M1S, 0x77754433);
++ rt2800_register_write(rt2x00dev, AMPDU_MAX_LEN_20M2S, 0x77765543);
++ rt2800_register_write(rt2x00dev, AMPDU_MAX_LEN_40M1S, 0x77765544);
++ rt2800_register_write(rt2x00dev, AMPDU_MAX_LEN_40M2S, 0x77765544);
++
++ rt2800_register_write(rt2x00dev, HT_FBK_TO_LEGACY, 0x1010);
++
+ } else {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+@@ -7231,6 +7253,8 @@ static void rt2800_init_bbp_6352(struct
+ rt2800_bbp_dcoc_write(rt2x00dev, 159, 0x64);
+
+ rt2800_bbp4_mac_if_ctrl(rt2x00dev);
++
++ rt2800_bbp_write(rt2x00dev, 84, 0x19);
+ }
+
+ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -760,6 +760,9 @@ int rt2800mmio_init_registers(struct rt2
+
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
++ if (rt2x00_rt(rt2x00dev, RT6352))
++ return 0;
++
+ reg = 0;
+ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1);
+ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1);
--- /dev/null
+From a28533c6be1711584bf3ec978309d5c590029821 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Thu, 19 Oct 2023 19:58:57 +0800
+Subject: wifi: rt2x00: rework MT7620 channel config function
+
+1. Move the channel configuration code from rt2800_vco_calibration()
+ to the rt2800_config_channel().
+2. Use MT7620 SoC specific AGC initial LNA value instead of the
+ RT5592's value.
+3. BBP{195,196} pairing write has been replaced with
+ rt2800_bbp_glrt_write() to reduce redundant code.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB0315622A4340BFFA530B1B86BCD4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 91 ++++++++++----------------
+ 1 file changed, 35 insertions(+), 56 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -3861,14 +3861,6 @@ static void rt2800_config_channel_rf7620
+ rfcsr |= tx_agc_fc;
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
+ }
+-
+- if (conf_is_ht40(conf)) {
+- rt2800_bbp_glrt_write(rt2x00dev, 141, 0x10);
+- rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2f);
+- } else {
+- rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1a);
+- rt2800_bbp_glrt_write(rt2x00dev, 157, 0x40);
+- }
+ }
+
+ static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
+@@ -4437,32 +4429,46 @@ static void rt2800_config_channel(struct
+ usleep_range(1000, 1500);
+ }
+
+- if (rt2x00_rt(rt2x00dev, RT5592) || rt2x00_rt(rt2x00dev, RT6352)) {
+- reg = 0x10;
+- if (!conf_is_ht40(conf)) {
+- if (rt2x00_rt(rt2x00dev, RT6352) &&
+- rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+- reg |= 0x5;
+- } else {
+- reg |= 0xa;
+- }
+- }
+- rt2800_bbp_write(rt2x00dev, 195, 141);
+- rt2800_bbp_write(rt2x00dev, 196, reg);
++ if (rt2x00_rt(rt2x00dev, RT5592)) {
++ bbp = conf_is_ht40(conf) ? 0x10 : 0x1a;
++ rt2800_bbp_glrt_write(rt2x00dev, 141, bbp);
+
+- /* AGC init.
+- * Despite the vendor driver using different values here for
+- * RT6352 chip, we use 0x1c for now. This may have to be changed
+- * once TSSI got implemented.
+- */
+- reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
+- rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
++ bbp = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain;
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
+
+- if (rt2x00_rt(rt2x00dev, RT5592))
+- rt2800_iq_calibrate(rt2x00dev, rf->channel);
++ rt2800_iq_calibrate(rt2x00dev, rf->channel);
+ }
+
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
++ /* BBP for GLRT BW */
++ bbp = conf_is_ht40(conf) ?
++ 0x10 : rt2x00_has_cap_external_lna_bg(rt2x00dev) ?
++ 0x15 : 0x1a;
++ rt2800_bbp_glrt_write(rt2x00dev, 141, bbp);
++
++ bbp = conf_is_ht40(conf) ? 0x2f : 0x40;
++ rt2800_bbp_glrt_write(rt2x00dev, 157, bbp);
++
++ if (rt2x00dev->default_ant.rx_chain_num == 1) {
++ rt2800_bbp_write(rt2x00dev, 91, 0x07);
++ rt2800_bbp_write(rt2x00dev, 95, 0x1a);
++ rt2800_bbp_glrt_write(rt2x00dev, 128, 0xa0);
++ rt2800_bbp_glrt_write(rt2x00dev, 170, 0x12);
++ rt2800_bbp_glrt_write(rt2x00dev, 171, 0x10);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 91, 0x06);
++ rt2800_bbp_write(rt2x00dev, 95, 0x9a);
++ rt2800_bbp_glrt_write(rt2x00dev, 128, 0xe0);
++ rt2800_bbp_glrt_write(rt2x00dev, 170, 0x30);
++ rt2800_bbp_glrt_write(rt2x00dev, 171, 0x30);
++ }
++
++ /* AGC init */
++ bbp = rf->channel <= 14 ? 0x04 + 2 * rt2x00dev->lna_gain : 0;
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
++
++ usleep_range(1000, 1500);
++
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
+ &rt2x00dev->cap_flags)) {
+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
+@@ -5608,26 +5614,6 @@ void rt2800_vco_calibration(struct rt2x0
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
+- if (rt2x00dev->default_ant.rx_chain_num == 1) {
+- rt2800_bbp_write(rt2x00dev, 91, 0x07);
+- rt2800_bbp_write(rt2x00dev, 95, 0x1A);
+- rt2800_bbp_write(rt2x00dev, 195, 128);
+- rt2800_bbp_write(rt2x00dev, 196, 0xA0);
+- rt2800_bbp_write(rt2x00dev, 195, 170);
+- rt2800_bbp_write(rt2x00dev, 196, 0x12);
+- rt2800_bbp_write(rt2x00dev, 195, 171);
+- rt2800_bbp_write(rt2x00dev, 196, 0x10);
+- } else {
+- rt2800_bbp_write(rt2x00dev, 91, 0x06);
+- rt2800_bbp_write(rt2x00dev, 95, 0x9A);
+- rt2800_bbp_write(rt2x00dev, 195, 128);
+- rt2800_bbp_write(rt2x00dev, 196, 0xE0);
+- rt2800_bbp_write(rt2x00dev, 195, 170);
+- rt2800_bbp_write(rt2x00dev, 196, 0x30);
+- rt2800_bbp_write(rt2x00dev, 195, 171);
+- rt2800_bbp_write(rt2x00dev, 196, 0x30);
+- }
+-
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_bbp_write(rt2x00dev, 75, 0x68);
+ rt2800_bbp_write(rt2x00dev, 76, 0x4C);
+@@ -5635,13 +5621,6 @@ void rt2800_vco_calibration(struct rt2x0
+ rt2800_bbp_write(rt2x00dev, 80, 0x0C);
+ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
+ }
+-
+- /* On 11A, We should delay and wait RF/BBP to be stable
+- * and the appropriate time should be 1000 micro seconds
+- * 2005/06/05 - On 11G, we also need this delay time.
+- * Otherwise it's difficult to pass the WHQL.
+- */
+- usleep_range(1000, 1500);
+ }
+ }
+ EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
--- /dev/null
+From cca74bed37af1c8217bcd8282d9b384efdbf73bd Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Thu, 19 Oct 2023 19:58:58 +0800
+Subject: wifi: rt2x00: rework MT7620 PA/LNA RF calibration
+
+1. Move MT7620 PA/LNA calibration code to dedicated functions.
+2. For external PA/LNA devices, restore RF and BBP registers before
+ R-Calibration.
+3. Do Rx DCOC calibration again before RXIQ calibration.
+4. Add some missing LNA related registers' initialization.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB0315979F92DC563019B8F238BCD4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 176 +++++++++++++++++--------
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 6 +
+ 2 files changed, 130 insertions(+), 52 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -4468,41 +4468,6 @@ static void rt2800_config_channel(struct
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
+
+ usleep_range(1000, 1500);
+-
+- if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
+- &rt2x00dev->cap_flags)) {
+- reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
+- reg |= 0x00000101;
+- rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
+-
+- reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
+- reg |= 0x00000101;
+- rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
+-
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
+-
+- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
+- 0x36303636);
+- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
+- 0x6C6C6B6C);
+- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
+- 0x6C6C6B6C);
+- }
+ }
+
+ bbp = rt2800_bbp_read(rt2x00dev, 4);
+@@ -5612,16 +5577,6 @@ void rt2800_vco_calibration(struct rt2x0
+ }
+ }
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+-
+- if (rt2x00_rt(rt2x00dev, RT6352)) {
+- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+- rt2800_bbp_write(rt2x00dev, 75, 0x68);
+- rt2800_bbp_write(rt2x00dev, 76, 0x4C);
+- rt2800_bbp_write(rt2x00dev, 79, 0x1C);
+- rt2800_bbp_write(rt2x00dev, 80, 0x0C);
+- rt2800_bbp_write(rt2x00dev, 82, 0xB6);
+- }
+- }
+ }
+ EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
+
+@@ -10348,6 +10303,128 @@ do_cal:
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, MAC_RF_BYPASS0);
+ }
+
++static void rt2800_restore_rf_bbp_rt6352(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0);
++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0);
++ }
++
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02);
++ }
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xd3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xb3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xd5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6c);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xfc);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1f);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xff);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1c);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6b);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xf7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
++ }
++
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt2800_bbp_write(rt2x00dev, 75, 0x60);
++ rt2800_bbp_write(rt2x00dev, 76, 0x44);
++ rt2800_bbp_write(rt2x00dev, 79, 0x1c);
++ rt2800_bbp_write(rt2x00dev, 80, 0x0c);
++ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
++ }
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x3630363a);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6c6c666c);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6c6c666c);
++ }
++}
++
++static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev)
++{
++ u32 reg;
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev) ||
++ rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ rt2800_restore_rf_bbp_rt6352(rt2x00dev);
++
++ rt2800_r_calibration(rt2x00dev);
++ rt2800_rf_self_txdc_cal(rt2x00dev);
++ rt2800_rxdcoc_calibration(rt2x00dev);
++ rt2800_bw_filter_calibration(rt2x00dev, true);
++ rt2800_bw_filter_calibration(rt2x00dev, false);
++ rt2800_loft_iq_calibration(rt2x00dev);
++
++ /* missing DPD calibration for internal PA devices */
++
++ rt2800_rxdcoc_calibration(rt2x00dev);
++ rt2800_rxiq_calibration(rt2x00dev);
++
++ if (!rt2x00_has_cap_external_pa(rt2x00dev) &&
++ !rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ return;
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
++ reg |= 0x00000101;
++ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
++
++ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
++ reg |= 0x00000101;
++ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
++ }
++
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
++ }
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xc8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xa4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xc8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xa4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xc8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xa4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
++ }
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev))
++ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
++
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt2800_bbp_write(rt2x00dev, 75, 0x68);
++ rt2800_bbp_write(rt2x00dev, 76, 0x4c);
++ rt2800_bbp_write(rt2x00dev, 79, 0x1c);
++ rt2800_bbp_write(rt2x00dev, 80, 0x0c);
++ rt2800_bbp_write(rt2x00dev, 82, 0xb6);
++ }
++
++ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x36303636);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6c6c6b6c);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6c6c6b6c);
++ }
++}
++
+ static void rt2800_init_rfcsr_6352(struct rt2x00_dev *rt2x00dev)
+ {
+ /* Initialize RF central register to default value */
+@@ -10612,13 +10689,8 @@ static void rt2800_init_rfcsr_6352(struc
+ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
+ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
+
+- rt2800_r_calibration(rt2x00dev);
+- rt2800_rf_self_txdc_cal(rt2x00dev);
+- rt2800_rxdcoc_calibration(rt2x00dev);
+- rt2800_bw_filter_calibration(rt2x00dev, true);
+- rt2800_bw_filter_calibration(rt2x00dev, false);
+- rt2800_loft_iq_calibration(rt2x00dev);
+- rt2800_rxiq_calibration(rt2x00dev);
++ /* Do calibration and init PA/LNA */
++ rt2800_calibration_rt6352(rt2x00dev);
+ }
+
+ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -1263,6 +1263,12 @@ rt2x00_has_cap_external_lna_bg(struct rt
+ }
+
+ static inline bool
++rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev)
++{
++ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0);
++}
++
++static inline bool
+ rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev)
+ {
+ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA);
--- /dev/null
+From b1275cdd7456ef811747dfb4f3c46310ddd300cd Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 4 Nov 2023 16:57:58 +0800
+Subject: wifi: rt2x00: introduce DMA busy check watchdog for rt2800
+
+When I tried to fix the watchdog of rt2800, I found that sometimes
+the watchdog can not reset the hung device. This is because the
+queue is not completely stuck, it just becomes very slow. The MTK
+vendor driver for the new chip MT7603/MT7612 has a DMA busy watchdog
+to detect device hangs by checking DMA busy status. This watchdog
+implementation is something similar to it. To reduce unnecessary
+reset, we can check the INT_SOURCE_CSR register together as I found
+that when the radio hung, the RX/TX coherent interrupt will always
+stuck at triggered state.
+
+The 'watchdog' module parameter has been extended to control all
+watchdogs(0=disabled, 1=hang watchdog, 2=DMA watchdog, 3=both). This
+new watchdog function is a slight schedule and it won't affect the
+transmission speed. So we can turn on it by default. Due to the
+INT_SOURCE_CSR register is invalid on rt2800 USB NICs, the DMA busy
+watchdog will be automatically disabled for them.
+
+Tested on MT7620 and RT5350.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB0315D7462CE08A119A99DE34BCA4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 4 ++
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 77 ++++++++++++++++++++++----
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 3 +
+ 3 files changed, 73 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -3194,4 +3194,8 @@ enum rt2800_eeprom_word {
+ */
+ #define BCN_TBTT_OFFSET 64
+
++/* Watchdog type mask */
++#define RT2800_WATCHDOG_HANG BIT(0)
++#define RT2800_WATCHDOG_DMA_BUSY BIT(1)
++
+ #endif /* RT2800_H */
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -30,9 +30,10 @@
+ #include "rt2800lib.h"
+ #include "rt2800.h"
+
+-static bool modparam_watchdog;
+-module_param_named(watchdog, modparam_watchdog, bool, S_IRUGO);
+-MODULE_PARM_DESC(watchdog, "Enable watchdog to detect tx/rx hangs and reset hardware if detected");
++static unsigned int modparam_watchdog = RT2800_WATCHDOG_DMA_BUSY;
++module_param_named(watchdog, modparam_watchdog, uint, 0444);
++MODULE_PARM_DESC(watchdog, "Enable watchdog to recover tx/rx hangs.\n"
++ "\t\t(0=disabled, 1=hang watchdog, 2=DMA watchdog(default), 3=both)");
+
+ /*
+ * Register access.
+@@ -1261,15 +1262,12 @@ static void rt2800_update_survey(struct
+ chan_survey->time_ext_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
+ }
+
+-void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
++static bool rt2800_watchdog_hung(struct rt2x00_dev *rt2x00dev)
+ {
+ struct data_queue *queue;
+ bool hung_tx = false;
+ bool hung_rx = false;
+
+- if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
+- return;
+-
+ rt2800_update_survey(rt2x00dev);
+
+ queue_for_each(rt2x00dev, queue) {
+@@ -1297,18 +1295,72 @@ void rt2800_watchdog(struct rt2x00_dev *
+ }
+ }
+
++ if (!hung_tx && !hung_rx)
++ return false;
++
+ if (hung_tx)
+ rt2x00_warn(rt2x00dev, "Watchdog TX hung detected\n");
+
+ if (hung_rx)
+ rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+
+- if (hung_tx || hung_rx) {
+- queue_for_each(rt2x00dev, queue)
+- queue->wd_count = 0;
++ queue_for_each(rt2x00dev, queue)
++ queue->wd_count = 0;
++
++ return true;
++}
++
++static bool rt2800_watchdog_dma_busy(struct rt2x00_dev *rt2x00dev)
++{
++ bool busy_rx, busy_tx;
++ u32 reg_cfg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
++ u32 reg_int = rt2800_register_read(rt2x00dev, INT_SOURCE_CSR);
++
++ if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_RX_DMA_BUSY) &&
++ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_RX_COHERENT))
++ rt2x00dev->rxdma_busy++;
++ else
++ rt2x00dev->rxdma_busy = 0;
+
++ if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
++ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_TX_COHERENT))
++ rt2x00dev->txdma_busy++;
++ else
++ rt2x00dev->txdma_busy = 0;
++
++ busy_rx = rt2x00dev->rxdma_busy > 30 ? true : false;
++ busy_tx = rt2x00dev->txdma_busy > 30 ? true : false;
++
++ if (!busy_rx && !busy_tx)
++ return false;
++
++ if (busy_rx)
++ rt2x00_warn(rt2x00dev, "Watchdog RX DMA busy detected\n");
++
++ if (busy_tx)
++ rt2x00_warn(rt2x00dev, "Watchdog TX DMA busy detected\n");
++
++ rt2x00dev->rxdma_busy = 0;
++ rt2x00dev->txdma_busy = 0;
++
++ return true;
++}
++
++void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
++{
++ bool reset = false;
++
++ if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
++ return;
++
++ if (modparam_watchdog & RT2800_WATCHDOG_DMA_BUSY)
++ reset = rt2800_watchdog_dma_busy(rt2x00dev);
++
++ if (modparam_watchdog & RT2800_WATCHDOG_HANG)
++ reset = rt2800_watchdog_hung(rt2x00dev) || reset;
++
++ if (reset)
+ ieee80211_restart_hw(rt2x00dev->hw);
+- }
+ }
+ EXPORT_SYMBOL_GPL(rt2800_watchdog);
+
+@@ -12016,6 +12068,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
+ }
+
++ /* USB NICs don't support DMA watchdog as INT_SOURCE_CSR is invalid */
++ if (rt2x00_is_usb(rt2x00dev))
++ modparam_watchdog &= ~RT2800_WATCHDOG_DMA_BUSY;
+ if (modparam_watchdog) {
+ __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
+ rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -926,6 +926,9 @@ struct rt2x00_dev {
+ */
+ u16 beacon_int;
+
++ /* Rx/Tx DMA busy watchdog counter */
++ u16 rxdma_busy, txdma_busy;
++
+ /**
+ * Timestamp of last received beacon
+ */
--- /dev/null
+From 570beb6285fd355904b22625da20809f477096c5 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 4 Nov 2023 16:57:59 +0800
+Subject: wifi: rt2x00: disable RTS threshold for rt2800 by default
+
+rt2800 has a lot of registers to control the RTS enable/disable
+status for different rates. And the driver control them via
+rt2800_set_rts_threshold(). When RTS was disabled in user
+interface, this function won't be called at all. This means that
+the RTS is still 'on' for CCK and OFDM rates. So we'd better to
+disable them by default because it should be like this. The RTS
+for HT20 and HT40 is already default off so we don't need to
+touch them. If we toggle the RTS status, these register bits
+will be enable/disable again by rt2800_set_rts_threshold().
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB03155DDB953155B7A2DE849ABCA4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -6100,7 +6100,7 @@ static int rt2800_init_registers(struct
+ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+- rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1);
++ rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 0);
+ rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+ reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
+@@ -6113,7 +6113,7 @@ static int rt2800_init_registers(struct
+ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+- rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1);
++ rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 0);
+ rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+ reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
--- /dev/null
+From a11d965a218f0cd95b13fe44d0bcd8a20ce134a8 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 4 Nov 2023 16:58:00 +0800
+Subject: wifi: rt2x00: restart beacon queue when hardware reset
+
+When a hardware reset is triggered, all registers are reset, so all
+queues are forced to stop in hardware interface. However, mac80211
+will not automatically stop the queue. If we don't manually stop the
+beacon queue, the queue will be deadlocked and unable to start again.
+This patch fixes the issue where Apple devices cannot connect to the
+AP after calling ieee80211_restart_hw().
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/TYAP286MB031530EB6D98DCE4DF20766CBCA4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 +++
+ drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 11 +++++++++++
+ 2 files changed, 14 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -101,6 +101,7 @@ void rt2x00lib_disable_radio(struct rt2x
+ rt2x00link_stop_tuner(rt2x00dev);
+ rt2x00queue_stop_queues(rt2x00dev);
+ rt2x00queue_flush_queues(rt2x00dev, true);
++ rt2x00queue_stop_queue(rt2x00dev->bcn);
+
+ /*
+ * Disable radio.
+@@ -1286,6 +1287,7 @@ int rt2x00lib_start(struct rt2x00_dev *r
+ rt2x00dev->intf_ap_count = 0;
+ rt2x00dev->intf_sta_count = 0;
+ rt2x00dev->intf_associated = 0;
++ rt2x00dev->intf_beaconing = 0;
+
+ /* Enable the radio */
+ retval = rt2x00lib_enable_radio(rt2x00dev);
+@@ -1312,6 +1314,7 @@ void rt2x00lib_stop(struct rt2x00_dev *r
+ rt2x00dev->intf_ap_count = 0;
+ rt2x00dev->intf_sta_count = 0;
+ rt2x00dev->intf_associated = 0;
++ rt2x00dev->intf_beaconing = 0;
+ }
+
+ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+@@ -598,6 +598,17 @@ void rt2x00mac_bss_info_changed(struct i
+ */
+ if (changes & BSS_CHANGED_BEACON_ENABLED) {
+ mutex_lock(&intf->beacon_skb_mutex);
++
++ /*
++ * Clear the 'enable_beacon' flag and clear beacon because
++ * the beacon queue has been stopped after hardware reset.
++ */
++ if (test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags) &&
++ intf->enable_beacon) {
++ intf->enable_beacon = false;
++ rt2x00queue_clear_beacon(rt2x00dev, vif);
++ }
++
+ if (!bss_conf->enable_beacon && intf->enable_beacon) {
+ rt2x00dev->intf_beaconing--;
+ intf->enable_beacon = false;
static const char *
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -83,5 +141,13 @@ err_exit:
+@@ -83,6 +141,14 @@ err_exit:
int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev)
{
+
return rt2x00lib_read_eeprom_file(rt2x00dev);
}
+ EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom);
static const char *
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -164,5 +199,9 @@ int rt2x00lib_read_eeprom(struct rt2x00_
+@@ -164,6 +199,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_
return 0;
#endif
+
return rt2x00lib_read_eeprom_file(rt2x00dev);
}
+ EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom);
#endif /* _RT2X00_PLATFORM_H */
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1007,6 +1007,22 @@ static int rt2x00lib_probe_hw_modes(stru
+@@ -1008,6 +1008,22 @@ static int rt2x00lib_probe_hw_modes(stru
unsigned int num_rates;
unsigned int i;
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -989,6 +989,12 @@ static void rt2x00lib_rate(struct ieee80
+@@ -990,6 +990,12 @@ static void rt2x00lib_rate(struct ieee80
void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
{
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1012,6 +1012,16 @@ static int rt2x00lib_probe_hw_modes(stru
+@@ -1013,6 +1013,16 @@ static int rt2x00lib_probe_hw_modes(stru
struct ieee80211_rate *rates;
unsigned int num_rates;
unsigned int i;
#include "rt2x00.h"
#include "rt2800lib.h"
-@@ -11129,6 +11130,17 @@ static int rt2800_init_eeprom(struct rt2
+@@ -11285,6 +11286,17 @@ static int rt2800_init_eeprom(struct rt2
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1359,7 +1359,7 @@ static inline void rt2x00lib_set_if_comb
+@@ -1362,7 +1362,7 @@ static inline void rt2x00lib_set_if_comb
*/
if_limit = &rt2x00dev->if_limits_ap;
if_limit->max = rt2x00dev->ops->max_ap_intf;
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -304,6 +304,24 @@ static void rt2800_rf_write(struct rt2x0
+@@ -305,6 +305,24 @@ static void rt2800_rf_write(struct rt2x0
mutex_unlock(&rt2x00dev->csr_mutex);
}
static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
[EEPROM_CHIP_ID] = 0x0000,
[EEPROM_VERSION] = 0x0001,
-@@ -4469,6 +4487,29 @@ static void rt2800_config_channel(struct
- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
- 0x6C6C6B6C);
- }
-+
-+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
-+
-+ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
-+
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
-+ rt2800_bbp_write(rt2x00dev, 75, 0x68);
-+ rt2800_bbp_write(rt2x00dev, 76, 0x4C);
-+ rt2800_bbp_write(rt2x00dev, 79, 0x1C);
-+ rt2800_bbp_write(rt2x00dev, 80, 0x0C);
-+ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-+ /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in
-+ * config channel function in dependence of channel and
-+ * HT20/HT40 so don't touch it
-+ */
-+ }
- }
+@@ -10407,8 +10425,10 @@ static void rt2800_calibration_rt6352(st
+ u32 reg;
- bbp = rt2800_bbp_read(rt2x00dev, 4);
-@@ -10581,6 +10622,7 @@ static void rt2800_init_rfcsr_6352(struc
- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
- rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
+ if (rt2x00_has_cap_external_pa(rt2x00dev) ||
+- rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt6352_enable_pa_pin(rt2x00dev, 0);
+ rt2800_restore_rf_bbp_rt6352(rt2x00dev);
++ }
-+ rt6352_enable_pa_pin(rt2x00dev, 0);
rt2800_r_calibration(rt2x00dev);
rt2800_rf_self_txdc_cal(rt2x00dev);
- rt2800_rxdcoc_calibration(rt2x00dev);
-@@ -10588,6 +10630,22 @@ static void rt2800_init_rfcsr_6352(struc
- rt2800_bw_filter_calibration(rt2x00dev, false);
- rt2800_loft_iq_calibration(rt2x00dev);
- rt2800_rxiq_calibration(rt2x00dev);
+@@ -10426,6 +10446,8 @@ static void rt2800_calibration_rt6352(st
+ !rt2x00_has_cap_external_lna_bg(rt2x00dev))
+ return;
+
+ rt6352_enable_pa_pin(rt2x00dev, 1);
+
-+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
-+ rt2800_bbp_write(rt2x00dev, 75, 0x68);
-+ rt2800_bbp_write(rt2x00dev, 76, 0x4C);
-+ rt2800_bbp_write(rt2x00dev, 79, 0x1C);
-+ rt2800_bbp_write(rt2x00dev, 80, 0x0C);
-+ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-+ /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in config
-+ * channel function in dependence of channel and HT20/HT40,
-+ * so don't touch them here.
-+ */
-+ }
- }
-
- static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
+ reg |= 0x00000101;
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -28,6 +28,7 @@
#include <linux/rt2x00_platform.h>
#include <net/mac80211.h>
-@@ -1024,6 +1025,11 @@ struct rt2x00_dev {
+@@ -1027,6 +1028,11 @@ struct rt2x00_dev {
/* Clock for System On Chip devices. */
struct clk *clk;
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
-@@ -1044,6 +1044,11 @@
+@@ -1056,6 +1056,11 @@
#define MIMO_PS_CFG_RX_STBY_POL FIELD32(0x00000010)
#define MIMO_PS_CFG_RX_RX_STBY0 FIELD32(0x00000020)
*/
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -3778,14 +3778,16 @@ static void rt2800_config_channel_rf7620
+@@ -3836,14 +3836,16 @@ static void rt2800_config_channel_rf7620
rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4);
rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620,
-@@ -3819,18 +3821,23 @@ static void rt2800_config_channel_rf7620
+@@ -3877,18 +3879,23 @@ static void rt2800_config_channel_rf7620
rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20);
}
if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) {
if (conf_is_ht40(conf)) {
-@@ -3929,25 +3936,29 @@ static void rt2800_config_alc(struct rt2
+@@ -4002,25 +4009,29 @@ static void rt2800_config_alc_rt6352(str
if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n");
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl);
rt2800_vco_calibration(rt2x00dev);
-@@ -6011,18 +6022,33 @@ static int rt2800_init_registers(struct
+@@ -4513,7 +4524,8 @@ static void rt2800_config_channel(struct
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
+ /* BBP for GLRT BW */
+ bbp = conf_is_ht40(conf) ?
+- 0x10 : rt2x00_has_cap_external_lna_bg(rt2x00dev) ?
++ 0x10 : !rt2x00_has_cap_external_lna_bg(rt2x00dev) ?
++ 0x1a : rt2800_hw_get_chippkg(rt2x00dev) == 1 ?
+ 0x15 : 0x1a;
+ rt2800_bbp_glrt_write(rt2x00dev, 141, bbp);
+
+@@ -6017,18 +6029,33 @@ static int rt2800_init_registers(struct
} else if (rt2x00_rt(rt2x00dev, RT5350)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
} else if (rt2x00_rt(rt2x00dev, RT6352)) {
reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
-@@ -7127,14 +7153,16 @@ static void rt2800_init_bbp_6352(struct
+@@ -7141,14 +7168,16 @@ static void rt2800_init_bbp_6352(struct
rt2800_bbp_write(rt2x00dev, 188, 0x00);
rt2800_bbp_write(rt2x00dev, 189, 0x00);
/* BBP for G band GLRT function (BBP_128 ~ BBP_221) */
rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00);
-@@ -10406,31 +10434,36 @@ static void rt2800_init_rfcsr_6352(struc
+@@ -10381,6 +10410,9 @@ static void rt2800_restore_rf_bbp_rt6352
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0);
+ }
+
++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1)
++ return;
++
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
+@@ -10458,6 +10490,9 @@ static void rt2800_calibration_rt6352(st
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
+ }
+
++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1)
++ return;
++
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
+@@ -10548,31 +10583,36 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write(rt2x00dev, 42, 0x5B);
rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
/* Initialize RF channel register to default value */
rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03);
-@@ -10496,63 +10529,71 @@ static void rt2800_init_rfcsr_6352(struc
+@@ -10638,63 +10678,71 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5);
- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
--
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
--
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
--
-- /* Initialize RF channel register for DRQFN */
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7);
+ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
+ }
-+
+
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
+ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
+ rt2800_hw_get_chipeco(rt2x00dev) >= 2) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
+ }
-+
+
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
+-
+- /* Initialize RF channel register for DRQFN */
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7);
+ if (rt2800_hw_get_chippkg(rt2x00dev) == 0 &&
+ rt2800_hw_get_chipver(rt2x00dev) == 1) {
+ /* Initialize RF channel register for DRQFN */
/* Initialize RF DC calibration register to default value */
rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47);
-@@ -10615,12 +10656,17 @@ static void rt2800_init_rfcsr_6352(struc
+@@ -10757,12 +10805,17 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00);
+ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
+ }
- rt6352_enable_pa_pin(rt2x00dev, 0);
- rt2800_r_calibration(rt2x00dev);
+ /* Do calibration and init PA/LNA */
+ rt2800_calibration_rt6352(rt2x00dev);
+++ /dev/null
-From: Shiji Yang <yangshiji66@outlook.com>
-Date: Sat, 22 Jul 2023 21:56:30 +0800
-Subject: [PATCH] wifi: rt2x00: limit MT7620 TX power based on eeprom
- calibration
-
-In the vendor driver, the current channel power is queried from
-EEPROM_TXPOWER_BG1 and EEPROM_TXPOWER_BG2. And then the mixed value
-will be written into the low half-word of the TX_ALC_CFG_0 register.
-The high half-word of the TX_ALC_CFG_0 is a fixed value 0x2f2f.
-
-We can't get the accurate TX power. Based on my tests and the new
-MediaTek mt76 driver source code, the real TX power is approximately
-equal to channel_power + (max) rate_power. Usually max rate_power is
-the gain of the OFDM 6M rate, which can be readed from the offset
-EEPROM_TXPOWER_BYRATE +1.
-
-Based on these eeprom values, this patch adds basic TX power control
-for the MT7620 and limits its maximum TX power. This can avoid the
-link speed decrease caused by chip overheating. rt2800_config_alc()
-function has also been renamed to rt2800_config_alc_rt6352() because
-it's only used by RT6352(MT7620).
-
-Notice:
-It's still need some work to sync the max channel power to the user
-interface. This part is missing from the rt2x00 driver structure. If
-we set the power exceed the calibration value, it won't take effect.
-
-Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
----
- .../net/wireless/ralink/rt2x00/rt2800lib.c | 49 +++++++++++++------
- 1 file changed, 34 insertions(+), 15 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -3891,28 +3891,47 @@ static void rt2800_config_channel_rf7620
- }
- }
-
--static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
-+static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_channel *chan,
- int power_level) {
-- u16 eeprom, target_power, max_power;
-+ u16 eeprom, chan_power, rate_power, target_power;
-+ u16 tx_power[2];
-+ s8 *power_group[2];
- u32 mac_sys_ctrl;
-- u32 reg;
-+ u32 cnt, reg;
- u8 bbp;
-
-- /* hardware unit is 0.5dBm, limited to 23.5dBm */
-- power_level *= 2;
-- if (power_level > 0x2f)
-- power_level = 0x2f;
--
-- max_power = chan->max_power * 2;
-- if (max_power > 0x2f)
-- max_power = 0x2f;
-+ /* get per channel power, 2 channels in total, unit is 0.5dBm */
-+ power_level = (power_level - 3) * 2;
-+ /*
-+ * We can't get the accurate TX power. Based on some tests, the real
-+ * TX power is approximately equal to channel_power + (max)rate_power.
-+ * Usually max rate_power is the gain of the OFDM 6M rate. The antenna
-+ * gain and externel PA gain are not included as we are unable to
-+ * obtain these values.
-+ */
-+ rate_power = rt2800_eeprom_read_from_array(rt2x00dev,
-+ EEPROM_TXPOWER_BYRATE, 1) & 0x3f;
-+ power_level -= rate_power;
-+ if (power_level < 1)
-+ power_level = 1;
-+ if (power_level > chan->max_power * 2)
-+ power_level = chan->max_power * 2;
-+
-+ power_group[0] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-+ power_group[1] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
-+ for (cnt = 0; cnt < 2; cnt++) {
-+ chan_power = power_group[cnt][rt2x00dev->rf_channel - 1];
-+ if (chan_power >= 0x20 || chan_power == 0)
-+ chan_power = 0x10;
-+ tx_power[cnt] = power_level < chan_power ? power_level : chan_power;
-+ }
-
- reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0);
-- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, power_level);
-- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, power_level);
-- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, max_power);
-- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, max_power);
-+ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, tx_power[0]);
-+ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, tx_power[1]);
-+ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, 0x2f);
-+ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, 0x2f);
-
- eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
-@@ -5321,7 +5340,7 @@ static void rt2800_config_txpower_rt6352
- rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t);
- rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg);
-
-- rt2800_config_alc(rt2x00dev, chan, power_level);
-+ rt2800_config_alc_rt6352(rt2x00dev, chan, power_level);
-
- /* TODO: temperature compensation code! */
- }
+++ /dev/null
-From: Shiji Yang <yangshiji66@outlook.com>
-Date: Tue, 25 Jul 2023 20:05:06 +0800
-Subject: [PATCH] wifi: rt2x00: rework MT7620 PA/LNA RF calibration
-
-1. Move MT7620 PA/LNA calibration code to dedicated functions.
-2. For external PA/LNA devices, restore RF and BBP registers before
- R-Calibration.
-3. Do Rx DCOC calibration again before RXIQ calibration.
-4. Correct MAC_SYS_CTRL register RX mask to 0x08 in R-Calibration
- function. For MAC_SYS_CTRL register, Bit[2] controls MAC_TX_EN
- and Bit[3] controls MAC_RX_EN (Bit index starts from 0).
-5. Move the channel configuration code from rt2800_vco_calibration()
- to the rt2800_config_channel().
-6. Use MT7620 SOC specific AGC initial LNA value instead of the
- RT5592's value.
-7. Adjust the register operation sequence according to the vendor
- driver code. This may not be useful, but it can make things
- clearer when developers try to review it.
-
-Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
----
- .../net/wireless/ralink/rt2x00/rt2800lib.c | 306 ++++++++++--------
- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 6 +
- 2 files changed, 182 insertions(+), 130 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -3881,14 +3881,6 @@ static void rt2800_config_channel_rf7620
- rfcsr |= tx_agc_fc;
- rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
- }
--
-- if (conf_is_ht40(conf)) {
-- rt2800_bbp_glrt_write(rt2x00dev, 141, 0x10);
-- rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2f);
-- } else {
-- rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1a);
-- rt2800_bbp_glrt_write(rt2x00dev, 157, 0x40);
-- }
- }
-
- static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
-@@ -4457,89 +4449,63 @@ static void rt2800_config_channel(struct
- usleep_range(1000, 1500);
- }
-
-- if (rt2x00_rt(rt2x00dev, RT5592) || rt2x00_rt(rt2x00dev, RT6352)) {
-+ if (rt2x00_rt(rt2x00dev, RT5592)) {
- reg = 0x10;
-- if (!conf_is_ht40(conf)) {
-- if (rt2x00_rt(rt2x00dev, RT6352) &&
-- rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-- reg |= 0x5;
-- } else {
-- reg |= 0xa;
-- }
-- }
-+ if (!conf_is_ht40(conf))
-+ reg |= 0xa;
- rt2800_bbp_write(rt2x00dev, 195, 141);
- rt2800_bbp_write(rt2x00dev, 196, reg);
-
-- /* AGC init.
-- * Despite the vendor driver using different values here for
-- * RT6352 chip, we use 0x1c for now. This may have to be changed
-- * once TSSI got implemented.
-- */
- reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
- rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
--
-- if (rt2x00_rt(rt2x00dev, RT5592))
-- rt2800_iq_calibrate(rt2x00dev, rf->channel);
-+
-+ rt2800_iq_calibrate(rt2x00dev, rf->channel);
- }
-
- if (rt2x00_rt(rt2x00dev, RT6352)) {
-- if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
-- &rt2x00dev->cap_flags)) {
-- reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
-- reg |= 0x00000101;
-- rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
--
-- reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
-- reg |= 0x00000101;
-- rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
--
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
-- rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
-+ /* BBP for GLRT BW */
-+ if (conf_is_ht40(conf)) {
-+ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x10);
-+ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2f);
-+ } else {
-+ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1a);
-+ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x40);
-
-- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
-- 0x36303636);
-- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
-- 0x6C6C6B6C);
-- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
-- 0x6C6C6B6C);
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev))
-+ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x15);
- }
-
-- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-- reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
-- reg |= 0x00000101;
-- rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
--
-- reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
-- reg |= 0x00000101;
-- rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
--
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
-- rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
-- rt2800_bbp_write(rt2x00dev, 75, 0x68);
-- rt2800_bbp_write(rt2x00dev, 76, 0x4C);
-- rt2800_bbp_write(rt2x00dev, 79, 0x1C);
-- rt2800_bbp_write(rt2x00dev, 80, 0x0C);
-- rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-- /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in
-- * config channel function in dependence of channel and
-- * HT20/HT40 so don't touch it
-- */
-+ if (rt2x00dev->default_ant.rx_chain_num == 1) {
-+ rt2800_bbp_write(rt2x00dev, 91, 0x07);
-+ rt2800_bbp_write(rt2x00dev, 95, 0x1A);
-+ rt2800_bbp_write(rt2x00dev, 195, 128);
-+ rt2800_bbp_write(rt2x00dev, 196, 0xA0);
-+ rt2800_bbp_write(rt2x00dev, 195, 170);
-+ rt2800_bbp_write(rt2x00dev, 196, 0x12);
-+ rt2800_bbp_write(rt2x00dev, 195, 171);
-+ rt2800_bbp_write(rt2x00dev, 196, 0x10);
-+ } else {
-+ rt2800_bbp_write(rt2x00dev, 91, 0x06);
-+ rt2800_bbp_write(rt2x00dev, 95, 0x9A);
-+ rt2800_bbp_write(rt2x00dev, 195, 128);
-+ rt2800_bbp_write(rt2x00dev, 196, 0xE0);
-+ rt2800_bbp_write(rt2x00dev, 195, 170);
-+ rt2800_bbp_write(rt2x00dev, 196, 0x30);
-+ rt2800_bbp_write(rt2x00dev, 195, 171);
-+ rt2800_bbp_write(rt2x00dev, 196, 0x30);
- }
-+
-+ /* AGC init */
-+ reg = rf->channel <= 14 ? 0x04 + 2 * rt2x00dev->lna_gain : 0;
-+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
-+
-+ /* On 11A, We should delay and wait RF/BBP to be stable
-+ * and the appropriate time should be 1000 micro seconds
-+ * 2005/06/05 - On 11G, we also need this delay time.
-+ * Otherwise it's difficult to pass the WHQL.
-+ */
-+ usleep_range(1000, 1500);
- }
-
- bbp = rt2800_bbp_read(rt2x00dev, 4);
-@@ -5649,43 +5615,6 @@ void rt2800_vco_calibration(struct rt2x0
- }
- }
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
--
-- if (rt2x00_rt(rt2x00dev, RT6352)) {
-- if (rt2x00dev->default_ant.rx_chain_num == 1) {
-- rt2800_bbp_write(rt2x00dev, 91, 0x07);
-- rt2800_bbp_write(rt2x00dev, 95, 0x1A);
-- rt2800_bbp_write(rt2x00dev, 195, 128);
-- rt2800_bbp_write(rt2x00dev, 196, 0xA0);
-- rt2800_bbp_write(rt2x00dev, 195, 170);
-- rt2800_bbp_write(rt2x00dev, 196, 0x12);
-- rt2800_bbp_write(rt2x00dev, 195, 171);
-- rt2800_bbp_write(rt2x00dev, 196, 0x10);
-- } else {
-- rt2800_bbp_write(rt2x00dev, 91, 0x06);
-- rt2800_bbp_write(rt2x00dev, 95, 0x9A);
-- rt2800_bbp_write(rt2x00dev, 195, 128);
-- rt2800_bbp_write(rt2x00dev, 196, 0xE0);
-- rt2800_bbp_write(rt2x00dev, 195, 170);
-- rt2800_bbp_write(rt2x00dev, 196, 0x30);
-- rt2800_bbp_write(rt2x00dev, 195, 171);
-- rt2800_bbp_write(rt2x00dev, 196, 0x30);
-- }
--
-- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-- rt2800_bbp_write(rt2x00dev, 75, 0x68);
-- rt2800_bbp_write(rt2x00dev, 76, 0x4C);
-- rt2800_bbp_write(rt2x00dev, 79, 0x1C);
-- rt2800_bbp_write(rt2x00dev, 80, 0x0C);
-- rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-- }
--
-- /* On 11A, We should delay and wait RF/BBP to be stable
-- * and the appropriate time should be 1000 micro seconds
-- * 2005/06/05 - On 11G, we also need this delay time.
-- * Otherwise it's difficult to pass the WHQL.
-- */
-- usleep_range(1000, 1500);
-- }
- }
- EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
-
-@@ -8650,7 +8579,7 @@ static void rt2800_r_calibration(struct
- rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n");
-
- maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
-- maccfg &= (~0x04);
-+ maccfg &= (~0x08);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
-
- if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX)))
-@@ -10686,30 +10615,143 @@ static void rt2800_init_rfcsr_6352(struc
- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
- rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
- }
-+}
-
-- rt6352_enable_pa_pin(rt2x00dev, 0);
-- rt2800_r_calibration(rt2x00dev);
-- rt2800_rf_self_txdc_cal(rt2x00dev);
-- rt2800_rxdcoc_calibration(rt2x00dev);
-- rt2800_bw_filter_calibration(rt2x00dev, true);
-- rt2800_bw_filter_calibration(rt2x00dev, false);
-- rt2800_loft_iq_calibration(rt2x00dev);
-- rt2800_rxiq_calibration(rt2x00dev);
-- rt6352_enable_pa_pin(rt2x00dev, 1);
-+static void rt2800_init_palna_rt6352(struct rt2x00_dev *rt2x00dev)
-+{
-+ u32 reg;
-+
-+ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
-+
-+ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
-+ }
-
-- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
- rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
- rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_pa(rt2x00dev))
-+ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
- rt2800_bbp_write(rt2x00dev, 75, 0x68);
- rt2800_bbp_write(rt2x00dev, 76, 0x4C);
- rt2800_bbp_write(rt2x00dev, 79, 0x1C);
- rt2800_bbp_write(rt2x00dev, 80, 0x0C);
- rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-- /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in config
-- * channel function in dependence of channel and HT20/HT40,
-- * so don't touch them here.
-- */
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x36303636);
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C6B6C);
-+ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C6B6C);
-+ }
-+}
-+
-+static void rt2800_restore_rf_bbp_rt6352(struct rt2x00_dev *rt2x00dev)
-+{
-+ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0);
-+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ rt2800_bbp_write(rt2x00dev, 75, 0x60);
-+ rt2800_bbp_write(rt2x00dev, 76, 0x44);
-+ rt2800_bbp_write(rt2x00dev, 79, 0x1C);
-+ rt2800_bbp_write(rt2x00dev, 80, 0x0C);
-+ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
-+ }
-+
-+ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 &&
-+ rt2x00_has_cap_external_pa(rt2x00dev)) {
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x3630363A);
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C);
-+ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C);
-+ }
-+}
-+
-+static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev)
-+{
-+ if (rt2x00_has_cap_external_pa(rt2x00dev) ||
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ rt6352_enable_pa_pin(rt2x00dev, 0);
-+ rt2800_restore_rf_bbp_rt6352(rt2x00dev);
-+ }
-+
-+ rt2800_r_calibration(rt2x00dev);
-+ rt2800_rf_self_txdc_cal(rt2x00dev);
-+ rt2800_rxdcoc_calibration(rt2x00dev);
-+ rt2800_bw_filter_calibration(rt2x00dev, true);
-+ rt2800_bw_filter_calibration(rt2x00dev, false);
-+ rt2800_loft_iq_calibration(rt2x00dev);
-+
-+ /* missing DPD Calibration for devices using internal PA */
-+
-+ rt2800_rxdcoc_calibration(rt2x00dev);
-+ rt2800_rxiq_calibration(rt2x00dev);
-+
-+ if (rt2x00_has_cap_external_pa(rt2x00dev) ||
-+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-+ rt6352_enable_pa_pin(rt2x00dev, 1);
-+ rt2800_init_palna_rt6352(rt2x00dev);
- }
- }
-
-@@ -10802,6 +10844,10 @@ int rt2800_enable_radio(struct rt2x00_de
- rt2800_init_bbp(rt2x00dev);
- rt2800_init_rfcsr(rt2x00dev);
-
-+ /* Do calibration and init PA/LNA for RT6352 */
-+ if (rt2x00_rt(rt2x00dev, RT6352))
-+ rt2800_calibration_rt6352(rt2x00dev);
-+
- if (rt2x00_is_usb(rt2x00dev) &&
- (rt2x00_rt(rt2x00dev, RT3070) ||
- rt2x00_rt(rt2x00dev, RT3071) ||
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -1272,6 +1272,12 @@ rt2x00_has_cap_external_lna_bg(struct rt
- }
-
- static inline bool
-+rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev)
-+{
-+ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0);
-+}
-+
-+static inline bool
- rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev)
- {
- return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA);
+++ /dev/null
-From: Shiji Yang <yangshiji66@outlook.com>
-Date: Sat, 23 Sep 2023 07:51:39 +0800
-Subject: [PATCH] wifi: rt2x00: fix MT7620 low RSSI issue
-
-On Mediatek vendor driver[1], MT7620 (RT6352) uses different RSSI
-base value '-2' compared to the other RT2x00 chips. This patch
-introduces the SoC specific base value to fix the low RSSI value
-reports on MT7620.
-
-[1] Found on MT76x2E_MT7620_LinuxAP_V3.0.4.0_P3 ConvertToRssi().
-
-Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -875,6 +875,7 @@ static int rt2800_agc_to_rssi(struct rt2
- s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
- s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
- s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
-+ s8 base_val = rt2x00_rt(rt2x00dev, RT6352) ? -2 : -12;
- u16 eeprom;
- u8 offset0;
- u8 offset1;
-@@ -899,9 +900,9 @@ static int rt2800_agc_to_rssi(struct rt2
- * If the value in the descriptor is 0, it is considered invalid
- * and the default (extremely low) rssi value is assumed
- */
-- rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
-- rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
-- rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
-+ rssi0 = (rssi0) ? (base_val - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
-+ rssi1 = (rssi1) ? (base_val - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
-+ rssi2 = (rssi2) ? (base_val - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
-
- /*
- * mac80211 only accepts a single RSSI value. Calculating the