[RFC PATCH wireless] wifi: rt2x00: retry RF3053 VCO calibration with higher bias

From: Ho Jie Feng

Date: Sun Oct 25 2026 - 12:12:29 EST


VCO calibration with the default RF3053 VCO IC can cause
RFCSR 4, the result register to saturate at 0x7f on 2.4 GHz,
leaving lower channels unusable.

When calibration fails, retry the calibration with a higher VCO_IC
for RT3593. This should allow existing devices to work as before,
while allowing devices with the VCO calibration failure to work
successfully.

Hardware: Netgear WNDA4100 (USB 0846:9013, RT3593 rev 0402, RF3053)

Signed-off-by: Ho Jie Feng <hjf3108@xxxxxxxxx>
---
.../net/wireless/ralink/rt2x00/rt2800lib.c | 66 ++++++++++++-------
1 file changed, 44 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 2e2e382b62475..68755e388fd59 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -2794,6 +2794,44 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}

+static void rt2800_set_vco_ic_rf3053(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf,
+ unsigned int attempt)
+{
+ u8 rfcsr;
+
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
+ if (rf->channel >= 1 && rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1 + attempt);
+ else if (rf->channel >= 36 && rf->channel <= 64)
+ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+ else if (rf->channel >= 100 && rf->channel <= 128)
+ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+}
+
+static void rt2800_vco_calibrate_rf3053(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf)
+{
+ u8 rfcsr;
+
+ /* Initiate VCO calibration */
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+ }
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+}
+
static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@@ -2977,16 +3015,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rfcsr = 0x12;
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);

- rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
- if (rf->channel >= 1 && rf->channel <= 14)
- rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
- else if (rf->channel >= 36 && rf->channel <= 64)
- rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
- else if (rf->channel >= 100 && rf->channel <= 128)
- rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
- else
- rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
- rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+ rt2800_set_vco_ic_rf3053(rt2x00dev, rf, 0);

rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
@@ -3046,19 +3075,12 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
}

- /* Initiate VCO calibration */
- rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
- if (rf->channel <= 14) {
- rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
- } else {
- rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
- rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
- rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
- rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
- rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
- rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+ rt2800_vco_calibrate_rf3053(rt2x00dev, rf);
+ usleep_range(1000, 2000);
+ if (rt2800_rfcsr_read(rt2x00dev, 4) == 0x7f) {
+ rt2800_set_vco_ic_rf3053(rt2x00dev, rf, 1);
+ rt2800_vco_calibrate_rf3053(rt2x00dev, rf);
}
- rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);

if (rf->channel >= 1 && rf->channel <= 14) {
rfcsr = 0x23;

base-commit: 9d8ec0b5b5295bd23d979d1b2b905de25c36fff2
--
2.55.0