diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index f467299b6363..d457da2a21fe 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3840,6 +3840,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; @@ -3849,6 +3851,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 { @@ -5561,6 +5565,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; }