[PATCH] mac80211: limit MT7620 TX power based on eeprom calibration

Shiji Yang yangshiji66 at outlook.com
Sat Jul 22 07:52:02 PDT 2023


From: Shiji Yang <yangshiji66 at qq.com>

This patch adds basic TX power control to 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 at qq.com>
---
 ...t-MT7620-TX-power-based-on-eeprom-ca.patch | 83 +++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 package/kernel/mac80211/patches/rt2x00/997-wifi-rt2x00-limit-MT7620-TX-power-based-on-eeprom-ca.patch

diff --git a/package/kernel/mac80211/patches/rt2x00/997-wifi-rt2x00-limit-MT7620-TX-power-based-on-eeprom-ca.patch b/package/kernel/mac80211/patches/rt2x00/997-wifi-rt2x00-limit-MT7620-TX-power-based-on-eeprom-ca.patch
new file mode 100644
index 0000000000..ecb8577752
--- /dev/null
+++ b/package/kernel/mac80211/patches/rt2x00/997-wifi-rt2x00-limit-MT7620-TX-power-based-on-eeprom-ca.patch
@@ -0,0 +1,83 @@
+From: Shiji Yang <yangshiji66 at 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
+to 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 at outlook.com>
+---
+ .../net/wireless/ralink/rt2x00/rt2800lib.c    | 43 +++++++++++++------
+ 1 file changed, 30 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -3894,25 +3894,42 @@ 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;
++	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;
++	/* get per channel power, 2 channels in total, unit is 0.5dBm */
++	power_level = (power_level - 3) * 2;
++	/*
++	 * We can't set 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.
++	 */
++	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;
+ 
+-	max_power = chan->max_power * 2;
+-	if (max_power > 0x2f)
+-		max_power = 0x2f;
++	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(&reg, TX_ALC_CFG_0_CH_INIT_0, power_level);
+-	rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, power_level);
+-	rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_0, max_power);
+-	rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_1, max_power);
++	rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_0, tx_power[0]);
++	rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, tx_power[1]);
++	rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_0, 0x2f);
++	rt2x00_set_field32(&reg, 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)) {
-- 
2.39.2




More information about the openwrt-devel mailing list