mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-28 17:48:58 +00:00
a680ac8bcb
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. Signed-off-by: Shiji Yang <yangshiji66@qq.com>
107 lines
4.2 KiB
Diff
107 lines
4.2 KiB
Diff
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! */
|
|
}
|