From: Zong-Zhe Yang Date: Wed, 20 May 2026 12:38:21 +0000 (+0800) Subject: wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed438b312d0758eaac868ab1275e743709fa4dac;p=thirdparty%2Fkernel%2Flinux.git wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU Support of Large MRU (Multiple Resource Unit) starts from RTL8922D_CID7090, i.e. RTL8922A and RTL8922D-VS variant do not support it. There are the new corresponding control registers. So, configure them. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20260520123823.1792954-6-pkshih@realtek.com --- diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 27d9a916d58cb..fb32d2bd9cb03 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -998,6 +998,9 @@ enum rtw89_ru_bandwidth { RTW89_RU106 = 2, RTW89_RU52_26 = 3, RTW89_RU106_26 = 4, + RTW89_RU484_242 = 5, + RTW89_RU996_484 = 6, + RTW89_RU996_484_242 = 7, RTW89_RU_NUM, }; diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 5af66656d0b88..532232892831f 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -568,6 +568,16 @@ struct rtw89_txpwr_limit_ru_be { s8 ru106_26[RTW89_RU_SEC_NUM_BE]; }; +#define RTW89_RU484_242_SEC_NUM_BE 4 +#define RTW89_RU996_484_SEC_NUM_BE 2 +#define RTW89_RU996_484_242_SEC_NUM_BE 2 + +struct rtw89_txpwr_limit_large_mru_be { + s8 ru484_242[RTW89_NSS_NUM][RTW89_RU484_242_SEC_NUM_BE]; + s8 ru996_484[RTW89_NSS_NUM][RTW89_RU996_484_SEC_NUM_BE]; + s8 ru996_484_242[RTW89_NSS_NUM][RTW89_RU996_484_242_SEC_NUM_BE]; +}; + struct rtw89_phy_rfk_log_fmt { const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM]; }; diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index d0a6dfdbfea73..99263355e2f15 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -1699,11 +1699,168 @@ static void rtw89_phy_fill_limit_ru_be(struct rtw89_dev *rtwdev, } } +static +void rtw89_phy_fill_limit_ru484_242_be(struct rtw89_dev *rtwdev, + s8 (*lmt)[RTW89_RU484_242_SEC_NUM_BE], + u8 ntx, u8 band, u8 ch, u8 bw) +{ + switch (bw) { + case RTW89_CHANNEL_WIDTH_80: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch); + break; + case RTW89_CHANNEL_WIDTH_160: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch - 8); + (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch + 8); + break; + case RTW89_CHANNEL_WIDTH_320: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch - 24); + (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch - 8); + (*lmt)[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch + 8); + (*lmt)[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU484_242, + ntx, ch + 24); + break; + } +} + +static +void rtw89_phy_fill_limit_ru996_484_be(struct rtw89_dev *rtwdev, + s8 (*lmt)[RTW89_RU996_484_SEC_NUM_BE], + u8 ntx, u8 band, u8 ch, u8 bw) +{ + switch (bw) { + case RTW89_CHANNEL_WIDTH_160: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484, + ntx, ch); + break; + case RTW89_CHANNEL_WIDTH_320: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484, + ntx, ch - 16); + (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484, + ntx, ch + 16); + break; + } +} + +static +void rtw89_phy_fill_limit_ru996_484_242_be(struct rtw89_dev *rtwdev, + s8 (*lmt)[RTW89_RU996_484_242_SEC_NUM_BE], + u8 ntx, u8 band, u8 ch, u8 bw) +{ + switch (bw) { + case RTW89_CHANNEL_WIDTH_160: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484_242, + ntx, ch); + break; + case RTW89_CHANNEL_WIDTH_320: + (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484_242, + ntx, ch - 16); + (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band, + RTW89_RU996_484_242, + ntx, ch + 16); + break; + } +} + +static +void rtw89_phy_fill_limit_large_mru_be(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + struct rtw89_txpwr_limit_large_mru_be *lmt, + bool has_bf) +{ + u8 band = chan->band_type; + u8 ch = chan->channel; + u8 bw = chan->band_width; + int i; + + memset(lmt, 0, sizeof(*lmt)); + + if (has_bf) + return; + + for (i = 0; i <= RTW89_NSS_2; i++) { + rtw89_phy_fill_limit_ru484_242_be(rtwdev, &lmt->ru484_242[i], + i, band, ch, bw); + rtw89_phy_fill_limit_ru996_484_be(rtwdev, &lmt->ru996_484[i], + i, band, ch, bw); + rtw89_phy_fill_limit_ru996_484_242_be(rtwdev, &lmt->ru996_484_242[i], + i, band, ch, bw); + } +} + +static +void rtw89_phy_conf_limit_large_mru_be(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx, + bool has_bf) +{ + struct rtw89_txpwr_limit_large_mru_be lmt_lmru; + u32 addr, val; + + rtw89_phy_fill_limit_large_mru_be(rtwdev, chan, &lmt_lmru, has_bf); + + addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 : + R_BE_TXAGC_MAX_1TX_RU484_242_0; + + val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][0], GENMASK(7, 0)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][1], GENMASK(15, 8)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][2], GENMASK(23, 16)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][3], GENMASK(31, 24)); + + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val); + + val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][0], GENMASK(7, 0)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][1], GENMASK(15, 8)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][2], GENMASK(23, 16)) | + u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][3], GENMASK(31, 24)); + + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr + 4, val); + + addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 : + R_BE_TXAGC_MAX_1TX_RU996_484_0; + + val = u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][0], GENMASK(7, 0)) | + u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][1], GENMASK(15, 8)) | + u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][0], GENMASK(23, 16)) | + u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][1], GENMASK(31, 24)); + + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val); + + addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 : + R_BE_TXAGC_MAX_1TX_RU996_484_242_0; + + val = u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][0], GENMASK(7, 0)) | + u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][1], GENMASK(15, 8)) | + u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][0], GENMASK(23, 16)) | + u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][1], GENMASK(31, 24)); + + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val); +} + static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_txpwr_limit_ru_be lmt_ru; + struct rtw89_hal *hal = &rtwdev->hal; const s8 *ptr; u32 addr, val; u8 i, j; @@ -1730,6 +1887,12 @@ static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev, rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val); } } + + if (!(chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7090)) + return; + + rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, false); + rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, true); } const struct rtw89_phy_gen_def rtw89_phy_gen_be = { diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index c2ffa6c196e46..2369fca3ede74 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -8362,6 +8362,11 @@ #define R_BE_PWR_LISTEN_PATH 0x11988 #define B_BE_PWR_LISTEN_PATH_EN GENMASK(31, 28) +#define R_BE_TXAGC_MAX_1TX_RU484_242_0 0x11990 +#define R_BE_TXAGC_MAX_1TX_RU996_484_0 0x119A4 +#define R_BE_TXAGC_MAX_1TX_RU996_484_242_0 0x119AC +#define R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 0x119DC + #define R_BE_PWR_REF_CTRL 0x11A20 #define B_BE_PWR_REF_CTRL_OFDM GENMASK(9, 1) #define B_BE_PWR_REF_CTRL_CCK GENMASK(18, 10) @@ -8399,6 +8404,8 @@ B_BE_PWR_FORCE_MACID_EN_VAL | \ B_BE_PWR_FORCE_MACID_EN_ON) +#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 0x11A4C + #define R_BE_PWR_REG_CTRL 0x11A50 #define B_BE_PWR_BT_EN BIT(23) @@ -8412,6 +8419,8 @@ #define R_BE_PWR_TH 0x11A78 #define R_BE_PWR_RSSI_TARGET_LMT 0x11A84 +#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 0x11ADC + #define R_BE_PWR_OFST_SW 0x11AE8 #define B_BE_PWR_OFST_SW_DB GENMASK(27, 24)