From 4260edb3b1a6da71b8cd362f57a9ac4329eb538c Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 7 Jul 2026 17:10:48 +0800 Subject: [PATCH] wifi: rtw89: efuse: read thermal calibration value for RTL8922D The thermal calibration value programmed in efuse is the offset to adjust thermal value read from hardware, so that output will be accurate. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20260707091056.42771-8-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 2 ++ drivers/net/wireless/realtek/rtw89/efuse.h | 6 ++++ drivers/net/wireless/realtek/rtw89/efuse_be.c | 29 +++++++++++++++++++ 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/rtw8922d.c | 2 ++ 7 files changed, 53 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 72aaef321d61..f467299b6363 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -6063,6 +6063,8 @@ struct rtw89_power_trim_info { u8 pa_bias_trim[RF_PATH_MAX]; u8 pad_bias_trim[RF_PATH_MAX]; u8 vco_trim[RF_PATH_MAX]; + + s16 thermal_k; }; enum rtw89_regd_func { diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h index a14a9dfed8e8..c6415da749a3 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.h +++ b/drivers/net/wireless/realtek/rtw89/efuse.h @@ -16,6 +16,11 @@ #define EF_CV_MASK GENMASK(7, 4) #define EF_CV_INV 15 +#define EFUSE_THERMAL_K_OFFSET_BE 0x17CC +#define EFUSE_THERMAL_K_VALID_BE BIT(9) +#define EFUSE_THERMAL_K_SIGN_BE BIT(8) +#define EFUSE_THERMAL_K_VAL_BE GENMASK(7, 0) + struct rtw89_efuse_block_cfg { u32 offset; u32 size; @@ -32,5 +37,6 @@ int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2); 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); #endif diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c index a716ad54fce5..67036c89883f 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse_be.c +++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c @@ -537,3 +537,32 @@ int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev) return 0; } + +int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + u32 dump_addr = EFUSE_THERMAL_K_OFFSET_BE; + u8 buff[4]; /* efuse access must be multiple of 4 bytes in size */ + bool no_k; + u16 val16; + int ret; + + ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); + if (ret) + return ret; + + val16 = buff[0] | buff[1] << 8; + + no_k = !!u16_get_bits(val16, EFUSE_THERMAL_K_VALID_BE); + if (no_k) { + info->thermal_k = 0; + return -ENOENT; + } + + info->thermal_k = u16_get_bits(val16, EFUSE_THERMAL_K_VAL_BE); + + if (u16_get_bits(val16, EFUSE_THERMAL_K_SIGN_BE)) + info->thermal_k *= -1; + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 99de1b202976..3d3f683046a7 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -1558,6 +1558,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) { rtw89_mac_efuse_read_ecv(rtwdev); mac->efuse_read_fw_secure(rtwdev); + rtw89_mac_efuse_read_thermal_k(rtwdev); } set_bit(RTW89_FLAG_POWERON, rtwdev->flags); @@ -7500,6 +7501,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .cnv_efuse_state = rtw89_cnv_efuse_state_ax, .efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax, .efuse_read_ecv = NULL, + .efuse_read_thermal_k = 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 539061fc15e8..7256d64ea07f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -1132,6 +1132,7 @@ struct rtw89_mac_gen_def { int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle); 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 (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt); u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band); @@ -1735,6 +1736,16 @@ static inline int rtw89_mac_efuse_read_ecv(struct rtw89_dev *rtwdev) return mac->efuse_read_ecv(rtwdev); } +static inline int rtw89_mac_efuse_read_thermal_k(struct rtw89_dev *rtwdev) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (!mac->efuse_read_thermal_k) + return -ENOENT; + + return mac->efuse_read_thermal_k(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 14f1e30066e9..077ddf4f77c5 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -3312,6 +3312,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .cnv_efuse_state = rtw89_cnv_efuse_state_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, .cfg_plt = rtw89_mac_cfg_plt_be, .get_plt_cnt = rtw89_mac_get_plt_cnt_be, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c index e8267173bd4c..8b91c552a309 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c @@ -3006,6 +3006,7 @@ static void rtw8922d_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) static u8 rtw8922d_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; u8 val; rtw89_phy_write32_mask(rtwdev, R_TC_EN_BE4, B_TC_EN_BE4, 0x1); @@ -3015,6 +3016,7 @@ static u8 rtw8922d_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p fsleep(100); val = rtw89_phy_read32_mask(rtwdev, R_TC_VAL_BE4, B_TC_VAL_BE4); + val = clamp_t(int, val + info->thermal_k, 0, 255); return val; }