* [PATCH 1/7] wifi: rtw89: mac: get TX power control register according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-05 6:54 ` Kalle Valo
2023-10-03 1:54 ` [PATCH 2/7] wifi: rtw89: phy: set TX power by rate " Ping-Ke Shih
` (5 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
There are two difference between Wi-Fi 6 and Wi-Fi 7 chips.
1. Address range of TX power control register
2. Checking code to get a TX power control register
So, separate the implementation of them, access according to
chip generation, and rename original things with a suffix `_ax`.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/mac.c | 14 ++++---
drivers/net/wireless/realtek/rtw89/mac.h | 16 +++++---
drivers/net/wireless/realtek/rtw89/mac_be.c | 40 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 42 ++++++++++++++++++++-
4 files changed, 98 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 070a2eddfd19..f1d14e84cda7 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -4774,21 +4774,22 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
handler(rtwdev, skb, len);
}
-bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx,
- u32 reg_base, u32 *cr)
+static
+bool rtw89_mac_get_txpwr_cr_ax(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ u32 reg_base, u32 *cr)
{
const struct rtw89_dle_mem *dle_mem = rtwdev->chip->dle_mem;
enum rtw89_qta_mode mode = dle_mem->mode;
u32 addr = rtw89_mac_reg_by_idx(rtwdev, reg_base, phy_idx);
- if (addr < R_AX_PWR_RATE_CTRL || addr > CMAC1_END_ADDR) {
+ if (addr < R_AX_PWR_RATE_CTRL || addr > CMAC1_END_ADDR_AX) {
rtw89_err(rtwdev, "[TXPWR] addr=0x%x exceed txpwr cr\n",
addr);
goto error;
}
- if (addr >= CMAC1_START_ADDR && addr <= CMAC1_END_ADDR)
+ if (addr >= CMAC1_START_ADDR_AX && addr <= CMAC1_END_ADDR_AX)
if (mode == RTW89_QTA_SCC) {
rtw89_err(rtwdev,
"[TXPWR] addr=0x%x but hw not enable\n",
@@ -4805,7 +4806,6 @@ bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
return false;
}
-EXPORT_SYMBOL(rtw89_mac_get_txpwr_cr);
int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
{
@@ -5756,5 +5756,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax,
.fwdl_get_status = rtw89_fw_get_rdy_ax,
.fwdl_check_path_ready = rtw89_fwdl_check_path_ready_ax,
+
+ .get_txpwr_cr = rtw89_mac_get_txpwr_cr_ax,
};
EXPORT_SYMBOL(rtw89_mac_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 3c17b57a8ca2..617fd2aea776 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -865,6 +865,10 @@ struct rtw89_mac_gen_def {
bool dlfw, bool include_bb);
u8 (*fwdl_get_status)(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type);
int (*fwdl_check_path_ready)(struct rtw89_dev *rtwdev, bool h2c_or_fwdl);
+
+ bool (*get_txpwr_cr)(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ u32 reg_base, u32 *cr);
};
extern const struct rtw89_mac_gen_def rtw89_mac_gen_ax;
@@ -1028,9 +1032,6 @@ u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev);
bool rtw89_mac_get_ctrl_path(struct rtw89_dev *rtwdev);
int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl);
int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl);
-bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx,
- u32 reg_base, u32 *cr);
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter);
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev);
void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
@@ -1060,9 +1061,10 @@ static inline int rtw89_mac_txpwr_read32(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 *val)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
- if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
+ if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
*val = rtw89_read32(rtwdev, cr);
@@ -1073,9 +1075,10 @@ static inline int rtw89_mac_txpwr_write32(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 val)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
- if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
+ if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
rtw89_write32(rtwdev, cr, val);
@@ -1086,9 +1089,10 @@ static inline int rtw89_mac_txpwr_write32_mask(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 mask, u32 val)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
- if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
+ if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
rtw89_write32_mask(rtwdev, cr, mask, val);
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index fbf55274e00e..8af71d8a659a 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -205,6 +205,44 @@ static int rtw89_fwdl_check_path_ready_be(struct rtw89_dev *rtwdev,
rtwdev, R_BE_WCPU_FW_CTRL);
}
+static bool rtw89_mac_get_txpwr_cr_be(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ u32 reg_base, u32 *cr)
+{
+ const struct rtw89_dle_mem *dle_mem = rtwdev->chip->dle_mem;
+ enum rtw89_qta_mode mode = dle_mem->mode;
+ int ret;
+
+ ret = rtw89_mac_check_mac_en(rtwdev, (enum rtw89_mac_idx)phy_idx,
+ RTW89_CMAC_SEL);
+ if (ret) {
+ if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
+ return false;
+
+ rtw89_err(rtwdev, "[TXPWR] check mac enable failed\n");
+ return false;
+ }
+
+ if (reg_base < R_BE_PWR_MODULE || reg_base > R_BE_CMAC_FUNC_EN_C1) {
+ rtw89_err(rtwdev, "[TXPWR] reg_base=0x%x exceed txpwr cr\n",
+ reg_base);
+ return false;
+ }
+
+ *cr = rtw89_mac_reg_by_idx(rtwdev, reg_base, phy_idx);
+
+ if (*cr >= CMAC1_START_ADDR_BE && *cr <= CMAC1_END_ADDR_BE) {
+ if (mode == RTW89_QTA_SCC) {
+ rtw89_err(rtwdev,
+ "[TXPWR] addr=0x%x but hw not enable\n",
+ *cr);
+ return false;
+ }
+ }
+
+ return true;
+}
+
const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.band1_offset = RTW89_MAC_BE_BAND_REG_OFFSET,
.filter_model_addr = R_BE_FILTER_MODEL_ADDR,
@@ -217,5 +255,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.fwdl_enable_wcpu = rtw89_mac_fwdl_enable_wcpu_be,
.fwdl_get_status = fwdl_get_status_be,
.fwdl_check_path_ready = rtw89_fwdl_check_path_ready_be,
+
+ .get_txpwr_cr = rtw89_mac_get_txpwr_cr_be,
};
EXPORT_SYMBOL(rtw89_mac_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index edaf2a13ef98..7b0408246fd4 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3581,8 +3581,8 @@
#define R_AX_MACID_ANT_TABLE 0xDC00
#define R_AX_MACID_ANT_TABLE_LAST 0xDDFC
-#define CMAC1_START_ADDR 0xE000
-#define CMAC1_END_ADDR 0xFFFF
+#define CMAC1_START_ADDR_AX 0xE000
+#define CMAC1_END_ADDR_AX 0xFFFF
#define R_AX_CMAC_REG_END 0xFFFF
#define R_AX_LTE_SW_CFG_1 0x0038
@@ -3736,6 +3736,38 @@
#define R_BE_PLE_DBG_FUN_INTF_DATA 0x9114
#define B_BE_PLE_DFI_DATA_MASK GENMASK(31, 0)
+#define R_BE_CMAC_FUNC_EN 0x10000
+#define R_BE_CMAC_FUNC_EN_C1 0x14000
+#define B_BE_CMAC_CRPRT BIT(31)
+#define B_BE_CMAC_EN BIT(30)
+#define B_BE_CMAC_TXEN BIT(29)
+#define B_BE_CMAC_RXEN BIT(28)
+#define B_BE_FORCE_RESP_PKTCTL_GCKEN BIT(26)
+#define B_BE_FORCE_SIGB_REG_GCKEN BIT(25)
+#define B_BE_FORCE_POWER_REG_GCKEN BIT(23)
+#define B_BE_FORCE_RMAC_REG_GCKEN BIT(22)
+#define B_BE_FORCE_TRXPTCL_REG_GCKEN BIT(21)
+#define B_BE_FORCE_TMAC_REG_GCKEN BIT(20)
+#define B_BE_FORCE_CMAC_DMA_REG_GCKEN BIT(19)
+#define B_BE_FORCE_PTCL_REG_GCKEN BIT(18)
+#define B_BE_FORCE_SCHEDULER_RREG_GCKEN BIT(17)
+#define B_BE_FORCE_CMAC_COMMON_REG_GCKEN BIT(16)
+#define B_BE_FORCE_CMACREG_GCKEN BIT(15)
+#define B_BE_TXTIME_EN BIT(8)
+#define B_BE_RESP_PKTCTL_EN BIT(7)
+#define B_BE_SIGB_EN BIT(6)
+#define B_BE_PHYINTF_EN BIT(5)
+#define B_BE_CMAC_DMA_EN BIT(4)
+#define B_BE_PTCLTOP_EN BIT(3)
+#define B_BE_SCHEDULER_EN BIT(2)
+#define B_BE_TMAC_EN BIT(1)
+#define B_BE_RMAC_EN BIT(0)
+#define B_BE_CMAC_FUNC_EN_SET (B_BE_CMAC_EN | B_BE_CMAC_TXEN | B_BE_CMAC_RXEN | \
+ B_BE_PHYINTF_EN | B_BE_CMAC_DMA_EN | B_BE_PTCLTOP_EN | \
+ B_BE_SCHEDULER_EN | B_BE_TMAC_EN | B_BE_RMAC_EN | \
+ B_BE_CMAC_CRPRT | B_BE_TXTIME_EN | B_BE_RESP_PKTCTL_EN | \
+ B_BE_SIGB_EN)
+
#define R_BE_PORT_0_TSF_SYNC 0x102A0
#define R_BE_PORT_0_TSF_SYNC_C1 0x142A0
#define B_BE_P0_SYNC_NOW_P BIT(30)
@@ -3902,6 +3934,12 @@
#define B_BE_A_A1_MATCH BIT(1)
#define B_BE_SNIFFER_MODE BIT(0)
+#define R_BE_PWR_MODULE 0x11900
+#define R_BE_PWR_MODULE_C1 0x15900
+
+#define CMAC1_START_ADDR_BE 0x14000
+#define CMAC1_END_ADDR_BE 0x17FFF
+
#define RR_MOD 0x00
#define RR_MOD_V1 0x10000
#define RR_MOD_IQK GENMASK(19, 4)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 2/7] wifi: rtw89: phy: set TX power by rate according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 1/7] wifi: rtw89: mac: get TX power control register according to chip gen Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 3/7] wifi: rtw89: phy: set TX power offset " Ping-Ke Shih
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Wi-Fi 6 chips and Wi-Fi 7 chips have different register design for
TX power by rate. We rename original setting stuffs with a suffix
`_ax` and implement setting flow for Wi-Fi 7 chips. Then, we set TX
power by rate according to chip generation.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/phy.c | 26 ++---
drivers/net/wireless/realtek/rtw89/phy.h | 16 ++-
drivers/net/wireless/realtek/rtw89/phy_be.c | 107 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 2 +
4 files changed, 137 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 6e1f4d6c345c..ec2d5e2f17ee 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1519,7 +1519,7 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
-static const u8 rtw89_rs_idx_num[] = {
+static const u8 rtw89_rs_idx_num_ax[] = {
[RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
[RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
[RTW89_RS_MCS] = RTW89_RATE_MCS_NUM_AX,
@@ -1527,7 +1527,7 @@ static const u8 rtw89_rs_idx_num[] = {
[RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM_AX,
};
-static const u8 rtw89_rs_nss_num[] = {
+static const u8 rtw89_rs_nss_num_ax[] = {
[RTW89_RS_CCK] = 1,
[RTW89_RS_OFDM] = 1,
[RTW89_RS_MCS] = RTW89_NSS_NUM,
@@ -1589,7 +1589,6 @@ static s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac);
}
-static
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
const struct rtw89_rate_desc *rate_desc)
{
@@ -2098,9 +2097,9 @@ void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
}
}
-void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx)
+static void rtw89_phy_set_txpwr_byrate_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
{
u8 max_nss_num = rtwdev->chip->rf_path_num;
static const u8 rs[] = {
@@ -2119,19 +2118,19 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] set txpwr byrate with ch=%d\n", ch);
- BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_CCK] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_OFDM] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_MCS] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_HEDCM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_CCK] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_OFDM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_MCS] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_HEDCM] % 4);
addr = R_AX_PWR_BY_RATE;
for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) {
for (i = 0; i < ARRAY_SIZE(rs); i++) {
- if (cur.nss >= rtw89_rs_nss_num[rs[i]])
+ if (cur.nss >= rtw89_rs_nss_num_ax[rs[i]])
continue;
cur.rs = rs[i];
- for (cur.idx = 0; cur.idx < rtw89_rs_idx_num[rs[i]];
+ for (cur.idx = 0; cur.idx < rtw89_rs_idx_num_ax[rs[i]];
cur.idx++) {
v[cur.idx % 4] =
rtw89_phy_read_txpwr_byrate(rtwdev,
@@ -2153,7 +2152,6 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
}
}
}
-EXPORT_SYMBOL(rtw89_phy_set_txpwr_byrate);
void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
@@ -4836,5 +4834,7 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
.cr_base = 0x10000,
.ccx = &rtw89_ccx_regs_ax,
.physts = &rtw89_physts_regs_ax,
+
+ .set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
};
EXPORT_SYMBOL(rtw89_phy_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 4684feac97b2..78beafda3726 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -404,6 +404,10 @@ struct rtw89_phy_gen_def {
u32 cr_base;
const struct rtw89_ccx_regs *ccx;
const struct rtw89_physts_regs *physts;
+
+ void (*set_txpwr_byrate)(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
};
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
@@ -616,13 +620,23 @@ u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
struct rtw89_txpwr_byrate *head,
const struct rtw89_rate_desc *desc);
+s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
+ const struct rtw89_rate_desc *rate_desc);
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl);
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
+
+static inline
void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx);
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+
+ phy->set_txpwr_byrate(rtwdev, chan, phy_idx);
+}
+
void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 778e4b0c8e87..7b43bcd0952c 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -2,6 +2,8 @@
/* Copyright(c) 2023 Realtek Corporation
*/
+#include "debug.h"
+#include "mac.h"
#include "phy.h"
#include "reg.h"
@@ -69,9 +71,114 @@ static const struct rtw89_physts_regs rtw89_physts_regs_be = {
.dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK,
};
+struct rtw89_byr_spec_ent_be {
+ struct rtw89_rate_desc init;
+ u8 num_of_idx;
+ bool no_over_bw40;
+ bool no_multi_nss;
+};
+
+static const struct rtw89_byr_spec_ent_be rtw89_byr_spec_be[] = {
+ {
+ .init = { .rs = RTW89_RS_CCK },
+ .num_of_idx = RTW89_RATE_CCK_NUM,
+ .no_over_bw40 = true,
+ .no_multi_nss = true,
+ },
+ {
+ .init = { .rs = RTW89_RS_OFDM },
+ .num_of_idx = RTW89_RATE_OFDM_NUM,
+ .no_multi_nss = true,
+ },
+ {
+ .init = { .rs = RTW89_RS_MCS, .idx = 14, .ofdma = RTW89_NON_OFDMA },
+ .num_of_idx = 2,
+ .no_multi_nss = true,
+ },
+ {
+ .init = { .rs = RTW89_RS_MCS, .idx = 14, .ofdma = RTW89_OFDMA },
+ .num_of_idx = 2,
+ .no_multi_nss = true,
+ },
+ {
+ .init = { .rs = RTW89_RS_MCS, .ofdma = RTW89_NON_OFDMA },
+ .num_of_idx = 14,
+ },
+ {
+ .init = { .rs = RTW89_RS_HEDCM, .ofdma = RTW89_NON_OFDMA },
+ .num_of_idx = RTW89_RATE_HEDCM_NUM,
+ },
+ {
+ .init = { .rs = RTW89_RS_MCS, .ofdma = RTW89_OFDMA },
+ .num_of_idx = 14,
+ },
+ {
+ .init = { .rs = RTW89_RS_HEDCM, .ofdma = RTW89_OFDMA },
+ .num_of_idx = RTW89_RATE_HEDCM_NUM,
+ },
+};
+
+static
+void __phy_set_txpwr_byrate_be(struct rtw89_dev *rtwdev, u8 band, u8 bw,
+ u8 nss, u32 *addr, enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_byr_spec_ent_be *ent;
+ struct rtw89_rate_desc desc;
+ int pos = 0;
+ int i, j;
+ u32 val;
+ s8 v[4];
+
+ for (i = 0; i < ARRAY_SIZE(rtw89_byr_spec_be); i++) {
+ ent = &rtw89_byr_spec_be[i];
+
+ if (bw > RTW89_CHANNEL_WIDTH_40 && ent->no_over_bw40)
+ continue;
+ if (nss > RTW89_NSS_1 && ent->no_multi_nss)
+ continue;
+
+ desc = ent->init;
+ desc.nss = nss;
+ for (j = 0; j < ent->num_of_idx; j++, desc.idx++) {
+ v[pos] = rtw89_phy_read_txpwr_byrate(rtwdev, band, bw,
+ &desc);
+ pos = (pos + 1) % 4;
+ if (pos)
+ continue;
+
+ val = u32_encode_bits(v[0], GENMASK(7, 0)) |
+ u32_encode_bits(v[1], GENMASK(15, 8)) |
+ u32_encode_bits(v[2], GENMASK(23, 16)) |
+ u32_encode_bits(v[3], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, *addr, val);
+ *addr += 4;
+ }
+ }
+}
+
+static void rtw89_phy_set_txpwr_byrate_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 addr = R_BE_PWR_BY_RATE;
+ u8 band = chan->band_type;
+ u8 bw, nss;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] set txpwr byrate on band %d\n", band);
+
+ for (bw = 0; bw <= RTW89_CHANNEL_WIDTH_320; bw++)
+ for (nss = 0; nss <= RTW89_NSS_2; nss++)
+ __phy_set_txpwr_byrate_be(rtwdev, band, bw, nss,
+ &addr, phy_idx);
+}
+
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.cr_base = 0x20000,
.ccx = &rtw89_ccx_regs_be,
.physts = &rtw89_physts_regs_be,
+
+ .set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be,
};
EXPORT_SYMBOL(rtw89_phy_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 7b0408246fd4..5c4c76ce7d2b 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3937,6 +3937,8 @@
#define R_BE_PWR_MODULE 0x11900
#define R_BE_PWR_MODULE_C1 0x15900
+#define R_BE_PWR_BY_RATE 0x11E00
+
#define CMAC1_START_ADDR_BE 0x14000
#define CMAC1_END_ADDR_BE 0x17FFF
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 3/7] wifi: rtw89: phy: set TX power offset according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 1/7] wifi: rtw89: mac: get TX power control register according to chip gen Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 2/7] wifi: rtw89: phy: set TX power by rate " Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 4/7] wifi: rtw89: phy: set TX power limit " Ping-Ke Shih
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
We have a register to control TX power of each rate section to increase
or decrease an offset. But, Wi-Fi 6 chips and Wi-Fi 7 chips have different
address and format for this control register. We rename original setting
stuffs with a suffix `_ax` and implement setting flow for Wi-Fi 7 chips.
Then, we set TX power offset according to chip generation.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/phy.c | 9 +++---
drivers/net/wireless/realtek/rtw89/phy.h | 12 +++++++-
drivers/net/wireless/realtek/rtw89/phy_be.c | 31 +++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 1 +
4 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index ec2d5e2f17ee..d77c71060bc1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -2153,9 +2153,10 @@ static void rtw89_phy_set_txpwr_byrate_ax(struct rtw89_dev *rtwdev,
}
}
-void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx)
+static
+void rtw89_phy_set_txpwr_offset_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
{
struct rtw89_rate_desc desc = {
.nss = RTW89_NSS_1,
@@ -2180,7 +2181,6 @@ void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_OFST_CTRL,
GENMASK(19, 0), val);
}
-EXPORT_SYMBOL(rtw89_phy_set_txpwr_offset);
void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
@@ -4836,5 +4836,6 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
.physts = &rtw89_physts_regs_ax,
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
+ .set_txpwr_offset = rtw89_phy_set_txpwr_offset_ax,
};
EXPORT_SYMBOL(rtw89_phy_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 78beafda3726..d69054c52df1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -408,6 +408,9 @@ struct rtw89_phy_gen_def {
void (*set_txpwr_byrate)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
+ void (*set_txpwr_offset)(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
};
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
@@ -637,9 +640,16 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
phy->set_txpwr_byrate(rtwdev, chan, phy_idx);
}
+static inline
void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx);
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+
+ phy->set_txpwr_offset(rtwdev, chan, phy_idx);
+}
+
void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 7b43bcd0952c..8ff875f3fec8 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -174,11 +174,42 @@ static void rtw89_phy_set_txpwr_byrate_be(struct rtw89_dev *rtwdev,
&addr, phy_idx);
}
+static void rtw89_phy_set_txpwr_offset_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_rate_desc desc = {
+ .nss = RTW89_NSS_1,
+ .rs = RTW89_RS_OFFSET,
+ };
+ u8 band = chan->band_type;
+ s8 v[RTW89_RATE_OFFSET_NUM_BE] = {};
+ u32 val;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] set txpwr offset on band %d\n", band);
+
+ for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM_BE; desc.idx++)
+ v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, 0, &desc);
+
+ val = u32_encode_bits(v[RTW89_RATE_OFFSET_CCK], GENMASK(3, 0)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_OFDM], GENMASK(7, 4)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_HT], GENMASK(11, 8)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_VHT], GENMASK(15, 12)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_HE], GENMASK(19, 16)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_EHT], GENMASK(23, 20)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_DLRU_HE], GENMASK(27, 24)) |
+ u32_encode_bits(v[RTW89_RATE_OFFSET_DLRU_EHT], GENMASK(31, 28));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_BE_PWR_RATE_OFST_CTRL, val);
+}
+
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.cr_base = 0x20000,
.ccx = &rtw89_ccx_regs_be,
.physts = &rtw89_physts_regs_be,
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be,
+ .set_txpwr_offset = rtw89_phy_set_txpwr_offset_be,
};
EXPORT_SYMBOL(rtw89_phy_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 5c4c76ce7d2b..51b074d0782e 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3937,6 +3937,7 @@
#define R_BE_PWR_MODULE 0x11900
#define R_BE_PWR_MODULE_C1 0x15900
+#define R_BE_PWR_RATE_OFST_CTRL 0x11A30
#define R_BE_PWR_BY_RATE 0x11E00
#define CMAC1_START_ADDR_BE 0x14000
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 4/7] wifi: rtw89: phy: set TX power limit according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
` (2 preceding siblings ...)
2023-10-03 1:54 ` [PATCH 3/7] wifi: rtw89: phy: set TX power offset " Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 5/7] wifi: rtw89: phy: set TX power RU " Ping-Ke Shih
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Wi-Fi 6 chips and Wi-Fi 7 chips have different register design for
TX power limit. We rename original setting stuffs with a suffix `_ax`,
concentrate related enum declaration in phy.h, and implement setting
flow for Wi-Fi 7 chips. Then, we set TX power limit according to chip
generation.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 20 --
drivers/net/wireless/realtek/rtw89/phy.c | 64 ++---
drivers/net/wireless/realtek/rtw89/phy.h | 56 +++-
drivers/net/wireless/realtek/rtw89/phy_be.c | 289 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 1 +
5 files changed, 377 insertions(+), 53 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 56cf47f2ae2b..7ef3ebe7f793 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -744,26 +744,6 @@ struct rtw89_txpwr_byrate {
s8 trap;
};
-enum rtw89_bandwidth_section_num {
- RTW89_BW20_SEC_NUM = 8,
- RTW89_BW40_SEC_NUM = 4,
- RTW89_BW80_SEC_NUM = 2,
-};
-
-#define RTW89_TXPWR_LMT_PAGE_SIZE 40
-
-struct rtw89_txpwr_limit {
- s8 cck_20m[RTW89_BF_NUM];
- s8 cck_40m[RTW89_BF_NUM];
- s8 ofdm[RTW89_BF_NUM];
- s8 mcs_20m[RTW89_BW20_SEC_NUM][RTW89_BF_NUM];
- s8 mcs_40m[RTW89_BW40_SEC_NUM][RTW89_BF_NUM];
- s8 mcs_80m[RTW89_BW80_SEC_NUM][RTW89_BF_NUM];
- s8 mcs_160m[RTW89_BF_NUM];
- s8 mcs_40m_0p5[RTW89_BF_NUM];
- s8 mcs_40m_2p5[RTW89_BF_NUM];
-};
-
#define RTW89_RU_SEC_NUM 8
#define RTW89_TXPWR_LMT_RU_PAGE_SIZE 24
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index d77c71060bc1..8c5b73294a93 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1711,9 +1711,9 @@ EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
(ch)); \
} while (0)
-static void rtw89_phy_fill_txpwr_limit_20m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit *lmt,
- u8 band, u8 ntx, u8 ch)
+static void rtw89_phy_fill_txpwr_limit_20m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ax *lmt,
+ u8 band, u8 ntx, u8 ch)
{
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
ntx, RTW89_RS_CCK, ch);
@@ -1726,9 +1726,9 @@ static void rtw89_phy_fill_txpwr_limit_20m(struct rtw89_dev *rtwdev,
ntx, RTW89_RS_MCS, ch);
}
-static void rtw89_phy_fill_txpwr_limit_40m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit *lmt,
- u8 band, u8 ntx, u8 ch, u8 pri_ch)
+static void rtw89_phy_fill_txpwr_limit_40m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ax *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
{
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
ntx, RTW89_RS_CCK, ch - 2);
@@ -1747,9 +1747,9 @@ static void rtw89_phy_fill_txpwr_limit_40m(struct rtw89_dev *rtwdev,
ntx, RTW89_RS_MCS, ch);
}
-static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit *lmt,
- u8 band, u8 ntx, u8 ch, u8 pri_ch)
+static void rtw89_phy_fill_txpwr_limit_80m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ax *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
{
s8 val_0p5_n[RTW89_BF_NUM];
s8 val_0p5_p[RTW89_BF_NUM];
@@ -1788,9 +1788,9 @@ static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
}
-static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit *lmt,
- u8 band, u8 ntx, u8 ch, u8 pri_ch)
+static void rtw89_phy_fill_txpwr_limit_160m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ax *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
{
s8 val_0p5_n[RTW89_BF_NUM];
s8 val_0p5_p[RTW89_BF_NUM];
@@ -1875,10 +1875,10 @@ static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
}
static
-void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- struct rtw89_txpwr_limit *lmt,
- u8 ntx)
+void rtw89_phy_fill_txpwr_limit_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ struct rtw89_txpwr_limit_ax *lmt,
+ u8 ntx)
{
u8 band = chan->band_type;
u8 pri_ch = chan->primary_channel;
@@ -1889,19 +1889,19 @@ void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
switch (bw) {
case RTW89_CHANNEL_WIDTH_20:
- rtw89_phy_fill_txpwr_limit_20m(rtwdev, lmt, band, ntx, ch);
+ rtw89_phy_fill_txpwr_limit_20m_ax(rtwdev, lmt, band, ntx, ch);
break;
case RTW89_CHANNEL_WIDTH_40:
- rtw89_phy_fill_txpwr_limit_40m(rtwdev, lmt, band, ntx, ch,
- pri_ch);
+ rtw89_phy_fill_txpwr_limit_40m_ax(rtwdev, lmt, band, ntx, ch,
+ pri_ch);
break;
case RTW89_CHANNEL_WIDTH_80:
- rtw89_phy_fill_txpwr_limit_80m(rtwdev, lmt, band, ntx, ch,
- pri_ch);
+ rtw89_phy_fill_txpwr_limit_80m_ax(rtwdev, lmt, band, ntx, ch,
+ pri_ch);
break;
case RTW89_CHANNEL_WIDTH_160:
- rtw89_phy_fill_txpwr_limit_160m(rtwdev, lmt, band, ntx, ch,
- pri_ch);
+ rtw89_phy_fill_txpwr_limit_160m_ax(rtwdev, lmt, band, ntx, ch,
+ pri_ch);
break;
}
}
@@ -2182,12 +2182,12 @@ void rtw89_phy_set_txpwr_offset_ax(struct rtw89_dev *rtwdev,
GENMASK(19, 0), val);
}
-void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx)
+static void rtw89_phy_set_txpwr_limit_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
{
u8 max_ntx_num = rtwdev->chip->rf_path_num;
- struct rtw89_txpwr_limit lmt;
+ struct rtw89_txpwr_limit_ax lmt;
u8 ch = chan->channel;
u8 bw = chan->band_width;
const s8 *ptr;
@@ -2197,15 +2197,15 @@ void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
- BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit) !=
- RTW89_TXPWR_LMT_PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ax) !=
+ RTW89_TXPWR_LMT_PAGE_SIZE_AX);
addr = R_AX_PWR_LMT;
for (i = 0; i < max_ntx_num; i++) {
- rtw89_phy_fill_txpwr_limit(rtwdev, chan, &lmt, i);
+ rtw89_phy_fill_txpwr_limit_ax(rtwdev, chan, &lmt, i);
ptr = (s8 *)&lmt;
- for (j = 0; j < RTW89_TXPWR_LMT_PAGE_SIZE;
+ for (j = 0; j < RTW89_TXPWR_LMT_PAGE_SIZE_AX;
j += 4, addr += 4, ptr += 4) {
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
@@ -2216,7 +2216,6 @@ void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
}
}
}
-EXPORT_SYMBOL(rtw89_phy_set_txpwr_limit);
void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
@@ -4837,5 +4836,6 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
.set_txpwr_offset = rtw89_phy_set_txpwr_offset_ax,
+ .set_txpwr_limit = rtw89_phy_set_txpwr_limit_ax,
};
EXPORT_SYMBOL(rtw89_phy_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index d69054c52df1..72bc00bcb04c 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -400,6 +400,50 @@ struct rtw89_physts_regs {
u32 dis_trigger_brk_mask;
};
+enum rtw89_bandwidth_section_num_ax {
+ RTW89_BW20_SEC_NUM_AX = 8,
+ RTW89_BW40_SEC_NUM_AX = 4,
+ RTW89_BW80_SEC_NUM_AX = 2,
+};
+
+enum rtw89_bandwidth_section_num_be {
+ RTW89_BW20_SEC_NUM_BE = 16,
+ RTW89_BW40_SEC_NUM_BE = 8,
+ RTW89_BW80_SEC_NUM_BE = 4,
+ RTW89_BW160_SEC_NUM_BE = 2,
+};
+
+#define RTW89_TXPWR_LMT_PAGE_SIZE_AX 40
+
+struct rtw89_txpwr_limit_ax {
+ s8 cck_20m[RTW89_BF_NUM];
+ s8 cck_40m[RTW89_BF_NUM];
+ s8 ofdm[RTW89_BF_NUM];
+ s8 mcs_20m[RTW89_BW20_SEC_NUM_AX][RTW89_BF_NUM];
+ s8 mcs_40m[RTW89_BW40_SEC_NUM_AX][RTW89_BF_NUM];
+ s8 mcs_80m[RTW89_BW80_SEC_NUM_AX][RTW89_BF_NUM];
+ s8 mcs_160m[RTW89_BF_NUM];
+ s8 mcs_40m_0p5[RTW89_BF_NUM];
+ s8 mcs_40m_2p5[RTW89_BF_NUM];
+};
+
+#define RTW89_TXPWR_LMT_PAGE_SIZE_BE 76
+
+struct rtw89_txpwr_limit_be {
+ s8 cck_20m[RTW89_BF_NUM];
+ s8 cck_40m[RTW89_BF_NUM];
+ s8 ofdm[RTW89_BF_NUM];
+ s8 mcs_20m[RTW89_BW20_SEC_NUM_BE][RTW89_BF_NUM];
+ s8 mcs_40m[RTW89_BW40_SEC_NUM_BE][RTW89_BF_NUM];
+ s8 mcs_80m[RTW89_BW80_SEC_NUM_BE][RTW89_BF_NUM];
+ s8 mcs_160m[RTW89_BW160_SEC_NUM_BE][RTW89_BF_NUM];
+ s8 mcs_320m[RTW89_BF_NUM];
+ s8 mcs_40m_0p5[RTW89_BF_NUM];
+ s8 mcs_40m_2p5[RTW89_BF_NUM];
+ s8 mcs_40m_4p5[RTW89_BF_NUM];
+ s8 mcs_40m_6p5[RTW89_BF_NUM];
+};
+
struct rtw89_phy_gen_def {
u32 cr_base;
const struct rtw89_ccx_regs *ccx;
@@ -411,6 +455,9 @@ struct rtw89_phy_gen_def {
void (*set_txpwr_offset)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
+ void (*set_txpwr_limit)(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
};
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
@@ -650,9 +697,16 @@ void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
phy->set_txpwr_offset(rtwdev, chan, phy_idx);
}
+static inline
void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx);
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+
+ phy->set_txpwr_limit(rtwdev, chan, phy_idx);
+}
+
void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 8ff875f3fec8..500f24b23d06 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -204,6 +204,294 @@ static void rtw89_phy_set_txpwr_offset_be(struct rtw89_dev *rtwdev,
rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_BE_PWR_RATE_OFST_CTRL, val);
}
+static void
+fill_limit_nonbf_bf(struct rtw89_dev *rtwdev, s8 (*ptr)[RTW89_BF_NUM],
+ u8 band, u8 bw, u8 ntx, u8 rs, u8 ch)
+{
+ int bf;
+
+ for (bf = 0; bf < RTW89_BF_NUM; bf++)
+ (*ptr)[bf] = rtw89_phy_read_txpwr_limit(rtwdev, band, bw, ntx,
+ rs, bf, ch);
+}
+
+static void
+fill_limit_nonbf_bf_min(struct rtw89_dev *rtwdev, s8 (*ptr)[RTW89_BF_NUM],
+ u8 band, u8 bw, u8 ntx, u8 rs, u8 ch1, u8 ch2)
+{
+ s8 v1[RTW89_BF_NUM];
+ s8 v2[RTW89_BF_NUM];
+ int bf;
+
+ fill_limit_nonbf_bf(rtwdev, &v1, band, bw, ntx, rs, ch1);
+ fill_limit_nonbf_bf(rtwdev, &v2, band, bw, ntx, rs, ch2);
+
+ for (bf = 0; bf < RTW89_BF_NUM; bf++)
+ (*ptr)[bf] = min(v1[bf], v2[bf]);
+}
+
+static void phy_fill_limit_20m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_nonbf_bf(rtwdev, &lmt->cck_20m, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_CCK, ch);
+ fill_limit_nonbf_bf(rtwdev, &lmt->cck_40m, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_CCK, ch);
+ fill_limit_nonbf_bf(rtwdev, &lmt->ofdm, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_OFDM, ch);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[0], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch);
+}
+
+static void phy_fill_limit_40m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
+{
+ fill_limit_nonbf_bf(rtwdev, &lmt->cck_20m, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_CCK, ch - 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->cck_40m, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_CCK, ch);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->ofdm, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_OFDM, pri_ch);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[0], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[1], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[0], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch);
+}
+
+static void phy_fill_limit_80m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
+{
+ fill_limit_nonbf_bf(rtwdev, &lmt->ofdm, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_OFDM, pri_ch);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[0], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[1], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[2], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[3], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[0], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[1], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[0], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch);
+
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_0p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch - 4, ch + 4);
+}
+
+static void phy_fill_limit_160m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
+{
+ fill_limit_nonbf_bf(rtwdev, &lmt->ofdm, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_OFDM, pri_ch);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[0], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 14);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[1], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 10);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[2], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[3], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[4], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[5], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[6], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 10);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[7], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 14);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[0], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 12);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[1], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[2], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[3], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 12);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[0], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch - 8);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[1], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch + 8);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_160m[0], band,
+ RTW89_CHANNEL_WIDTH_160, ntx, RTW89_RS_MCS, ch);
+
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_0p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch - 12, ch - 4);
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_2p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch + 4, ch + 12);
+}
+
+static void phy_fill_limit_320m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 band, u8 ntx, u8 ch, u8 pri_ch)
+{
+ fill_limit_nonbf_bf(rtwdev, &lmt->ofdm, band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_OFDM, pri_ch);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[0], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 30);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[1], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 26);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[2], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 22);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[3], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 18);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[4], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 14);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[5], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 10);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[6], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[7], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch - 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[8], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 2);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[9], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 6);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[10], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 10);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[11], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 14);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[12], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 18);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[13], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 22);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[14], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 26);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_20m[15], band,
+ RTW89_CHANNEL_WIDTH_20, ntx, RTW89_RS_MCS, ch + 30);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[0], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 28);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[1], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 20);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[2], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 12);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[3], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch - 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[4], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 4);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[5], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 12);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[6], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 20);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_40m[7], band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS, ch + 28);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[0], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch - 24);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[1], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch - 8);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[2], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch + 8);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_80m[3], band,
+ RTW89_CHANNEL_WIDTH_80, ntx, RTW89_RS_MCS, ch + 24);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_160m[0], band,
+ RTW89_CHANNEL_WIDTH_160, ntx, RTW89_RS_MCS, ch - 16);
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_160m[1], band,
+ RTW89_CHANNEL_WIDTH_160, ntx, RTW89_RS_MCS, ch + 16);
+
+ fill_limit_nonbf_bf(rtwdev, &lmt->mcs_320m, band,
+ RTW89_CHANNEL_WIDTH_320, ntx, RTW89_RS_MCS, ch);
+
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_0p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch - 28, ch - 20);
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_2p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch - 12, ch - 4);
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_4p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch + 4, ch + 12);
+ fill_limit_nonbf_bf_min(rtwdev, &lmt->mcs_40m_6p5, band,
+ RTW89_CHANNEL_WIDTH_40, ntx, RTW89_RS_MCS,
+ ch + 20, ch + 28);
+}
+
+static void rtw89_phy_fill_limit_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ struct rtw89_txpwr_limit_be *lmt,
+ u8 ntx)
+{
+ u8 band = chan->band_type;
+ u8 pri_ch = chan->primary_channel;
+ u8 ch = chan->channel;
+ u8 bw = chan->band_width;
+
+ memset(lmt, 0, sizeof(*lmt));
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_20:
+ phy_fill_limit_20m_be(rtwdev, lmt, band, ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ phy_fill_limit_40m_be(rtwdev, lmt, band, ntx, ch, pri_ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ phy_fill_limit_80m_be(rtwdev, lmt, band, ntx, ch, pri_ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_160:
+ phy_fill_limit_160m_be(rtwdev, lmt, band, ntx, ch, pri_ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_320:
+ phy_fill_limit_320m_be(rtwdev, lmt, band, ntx, ch, pri_ch);
+ break;
+ }
+}
+
+static void rtw89_phy_set_txpwr_limit_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_txpwr_limit_be lmt;
+ const s8 *ptr;
+ u32 addr, val;
+ u8 i, j;
+
+ BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_be) !=
+ RTW89_TXPWR_LMT_PAGE_SIZE_BE);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] set txpwr limit on band %d bw %d\n",
+ chan->band_type, chan->band_width);
+
+ addr = R_BE_PWR_LMT;
+ for (i = 0; i <= RTW89_NSS_2; i++) {
+ rtw89_phy_fill_limit_be(rtwdev, chan, &lmt, i);
+
+ ptr = (s8 *)&lmt;
+ for (j = 0; j < RTW89_TXPWR_LMT_PAGE_SIZE_BE;
+ j += 4, addr += 4, ptr += 4) {
+ val = u32_encode_bits(ptr[0], GENMASK(7, 0)) |
+ u32_encode_bits(ptr[1], GENMASK(15, 8)) |
+ u32_encode_bits(ptr[2], GENMASK(23, 16)) |
+ u32_encode_bits(ptr[3], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+ }
+ }
+}
+
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.cr_base = 0x20000,
.ccx = &rtw89_ccx_regs_be,
@@ -211,5 +499,6 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be,
.set_txpwr_offset = rtw89_phy_set_txpwr_offset_be,
+ .set_txpwr_limit = rtw89_phy_set_txpwr_limit_be,
};
EXPORT_SYMBOL(rtw89_phy_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 51b074d0782e..62fc2cd12ae5 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3939,6 +3939,7 @@
#define R_BE_PWR_RATE_OFST_CTRL 0x11A30
#define R_BE_PWR_BY_RATE 0x11E00
+#define R_BE_PWR_LMT 0x11FAC
#define CMAC1_START_ADDR_BE 0x14000
#define CMAC1_END_ADDR_BE 0x17FFF
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 5/7] wifi: rtw89: phy: set TX power RU limit according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
` (3 preceding siblings ...)
2023-10-03 1:54 ` [PATCH 4/7] wifi: rtw89: phy: set TX power limit " Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 6/7] wifi: rtw89: debug: show txpwr table " Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 7/7] wifi: rtw89: debug: txpwr table supports Wi-Fi 7 chips Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Wi-Fi 6 chips and Wi-Fi 7 chips have different register design for TX
power RU limit. We rename original setting stuffs with a suffix `_ax`,
concentrate related enum declaration in phy.h, and implement setting
flow for Wi-Fi 7 chips. Then, we set TX power RU limit according to
chip generation.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 10 --
drivers/net/wireless/realtek/rtw89/phy.c | 74 +++++-----
drivers/net/wireless/realtek/rtw89/phy.h | 36 ++++-
drivers/net/wireless/realtek/rtw89/phy_be.c | 141 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 1 +
5 files changed, 214 insertions(+), 48 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 7ef3ebe7f793..06d3c026e1de 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -744,16 +744,6 @@ struct rtw89_txpwr_byrate {
s8 trap;
};
-#define RTW89_RU_SEC_NUM 8
-
-#define RTW89_TXPWR_LMT_RU_PAGE_SIZE 24
-
-struct rtw89_txpwr_limit_ru {
- s8 ru26[RTW89_RU_SEC_NUM];
- s8 ru52[RTW89_RU_SEC_NUM];
- s8 ru106[RTW89_RU_SEC_NUM];
-};
-
struct rtw89_rate_desc {
enum rtw89_nss nss;
enum rtw89_rate_section rs;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 8c5b73294a93..ded15ffa30bb 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1906,8 +1906,8 @@ void rtw89_phy_fill_txpwr_limit_ax(struct rtw89_dev *rtwdev,
}
}
-static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
- u8 ru, u8 ntx, u8 ch)
+s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
+ u8 ru, u8 ntx, u8 ch)
{
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
@@ -1957,9 +1957,9 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
}
static void
-rtw89_phy_fill_txpwr_limit_ru_20m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit_ru *lmt_ru,
- u8 band, u8 ntx, u8 ch)
+rtw89_phy_fill_txpwr_limit_ru_20m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_ax *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
{
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
RTW89_RU26,
@@ -1973,9 +1973,9 @@ rtw89_phy_fill_txpwr_limit_ru_20m(struct rtw89_dev *rtwdev,
}
static void
-rtw89_phy_fill_txpwr_limit_ru_40m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit_ru *lmt_ru,
- u8 band, u8 ntx, u8 ch)
+rtw89_phy_fill_txpwr_limit_ru_40m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_ax *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
{
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
RTW89_RU26,
@@ -1998,9 +1998,9 @@ rtw89_phy_fill_txpwr_limit_ru_40m(struct rtw89_dev *rtwdev,
}
static void
-rtw89_phy_fill_txpwr_limit_ru_80m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit_ru *lmt_ru,
- u8 band, u8 ntx, u8 ch)
+rtw89_phy_fill_txpwr_limit_ru_80m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_ax *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
{
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
RTW89_RU26,
@@ -2041,15 +2041,15 @@ rtw89_phy_fill_txpwr_limit_ru_80m(struct rtw89_dev *rtwdev,
}
static void
-rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
- struct rtw89_txpwr_limit_ru *lmt_ru,
- u8 band, u8 ntx, u8 ch)
+rtw89_phy_fill_txpwr_limit_ru_160m_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_ax *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
{
static const int ofst[] = { -14, -10, -6, -2, 2, 6, 10, 14 };
int i;
- static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM);
- for (i = 0; i < RTW89_RU_SEC_NUM; i++) {
+ static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM_AX);
+ for (i = 0; i < RTW89_RU_SEC_NUM_AX; i++) {
lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
RTW89_RU26,
ntx,
@@ -2066,10 +2066,10 @@ rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
}
static
-void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- struct rtw89_txpwr_limit_ru *lmt_ru,
- u8 ntx)
+void rtw89_phy_fill_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ struct rtw89_txpwr_limit_ru_ax *lmt_ru,
+ u8 ntx)
{
u8 band = chan->band_type;
u8 ch = chan->channel;
@@ -2079,20 +2079,20 @@ void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
switch (bw) {
case RTW89_CHANNEL_WIDTH_20:
- rtw89_phy_fill_txpwr_limit_ru_20m(rtwdev, lmt_ru, band, ntx,
- ch);
+ rtw89_phy_fill_txpwr_limit_ru_20m_ax(rtwdev, lmt_ru, band, ntx,
+ ch);
break;
case RTW89_CHANNEL_WIDTH_40:
- rtw89_phy_fill_txpwr_limit_ru_40m(rtwdev, lmt_ru, band, ntx,
- ch);
+ rtw89_phy_fill_txpwr_limit_ru_40m_ax(rtwdev, lmt_ru, band, ntx,
+ ch);
break;
case RTW89_CHANNEL_WIDTH_80:
- rtw89_phy_fill_txpwr_limit_ru_80m(rtwdev, lmt_ru, band, ntx,
- ch);
+ rtw89_phy_fill_txpwr_limit_ru_80m_ax(rtwdev, lmt_ru, band, ntx,
+ ch);
break;
case RTW89_CHANNEL_WIDTH_160:
- rtw89_phy_fill_txpwr_limit_ru_160m(rtwdev, lmt_ru, band, ntx,
- ch);
+ rtw89_phy_fill_txpwr_limit_ru_160m_ax(rtwdev, lmt_ru, band, ntx,
+ ch);
break;
}
}
@@ -2217,12 +2217,12 @@ static void rtw89_phy_set_txpwr_limit_ax(struct rtw89_dev *rtwdev,
}
}
-void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx)
+static void rtw89_phy_set_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
{
u8 max_ntx_num = rtwdev->chip->rf_path_num;
- struct rtw89_txpwr_limit_ru lmt_ru;
+ struct rtw89_txpwr_limit_ru_ax lmt_ru;
u8 ch = chan->channel;
u8 bw = chan->band_width;
const s8 *ptr;
@@ -2232,15 +2232,15 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
- BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ru) !=
- RTW89_TXPWR_LMT_RU_PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ru_ax) !=
+ RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX);
addr = R_AX_PWR_RU_LMT;
for (i = 0; i < max_ntx_num; i++) {
- rtw89_phy_fill_txpwr_limit_ru(rtwdev, chan, &lmt_ru, i);
+ rtw89_phy_fill_txpwr_limit_ru_ax(rtwdev, chan, &lmt_ru, i);
ptr = (s8 *)&lmt_ru;
- for (j = 0; j < RTW89_TXPWR_LMT_RU_PAGE_SIZE;
+ for (j = 0; j < RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX;
j += 4, addr += 4, ptr += 4) {
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
@@ -2251,7 +2251,6 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
}
}
}
-EXPORT_SYMBOL(rtw89_phy_set_txpwr_limit_ru);
struct rtw89_phy_iter_ra_data {
struct rtw89_dev *rtwdev;
@@ -4837,5 +4836,6 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
.set_txpwr_offset = rtw89_phy_set_txpwr_offset_ax,
.set_txpwr_limit = rtw89_phy_set_txpwr_limit_ax,
+ .set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_ax,
};
EXPORT_SYMBOL(rtw89_phy_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 72bc00bcb04c..9473798b9dac 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -444,6 +444,28 @@ struct rtw89_txpwr_limit_be {
s8 mcs_40m_6p5[RTW89_BF_NUM];
};
+#define RTW89_RU_SEC_NUM_AX 8
+
+#define RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX 24
+
+struct rtw89_txpwr_limit_ru_ax {
+ s8 ru26[RTW89_RU_SEC_NUM_AX];
+ s8 ru52[RTW89_RU_SEC_NUM_AX];
+ s8 ru106[RTW89_RU_SEC_NUM_AX];
+};
+
+#define RTW89_RU_SEC_NUM_BE 16
+
+#define RTW89_TXPWR_LMT_RU_PAGE_SIZE_BE 80
+
+struct rtw89_txpwr_limit_ru_be {
+ s8 ru26[RTW89_RU_SEC_NUM_BE];
+ s8 ru52[RTW89_RU_SEC_NUM_BE];
+ s8 ru106[RTW89_RU_SEC_NUM_BE];
+ s8 ru52_26[RTW89_RU_SEC_NUM_BE];
+ s8 ru106_26[RTW89_RU_SEC_NUM_BE];
+};
+
struct rtw89_phy_gen_def {
u32 cr_base;
const struct rtw89_ccx_regs *ccx;
@@ -458,6 +480,9 @@ struct rtw89_phy_gen_def {
void (*set_txpwr_limit)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
+ void (*set_txpwr_limit_ru)(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
};
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
@@ -676,6 +701,8 @@ void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl);
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
+s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
+ u8 ru, u8 ntx, u8 ch);
static inline
void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
@@ -707,9 +734,16 @@ void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
phy->set_txpwr_limit(rtwdev, chan, phy_idx);
}
+static inline
void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
- enum rtw89_phy_idx phy_idx);
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+
+ phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+}
+
void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 500f24b23d06..f0e1da2c2a91 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -492,6 +492,146 @@ static void rtw89_phy_set_txpwr_limit_be(struct rtw89_dev *rtwdev,
}
}
+static void fill_limit_ru_each(struct rtw89_dev *rtwdev, u8 index,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ lmt_ru->ru26[index] =
+ rtw89_phy_read_txpwr_limit_ru(rtwdev, band, RTW89_RU26, ntx, ch);
+ lmt_ru->ru52[index] =
+ rtw89_phy_read_txpwr_limit_ru(rtwdev, band, RTW89_RU52, ntx, ch);
+ lmt_ru->ru106[index] =
+ rtw89_phy_read_txpwr_limit_ru(rtwdev, band, RTW89_RU106, ntx, ch);
+ lmt_ru->ru52_26[index] =
+ rtw89_phy_read_txpwr_limit_ru(rtwdev, band, RTW89_RU52_26, ntx, ch);
+ lmt_ru->ru106_26[index] =
+ rtw89_phy_read_txpwr_limit_ru(rtwdev, band, RTW89_RU106_26, ntx, ch);
+}
+
+static void phy_fill_limit_ru_20m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_ru_each(rtwdev, 0, lmt_ru, band, ntx, ch);
+}
+
+static void phy_fill_limit_ru_40m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_ru_each(rtwdev, 0, lmt_ru, band, ntx, ch - 2);
+ fill_limit_ru_each(rtwdev, 1, lmt_ru, band, ntx, ch + 2);
+}
+
+static void phy_fill_limit_ru_80m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_ru_each(rtwdev, 0, lmt_ru, band, ntx, ch - 6);
+ fill_limit_ru_each(rtwdev, 1, lmt_ru, band, ntx, ch - 2);
+ fill_limit_ru_each(rtwdev, 2, lmt_ru, band, ntx, ch + 2);
+ fill_limit_ru_each(rtwdev, 3, lmt_ru, band, ntx, ch + 6);
+}
+
+static void phy_fill_limit_ru_160m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_ru_each(rtwdev, 0, lmt_ru, band, ntx, ch - 14);
+ fill_limit_ru_each(rtwdev, 1, lmt_ru, band, ntx, ch - 10);
+ fill_limit_ru_each(rtwdev, 2, lmt_ru, band, ntx, ch - 6);
+ fill_limit_ru_each(rtwdev, 3, lmt_ru, band, ntx, ch - 2);
+ fill_limit_ru_each(rtwdev, 4, lmt_ru, band, ntx, ch + 2);
+ fill_limit_ru_each(rtwdev, 5, lmt_ru, band, ntx, ch + 6);
+ fill_limit_ru_each(rtwdev, 6, lmt_ru, band, ntx, ch + 10);
+ fill_limit_ru_each(rtwdev, 7, lmt_ru, band, ntx, ch + 14);
+}
+
+static void phy_fill_limit_ru_320m_be(struct rtw89_dev *rtwdev,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 band, u8 ntx, u8 ch)
+{
+ fill_limit_ru_each(rtwdev, 0, lmt_ru, band, ntx, ch - 30);
+ fill_limit_ru_each(rtwdev, 1, lmt_ru, band, ntx, ch - 26);
+ fill_limit_ru_each(rtwdev, 2, lmt_ru, band, ntx, ch - 22);
+ fill_limit_ru_each(rtwdev, 3, lmt_ru, band, ntx, ch - 18);
+ fill_limit_ru_each(rtwdev, 4, lmt_ru, band, ntx, ch - 14);
+ fill_limit_ru_each(rtwdev, 5, lmt_ru, band, ntx, ch - 10);
+ fill_limit_ru_each(rtwdev, 6, lmt_ru, band, ntx, ch - 6);
+ fill_limit_ru_each(rtwdev, 7, lmt_ru, band, ntx, ch - 2);
+ fill_limit_ru_each(rtwdev, 8, lmt_ru, band, ntx, ch + 2);
+ fill_limit_ru_each(rtwdev, 9, lmt_ru, band, ntx, ch + 6);
+ fill_limit_ru_each(rtwdev, 10, lmt_ru, band, ntx, ch + 10);
+ fill_limit_ru_each(rtwdev, 11, lmt_ru, band, ntx, ch + 14);
+ fill_limit_ru_each(rtwdev, 12, lmt_ru, band, ntx, ch + 18);
+ fill_limit_ru_each(rtwdev, 13, lmt_ru, band, ntx, ch + 22);
+ fill_limit_ru_each(rtwdev, 14, lmt_ru, band, ntx, ch + 26);
+ fill_limit_ru_each(rtwdev, 15, lmt_ru, band, ntx, ch + 30);
+}
+
+static void rtw89_phy_fill_limit_ru_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ struct rtw89_txpwr_limit_ru_be *lmt_ru,
+ u8 ntx)
+{
+ u8 band = chan->band_type;
+ u8 ch = chan->channel;
+ u8 bw = chan->band_width;
+
+ memset(lmt_ru, 0, sizeof(*lmt_ru));
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_20:
+ phy_fill_limit_ru_20m_be(rtwdev, lmt_ru, band, ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ phy_fill_limit_ru_40m_be(rtwdev, lmt_ru, band, ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ phy_fill_limit_ru_80m_be(rtwdev, lmt_ru, band, ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_160:
+ phy_fill_limit_ru_160m_be(rtwdev, lmt_ru, band, ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_320:
+ phy_fill_limit_ru_320m_be(rtwdev, lmt_ru, band, ntx, ch);
+ break;
+ }
+}
+
+static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_txpwr_limit_ru_be lmt_ru;
+ const s8 *ptr;
+ u32 addr, val;
+ u8 i, j;
+
+ BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ru_be) !=
+ RTW89_TXPWR_LMT_RU_PAGE_SIZE_BE);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] set txpwr limit ru on band %d bw %d\n",
+ chan->band_type, chan->band_width);
+
+ addr = R_BE_PWR_RU_LMT;
+ for (i = 0; i <= RTW89_NSS_2; i++) {
+ rtw89_phy_fill_limit_ru_be(rtwdev, chan, &lmt_ru, i);
+
+ ptr = (s8 *)&lmt_ru;
+ for (j = 0; j < RTW89_TXPWR_LMT_RU_PAGE_SIZE_BE;
+ j += 4, addr += 4, ptr += 4) {
+ val = u32_encode_bits(ptr[0], GENMASK(7, 0)) |
+ u32_encode_bits(ptr[1], GENMASK(15, 8)) |
+ u32_encode_bits(ptr[2], GENMASK(23, 16)) |
+ u32_encode_bits(ptr[3], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+ }
+ }
+}
+
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.cr_base = 0x20000,
.ccx = &rtw89_ccx_regs_be,
@@ -500,5 +640,6 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be,
.set_txpwr_offset = rtw89_phy_set_txpwr_offset_be,
.set_txpwr_limit = rtw89_phy_set_txpwr_limit_be,
+ .set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_be,
};
EXPORT_SYMBOL(rtw89_phy_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 62fc2cd12ae5..27444801996f 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3940,6 +3940,7 @@
#define R_BE_PWR_RATE_OFST_CTRL 0x11A30
#define R_BE_PWR_BY_RATE 0x11E00
#define R_BE_PWR_LMT 0x11FAC
+#define R_BE_PWR_RU_LMT 0x12048
#define CMAC1_START_ADDR_BE 0x14000
#define CMAC1_END_ADDR_BE 0x17FFF
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 6/7] wifi: rtw89: debug: show txpwr table according to chip gen
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
` (4 preceding siblings ...)
2023-10-03 1:54 ` [PATCH 5/7] wifi: rtw89: phy: set TX power RU " Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
2023-10-03 1:54 ` [PATCH 7/7] wifi: rtw89: debug: txpwr table supports Wi-Fi 7 chips Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Since current TX power stuffs are for ax chips, add a suffix `_ax` to
them. Then, when requested to show txpwr table, select table according
to chip generation first.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/debug.c | 60 +++++++++++++++-------
1 file changed, 42 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index d162e64f6064..afdcc596c4a6 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -390,7 +390,7 @@ struct txpwr_map {
_e0 " " _e1 " " _e2 " " _e3 " " \
_e4 " " _e5 " " _e6 " " _e7 }
-static const struct txpwr_ent __txpwr_ent_byr[] = {
+static const struct txpwr_ent __txpwr_ent_byr_ax[] = {
__GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
@@ -406,18 +406,18 @@ static const struct txpwr_ent __txpwr_ent_byr[] = {
__GEN_TXPWR_ENT4("HEDCM_2NSS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
};
-static_assert((ARRAY_SIZE(__txpwr_ent_byr) * 4) ==
+static_assert((ARRAY_SIZE(__txpwr_ent_byr_ax) * 4) ==
(R_AX_PWR_BY_RATE_MAX - R_AX_PWR_BY_RATE + 4));
-static const struct txpwr_map __txpwr_map_byr = {
- .ent = __txpwr_ent_byr,
- .size = ARRAY_SIZE(__txpwr_ent_byr),
+static const struct txpwr_map __txpwr_map_byr_ax = {
+ .ent = __txpwr_ent_byr_ax,
+ .size = ARRAY_SIZE(__txpwr_ent_byr_ax),
.addr_from = R_AX_PWR_BY_RATE,
.addr_to = R_AX_PWR_BY_RATE_MAX,
.addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
};
-static const struct txpwr_ent __txpwr_ent_lmt[] = {
+static const struct txpwr_ent __txpwr_ent_lmt_ax[] = {
/* 1TX */
__GEN_TXPWR_ENT2("CCK_1TX_20M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("CCK_1TX_40M ", "NON_BF", "BF"),
@@ -462,18 +462,18 @@ static const struct txpwr_ent __txpwr_ent_lmt[] = {
__GEN_TXPWR_ENT2("MCS_2TX_40M_2p5", "NON_BF", "BF"),
};
-static_assert((ARRAY_SIZE(__txpwr_ent_lmt) * 2) ==
+static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ax) * 2) ==
(R_AX_PWR_LMT_MAX - R_AX_PWR_LMT + 4));
-static const struct txpwr_map __txpwr_map_lmt = {
- .ent = __txpwr_ent_lmt,
- .size = ARRAY_SIZE(__txpwr_ent_lmt),
+static const struct txpwr_map __txpwr_map_lmt_ax = {
+ .ent = __txpwr_ent_lmt_ax,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ax),
.addr_from = R_AX_PWR_LMT,
.addr_to = R_AX_PWR_LMT_MAX,
.addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
};
-static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
+static const struct txpwr_ent __txpwr_ent_lmt_ru_ax[] = {
/* 1TX */
__GEN_TXPWR_ENT8("1TX", "RU26__0", "RU26__1", "RU26__2", "RU26__3",
"RU26__4", "RU26__5", "RU26__6", "RU26__7"),
@@ -490,12 +490,12 @@ static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
"RU106_4", "RU106_5", "RU106_6", "RU106_7"),
};
-static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru) * 8) ==
+static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru_ax) * 8) ==
(R_AX_PWR_RU_LMT_MAX - R_AX_PWR_RU_LMT + 4));
-static const struct txpwr_map __txpwr_map_lmt_ru = {
- .ent = __txpwr_ent_lmt_ru,
- .size = ARRAY_SIZE(__txpwr_ent_lmt_ru),
+static const struct txpwr_map __txpwr_map_lmt_ru_ax = {
+ .ent = __txpwr_ent_lmt_ru_ax,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ru_ax),
.addr_from = R_AX_PWR_RU_LMT,
.addr_to = R_AX_PWR_RU_LMT_MAX,
.addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
@@ -600,10 +600,28 @@ static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev,
#undef case_REGD
+struct dbgfs_txpwr_table {
+ const struct txpwr_map *byr;
+ const struct txpwr_map *lmt;
+ const struct txpwr_map *lmt_ru;
+};
+
+static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
+ .byr = &__txpwr_map_byr_ax,
+ .lmt = &__txpwr_map_lmt_ax,
+ .lmt_ru = &__txpwr_map_lmt_ru_ax,
+};
+
+static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
+ [RTW89_CHIP_AX] = &dbgfs_txpwr_table_ax,
+};
+
static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
+ enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
+ const struct dbgfs_txpwr_table *tbl;
const struct rtw89_chan *chan;
int ret = 0;
@@ -620,18 +638,24 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
seq_puts(m, "[TAS]\n");
rtw89_print_tas(m, rtwdev);
+ tbl = dbgfs_txpwr_tables[chip_gen];
+ if (!tbl) {
+ ret = -EOPNOTSUPP;
+ goto err;
+ }
+
seq_puts(m, "\n[TX power byrate]\n");
- ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_byr);
+ ret = __print_txpwr_map(m, rtwdev, tbl->byr);
if (ret)
goto err;
seq_puts(m, "\n[TX power limit]\n");
- ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_lmt);
+ ret = __print_txpwr_map(m, rtwdev, tbl->lmt);
if (ret)
goto err;
seq_puts(m, "\n[TX power limit_ru]\n");
- ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_lmt_ru);
+ ret = __print_txpwr_map(m, rtwdev, tbl->lmt_ru);
if (ret)
goto err;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 7/7] wifi: rtw89: debug: txpwr table supports Wi-Fi 7 chips
2023-10-03 1:54 [PATCH 0/7] wifi: rtw89: apply TX power read from firmware file Ping-Ke Shih
` (5 preceding siblings ...)
2023-10-03 1:54 ` [PATCH 6/7] wifi: rtw89: debug: show txpwr table " Ping-Ke Shih
@ 2023-10-03 1:54 ` Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2023-10-03 1:54 UTC (permalink / raw)
To: kvalo; +Cc: kevin_yang, linux-wireless
From: Zong-Zhe Yang <kevin_yang@realtek.com>
We add TX power table format for Wi-Fi 7 chips. Since Wi-Fi 7 tables are
larger, in order to reuse some chunks, we extend code to process nested
entries. Now, dbgfs txpwr_table can work with Wi-Fi 7 chips.
An output example of dbgfs txpwr_table on Wi-Fi 7 chips is shown below.
...
[TX power byrate]
<< BW20 >>
CCK - 1M 2M 5.5M 11M | 20, 20, 20, 20, dBm
LEGACY - 6M 9M 12M 18M | 18, 18, 18, 18, dBm
LEGACY - 24M 36M 48M 54M | 18, 18, 17, 16, dBm
EHT - MCS14 MCS15 | 0, 0, dBm
DLRU_EHT - MCS14 MCS15 | 0, 18, dBm
MCS_1SS - MCS0 MCS1 MCS2 MCS3 | 18, 18, 18, 18, dBm
MCS_1SS - MCS4 MCS5 MCS6 MCS7 | 18, 17, 16, 15, dBm
MCS_1SS - MCS8 MCS9 MCS10 MCS11 | 14, 13, 12, 11, dBm
MCS_1SS - MCS12 MCS13 | 10, 9, dBm
HEDCM_1SS - MCS0 MCS1 MCS3 MCS4 | 18, 18, 18, 18, dBm
DLRU_MCS_1SS - MCS0 MCS1 MCS2 MCS3 | 18, 18, 18, 18, dBm
DLRU_MCS_1SS - MCS4 MCS5 MCS6 MCS7 | 18, 17, 16, 15, dBm
DLRU_MCS_1SS - MCS8 MCS9 MCS10 MCS11 | 14, 13, 12, 11, dBm
DLRU_MCS_1SS - MCS12 MCS13 | 10, 9, dBm
DLRU_HEDCM_1SS - MCS0 MCS1 MCS3 MCS4 | 18, 18, 18, 18, dBm
MCS_2SS - MCS0 MCS1 MCS2 MCS3 | 18, 18, 18, 18, dBm
...
[TX power limit]
<< 1TX >>
CCK_20M - NON_BF BF | 0, 0, dBm
CCK_40M - NON_BF BF | 0, 0, dBm
OFDM - NON_BF BF | 18, 0, dBm
MCS_20M_0 - NON_BF BF | 18, 0, dBm
MCS_20M_1 - NON_BF BF | 0, 0, dBm
...
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/debug.c | 212 ++++++++++++++++++++-
drivers/net/wireless/realtek/rtw89/reg.h | 3 +
2 files changed, 210 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index afdcc596c4a6..6990d3679bc0 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -367,7 +367,11 @@ static int rtw89_debug_priv_rf_reg_dump_get(struct seq_file *m, void *v)
}
struct txpwr_ent {
- const char *txt;
+ bool nested;
+ union {
+ const char *txt;
+ const struct txpwr_ent *ptr;
+ };
u8 len;
};
@@ -379,6 +383,12 @@ struct txpwr_map {
u32 addr_to_1ss;
};
+#define __GEN_TXPWR_ENT_NESTED(_e) \
+ { .nested = true, .ptr = __txpwr_ent_##_e, \
+ .len = ARRAY_SIZE(__txpwr_ent_##_e) }
+
+#define __GEN_TXPWR_ENT0(_t) { .len = 0, .txt = _t }
+
#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
{ .len = 2, .txt = _t "\t- " _e0 " " _e1 }
@@ -501,14 +511,196 @@ static const struct txpwr_map __txpwr_map_lmt_ru_ax = {
.addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
};
-static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
- const s8 *buf, const u8 cur)
+static const struct txpwr_ent __txpwr_ent_byr_mcs_be[] = {
+ __GEN_TXPWR_ENT4("MCS_1SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
+ __GEN_TXPWR_ENT4("MCS_1SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
+ __GEN_TXPWR_ENT4("MCS_1SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
+ __GEN_TXPWR_ENT2("MCS_1SS ", "MCS12 ", "MCS13 \t"),
+ __GEN_TXPWR_ENT4("HEDCM_1SS ", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
+ __GEN_TXPWR_ENT2("DLRU_MCS_1SS ", "MCS12 ", "MCS13 \t"),
+ __GEN_TXPWR_ENT4("DLRU_HEDCM_1SS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
+ __GEN_TXPWR_ENT4("MCS_2SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
+ __GEN_TXPWR_ENT4("MCS_2SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
+ __GEN_TXPWR_ENT4("MCS_2SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
+ __GEN_TXPWR_ENT2("MCS_2SS ", "MCS12 ", "MCS13 \t"),
+ __GEN_TXPWR_ENT4("HEDCM_2SS ", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
+ __GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
+ __GEN_TXPWR_ENT2("DLRU_MCS_2SS ", "MCS12 ", "MCS13 \t"),
+ __GEN_TXPWR_ENT4("DLRU_HEDCM_2SS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
+};
+
+static const struct txpwr_ent __txpwr_ent_byr_be[] = {
+ __GEN_TXPWR_ENT0("BW20"),
+ __GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
+ __GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
+
+ __GEN_TXPWR_ENT0("BW40"),
+ __GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
+ __GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
+
+ /* there is no CCK section after BW80 */
+ __GEN_TXPWR_ENT0("BW80"),
+ __GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
+ __GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
+
+ __GEN_TXPWR_ENT0("BW160"),
+ __GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
+ __GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
+
+ __GEN_TXPWR_ENT0("BW320"),
+ __GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
+ __GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
+ __GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
+ __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
+};
+
+static const struct txpwr_map __txpwr_map_byr_be = {
+ .ent = __txpwr_ent_byr_be,
+ .size = ARRAY_SIZE(__txpwr_ent_byr_be),
+ .addr_from = R_BE_PWR_BY_RATE,
+ .addr_to = R_BE_PWR_BY_RATE_MAX,
+ .addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_mcs_be[] = {
+ __GEN_TXPWR_ENT2("MCS_20M_0 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_1 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_2 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_3 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_4 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_5 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_6 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_7 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_8 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_9 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_10 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_11 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_12 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_13 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_14 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_20M_15 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_0 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_1 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_2 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_3 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_4 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_5 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_6 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_7 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_80M_0 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_80M_1 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_80M_2 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_80M_3 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_160M_0 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_160M_1 ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_320M ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_0p5", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_2p5", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_4p5", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("MCS_40M_6p5", "NON_BF", "BF"),
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_be[] = {
+ __GEN_TXPWR_ENT0("1TX"),
+ __GEN_TXPWR_ENT2("CCK_20M ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("CCK_40M ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("OFDM ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
+
+ __GEN_TXPWR_ENT0("2TX"),
+ __GEN_TXPWR_ENT2("CCK_20M ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("CCK_40M ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT2("OFDM ", "NON_BF", "BF"),
+ __GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_be = {
+ .ent = __txpwr_ent_lmt_be,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_be),
+ .addr_from = R_BE_PWR_LMT,
+ .addr_to = R_BE_PWR_LMT_MAX,
+ .addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru_indexes_be[] = {
+ __GEN_TXPWR_ENT8("RU26 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
+ "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
+ __GEN_TXPWR_ENT8("RU26 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
+ "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
+ __GEN_TXPWR_ENT8("RU52 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
+ "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
+ __GEN_TXPWR_ENT8("RU52 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
+ "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
+ __GEN_TXPWR_ENT8("RU106 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
+ "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
+ __GEN_TXPWR_ENT8("RU106 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
+ "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
+ __GEN_TXPWR_ENT8("RU52_26 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
+ "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
+ __GEN_TXPWR_ENT8("RU52_26 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
+ "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
+ __GEN_TXPWR_ENT8("RU106_26", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
+ "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
+ __GEN_TXPWR_ENT8("RU106_26", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
+ "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru_be[] = {
+ __GEN_TXPWR_ENT0("1TX"),
+ __GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
+
+ __GEN_TXPWR_ENT0("2TX"),
+ __GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru_be = {
+ .ent = __txpwr_ent_lmt_ru_be,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ru_be),
+ .addr_from = R_BE_PWR_RU_LMT,
+ .addr_to = R_BE_PWR_RU_LMT_MAX,
+ .addr_to_1ss = 0, /* not support */
+};
+
+static unsigned int
+__print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
+ const s8 *buf, const unsigned int cur)
{
+ unsigned int cnt, i;
char *fmt;
+ if (ent->nested) {
+ for (cnt = 0, i = 0; i < ent->len; i++)
+ cnt += __print_txpwr_ent(m, ent->ptr + i, buf,
+ cur + cnt);
+ return cnt;
+ }
+
switch (ent->len) {
+ case 0:
+ seq_printf(m, "\t<< %s >>\n", ent->txt);
+ return 0;
case 2:
- fmt = "%s\t| %3d, %3d,\tdBm\n";
+ fmt = "%s\t| %3d, %3d,\t\tdBm\n";
seq_printf(m, fmt, ent->txt, buf[cur], buf[cur + 1]);
return 2;
case 4:
@@ -532,10 +724,10 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
{
u8 fct = rtwdev->chip->txpwr_factor_mac;
u8 path_num = rtwdev->chip->rf_path_num;
+ unsigned int cur, i;
u32 max_valid_addr;
u32 val, addr;
s8 *buf, tmp;
- u8 cur, i;
int ret;
buf = vzalloc(map->addr_to - map->addr_from + 4);
@@ -547,6 +739,9 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
else
max_valid_addr = map->addr_to;
+ if (max_valid_addr == 0)
+ return -EOPNOTSUPP;
+
for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
if (ret)
@@ -612,8 +807,15 @@ static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
.lmt_ru = &__txpwr_map_lmt_ru_ax,
};
+static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
+ .byr = &__txpwr_map_byr_be,
+ .lmt = &__txpwr_map_lmt_be,
+ .lmt_ru = &__txpwr_map_lmt_ru_be,
+};
+
static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
[RTW89_CHIP_AX] = &dbgfs_txpwr_table_ax,
+ [RTW89_CHIP_BE] = &dbgfs_txpwr_table_be,
};
static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 27444801996f..2494c919bdce 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -3939,8 +3939,11 @@
#define R_BE_PWR_RATE_OFST_CTRL 0x11A30
#define R_BE_PWR_BY_RATE 0x11E00
+#define R_BE_PWR_BY_RATE_MAX 0x11FA8
#define R_BE_PWR_LMT 0x11FAC
+#define R_BE_PWR_LMT_MAX 0x12040
#define R_BE_PWR_RU_LMT 0x12048
+#define R_BE_PWR_RU_LMT_MAX 0x120E4
#define CMAC1_START_ADDR_BE 0x14000
#define CMAC1_END_ADDR_BE 0x17FFF
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread