* [RFC PATCH wireless] wifi: rt2x00: retry RF3053 VCO calibration with higher bias
@ 2026-10-25 16:11 Ho Jie Feng
0 siblings, 0 replies; only message in thread
From: Ho Jie Feng @ 2026-10-25 16:11 UTC (permalink / raw)
To: linux-wireless; +Cc: Ho Jie Feng, Stanislaw Gruszka, linux-kernel
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@gmail.com>
---
.../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
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-25 16:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-25 16:11 [RFC PATCH wireless] wifi: rt2x00: retry RF3053 VCO calibration with higher bias Ho Jie Feng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox