Linux wireless drivers development
 help / color / mirror / Atom feed
From: Ping-Ke Shih <pkshih@realtek.com>
To: <linux-wireless@vger.kernel.org>
Cc: <gary.chang@realtek.com>, <echuang@realtek.com>
Subject: [PATCH rtw-next 08/15] wifi: rtw89: 8922d: read default digital voltage calibration values
Date: Tue, 7 Jul 2026 17:10:49 +0800	[thread overview]
Message-ID: <20260707091056.42771-9-pkshih@realtek.com> (raw)
In-Reply-To: <20260707091056.42771-1-pkshih@realtek.com>

In order to lower temperature when WiFi is running, reduce the digital
voltage for the purpose.

The calibration values of digital voltage are programmed in efuse. One is
for normal use, which driver stores it into hal->thermal_prot_vmax. The
other is the minimum voltage, which is stored into hal->thermal_prot_vmin.
These two values define a range of supported voltage, which latter patch
uses them to adjust voltage depends on thermal value (temperature).

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     |  7 ++
 drivers/net/wireless/realtek/rtw89/efuse.h    |  1 +
 drivers/net/wireless/realtek/rtw89/efuse_be.c | 87 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/mac.c      |  2 +
 drivers/net/wireless/realtek/rtw89/mac.h      | 11 +++
 drivers/net/wireless/realtek/rtw89/mac_be.c   |  1 +
 drivers/net/wireless/realtek/rtw89/reg.h      | 17 ++++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 24 +++++
 8 files changed, 150 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 888a09fb2a9a..7729e7d4a792 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3661,6 +3661,8 @@ struct rtw89_sta_link {
 struct rtw89_efuse {
 	bool valid;
 	bool power_k_valid;
+	bool vcore_valid;
+	bool dswr_valid;
 	u8 xtal_cap;
 	u8 addr[ETH_ALEN];
 	u8 rfe_type;
@@ -3670,6 +3672,8 @@ struct rtw89_efuse {
 	u8 bt_setting_3;
 	u8 sn[RTW89_EFUSE_SN_LEN];
 	u8 uuid[RTW89_EFUSE_UUID_LEN];
+	u8 vcore_vmax_reduce;
+	u8 dswr_vmin;
 };
 
 struct rtw89_phy_rate_pattern {
@@ -5382,6 +5386,9 @@ struct rtw89_hal {
 	u8 thermal_prot_th;
 	u8 thermal_prot_lv; /* 0 ~ RTW89_THERMAL_PROT_LV_MAX */
 
+	u8 thermal_prot_vmax;
+	u8 thermal_prot_vmin;
+
 	u8 fixed_dig_pd_th; /* v = (X(dBm) + 102)/2 */
 	s8 fixed_dig_cck_pd_th; /* dBm */
 };
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index c6415da749a3..4eb629273ab9 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -38,5 +38,6 @@ int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev);
+int rtw89_efuse_read_pwr_data_be(struct rtw89_dev *rtwdev);
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index 67036c89883f..825274bd7c41 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -16,6 +16,15 @@
 #define EFUSE_SEC_BE_START 0x1580
 #define EFUSE_SEC_BE_SIZE 4
 
+#define EFUSE_VCORE_PWR_BE 0x17D6
+#define EFUSE_VCORE_PWR_BE_VALID BIT(12)
+#define EFUSE_VCORE_PWR_BE_VAL GENMASK(11, 0)
+#define SWR_DIG_MIN 860
+#define EFUSE_DIG_K_STEP 0xC
+#define EFUSE_DSWR_V0_86_BE 0x17DA
+#define EFUSE_DSWR_V0_86_BE_VALID BIT(5)
+#define EFUSE_DSWR_V0_86_BE_VAL GENMASK(4, 0)
+
 static const u32 sb_sel_mgn[SB_SEL_MGN_MAX_SIZE] = {
 	0x8000100, 0xC000180
 };
@@ -392,6 +401,17 @@ int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev)
 		goto out_free;
 	}
 
+	if (rtwdev->chip->chip_id != RTL8922D)
+		goto out_free;
+
+	ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size,
+						 RTW89_EFUSE_BLOCK_SYS);
+	if (ret) {
+		rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n",
+			   RTW89_EFUSE_BLOCK_SYS);
+		goto out_free;
+	}
+
 out_free:
 	kfree(dav_phy_map);
 	kfree(phy_map);
@@ -566,3 +586,70 @@ int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev)
 
 	return 0;
 }
+
+static int rtw89_efuse_read_pwr_data_vcore_be(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	u32 dump_addr;
+	u8 buff[4]; /* efuse access must 4 bytes align */
+	u16 val16;
+	int ret;
+
+	dump_addr = ALIGN_DOWN(EFUSE_VCORE_PWR_BE, 4);
+
+	ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+	if (ret)
+		return ret;
+
+	val16 = buff[EFUSE_VCORE_PWR_BE - dump_addr] |
+		buff[EFUSE_VCORE_PWR_BE - dump_addr + 1] << 8;
+
+	if (val16 & EFUSE_VCORE_PWR_BE_VALID)
+		return 0;
+
+	efuse->vcore_valid = true;
+	efuse->vcore_vmax_reduce =
+		(u16_get_bits(val16, EFUSE_VCORE_PWR_BE_VAL) - SWR_DIG_MIN) /
+		EFUSE_DIG_K_STEP;
+
+	return 0;
+}
+
+static int rtw89_efuse_read_pwr_data_dswr_be(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	u32 dump_addr;
+	u8 buff[4]; /* efuse access must 4 bytes align */
+	u8 val8;
+	int ret;
+
+	dump_addr = ALIGN_DOWN(EFUSE_DSWR_V0_86_BE, 4);
+
+	ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+	if (ret)
+		return ret;
+
+	val8 = buff[EFUSE_DSWR_V0_86_BE - dump_addr];
+
+	if (val8 & EFUSE_DSWR_V0_86_BE_VALID)
+		return 0;
+
+	efuse->dswr_valid = true;
+	efuse->dswr_vmin = u8_get_bits(val8, EFUSE_DSWR_V0_86_BE_VAL);
+
+	return 0;
+}
+
+int rtw89_efuse_read_pwr_data_be(struct rtw89_dev *rtwdev)
+{
+	int ret;
+
+	if (rtwdev->chip->chip_id != RTL8922D)
+		return 0;
+
+	ret = rtw89_efuse_read_pwr_data_vcore_be(rtwdev);
+	if (ret)
+		return ret;
+
+	return rtw89_efuse_read_pwr_data_dswr_be(rtwdev);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 3d3f683046a7..f5e55e6be119 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1559,6 +1559,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
 			rtw89_mac_efuse_read_ecv(rtwdev);
 			mac->efuse_read_fw_secure(rtwdev);
 			rtw89_mac_efuse_read_thermal_k(rtwdev);
+			rtw89_mac_efuse_read_pwr_data(rtwdev);
 		}
 
 		set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
@@ -7502,6 +7503,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax,
 	.efuse_read_ecv = NULL,
 	.efuse_read_thermal_k = NULL,
+	.efuse_read_pwr_data = NULL,
 
 	.cfg_plt = rtw89_mac_cfg_plt_ax,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 7256d64ea07f..8bbe49492d4c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1133,6 +1133,7 @@ struct rtw89_mac_gen_def {
 	int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev);
 	int (*efuse_read_ecv)(struct rtw89_dev *rtwdev);
 	int (*efuse_read_thermal_k)(struct rtw89_dev *rtwdev);
+	int (*efuse_read_pwr_data)(struct rtw89_dev *rtwdev);
 
 	int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
 	u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
@@ -1746,6 +1747,16 @@ static inline int rtw89_mac_efuse_read_thermal_k(struct rtw89_dev *rtwdev)
 	return mac->efuse_read_thermal_k(rtwdev);
 }
 
+static inline int rtw89_mac_efuse_read_pwr_data(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+	if (!mac->efuse_read_pwr_data)
+		return -ENOENT;
+
+	return mac->efuse_read_pwr_data(rtwdev);
+}
+
 static inline
 void rtw89_mac_fwdl_preconfig(struct rtw89_dev *rtwdev)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 077ddf4f77c5..0fe317929b1b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -3313,6 +3313,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be,
 	.efuse_read_ecv = rtw89_efuse_read_ecv_be,
 	.efuse_read_thermal_k = rtw89_efuse_read_thermal_k_be,
+	.efuse_read_pwr_data = rtw89_efuse_read_pwr_data_be,
 
 	.cfg_plt = rtw89_mac_cfg_plt_be,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_be,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 3908f9729736..72f7b80fe1fb 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -4573,6 +4573,23 @@
 #define R_BE_UDM2 0x01F8
 #define B_BE_UDM2_EPC_RA_MASK GENMASK(31, 0)
 
+#define R_BE_SPS_DIG_ON_CTRL0 0x0200
+#define B_BE_PFMCMP_IQ BIT(31)
+#define B_BE_FREQ_MASK GENMASK(30, 27)
+#define B_BE_OFF_END_SEL BIT(26)
+#define B_BE_POW_MINOFF_L BIT(25)
+#define B_BE_REG_BYPASS_L BIT(24)
+#define B_BE_VREFPFM_L_MASK GENMASK(23, 19)
+#define B_BE_REG_ZCDC_H_MASK GENMASK(18, 17)
+#define B_BE_FORCE_ZCD_BIAS BIT(16)
+#define B_BE_ZCD_SDZ_L_MASK GENMASK(15, 14)
+#define B_BE_ISAW_MASK GENMASK(13, 10)
+#define B_BE_SS_DIVSEL_MASK GENMASK(9, 8)
+#define B_BE_REG_BG_H BIT(7)
+#define B_BE_FPWM_L1 BIT(6)
+#define B_BE_POW_ZCD_L BIT(5)
+#define B_BE_PWMTUNE_MASK GENMASK(4, 0)
+
 #define R_BE_SPS_DIG_ON_CTRL1 0x0204
 #define B_BE_SN_N_L_MASK GENMASK(31, 28)
 #define B_BE_SP_N_L_MASK GENMASK(27, 24)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 8b91c552a309..a6693c8413d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -881,6 +881,28 @@ static int rtw8922d_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
 	return 0;
 }
 
+static int rtw8922d_read_sys(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u16 digk;
+	u8 vmin;
+
+	digk = log_map[0x200] | log_map[0x201] << 8;
+	hal->thermal_prot_vmax = u16_get_bits(digk, B_BE_PWMTUNE_MASK);
+
+	if (efuse->dswr_valid)
+		vmin = efuse->dswr_vmin;
+	else if (efuse->vcore_valid)
+		vmin = hal->thermal_prot_vmax - efuse->vcore_vmax_reduce;
+	else
+		vmin = hal->thermal_prot_vmax - 3;
+
+	hal->thermal_prot_vmin = vmin;
+
+	return 0;
+}
+
 static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 			       enum rtw89_efuse_block block)
 {
@@ -891,6 +913,8 @@ static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 		return rtw8922d_read_efuse_usb(rtwdev, log_map);
 	case RTW89_EFUSE_BLOCK_RF:
 		return rtw8922d_read_efuse_rf(rtwdev, log_map);
+	case RTW89_EFUSE_BLOCK_SYS:
+		return rtw8922d_read_sys(rtwdev, log_map);
 	default:
 		return 0;
 	}
-- 
2.25.1


  parent reply	other threads:[~2026-07-07  9:12 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
2026-07-12  1:55   ` Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 02/15] wifi: rtw89: 8922d: dynamic adjust channel smoothing Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 03/15] wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 04/15] wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 05/15] wifi: rtw89: 8922d: set TX compensation by format v2 Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 06/15] wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be() Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 07/15] wifi: rtw89: efuse: read thermal calibration value for RTL8922D Ping-Ke Shih
2026-07-07  9:10 ` Ping-Ke Shih [this message]
2026-07-07  9:10 ` [PATCH rtw-next 09/15] wifi: rtw89: add thermal protect by digital voltage reduction Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 10/15] wifi: rtw89: 8922d: set ANA CLK enter to 500KHz Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 11/15] wifi: rtw89: 8922d: update scaling factor for RX path Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 12/15] wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 13/15] wifi: rtw89: phy: add NCTL check for WiFi 7 chips Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 14/15] wifi: rtw89: unify access struct of TX power track tables Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 15/15] wifi: rtw89: set needed firmware elements for early chips transition Ping-Ke Shih

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707091056.42771-9-pkshih@realtek.com \
    --to=pkshih@realtek.com \
    --cc=echuang@realtek.com \
    --cc=gary.chang@realtek.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox