* [PATCH rtw-next 1/7] wifi: rtw89: 8922d: add definition of quota, registers and efuse block
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 2/7] wifi: rtw89: 8922d: add power on/off functions Ping-Ke Shih
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The quota is used to configure memory size for TX/RX, and the definition
of registers includes H2C command, C2H event, WoWLAN reason, IMR of CMAC
and DMAC, ACK rate selector, RF kill GPIO, and BB functions of dynamic
initial gain and EDCCA. The layout of efuse block is to define logic
map of efuse, such as MAC address and RF calibration values.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/reg.h | 30 +++
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 238 ++++++++++++++++++
drivers/net/wireless/realtek/rtw89/rtw8922d.h | 10 +
3 files changed, 278 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8922d.c
create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8922d.h
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 9b605617c3f0..2cb35458a822 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8737,6 +8737,7 @@
#define R_PHY_STS_BITMAP_EHT 0x0788
#define R_PHY_STS_BITMAP_EHT_BE4 0x20788
#define R_EDCCA_RPTREG_SEL_BE 0x078C
+#define R_EDCCA_RPTREG_SEL_BE4 0x2078C
#define B_EDCCA_RPTREG_SEL_BE_MSK GENMASK(22, 20)
#define R_PMAC_GNT 0x0980
#define B_PMAC_GNT_TXEN BIT(0)
@@ -8850,6 +8851,7 @@
#define R_UDP_COEEF 0x0CBC
#define B_UDP_COEEF BIT(19)
#define R_TX_COLLISION_T2R_ST_BE 0x0CC8
+#define R_TX_COLLISION_T2R_ST_BE4 0x20CC8
#define B_TX_COLLISION_T2R_ST_BE_M GENMASK(13, 8)
#define R_RXHT_MCS_LIMIT 0x0D18
#define B_RXHT_MCS_LIMIT GENMASK(9, 8)
@@ -9078,7 +9080,11 @@
#define R_P1_EN_SOUND_WO_NDP 0x2D7C
#define B_P1_EN_SOUND_WO_NDP BIT(1)
#define R_EDCCA_RPT_A_BE 0x2E38
+#define R_EDCCA_RPT_A_BE4 0x2EE30
+#define R_EDCCA_RPT_A_BE4_C1 0x2FE30
#define R_EDCCA_RPT_B_BE 0x2E3C
+#define R_EDCCA_RPT_B_BE4 0x2EE34
+#define R_EDCCA_RPT_B_BE4_C1 0x2FE34
#define R_EDCCA_RPT_P1_A_BE 0x2E40
#define R_EDCCA_RPT_P1_B_BE 0x2E44
#define R_S1_HW_SI_DIS 0x3200
@@ -9262,11 +9268,13 @@
#define R_PATH0_P20_FOLLOW_BY_PAGCUGC_V1 0x4C24
#define R_PATH0_P20_FOLLOW_BY_PAGCUGC_V2 0x46E8
#define R_PATH0_P20_FOLLOW_BY_PAGCUGC_V3 0x41C8
+#define R_PATH0_P20_FOLLOW_BY_PAGCUGC_BE4 0x241C8
#define B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK BIT(5)
#define R_PATH0_S20_FOLLOW_BY_PAGCUGC 0x46A4
#define R_PATH0_S20_FOLLOW_BY_PAGCUGC_V1 0x4C28
#define R_PATH0_S20_FOLLOW_BY_PAGCUGC_V2 0x46EC
#define R_PATH0_S20_FOLLOW_BY_PAGCUGC_V3 0x41CC
+#define R_PATH0_S20_FOLLOW_BY_PAGCUGC_BE4 0x241CC
#define B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK BIT(5)
#define R_PATH0_RXB_INIT_V1 0x46A8
#define B_PATH0_RXB_INIT_IDX_MSK_V1 GENMASK(14, 10)
@@ -9313,11 +9321,13 @@
#define R_PATH1_P20_FOLLOW_BY_PAGCUGC_V1 0x4CE8
#define R_PATH1_P20_FOLLOW_BY_PAGCUGC_V2 0x47A8
#define R_PATH1_P20_FOLLOW_BY_PAGCUGC_V3 0x45C8
+#define R_PATH1_P20_FOLLOW_BY_PAGCUGC_BE4 0x245C8
#define B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK BIT(5)
#define R_PATH1_S20_FOLLOW_BY_PAGCUGC 0x4778
#define R_PATH1_S20_FOLLOW_BY_PAGCUGC_V1 0x4CEC
#define R_PATH1_S20_FOLLOW_BY_PAGCUGC_V2 0x47AC
#define R_PATH1_S20_FOLLOW_BY_PAGCUGC_V3 0x45CC
+#define R_PATH1_S20_FOLLOW_BY_PAGCUGC_BE4 0x245CC
#define B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK BIT(5)
#define R_PATH1_G_TIA0_LNA6_OP1DB_V1 0x4778
#define B_PATH1_G_TIA0_LNA6_OP1DB_V1 GENMASK(7, 0)
@@ -9338,6 +9348,7 @@
#define R_SEG0R_PD 0x481C
#define R_SEG0R_PD_V1 0x4860
#define R_SEG0R_PD_V2 0x6A74
+#define R_SEG0R_PD_BE4 0x26210
#define R_SEG0R_EDCCA_LVL 0x4840
#define R_SEG0R_EDCCA_LVL_V1 0x4884
#define B_EDCCA_LVL_MSK3 GENMASK(31, 24)
@@ -9476,9 +9487,11 @@
#define B_DCFO_COMP_S0_V1_MSK GENMASK(13, 0)
#define R_BMODE_PDTH_V1 0x4B64
#define R_BMODE_PDTH_V2 0x6708
+#define R_BMODE_PDTH_BE4 0x26040
#define B_BMODE_PDTH_LOWER_BOUND_MSK_V1 GENMASK(31, 24)
#define R_BMODE_PDTH_EN_V1 0x4B74
#define R_BMODE_PDTH_EN_V2 0x6718
+#define R_BMODE_PDTH_EN_BE4 0x26050
#define B_BMODE_PDTH_LIMIT_EN_MSK_V1 BIT(30)
#define R_BSS_CLR_VLD_V2 0x4EBC
#define B_BSS_CLR_VLD0_V2 BIT(2)
@@ -9653,7 +9666,9 @@
#define R_CCK_FC0INV 0x675c
#define B_CCK_FC0INV GENMASK(18, 0)
#define R_SEG0R_EDCCA_LVL_BE 0x69EC
+#define R_SEG0R_EDCCA_LVL_BE4 0x2623C
#define R_SEG0R_PPDU_LVL_BE 0x69F0
+#define R_SEG0R_PPDU_LVL_BE4 0x26240
#define R_SEGSND 0x6A14
#define B_SEGSND_EN BIT(31)
#define R_DBCC 0x6B48
@@ -10380,6 +10395,9 @@
#define B_SW_SI_DATA_DAT_BE4 GENMASK(19, 0)
#define R_SW_SI_READ_ADDR_BE4 0x20378
#define B_SW_SI_READ_ADDR_BE4 GENMASK(10, 0)
+#define R_EDCCA_RPT_SEL_BE4 0x20780
+#define R_EDCCA_RPT_SEL_BE4_C1 0x21780
+#define B_EDCCA_RPT_SEL_BE4_MSK 0xE0000
#define R_IFS_T1_AVG_BE4 0x20EDC
#define B_IFS_T1_AVG_BE4 GENMASK(15, 0)
#define B_IFS_T2_AVG_BE4 GENMASK(31, 16)
@@ -10402,6 +10420,18 @@
#define B_IFS_T3_HIS_BE4 GENMASK(15, 0)
#define B_IFS_T4_HIS_BE4 GENMASK(31, 16)
+#define R_PATH0_RXIDX_INIT_BE4 0x24108
+#define B_PATH0_RXIDX_INIT_BE4 GENMASK(29, 25)
+#define R_PATH0_LNA_INIT_BE4 0x24158
+#define B_PATH0_LNA_INIT_IDX_BE4 GENMASK(14, 12)
+#define R_PATH0_TIA_INIT_BE4 0x24168
+#define B_PATH0_TIA_INIT_IDX_BE4 BIT(18)
+#define R_PATH1_RXIDX_INIT_BE4 0x24508
+#define B_PATH1_RXIDX_INIT_BE4 GENMASK(29, 25)
+#define R_PATH1_LNA_INIT_BE4 0x24558
+#define B_PATH1_LNA_INIT_IDX_BE4 GENMASK(14, 12)
+#define R_PATH1_TIA_INIT_BE4 0x24568
+#define B_PATH1_TIA_INIT_IDX_BE4 BIT(18)
#define R_TX_CFR_MANUAL_EN_BE4 0x2483C
#define B_TX_CFR_MANUAL_EN_BE4_M BIT(30)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
new file mode 100644
index 000000000000..6a90ded1b33e
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2026 Realtek Corporation
+ */
+
+#include "efuse.h"
+#include "mac.h"
+#include "reg.h"
+#include "rtw8922d.h"
+
+#define RTW8922D_FW_FORMAT_MAX 0
+#define RTW8922D_FW_BASENAME "rtw89/rtw8922d_fw"
+#define RTW8922D_MODULE_FIRMWARE \
+ RTW89_GEN_MODULE_FWNAME(RTW8922D_FW_BASENAME, RTW8922D_FW_FORMAT_MAX)
+
+#define RTW8922DS_FW_FORMAT_MAX 0
+#define RTW8922DS_FW_BASENAME "rtw89/rtw8922ds_fw"
+#define RTW8922DS_MODULE_FIRMWARE \
+ RTW89_GEN_MODULE_FWNAME(RTW8922DS_FW_BASENAME, RTW8922DS_FW_FORMAT_MAX)
+
+static const struct rtw89_hfc_ch_cfg rtw8922d_hfc_chcfg_pcie[] = {
+ {2, 603, 0}, /* ACH 0 */
+ {0, 601, 0}, /* ACH 1 */
+ {2, 603, 0}, /* ACH 2 */
+ {0, 601, 0}, /* ACH 3 */
+ {2, 603, 0}, /* ACH 4 */
+ {0, 601, 0}, /* ACH 5 */
+ {2, 603, 0}, /* ACH 6 */
+ {0, 601, 0}, /* ACH 7 */
+ {2, 603, 0}, /* B0MGQ */
+ {0, 601, 0}, /* B0HIQ */
+ {2, 603, 0}, /* B1MGQ */
+ {0, 601, 0}, /* B1HIQ */
+ {0, 0, 0}, /* FWCMDQ */
+ {0, 0, 0}, /* BMC */
+ {0, 0, 0}, /* H2D */
+};
+
+static const struct rtw89_hfc_pub_cfg rtw8922d_hfc_pubcfg_pcie = {
+ 613, /* Group 0 */
+ 0, /* Group 1 */
+ 613, /* Public Max */
+ 0, /* WP threshold */
+};
+
+static const struct rtw89_hfc_param_ini rtw8922d_hfc_param_ini_pcie[] = {
+ [RTW89_QTA_SCC] = {rtw8922d_hfc_chcfg_pcie, &rtw8922d_hfc_pubcfg_pcie,
+ &rtw89_mac_size.hfc_prec_cfg_c0, RTW89_HCIFC_POH},
+ [RTW89_QTA_DBCC] = {rtw8922d_hfc_chcfg_pcie, &rtw8922d_hfc_pubcfg_pcie,
+ &rtw89_mac_size.hfc_prec_cfg_c0, RTW89_HCIFC_POH},
+ [RTW89_QTA_DLFW] = {NULL, NULL, &rtw89_mac_size.hfc_prec_cfg_c2,
+ RTW89_HCIFC_POH},
+ [RTW89_QTA_INVALID] = {NULL},
+};
+
+static const struct rtw89_dle_mem rtw8922d_dle_mem_pcie[] = {
+ [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size16_v1,
+ &rtw89_mac_size.ple_size20_v1, &rtw89_mac_size.wde_qt19_v1,
+ &rtw89_mac_size.wde_qt19_v1, &rtw89_mac_size.ple_qt42_v2,
+ &rtw89_mac_size.ple_qt43_v2, &rtw89_mac_size.ple_rsvd_qt9,
+ &rtw89_mac_size.rsvd0_size6, &rtw89_mac_size.rsvd1_size2,
+ &rtw89_mac_size.dle_input18},
+ [RTW89_QTA_DBCC] = {RTW89_QTA_DBCC, &rtw89_mac_size.wde_size16_v1,
+ &rtw89_mac_size.ple_size20_v1, &rtw89_mac_size.wde_qt19_v1,
+ &rtw89_mac_size.wde_qt19_v1, &rtw89_mac_size.ple_qt42_v2,
+ &rtw89_mac_size.ple_qt43_v2, &rtw89_mac_size.ple_rsvd_qt9,
+ &rtw89_mac_size.rsvd0_size6, &rtw89_mac_size.rsvd1_size2,
+ &rtw89_mac_size.dle_input18},
+ [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size18_v1,
+ &rtw89_mac_size.ple_size22_v1, &rtw89_mac_size.wde_qt3,
+ &rtw89_mac_size.wde_qt3, &rtw89_mac_size.ple_qt5_v2,
+ &rtw89_mac_size.ple_qt5_v2, &rtw89_mac_size.ple_rsvd_qt1,
+ &rtw89_mac_size.rsvd0_size6, &rtw89_mac_size.rsvd1_size2,
+ &rtw89_mac_size.dle_input3},
+ [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL,
+ NULL},
+};
+
+static const u32 rtw8922d_h2c_regs[RTW89_H2CREG_MAX] = {
+ R_BE_H2CREG_DATA0, R_BE_H2CREG_DATA1, R_BE_H2CREG_DATA2,
+ R_BE_H2CREG_DATA3
+};
+
+static const u32 rtw8922d_c2h_regs[RTW89_H2CREG_MAX] = {
+ R_BE_C2HREG_DATA0, R_BE_C2HREG_DATA1, R_BE_C2HREG_DATA2,
+ R_BE_C2HREG_DATA3
+};
+
+static const u32 rtw8922d_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = {
+ R_BE_DBG_WOW, R_BE_DBG_WOW,
+};
+
+static const struct rtw89_page_regs rtw8922d_page_regs = {
+ .hci_fc_ctrl = R_BE_HCI_FC_CTRL,
+ .ch_page_ctrl = R_BE_CH_PAGE_CTRL,
+ .ach_page_ctrl = R_BE_CH0_PAGE_CTRL,
+ .ach_page_info = R_BE_CH0_PAGE_INFO,
+ .pub_page_info3 = R_BE_PUB_PAGE_INFO3,
+ .pub_page_ctrl1 = R_BE_PUB_PAGE_CTRL1,
+ .pub_page_ctrl2 = R_BE_PUB_PAGE_CTRL2,
+ .pub_page_info1 = R_BE_PUB_PAGE_INFO1,
+ .pub_page_info2 = R_BE_PUB_PAGE_INFO2,
+ .wp_page_ctrl1 = R_BE_WP_PAGE_CTRL1,
+ .wp_page_ctrl2 = R_BE_WP_PAGE_CTRL2,
+ .wp_page_info1 = R_BE_WP_PAGE_INFO1,
+};
+
+static const struct rtw89_reg_imr rtw8922d_imr_dmac_regs[] = {
+ {R_BE_HCI_BUF_IMR, B_BE_HCI_BUF_IMR_CLR, B_BE_HCI_BUF_IMR_SET},
+ {R_BE_DISP_HOST_IMR, B_BE_DISP_HOST_IMR_CLR_V1, B_BE_DISP_HOST_IMR_SET_V1},
+ {R_BE_DISP_CPU_IMR, B_BE_DISP_CPU_IMR_CLR_V1, B_BE_DISP_CPU_IMR_SET_V1},
+ {R_BE_DISP_OTHER_IMR, B_BE_DISP_OTHER_IMR_CLR_V1, B_BE_DISP_OTHER_IMR_SET_V1},
+ {R_BE_PKTIN_ERR_IMR, B_BE_PKTIN_ERR_IMR_CLR, B_BE_PKTIN_ERR_IMR_SET},
+ {R_BE_MLO_ERR_IDCT_IMR, B_BE_MLO_ERR_IDCT_IMR_CLR, B_BE_MLO_ERR_IDCT_IMR_SET},
+ {R_BE_MPDU_TX_ERR_IMR, B_BE_MPDU_TX_ERR_IMR_CLR, B_BE_MPDU_TX_ERR_IMR_SET},
+ {R_BE_MPDU_RX_ERR_IMR, B_BE_MPDU_RX_ERR_IMR_CLR, B_BE_MPDU_RX_ERR_IMR_SET},
+ {R_BE_SEC_ERROR_IMR, B_BE_SEC_ERROR_IMR_CLR, B_BE_SEC_ERROR_IMR_SET},
+ {R_BE_CPUIO_ERR_IMR, B_BE_CPUIO_ERR_IMR_CLR, B_BE_CPUIO_ERR_IMR_SET},
+ {R_BE_WDE_ERR_IMR, B_BE_WDE_ERR_IMR_CLR, B_BE_WDE_ERR_IMR_SET},
+ {R_BE_PLE_ERR_IMR, B_BE_PLE_ERR_IMR_CLR, B_BE_PLE_ERR_IMR_SET},
+ {R_BE_WDRLS_ERR_IMR, B_BE_WDRLS_ERR_IMR_CLR, B_BE_WDRLS_ERR_IMR_SET},
+ {R_BE_TXPKTCTL_B0_ERRFLAG_IMR, B_BE_TXPKTCTL_B0_ERRFLAG_IMR_CLR,
+ B_BE_TXPKTCTL_B0_ERRFLAG_IMR_SET},
+ {R_BE_TXPKTCTL_B1_ERRFLAG_IMR, B_BE_TXPKTCTL_B1_ERRFLAG_IMR_CLR,
+ B_BE_TXPKTCTL_B1_ERRFLAG_IMR_SET},
+ {R_BE_BBRPT_COM_ERR_IMR, B_BE_BBRPT_COM_ERR_IMR_CLR, B_BE_BBRPT_COM_ERR_IMR_SET},
+ {R_BE_BBRPT_CHINFO_ERR_IMR, B_BE_BBRPT_CHINFO_ERR_IMR_CLR,
+ B_BE_BBRPT_CHINFO_ERR_IMR_SET},
+ {R_BE_BBRPT_DFS_ERR_IMR, B_BE_BBRPT_DFS_ERR_IMR_CLR, B_BE_BBRPT_DFS_ERR_IMR_SET},
+ {R_BE_LA_ERRFLAG_IMR, B_BE_LA_ERRFLAG_IMR_CLR, B_BE_LA_ERRFLAG_IMR_SET},
+ {R_BE_CH_INFO_DBGFLAG_IMR, B_BE_CH_INFO_DBGFLAG_IMR_CLR, B_BE_CH_INFO_DBGFLAG_IMR_SET},
+ {R_BE_PLRLS_ERR_IMR_V1, B_BE_PLRLS_ERR_IMR_V1_CLR, B_BE_PLRLS_ERR_IMR_V1_SET},
+ {R_BE_HAXI_IDCT_MSK, B_BE_HAXI_IDCT_MSK_CLR, B_BE_HAXI_IDCT_MSK_SET},
+};
+
+static const struct rtw89_imr_table rtw8922d_imr_dmac_table = {
+ .regs = rtw8922d_imr_dmac_regs,
+ .n_regs = ARRAY_SIZE(rtw8922d_imr_dmac_regs),
+};
+
+static const struct rtw89_reg_imr rtw8922d_imr_cmac_regs[] = {
+ {R_BE_RESP_IMR, B_BE_RESP_IMR_CLR_V1, B_BE_RESP_IMR_SET_V1},
+ {R_BE_RESP_IMR1, B_BE_RESP_IMR1_CLR, B_BE_RESP_IMR1_SET},
+ {R_BE_RX_ERROR_FLAG_IMR, B_BE_RX_ERROR_FLAG_IMR_CLR_V1, B_BE_RX_ERROR_FLAG_IMR_SET_V1},
+ {R_BE_TX_ERROR_FLAG_IMR, B_BE_TX_ERROR_FLAG_IMR_CLR, B_BE_TX_ERROR_FLAG_IMR_SET},
+ {R_BE_RX_ERROR_FLAG_IMR_1, B_BE_TX_ERROR_FLAG_IMR_1_CLR, B_BE_TX_ERROR_FLAG_IMR_1_SET},
+ {R_BE_PTCL_IMR1, B_BE_PTCL_IMR1_CLR, B_BE_PTCL_IMR1_SET},
+ {R_BE_PTCL_IMR0, B_BE_PTCL_IMR0_CLR, B_BE_PTCL_IMR0_SET},
+ {R_BE_PTCL_IMR_2, B_BE_PTCL_IMR_2_CLR, B_BE_PTCL_IMR_2_SET},
+ {R_BE_SCHEDULE_ERR_IMR, B_BE_SCHEDULE_ERR_IMR_CLR, B_BE_SCHEDULE_ERR_IMR_SET},
+ {R_BE_C0_TXPWR_IMR, B_BE_C0_TXPWR_IMR_CLR, B_BE_C0_TXPWR_IMR_SET},
+ {R_BE_TRXPTCL_ERROR_INDICA_MASK, B_BE_TRXPTCL_ERROR_INDICA_MASK_CLR,
+ B_BE_TRXPTCL_ERROR_INDICA_MASK_SET},
+ {R_BE_RX_ERR_IMR, B_BE_RX_ERR_IMR_CLR, B_BE_RX_ERR_IMR_SET},
+ {R_BE_PHYINFO_ERR_IMR_V1, B_BE_PHYINFO_ERR_IMR_V1_CLR, B_BE_PHYINFO_ERR_IMR_V1_SET},
+};
+
+static const struct rtw89_imr_table rtw8922d_imr_cmac_table = {
+ .regs = rtw8922d_imr_cmac_regs,
+ .n_regs = ARRAY_SIZE(rtw8922d_imr_cmac_regs),
+};
+
+static const struct rtw89_rrsr_cfgs rtw8922d_rrsr_cfgs = {
+ .ref_rate = {R_BE_TRXPTCL_RESP_1, B_BE_WMAC_RESP_REF_RATE_SEL, 0},
+ .rsc = {R_BE_PTCL_RRSR1, B_BE_RSC_MASK, 2},
+};
+
+static const struct rtw89_rfkill_regs rtw8922d_rfkill_regs = {
+ .pinmux = {R_BE_GPIO8_15_FUNC_SEL,
+ B_BE_PINMUX_GPIO9_FUNC_SEL_MASK,
+ 0xf},
+ .mode = {R_BE_GPIO_EXT_CTRL + 2,
+ (B_BE_GPIO_MOD_9 | B_BE_GPIO_IO_SEL_9) >> 16,
+ 0x0},
+};
+
+static const struct rtw89_dig_regs rtw8922d_dig_regs = {
+ .seg0_pd_reg = R_SEG0R_PD_BE4,
+ .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
+ .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
+ .bmode_pd_reg = R_BMODE_PDTH_EN_BE4,
+ .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
+ .bmode_pd_lower_bound_reg = R_BMODE_PDTH_BE4,
+ .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
+ .p0_lna_init = {R_PATH0_LNA_INIT_BE4, B_PATH0_LNA_INIT_IDX_BE4},
+ .p1_lna_init = {R_PATH1_LNA_INIT_BE4, B_PATH1_LNA_INIT_IDX_BE4},
+ .p0_tia_init = {R_PATH0_TIA_INIT_BE4, B_PATH0_TIA_INIT_IDX_BE4},
+ .p1_tia_init = {R_PATH1_TIA_INIT_BE4, B_PATH1_TIA_INIT_IDX_BE4},
+ .p0_rxb_init = {R_PATH0_RXIDX_INIT_BE4, B_PATH0_RXIDX_INIT_BE4},
+ .p1_rxb_init = {R_PATH1_RXIDX_INIT_BE4, B_PATH1_RXIDX_INIT_BE4},
+ .p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_BE4,
+ B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_BE4,
+ B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_BE4,
+ B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_BE4,
+ B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+};
+
+static const struct rtw89_edcca_regs rtw8922d_edcca_regs = {
+ .edcca_level = R_SEG0R_EDCCA_LVL_BE4,
+ .edcca_mask = B_EDCCA_LVL_MSK0,
+ .edcca_p_mask = B_EDCCA_LVL_MSK1,
+ .ppdu_level = R_SEG0R_PPDU_LVL_BE4,
+ .ppdu_mask = B_EDCCA_LVL_MSK1,
+ .p = {{
+ .rpt_a = R_EDCCA_RPT_A_BE4,
+ .rpt_b = R_EDCCA_RPT_B_BE4,
+ .rpt_sel = R_EDCCA_RPT_SEL_BE4,
+ .rpt_sel_mask = B_EDCCA_RPT_SEL_BE4_MSK,
+ }, {
+ .rpt_a = R_EDCCA_RPT_A_BE4_C1,
+ .rpt_b = R_EDCCA_RPT_A_BE4_C1,
+ .rpt_sel = R_EDCCA_RPT_SEL_BE4_C1,
+ .rpt_sel_mask = B_EDCCA_RPT_SEL_BE4_MSK,
+ }},
+ .rpt_sel_be = R_EDCCA_RPTREG_SEL_BE4,
+ .rpt_sel_be_mask = B_EDCCA_RPTREG_SEL_BE_MSK,
+ .tx_collision_t2r_st = R_TX_COLLISION_T2R_ST_BE4,
+ .tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_BE_M,
+};
+
+static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
+ [RTW89_EFUSE_BLOCK_SYS] = {.offset = 0x00000, .size = 0x310},
+ [RTW89_EFUSE_BLOCK_RF] = {.offset = 0x10000, .size = 0x240},
+ [RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO] = {.offset = 0x20000, .size = 0x4800},
+ [RTW89_EFUSE_BLOCK_HCI_DIG_USB] = {.offset = 0x30000, .size = 0x890},
+ [RTW89_EFUSE_BLOCK_HCI_PHY_PCIE] = {.offset = 0x40000, .size = 0x400},
+ [RTW89_EFUSE_BLOCK_HCI_PHY_USB3] = {.offset = 0x50000, .size = 0x80},
+ [RTW89_EFUSE_BLOCK_HCI_PHY_USB2] = {.offset = 0x60000, .size = 0x50},
+ [RTW89_EFUSE_BLOCK_ADIE] = {.offset = 0x70000, .size = 0x10},
+};
+
+MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
+MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11be wireless 8922D driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.h b/drivers/net/wireless/realtek/rtw89/rtw8922d.h
new file mode 100644
index 000000000000..7ef3f263274e
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2026 Realtek Corporation
+ */
+
+#ifndef __RTW89_8922D_H__
+#define __RTW89_8922D_H__
+
+#include "core.h"
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH rtw-next 2/7] wifi: rtw89: 8922d: add power on/off functions
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 1/7] wifi: rtw89: 8922d: add definition of quota, registers and efuse block Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 3/7] wifi: rtw89: 8922d: define efuse map and read necessary fields Ping-Ke Shih
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The power on function is the first entry to power on hardware including
all MAC/BB/RF circuits, and then it becomes possible to do high level
operations, such as WiFi scan, connection.
If connection becomes unavailable, device stays into idle mode, calling
power off function to cut power.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/reg.h | 63 +++++
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 237 ++++++++++++++++++
2 files changed, 300 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 2cb35458a822..b6fd7b434de9 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -4403,6 +4403,31 @@
#define B_BE_FS_GPIO17_INT_EN BIT(1)
#define B_BE_FS_GPIO16_INT_EN BIT(0)
+#define R_BE_FWS1ISR 0x019C
+#define B_BE_FS_WL_HW_RADIO_OFF_INT BIT(28)
+#define B_BE_SWRD_BOD_INT BIT(27)
+#define B_BE_HCIDBG_INT BIT(25)
+#define B_BE_FS_RPWM_INT_V1 BIT(24)
+#define B_BE_PCIE_HOTRST BIT(22)
+#define B_BE_PCIE_SER_TIMEOUT_INDIC BIT(21)
+#define B_BE_PCIE_RXI300_SLVTOUT_INDIC BIT(20)
+#define B_BE_AON_PCIE_FLR_INT BIT(19)
+#define B_BE_PCIE_ERR_INDIC BIT(18)
+#define B_BE_SDIO_ERR_INDIC BIT(17)
+#define B_BE_USB_ERR_INDIC BIT(16)
+#define B_BE_FS_GPIO27_INT BIT(11)
+#define B_BE_FS_GPIO26_INT BIT(10)
+#define B_BE_FS_GPIO25_INT BIT(9)
+#define B_BE_FS_GPIO24_INT BIT(8)
+#define B_BE_FS_GPIO23_INT BIT(7)
+#define B_BE_FS_GPIO22_INT BIT(6)
+#define B_BE_FS_GPIO21_INT BIT(5)
+#define B_BE_FS_GPIO20_INT BIT(4)
+#define B_BE_FS_GPIO19_INT BIT(3)
+#define B_BE_FS_GPIO18_INT BIT(2)
+#define B_BE_FS_GPIO17_INT BIT(1)
+#define B_BE_FS_GPIO16_INT BIT(0)
+
#define R_BE_HIMR0 0x01A0
#define B_BE_WDT_DATACPU_TIMEOUT_INT_EN BIT(25)
#define B_BE_HALT_D2H_INT_EN BIT(24)
@@ -4503,6 +4528,44 @@
#define R_BE_UDM2 0x01F8
#define B_BE_UDM2_EPC_RA_MASK GENMASK(31, 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)
+#define B_BE_SN_P_L_MASK GENMASK(23, 20)
+#define B_BE_SP_P_L_MASK GENMASK(19, 16)
+#define B_BE_VO_DISCHG_PWM_H BIT(15)
+#define B_BE_REG_MODE_PREDRIVER BIT(14)
+#define B_BE_VREFOCP_MASK GENMASK(13, 10)
+#define B_BE_POWOCP_L1 BIT(9)
+#define B_BE_PWM_FORCE BIT(8)
+#define B_BE_PFM_PD_RST BIT(7)
+#define B_BE_VC_PFM_RSTB BIT(6)
+#define B_BE_PFM_IN_SEL BIT(5)
+#define B_BE_VC_RSTB BIT(4)
+#define B_BE_FPWMDELAY BIT(3)
+#define B_BE_ENFPWMDELAY_H BIT(2)
+#define B_BE_REG_MOS_HALF_L BIT(1)
+#define B_BE_CURRENT_SENSE_MOS BIT(0)
+
+#define R_BE_SPS_ANA_ON_CTRL1 0x0224
+#define B_BE_SN_N_L_ANA_MASK GENMASK(31, 28)
+#define B_BE_SP_N_L_ANA_MASK GENMASK(27, 24)
+#define B_BE_SN_P_L_ANA_MASK GENMASK(23, 20)
+#define B_BE_SP_P_L_ANA_MASK GENMASK(19, 16)
+#define B_BE_VO_DISCHG_PWM_H_ANA BIT(15)
+#define B_BE_REG_MODE_PREDRIVER_ANA BIT(14)
+#define B_BE_VREFOCP_ANA_MASK GENMASK(13, 10)
+#define B_BE_POWOCP_L1_ANA BIT(9)
+#define B_BE_PWM_FORCE_ANA BIT(8)
+#define B_BE_PFM_PD_RST_ANA BIT(7)
+#define B_BE_VC_PFM_RSTB_ANA BIT(6)
+#define B_BE_PFM_IN_SEL_ANA BIT(5)
+#define B_BE_VC_RSTB_ANA BIT(4)
+#define B_BE_FPWMDELAY_ANA BIT(3)
+#define B_BE_ENFPWMDELAY_H_ANA BIT(2)
+#define B_BE_REG_MOS_HALF_L_ANA BIT(1)
+#define B_BE_CURRENT_SENSE_MOS_ANA BIT(0)
+
#define R_BE_AFE_ON_CTRL0 0x0240
#define B_BE_REG_LPF_R3_3_0_MASK GENMASK(31, 29)
#define B_BE_REG_LPF_R2_MASK GENMASK(28, 24)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 6a90ded1b33e..194e2901232b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -231,6 +231,243 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
[RTW89_EFUSE_BLOCK_ADIE] = {.offset = 0x70000, .size = 0x10},
};
+static int rtw8922d_pwr_on_func(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u32 val32;
+ int ret;
+
+ if (hal->cid != RTL8922D_CID7025)
+ goto begin;
+
+ switch (hal->cv) {
+ case CHIP_CAV:
+ case CHIP_CBV:
+ rtw89_write32_set(rtwdev, R_BE_SPS_DIG_ON_CTRL1, B_BE_PWM_FORCE);
+ rtw89_write32_set(rtwdev, R_BE_SPS_ANA_ON_CTRL1, B_BE_PWM_FORCE_ANA);
+ break;
+ default:
+ break;
+ }
+
+begin:
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_AFSM_WLSUS_EN |
+ B_BE_AFSM_PCIE_SUS_EN);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_DIS_WLBT_PDNSUSEN_SOPC);
+ rtw89_write32_set(rtwdev, R_BE_WLLPS_CTRL, B_BE_DIS_WLBT_LPSEN_LOPC);
+ if (hal->cid != RTL8922D_CID7090)
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APDM_HPDN);
+ rtw89_write32_clr(rtwdev, R_BE_FWS1ISR, B_BE_FS_WL_HW_RADIO_OFF_INT);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+
+ ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_RDY_SYSPWR,
+ 1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_set(rtwdev, R_BE_WLRESUME_CTRL, B_BE_LPSROP_CMAC0 |
+ B_BE_LPSROP_CMAC1);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFN_ONMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_APFN_ONMAC),
+ 1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write8_set(rtwdev, R_BE_PLATFORM_ENABLE, B_BE_PLATFORM_EN);
+ rtw89_write32_set(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_HAXIDMA_IO_ST,
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HAXIDMA_BACKUP_RESTORE_ST),
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_HCI_WLAN_IO_ST,
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_clr(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_PCIE_FORCE_IBX_EN);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_NORMAL_WRITE, 0x10, 0x10);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL, B_BE_SYM_PADPDN_WL_RFC1_1P3);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x40, 0x40);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL, B_BE_SYM_PADPDN_WL_RFC0_1P3);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x20, 0x20);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x04, 0x04);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x08, 0x08);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x10);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xEB, 0xFF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xEB, 0xFF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x01, 0x01);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x02, 0x02);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x80);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, 0x70);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, 0x02);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
+ rtw89_write32_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B);
+
+ mdelay(1);
+
+ rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S);
+ rtw89_write32_clr(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
+
+ rtw89_write32_set(rtwdev, R_BE_DMAC_FUNC_EN,
+ B_BE_MAC_FUNC_EN | B_BE_DMAC_FUNC_EN |
+ B_BE_MPDU_PROC_EN | B_BE_WD_RLS_EN |
+ B_BE_DLE_WDE_EN | B_BE_TXPKT_CTRL_EN |
+ B_BE_STA_SCH_EN | B_BE_DLE_PLE_EN |
+ B_BE_PKT_BUF_EN | B_BE_DMAC_TBL_EN |
+ B_BE_PKT_IN_EN | B_BE_DLE_CPUIO_EN |
+ B_BE_DISPATCHER_EN | B_BE_BBRPT_EN |
+ B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN |
+ B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |
+ B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN |
+ B_BE_LTR_CTL_EN);
+
+ set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
+
+ rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_FUNC_EN,
+ B_BE_CMAC_SHARE_EN | B_BE_RESPBA_EN |
+ B_BE_ADDRSRCH_EN | B_BE_BTCOEX_EN);
+
+ rtw89_write32_set(rtwdev, R_BE_CMAC_FUNC_EN,
+ B_BE_CMAC_EN | B_BE_CMAC_TXEN |
+ B_BE_CMAC_RXEN | B_BE_SIGB_EN |
+ 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_TXTIME_EN | B_BE_RESP_PKTCTL_EN);
+
+ set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
+
+ rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_FEN_BB_IP_RSTN | B_BE_FEN_BBPLAT_RSTB);
+
+ return 0;
+}
+
+static int rtw8922d_pwr_off_func(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ int ret;
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x10, 0x10);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x08);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x04);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, 0x01);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0, 0x01);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x80, 0x80);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x02);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x01);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write8_clr(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_FEN_BB_IP_RSTN |
+ B_BE_FEN_BBPLAT_RSTB);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL,
+ B_BE_SYM_PADPDN_WL_RFC0_1P3);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x20);
+ if (ret)
+ return ret;
+
+ rtw89_write32_clr(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL,
+ B_BE_SYM_PADPDN_WL_RFC1_1P3);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x40);
+ if (ret)
+ return ret;
+
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HAXIDMA_IO_ST),
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+ ret = read_poll_timeout(rtw89_read32, val32,
+ !(val32 & B_BE_HAXIDMA_BACKUP_RESTORE_ST),
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HCI_WLAN_IO_ST),
+ 1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_APFM_OFFMAC),
+ 1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32(rtwdev, R_BE_WLLPS_CTRL, 0x00015002);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_XTAL_OFF_A_DIE);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+ rtw89_write32(rtwdev, R_BE_UDM1, 0);
+
+ return 0;
+}
+
MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH rtw-next 3/7] wifi: rtw89: 8922d: define efuse map and read necessary fields
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 1/7] wifi: rtw89: 8922d: add definition of quota, registers and efuse block Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 2/7] wifi: rtw89: 8922d: add power on/off functions Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 4/7] wifi: rtw89: 8922d: read and configure RF by calibration data from efuse physical map Ping-Ke Shih
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
Define specific efuse map for RTL8922D, including TSSI, RX gain, MAC
address, RFE type and etc. The additional fields comparing to existing
chips are BT setting (define BT switch GPIO, antenna number and etc) and
gain offset2 (define more fields like existing RX gain offset).
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 3 +
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 162 ++++++++++++++++++
drivers/net/wireless/realtek/rtw89/rtw8922d.h | 70 ++++++++
3 files changed, 235 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 94e4faf70e12..d0ae3e15253b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3562,6 +3562,8 @@ struct rtw89_efuse {
u8 rfe_type;
char country_code[2];
u8 adc_td;
+ u8 bt_setting_2;
+ u8 bt_setting_3;
};
struct rtw89_phy_rate_pattern {
@@ -5926,6 +5928,7 @@ struct rtw89_phy_efuse_gain {
bool offset_valid;
bool comp_valid;
s8 offset[RF_PATH_MAX][RTW89_GAIN_OFFSET_NR]; /* S(8, 0) */
+ s8 offset2[RF_PATH_MAX][RTW89_GAIN_OFFSET_NR]; /* S(8, 0) */
s8 offset_base[RTW89_PHY_NUM]; /* S(8, 4) */
s8 rssi_base[RTW89_PHY_NUM]; /* S(8, 4) */
s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 194e2901232b..0ae34a4f8d79 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2026 Realtek Corporation
*/
+#include "debug.h"
#include "efuse.h"
#include "mac.h"
#include "reg.h"
@@ -468,6 +469,167 @@ static int rtw8922d_pwr_off_func(struct rtw89_dev *rtwdev)
return 0;
}
+static void rtw8922d_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
+ struct rtw8922d_efuse *map)
+{
+ const struct rtw8922d_tssi_offset_6g * const ofst_6g[] = {
+ &map->path_a_tssi_6g,
+ &map->path_b_tssi_6g,
+ };
+ const struct rtw8922d_tssi_offset * const ofst[] = {
+ &map->path_a_tssi,
+ &map->path_b_tssi,
+ };
+ struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+ u8 i, j;
+
+ tssi->thermal[RF_PATH_A] = map->path_a_therm;
+ tssi->thermal[RF_PATH_B] = map->path_b_therm;
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi, TSSI_CCK_CH_GROUP_NUM);
+
+ for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n",
+ i, j, tssi->tssi_cck[i][j]);
+
+ memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi,
+ TSSI_MCS_2G_CH_GROUP_NUM);
+ memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM,
+ ofst[i]->bw40_1s_tssi_5g, TSSI_MCS_5G_CH_GROUP_NUM);
+ memcpy(tssi->tssi_6g_mcs[i], ofst_6g[i]->bw40_1s_tssi_6g,
+ TSSI_MCS_6G_CH_GROUP_NUM);
+
+ for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n",
+ i, j, tssi->tssi_mcs[i][j]);
+
+ for (j = 0; j < TSSI_MCS_6G_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d mcs_6g[%d]=0x%x\n",
+ i, j, tssi->tssi_6g_mcs[i][j]);
+ }
+}
+
+static void
+__rtw8922d_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+ s8 offset[RTW89_GAIN_OFFSET_NR],
+ const s8 *offset_default,
+ const struct rtw8922d_rx_gain *rx_gain,
+ const struct rtw8922d_rx_gain_6g *rx_gain_6g)
+{
+ int i;
+ u8 t;
+
+ offset[RTW89_GAIN_OFFSET_2G_CCK] = rx_gain->_2g_cck;
+ offset[RTW89_GAIN_OFFSET_2G_OFDM] = rx_gain->_2g_ofdm;
+ offset[RTW89_GAIN_OFFSET_5G_LOW] = rx_gain->_5g_low;
+ offset[RTW89_GAIN_OFFSET_5G_MID] = rx_gain->_5g_mid;
+ offset[RTW89_GAIN_OFFSET_5G_HIGH] = rx_gain->_5g_high;
+ offset[RTW89_GAIN_OFFSET_6G_L0] = rx_gain_6g->_6g_l0;
+ offset[RTW89_GAIN_OFFSET_6G_L1] = rx_gain_6g->_6g_l1;
+ offset[RTW89_GAIN_OFFSET_6G_M0] = rx_gain_6g->_6g_m0;
+ offset[RTW89_GAIN_OFFSET_6G_M1] = rx_gain_6g->_6g_m1;
+ offset[RTW89_GAIN_OFFSET_6G_H0] = rx_gain_6g->_6g_h0;
+ offset[RTW89_GAIN_OFFSET_6G_H1] = rx_gain_6g->_6g_h1;
+ offset[RTW89_GAIN_OFFSET_6G_UH0] = rx_gain_6g->_6g_uh0;
+ offset[RTW89_GAIN_OFFSET_6G_UH1] = rx_gain_6g->_6g_uh1;
+
+ for (i = 0; i < RTW89_GAIN_OFFSET_NR; i++) {
+ t = offset[i];
+ if (t == 0xff) {
+ if (offset_default) {
+ offset[i] = offset_default[i];
+ continue;
+ }
+ t = 0;
+ }
+
+ /* transform: sign-bit + U(7,2) to S(8,2) */
+ if (t & 0x80)
+ offset[i] = (t ^ 0x7f) + 1;
+ else
+ offset[i] = t;
+ }
+}
+
+static void rtw8922d_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+ struct rtw8922d_efuse *map)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+
+ __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset[RF_PATH_A],
+ NULL,
+ &map->rx_gain_a, &map->rx_gain_6g_a);
+ __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset[RF_PATH_B],
+ NULL,
+ &map->rx_gain_b, &map->rx_gain_6g_b);
+
+ __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset2[RF_PATH_A],
+ gain->offset[RF_PATH_A],
+ &map->rx_gain_a_2, &map->rx_gain_6g_a_2);
+ __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset2[RF_PATH_B],
+ gain->offset[RF_PATH_B],
+ &map->rx_gain_b_2, &map->rx_gain_6g_b_2);
+
+ gain->offset_valid = true;
+}
+
+static int rtw8922d_read_efuse_pci_sdio(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+ if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE)
+ ether_addr_copy(efuse->addr, log_map + 0x4104);
+ else
+ ether_addr_copy(efuse->addr, log_map + 0x001A);
+
+ return 0;
+}
+
+static int rtw8922d_read_efuse_usb(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+ ether_addr_copy(efuse->addr, log_map + 0x0078);
+
+ return 0;
+}
+
+static int rtw8922d_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+ struct rtw8922d_efuse *map = (struct rtw8922d_efuse *)log_map;
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+ efuse->rfe_type = map->rfe_type;
+ efuse->xtal_cap = map->xtal_k;
+ efuse->country_code[0] = map->country_code[0];
+ efuse->country_code[1] = map->country_code[1];
+ efuse->bt_setting_2 = map->bt_setting_2;
+ efuse->bt_setting_3 = map->bt_setting_3;
+ rtw8922d_efuse_parsing_tssi(rtwdev, map);
+ rtw8922d_efuse_parsing_gain_offset(rtwdev, map);
+
+ return 0;
+}
+
+static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
+ enum rtw89_efuse_block block)
+{
+ switch (block) {
+ case RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO:
+ return rtw8922d_read_efuse_pci_sdio(rtwdev, log_map);
+ case RTW89_EFUSE_BLOCK_HCI_DIG_USB:
+ return rtw8922d_read_efuse_usb(rtwdev, log_map);
+ case RTW89_EFUSE_BLOCK_RF:
+ return rtw8922d_read_efuse_rf(rtwdev, log_map);
+ default:
+ return 0;
+ }
+}
+
MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.h b/drivers/net/wireless/realtek/rtw89/rtw8922d.h
index 7ef3f263274e..a3b98ad6636c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.h
@@ -7,4 +7,74 @@
#include "core.h"
+#define RF_PATH_NUM_8922D 2
+#define BB_PATH_NUM_8922D 2
+
+struct rtw8922d_tssi_offset {
+ u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
+ u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
+ u8 rsvd[7];
+ u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
+ u8 bw_diff_5g[10];
+} __packed;
+
+struct rtw8922d_tssi_offset_6g {
+ u8 bw40_1s_tssi_6g[TSSI_MCS_6G_CH_GROUP_NUM];
+ u8 rsvd[0xa];
+} __packed;
+
+struct rtw8922d_rx_gain {
+ u8 _2g_ofdm;
+ u8 _2g_cck;
+ u8 _5g_low;
+ u8 _5g_mid;
+ u8 _5g_high;
+} __packed;
+
+struct rtw8922d_rx_gain_6g {
+ u8 _6g_l0;
+ u8 _6g_l1;
+ u8 _6g_m0;
+ u8 _6g_m1;
+ u8 _6g_h0;
+ u8 _6g_h1;
+ u8 _6g_uh0;
+ u8 _6g_uh1;
+} __packed;
+
+struct rtw8922d_efuse {
+ u8 country_code[2];
+ u8 rsvd[0xe];
+ struct rtw8922d_tssi_offset path_a_tssi;
+ struct rtw8922d_tssi_offset path_b_tssi;
+ u8 rsvd1[0x54];
+ u8 channel_plan;
+ u8 xtal_k;
+ u8 rsvd2[0x7];
+ u8 board_info;
+ u8 rsvd3[0x8];
+ u8 rfe_type;
+ u8 rsvd4[2];
+ u8 bt_setting_2;
+ u8 bt_setting_3;
+ u8 rsvd4_2;
+ u8 path_a_therm;
+ u8 path_b_therm;
+ u8 rsvd5[0x2];
+ struct rtw8922d_rx_gain rx_gain_a;
+ struct rtw8922d_rx_gain rx_gain_b;
+ u8 rsvd6[0x18];
+ struct rtw8922d_rx_gain rx_gain_a_2;
+ struct rtw8922d_rx_gain rx_gain_b_2;
+ struct rtw8922d_tssi_offset_6g path_a_tssi_6g;
+ struct rtw8922d_tssi_offset_6g path_b_tssi_6g;
+ struct rtw8922d_tssi_offset_6g path_c_tssi_6g;
+ struct rtw8922d_tssi_offset_6g path_d_tssi_6g;
+ struct rtw8922d_rx_gain_6g rx_gain_6g_a;
+ struct rtw8922d_rx_gain_6g rx_gain_6g_b;
+ u8 rsvd7[0x5a];
+ struct rtw8922d_rx_gain_6g rx_gain_6g_a_2;
+ struct rtw8922d_rx_gain_6g rx_gain_6g_b_2;
+} __packed;
+
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH rtw-next 4/7] wifi: rtw89: 8922d: read and configure RF by calibration data from efuse physical map
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
` (2 preceding siblings ...)
2026-03-23 3:25 ` [PATCH rtw-next 3/7] wifi: rtw89: 8922d: define efuse map and read necessary fields Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 5/7] wifi: rtw89: 8922d: add set channel of MAC part Ping-Ke Shih
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The calibration data is from physical map, including 1) thermal trim to
align output thermal value across chips, and 2) PA bias to transmit
expected power by controller.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 2 +
drivers/net/wireless/realtek/rtw89/reg.h | 2 +
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 205 ++++++++++++++++++
3 files changed, 209 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index d0ae3e15253b..cde46ed21d32 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5595,9 +5595,11 @@ struct rtw89_tssi_info {
struct rtw89_power_trim_info {
bool pg_thermal_trim;
bool pg_pa_bias_trim;
+ bool pg_vco_trim;
u8 thermal_trim[RF_PATH_MAX];
u8 pa_bias_trim[RF_PATH_MAX];
u8 pad_bias_trim[RF_PATH_MAX];
+ u8 vco_trim[RF_PATH_MAX];
};
enum rtw89_regd_func {
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index b6fd7b434de9..179006c8e499 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8517,6 +8517,7 @@
#define RR_LUTWD0_LB GENMASK(5, 0)
#define RR_TM 0x42
#define RR_TM_TRI BIT(19)
+#define RR_TM_TRM GENMASK(17, 11)
#define RR_TM_VAL_V1 GENMASK(7, 0)
#define RR_TM_VAL GENMASK(6, 1)
#define RR_TM2 0x43
@@ -8649,6 +8650,7 @@
#define RR_LDO 0xb1
#define RR_LDO_SEL GENMASK(8, 6)
#define RR_VCO 0xb2
+#define RR_VCO_VAL GENMASK(18, 14)
#define RR_VCO_SEL GENMASK(9, 8)
#define RR_VCI 0xb3
#define RR_VCI_ON BIT(7)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 0ae34a4f8d79..cbe8e067ae55 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -630,6 +630,211 @@ static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
}
}
+static void rtw8922d_phycap_parsing_vco_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ static const u32 vco_trim_addr[RF_PATH_NUM_8922D] = {0x175E, 0x175F};
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u32 addr = rtwdev->chip->phycap_addr;
+ const u32 vco_check_addr = 0x1700;
+ u8 val;
+
+ val = phycap_map[vco_check_addr - addr];
+ if (val & BIT(1))
+ return;
+
+ info->pg_vco_trim = true;
+
+ info->vco_trim[0] = u8_get_bits(phycap_map[vco_trim_addr[0] - addr], GENMASK(4, 0));
+ info->vco_trim[1] = u8_get_bits(phycap_map[vco_trim_addr[1] - addr], GENMASK(4, 0));
+}
+
+static void rtw8922d_vco_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+
+ if (!info->pg_vco_trim)
+ return;
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_VAL, info->vco_trim[0]);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_VCO, RR_VCO_VAL, info->vco_trim[1]);
+}
+
+#define THM_TRIM_POSITIVE_MASK BIT(6)
+#define THM_TRIM_MAGNITUDE_MASK GENMASK(5, 0)
+#define THM_TRIM_MAX (15)
+#define THM_TRIM_MIN (-15)
+
+static void rtw8922d_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ static const u32 thm_trim_addr[RF_PATH_NUM_8922D] = {0x1706, 0x1732};
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u32 addr = rtwdev->chip->phycap_addr;
+ bool pg = true;
+ u8 pg_th;
+ s8 val;
+ u8 i;
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ pg_th = phycap_map[thm_trim_addr[i] - addr];
+ if (pg_th == 0xff) {
+ memset(info->thermal_trim, 0, sizeof(info->thermal_trim));
+ pg = false;
+ goto out;
+ }
+
+ val = u8_get_bits(pg_th, THM_TRIM_MAGNITUDE_MASK);
+
+ if (!(pg_th & THM_TRIM_POSITIVE_MASK))
+ val *= -1;
+
+ if (val <= THM_TRIM_MIN || val >= THM_TRIM_MAX) {
+ val = 0;
+ info->thermal_trim[i] = 0;
+ } else {
+ info->thermal_trim[i] = pg_th;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] path=%d thermal_trim=0x%x (%d)\n",
+ i, pg_th, val);
+ }
+
+out:
+ info->pg_thermal_trim = pg;
+}
+
+static void rtw8922d_thermal_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 thermal;
+ int i;
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ thermal = info->pg_thermal_trim ? info->thermal_trim[i] : 0;
+ rtw89_write_rf(rtwdev, i, RR_TM, RR_TM_TRM, thermal & 0x7f);
+ }
+}
+
+static void rtw8922d_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ static const u32 pabias_trim_addr[RF_PATH_NUM_8922D] = {0x1707, 0x1733};
+ static const u32 check_pa_pad_trim_addr = 0x1700;
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u32 addr = rtwdev->chip->phycap_addr;
+ bool pg = true;
+ u8 val;
+ u8 i;
+
+ val = phycap_map[check_pa_pad_trim_addr - addr];
+ if (val == 0xff) {
+ pg = false;
+ goto out;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n",
+ i, info->pa_bias_trim[i]);
+ }
+
+out:
+ info->pg_pa_bias_trim = pg;
+}
+
+static void rtw8922d_pa_bias_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 pabias_2g, pabias_5g;
+ u8 i;
+
+ if (!info->pg_pa_bias_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] no PG, do nothing\n");
+
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ pabias_2g = FIELD_GET(GENMASK(3, 0), info->pa_bias_trim[i]);
+ pabias_5g = FIELD_GET(GENMASK(7, 4), info->pa_bias_trim[i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n",
+ i, pabias_2g, pabias_5g);
+
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG_V1, pabias_2g);
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA_V1, pabias_5g);
+ }
+}
+
+static void rtw8922d_phycap_parsing_pad_bias_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ static const u32 pad_bias_trim_addr[RF_PATH_NUM_8922D] = {0x1708, 0x1734};
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u32 addr = rtwdev->chip->phycap_addr;
+ u8 i;
+
+ if (!info->pg_pa_bias_trim)
+ return;
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ info->pad_bias_trim[i] = phycap_map[pad_bias_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PAD_BIAS][TRIM] path=%d pad_bias_trim=0x%x\n",
+ i, info->pad_bias_trim[i]);
+ }
+}
+
+static void rtw8922d_pad_bias_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 pad_bias_2g, pad_bias_5g;
+ u8 i;
+
+ if (!info->pg_pa_bias_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PAD_BIAS][TRIM] no PG, do nothing\n");
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+ pad_bias_2g = u8_get_bits(info->pad_bias_trim[i], GENMASK(3, 0));
+ pad_bias_5g = u8_get_bits(info->pad_bias_trim[i], GENMASK(7, 4));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PAD_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n",
+ i, pad_bias_2g, pad_bias_5g);
+
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASD_TXG_V1, pad_bias_2g);
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASD_TXA_V1, pad_bias_5g);
+ }
+}
+
+static int rtw8922d_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ rtw8922d_phycap_parsing_vco_trim(rtwdev, phycap_map);
+ rtw8922d_phycap_parsing_thermal_trim(rtwdev, phycap_map);
+ rtw8922d_phycap_parsing_pa_bias_trim(rtwdev, phycap_map);
+ rtw8922d_phycap_parsing_pad_bias_trim(rtwdev, phycap_map);
+
+ return 0;
+}
+
+static void rtw8922d_power_trim(struct rtw89_dev *rtwdev)
+{
+ rtw8922d_vco_trim(rtwdev);
+ rtw8922d_thermal_trim(rtwdev);
+ rtw8922d_pa_bias_trim(rtwdev);
+ rtw8922d_pad_bias_trim(rtwdev);
+}
+
MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH rtw-next 5/7] wifi: rtw89: 8922d: add set channel of MAC part
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
` (3 preceding siblings ...)
2026-03-23 3:25 ` [PATCH rtw-next 4/7] wifi: rtw89: 8922d: read and configure RF by calibration data from efuse physical map Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part Ping-Ke Shih
2026-03-23 3:25 ` [PATCH rtw-next 7/7] wifi: rtw89: 8922d: add set channel of RF part Ping-Ke Shih
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The set channel is a key function to switch to specific operating channel.
For MAC part, configure hardware according to channel bandwidth, and
enable CCK rate for 2GHz band only.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/reg.h | 1 +
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 92 +++++++++++++++++++
2 files changed, 93 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 179006c8e499..2195f576facc 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -6801,6 +6801,7 @@
#define R_BE_MUEDCA_EN 0x10370
#define R_BE_MUEDCA_EN_C1 0x14370
#define B_BE_SIFS_TIMEOUT_TB_T2_MASK GENMASK(30, 24)
+#define B_BE_SIFS_MACTXEN_TB_T1_DOT05US_MASK GENMASK(23, 16)
#define B_BE_SIFS_MACTXEN_TB_T1_MASK GENMASK(22, 16)
#define B_BE_MUEDCA_WMM_SEL BIT(8)
#define B_BE_SET_MUEDCATIMER_TF_MASK GENMASK(5, 4)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index cbe8e067ae55..a341734ef54d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -5,6 +5,7 @@
#include "debug.h"
#include "efuse.h"
#include "mac.h"
+#include "phy.h"
#include "reg.h"
#include "rtw8922d.h"
@@ -835,6 +836,97 @@ static void rtw8922d_power_trim(struct rtw89_dev *rtwdev)
rtw8922d_pad_bias_trim(rtwdev);
}
+static void rtw8922d_set_channel_mac(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ u8 mac_idx)
+{
+ u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_BE_TX_SUB_BAND_VALUE, mac_idx);
+ u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_BE_TXRATE_CHK, mac_idx);
+ u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMAC_RFMOD, mac_idx);
+ u8 txsb20 = 0, txsb40 = 0, txsb80 = 0;
+ u8 rf_mod_val, chk_rate_mask, sifs;
+ u32 txsb;
+ u32 reg;
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_160:
+ txsb80 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_80);
+ fallthrough;
+ case RTW89_CHANNEL_WIDTH_80:
+ txsb40 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_40);
+ fallthrough;
+ case RTW89_CHANNEL_WIDTH_40:
+ txsb20 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_20);
+ break;
+ default:
+ break;
+ }
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_160:
+ rf_mod_val = BE_WMAC_RFMOD_160M;
+ txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK) |
+ u32_encode_bits(txsb40, B_BE_TXSB_40M_MASK) |
+ u32_encode_bits(txsb80, B_BE_TXSB_80M_MASK);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rf_mod_val = BE_WMAC_RFMOD_80M;
+ txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK) |
+ u32_encode_bits(txsb40, B_BE_TXSB_40M_MASK);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rf_mod_val = BE_WMAC_RFMOD_40M;
+ txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ default:
+ rf_mod_val = BE_WMAC_RFMOD_20M;
+ txsb = 0;
+ break;
+ }
+
+ if (txsb20 <= BE_PRI20_BITMAP_MAX)
+ txsb |= u32_encode_bits(BIT(txsb20), B_BE_PRI20_BITMAP_MASK);
+
+ rtw89_write8_mask(rtwdev, rf_mod, B_BE_WMAC_RFMOD_MASK, rf_mod_val);
+ rtw89_write32(rtwdev, sub_carr, txsb);
+
+ switch (chan->band_type) {
+ case RTW89_BAND_2G:
+ chk_rate_mask = B_BE_BAND_MODE;
+ break;
+ case RTW89_BAND_5G:
+ case RTW89_BAND_6G:
+ chk_rate_mask = B_BE_CHECK_CCK_EN | B_BE_RTS_LIMIT_IN_OFDM6;
+ break;
+ default:
+ rtw89_warn(rtwdev, "Invalid band_type:%d\n", chan->band_type);
+ return;
+ }
+
+ rtw89_write8_clr(rtwdev, chk_rate, B_BE_BAND_MODE | B_BE_CHECK_CCK_EN |
+ B_BE_RTS_LIMIT_IN_OFDM6);
+ rtw89_write8_set(rtwdev, chk_rate, chk_rate_mask);
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_160:
+ sifs = 0x8C;
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ sifs = 0x8A;
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ sifs = 0x84;
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ default:
+ sifs = 0x82;
+ }
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_MUEDCA_EN, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_TB_T1_DOT05US_MASK, sifs);
+}
+
MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
` (4 preceding siblings ...)
2026-03-23 3:25 ` [PATCH rtw-next 5/7] wifi: rtw89: 8922d: add set channel of MAC part Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
2026-03-23 10:53 ` Bitterblue Smith
2026-03-23 3:25 ` [PATCH rtw-next 7/7] wifi: rtw89: 8922d: add set channel of RF part Ping-Ke Shih
6 siblings, 1 reply; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The set channel of BB part is the main part, which according to channel
and bandwidth to configure CCK SCO, RX gain of LNA and TIA programmed
in efuse for CCK and OFDM rate, and spur elimination of CSI and NBI tones.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 2 +
drivers/net/wireless/realtek/rtw89/reg.h | 64 +-
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 820 ++++++++++++++++++
3 files changed, 885 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index cde46ed21d32..696a1d92d62b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5933,6 +5933,8 @@ struct rtw89_phy_efuse_gain {
s8 offset2[RF_PATH_MAX][RTW89_GAIN_OFFSET_NR]; /* S(8, 0) */
s8 offset_base[RTW89_PHY_NUM]; /* S(8, 4) */
s8 rssi_base[RTW89_PHY_NUM]; /* S(8, 4) */
+ s8 ref_gain_base[RTW89_PHY_NUM]; /* S(8, 2) */
+ s8 cck_rpl_base[RTW89_PHY_NUM]; /* S(8, 0) */
s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */
};
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 2195f576facc..5d284f310069 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8775,6 +8775,7 @@
#define B_P0_HW_ANTSW_DIS_BY_GNT_BT BIT(12)
#define B_P0_TRSW_TX_EXTEND GENMASK(3, 0)
#define R_MAC_PIN_SEL 0x0734
+#define R_MAC_PIN_SEL_BE4 0x20734
#define B_CH_IDX_SEG0 GENMASK(23, 16)
#define R_PLCP_HISTOGRAM 0x0738
#define R_PLCP_HISTOGRAM_BE_V1 0x20738
@@ -10461,6 +10462,13 @@
#define B_SW_SI_DATA_DAT_BE4 GENMASK(19, 0)
#define R_SW_SI_READ_ADDR_BE4 0x20378
#define B_SW_SI_READ_ADDR_BE4 GENMASK(10, 0)
+#define R_RXBW67_BE4 0x2040C
+#define B_RXBW6_BE4 GENMASK(22, 20)
+#define B_RXBW7_BE4 GENMASK(25, 23)
+#define R_RXBW_BE4 0x20410
+#define B_RXBW_BE4 GENMASK(29, 27)
+#define R_ENABLE_CCK0_BE4 0x20700
+#define B_ENABLE_CCK0_BE4 BIT(5)
#define R_EDCCA_RPT_SEL_BE4 0x20780
#define R_EDCCA_RPT_SEL_BE4_C1 0x21780
#define B_EDCCA_RPT_SEL_BE4_MSK 0xE0000
@@ -10486,21 +10494,75 @@
#define B_IFS_T3_HIS_BE4 GENMASK(15, 0)
#define B_IFS_T4_HIS_BE4 GENMASK(31, 16)
+#define R_TXPWR_RSTB0_BE4 0x2250C
+#define B_TXPWR_RSTB0_BE4 BIT(16)
+#define R_TXPWR_RSTB1_BE4 0x2260C
+#define B_TXPWR_RSTB1_BE4 BIT(16)
+
+#define R_OFDM_OFST_P0_BE4 0x240C8
+#define B_OFDM_OFST_P0_BE4 GENMASK(31, 24)
#define R_PATH0_RXIDX_INIT_BE4 0x24108
#define B_PATH0_RXIDX_INIT_BE4 GENMASK(29, 25)
#define R_PATH0_LNA_INIT_BE4 0x24158
#define B_PATH0_LNA_INIT_IDX_BE4 GENMASK(14, 12)
+#define R_BAND_SEL0_BE4 0x24160
+#define B_BAND_SEL0_BE4 BIT(26)
#define R_PATH0_TIA_INIT_BE4 0x24168
#define B_PATH0_TIA_INIT_IDX_BE4 BIT(18)
+#define R_OFDM_RPL_BIAS_P0_BE4 0x2420C
+#define B_OFDM_RPL_BIAS_P0_BE4 GENMASK(11, 2)
+#define R_OFDM_OFST_P1_BE4 0x244C8
+#define B_OFDM_OFST_P1_BE4 GENMASK(31, 24)
#define R_PATH1_RXIDX_INIT_BE4 0x24508
#define B_PATH1_RXIDX_INIT_BE4 GENMASK(29, 25)
#define R_PATH1_LNA_INIT_BE4 0x24558
#define B_PATH1_LNA_INIT_IDX_BE4 GENMASK(14, 12)
+#define R_BAND_SEL1_BE4 0x24560
+#define B_BAND_SEL1_BE4 BIT(26)
#define R_PATH1_TIA_INIT_BE4 0x24568
#define B_PATH1_TIA_INIT_IDX_BE4 BIT(18)
+#define R_OFDM_RPL_BIAS_P1_BE4 0x2460C
+#define B_OFDM_RPL_BIAS_P1_BE4 GENMASK(11, 2)
#define R_TX_CFR_MANUAL_EN_BE4 0x2483C
#define B_TX_CFR_MANUAL_EN_BE4_M BIT(30)
-
+#define R_PCOEFF0_BE4 0x24880
+#define B_PCOEFF01_BE4 GENMASK(23, 0)
+#define R_PCOEFF2_BE4 0x24884
+#define B_PCOEFF23_BE4 GENMASK(23, 0)
+#define R_PCOEFF4_BE4 0x24888
+#define B_PCOEFF45_BE4 GENMASK(23, 0)
+#define R_PCOEFF6_BE4 0x2488C
+#define B_PCOEFF67_BE4 GENMASK(23, 0)
+#define R_PCOEFF8_BE4 0x24890
+#define B_PCOEFF89_BE4 GENMASK(23, 0)
+#define R_PCOEFF10_BE4 0x24894
+#define B_PCOEFF10_BE4 GENMASK(23, 0)
+#define R_PCOEFF12_BE4 0x24898
+#define B_PCOEFF12_BE4 GENMASK(23, 0)
+#define R_PCOEFF14_BE4 0x2489C
+#define B_PCOEFF14_BE4 GENMASK(23, 0)
+#define R_BW_BE4 0x24EE4
+#define B_BW_BE4 GENMASK(6, 4)
+#define B_PRISB_BE4 GENMASK(3, 0)
+#define R_FC0_BE4 0x24EE8
+#define B_FC0_BE4 GENMASK(12, 0)
+#define R_FC0_INV_BE4 0x24EF4
+#define B_FC0_INV_BE4 GENMASK(15, 0)
+
+#define R_CCK_RPL_OFST_BE4 0x26084
+#define B_CCK_RPL_OFST_BE4 GENMASK(7, 0)
+#define R_BK_FC0_INV_BE4 0x2608C
+#define B_BK_FC0_INV_BE4 GENMASK(18, 0)
+#define R_CCK_FC0_INV_BE4 0x26090
+#define B_CCK_FC0_INV_BE4 GENMASK(18, 0)
+#define R_GAIN_BIAS_BE4 0x260A0
+#define B_GAIN_BIAS_BW20_BE4 GENMASK(11, 6)
+#define B_GAIN_BIAS_BW40_BE4 GENMASK(17, 12)
+#define R_AWGN_DET_BE4 0x2668C
+#define B_AWGN_DET_BE4 GENMASK(17, 9)
+#define R_CSI_WGT_BE4 0x26770
+#define B_CSI_WGT_EN_BE4 BIT(0)
+#define B_CSI_WGT_IDX_BE4 GENMASK(31, 20)
#define R_CHINFO_OPT_BE4 0x267C8
#define B_CHINFO_OPT_BE4 GENMASK(14, 13)
#define R_CHINFO_NX_BE4 0x267D0
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index a341734ef54d..f6b36b90dec8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -8,6 +8,7 @@
#include "phy.h"
#include "reg.h"
#include "rtw8922d.h"
+#include "util.h"
#define RTW8922D_FW_FORMAT_MAX 0
#define RTW8922D_FW_BASENAME "rtw89/rtw8922d_fw"
@@ -927,6 +928,825 @@ static void rtw8922d_set_channel_mac(struct rtw89_dev *rtwdev,
rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_TB_T1_DOT05US_MASK, sifs);
}
+static const u32 rtw8922d_sco_barker_threshold[14] = {
+ 0x1fe4f, 0x1ff5e, 0x2006c, 0x2017b, 0x2028a, 0x20399, 0x204a8, 0x205b6,
+ 0x206c5, 0x207d4, 0x208e3, 0x209f2, 0x20b00, 0x20d8a
+};
+
+static const u32 rtw8922d_sco_cck_threshold[14] = {
+ 0x2bdac, 0x2bf21, 0x2c095, 0x2c209, 0x2c37e, 0x2c4f2, 0x2c666, 0x2c7db,
+ 0x2c94f, 0x2cac3, 0x2cc38, 0x2cdac, 0x2cf21, 0x2d29e
+};
+
+static int rtw8922d_ctrl_sco_cck(struct rtw89_dev *rtwdev,
+ u8 primary_ch, enum rtw89_bandwidth bw,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 ch_element;
+
+ if (primary_ch >= 14)
+ return -EINVAL;
+
+ ch_element = primary_ch - 1;
+
+ rtw89_phy_write32_idx(rtwdev, R_BK_FC0_INV_BE4, B_BK_FC0_INV_BE4,
+ rtw8922d_sco_barker_threshold[ch_element],
+ phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CCK_FC0_INV_BE4, B_CCK_FC0_INV_BE4,
+ rtw8922d_sco_cck_threshold[ch_element],
+ phy_idx);
+
+ return 0;
+}
+
+static void rtw8922d_ctrl_ch_core(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u16 central_freq = chan->freq;
+ u16 sco;
+
+ if (chan->band_type == RTW89_BAND_2G) {
+ rtw89_phy_write32_idx(rtwdev, R_BAND_SEL0_BE4, B_BAND_SEL0_BE4,
+ 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BAND_SEL1_BE4, B_BAND_SEL1_BE4,
+ 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_ENABLE_CCK0_BE4, B_ENABLE_CCK0_BE4,
+ 1, phy_idx);
+ } else {
+ rtw89_phy_write32_idx(rtwdev, R_BAND_SEL0_BE4, B_BAND_SEL0_BE4,
+ 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BAND_SEL1_BE4, B_BAND_SEL1_BE4,
+ 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_ENABLE_CCK0_BE4, B_ENABLE_CCK0_BE4,
+ 0, phy_idx);
+ }
+
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BE4, B_FC0_BE4, central_freq, phy_idx);
+
+ sco = phy_div((BIT(0) << 27) + (central_freq / 2), central_freq);
+ rtw89_phy_write32_idx(rtwdev, R_FC0_INV_BE4, B_FC0_INV_BE4, sco, phy_idx);
+}
+
+struct rtw8922d_bb_gain {
+ u32 gain_g[BB_PATH_NUM_8922D];
+ u32 gain_a[BB_PATH_NUM_8922D];
+ u32 gain_g_mask;
+ u32 gain_a_mask;
+};
+
+static const struct rtw89_reg_def rpl_comp_bw160[RTW89_BW20_SC_160M] = {
+ { .addr = 0x241E8, .mask = 0xFF00},
+ { .addr = 0x241E8, .mask = 0xFF0000},
+ { .addr = 0x241E8, .mask = 0xFF000000},
+ { .addr = 0x241EC, .mask = 0xFF},
+ { .addr = 0x241EC, .mask = 0xFF00},
+ { .addr = 0x241EC, .mask = 0xFF0000},
+ { .addr = 0x241EC, .mask = 0xFF000000},
+ { .addr = 0x241F0, .mask = 0xFF}
+};
+
+static const struct rtw89_reg_def rpl_comp_bw80[RTW89_BW20_SC_80M] = {
+ { .addr = 0x241F4, .mask = 0xFF},
+ { .addr = 0x241F4, .mask = 0xFF00},
+ { .addr = 0x241F4, .mask = 0xFF0000},
+ { .addr = 0x241F4, .mask = 0xFF000000}
+};
+
+static const struct rtw89_reg_def rpl_comp_bw40[RTW89_BW20_SC_40M] = {
+ { .addr = 0x241F0, .mask = 0xFF0000},
+ { .addr = 0x241F0, .mask = 0xFF000000}
+};
+
+static const struct rtw89_reg_def rpl_comp_bw20[RTW89_BW20_SC_20M] = {
+ { .addr = 0x241F0, .mask = 0xFF00}
+};
+
+static const struct rtw8922d_bb_gain bb_gain_lna[LNA_GAIN_NUM] = {
+ { .gain_g = {0x2409C, 0x2449C}, .gain_a = {0x2406C, 0x2446C},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF},
+ { .gain_g = {0x2409C, 0x2449C}, .gain_a = {0x2406C, 0x2446C},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x240A0, 0x244A0}, .gain_a = {0x24070, 0x24470},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240A0, 0x244A0}, .gain_a = {0x24070, 0x24470},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x240A4, 0x244A4}, .gain_a = {0x24074, 0x24474},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240A4, 0x244A4}, .gain_a = {0x24074, 0x24474},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x240A8, 0x244A8}, .gain_a = {0x24078, 0x24478},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF},
+};
+
+static const struct rtw8922d_bb_gain bb_gain_tia[TIA_GAIN_NUM] = {
+ { .gain_g = {0x24054, 0x24454}, .gain_a = {0x24054, 0x24454},
+ .gain_g_mask = 0x7FC0000, .gain_a_mask = 0x1FF},
+ { .gain_g = {0x24058, 0x24458}, .gain_a = {0x24054, 0x24454},
+ .gain_g_mask = 0x1FF, .gain_a_mask = 0x3FE00 },
+};
+
+static const struct rtw8922d_bb_gain bb_op1db_lna[LNA_GAIN_NUM] = {
+ { .gain_g = {0x240AC, 0x244AC}, .gain_a = {0x24078, 0x24478},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x240AC, 0x244AC}, .gain_a = {0x2407C, 0x2447C},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240AC, 0x244AC}, .gain_a = {0x2407C, 0x2447C},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x240B0, 0x244B0}, .gain_a = {0x2407C, 0x2447C},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x240B0, 0x244B0}, .gain_a = {0x2407C, 0x2447C},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x240B0, 0x244B0}, .gain_a = {0x24080, 0x24480},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240B0, 0x244B0}, .gain_a = {0x24080, 0x24480},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF00},
+};
+
+static const struct rtw8922d_bb_gain bb_op1db_tia_lna[TIA_LNA_OP1DB_NUM] = {
+ { .gain_g = {0x240B4, 0x244B4}, .gain_a = {0x24080, 0x24480},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x240B4, 0x244B4}, .gain_a = {0x24084, 0x24484},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240B8, 0x244B8}, .gain_a = {0x24084, 0x24484},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x240B8, 0x244B8}, .gain_a = {0x24084, 0x24484},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x240B8, 0x244B8}, .gain_a = {0x24084, 0x24484},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x240B8, 0x244B8}, .gain_a = {0x24088, 0x24488},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x240BC, 0x244BC}, .gain_a = {0x24088, 0x24488},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x240BC, 0x244BC}, .gain_a = {0x24088, 0x24488},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF0000},
+};
+
+static void rtw8922d_set_rpl_gain(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be;
+ u8 gain_band = rtw89_subband_to_gain_band_be(chan->subband_type);
+ u32 reg_path_ofst = 0;
+ u32 mask;
+ s32 val;
+ u32 reg;
+ int i;
+
+ if (path == RF_PATH_B)
+ reg_path_ofst = 0x400;
+
+ for (i = 0; i < RTW89_BW20_SC_160M; i++) {
+ reg = rpl_comp_bw160[i].addr | reg_path_ofst;
+ mask = rpl_comp_bw160[i].mask;
+ val = gain->rpl_ofst_160[gain_band][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < RTW89_BW20_SC_80M; i++) {
+ reg = rpl_comp_bw80[i].addr | reg_path_ofst;
+ mask = rpl_comp_bw80[i].mask;
+ val = gain->rpl_ofst_80[gain_band][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < RTW89_BW20_SC_40M; i++) {
+ reg = rpl_comp_bw40[i].addr | reg_path_ofst;
+ mask = rpl_comp_bw40[i].mask;
+ val = gain->rpl_ofst_40[gain_band][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < RTW89_BW20_SC_20M; i++) {
+ reg = rpl_comp_bw20[i].addr | reg_path_ofst;
+ mask = rpl_comp_bw20[i].mask;
+ val = gain->rpl_ofst_20[gain_band][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+}
+
+static void rtw8922d_set_lna_tia_gain(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be;
+ u8 gain_band = rtw89_subband_to_gain_band_be(chan->subband_type);
+ enum rtw89_phy_bb_bw_be bw_type;
+ u32 mask;
+ s32 val;
+ u32 reg;
+ int i;
+
+ bw_type = chan->band_width <= RTW89_CHANNEL_WIDTH_40 ?
+ RTW89_BB_BW_20_40 : RTW89_BB_BW_80_160_320;
+
+ for (i = 0; i < LNA_GAIN_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_gain_lna[i].gain_g[path];
+ mask = bb_gain_lna[i].gain_g_mask;
+ } else {
+ reg = bb_gain_lna[i].gain_a[path];
+ mask = bb_gain_lna[i].gain_a_mask;
+ }
+ val = gain->lna_gain[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < TIA_GAIN_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_gain_tia[i].gain_g[path];
+ mask = bb_gain_tia[i].gain_g_mask;
+ } else {
+ reg = bb_gain_tia[i].gain_a[path];
+ mask = bb_gain_tia[i].gain_a_mask;
+ }
+ val = gain->tia_gain[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+}
+
+static void rtw8922d_set_op1db(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be;
+ u8 gain_band = rtw89_subband_to_gain_band_be(chan->subband_type);
+ enum rtw89_phy_bb_bw_be bw_type;
+ u32 mask;
+ s32 val;
+ u32 reg;
+ int i;
+
+ bw_type = chan->band_width <= RTW89_CHANNEL_WIDTH_40 ?
+ RTW89_BB_BW_20_40 : RTW89_BB_BW_80_160_320;
+
+ for (i = 0; i < LNA_GAIN_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_op1db_lna[i].gain_g[path];
+ mask = bb_op1db_lna[i].gain_g_mask;
+ } else {
+ reg = bb_op1db_lna[i].gain_a[path];
+ mask = bb_op1db_lna[i].gain_a_mask;
+ }
+ val = gain->lna_op1db[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < TIA_LNA_OP1DB_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_op1db_tia_lna[i].gain_g[path];
+ mask = bb_op1db_tia_lna[i].gain_g_mask;
+ } else {
+ reg = bb_op1db_tia_lna[i].gain_a[path];
+ mask = bb_op1db_tia_lna[i].gain_a_mask;
+ }
+ val = gain->tia_lna_op1db[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+}
+
+static void rtw8922d_set_gain(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8922d_set_rpl_gain(rtwdev, chan, path, phy_idx);
+ rtw8922d_set_lna_tia_gain(rtwdev, chan, path, phy_idx);
+ rtw8922d_set_op1db(rtwdev, chan, path, phy_idx);
+}
+
+static s8 rtw8922d_get_rx_gain_by_chan(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path, bool is_cck)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ enum rtw89_gain_offset band;
+ u8 fc_ch = chan->channel;
+ s8 normal_efuse = 0;
+
+ if (path > RF_PATH_B)
+ return 0;
+
+ if (is_cck) {
+ if (fc_ch >= 1 && fc_ch <= 7)
+ return gain->offset[path][RTW89_GAIN_OFFSET_2G_CCK];
+ else if (fc_ch >= 8 && fc_ch <= 14)
+ return gain->offset2[path][RTW89_GAIN_OFFSET_2G_CCK];
+
+ return 0;
+ }
+
+ band = rtw89_subband_to_gain_offset_band_of_ofdm(chan->subband_type);
+
+ if (band == RTW89_GAIN_OFFSET_2G_OFDM) {
+ if (fc_ch >= 1 && fc_ch <= 7)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 8 && fc_ch <= 14)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_5G_LOW) {
+ if (fc_ch == 50)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 36 && fc_ch <= 48)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 52 && fc_ch <= 64)
+ normal_efuse = gain->offset2[path][band];
+
+ } else if (band == RTW89_GAIN_OFFSET_5G_MID) {
+ if (fc_ch == 122)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 100 && fc_ch <= 120)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 124 && fc_ch <= 144)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_5G_HIGH) {
+ if (fc_ch == 163)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 149 && fc_ch <= 161)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 165 && fc_ch <= 177)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_L0) {
+ if (fc_ch == 15)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 1 && fc_ch <= 13)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 17 && fc_ch <= 29)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_L1) {
+ if (fc_ch == 47)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 33 && fc_ch <= 45)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 49 && fc_ch <= 61)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_M0) {
+ if (fc_ch == 79)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 65 && fc_ch <= 77)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 81 && fc_ch <= 93)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_M1) {
+ if (fc_ch == 111)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 97 && fc_ch <= 109)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 113 && fc_ch <= 125)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_H0) {
+ if (fc_ch == 143)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 129 && fc_ch <= 141)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 145 && fc_ch <= 157)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_H1) {
+ if (fc_ch == 175)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 161 && fc_ch <= 173)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 177 && fc_ch <= 189)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_UH0) {
+ if (fc_ch == 207)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 193 && fc_ch <= 205)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 209 && fc_ch <= 221)
+ normal_efuse = gain->offset2[path][band];
+ } else if (band == RTW89_GAIN_OFFSET_6G_UH1) {
+ if (fc_ch == 239)
+ normal_efuse = (gain->offset[path][band] + gain->offset2[path][band]) >> 1;
+ else if (fc_ch >= 225 && fc_ch <= 237)
+ normal_efuse = gain->offset[path][band];
+ else if (fc_ch >= 241 && fc_ch <= 253)
+ normal_efuse = gain->offset2[path][band];
+ } else {
+ normal_efuse = gain->offset[path][band];
+ }
+
+ return normal_efuse;
+}
+
+static void rtw8922d_calc_rx_gain_normal_cck(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx,
+ struct rtw89_phy_calc_efuse_gain *calc)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ s8 rx_gain_offset;
+
+ rx_gain_offset = -rtw8922d_get_rx_gain_by_chan(rtwdev, chan, path, true);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_40)
+ rx_gain_offset += (3 << 2); /* compensate RPL loss of 3dB */
+
+ calc->cck_mean_gain_bias = (rx_gain_offset & 0x3) << 1;
+ calc->cck_rpl_ofst = (rx_gain_offset >> 2) + gain->cck_rpl_base[phy_idx];
+}
+
+static void rtw8922d_set_rx_gain_normal_cck(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_phy_calc_efuse_gain calc = {};
+
+ rtw8922d_calc_rx_gain_normal_cck(rtwdev, chan, path, phy_idx, &calc);
+
+ rtw89_phy_write32_idx(rtwdev, R_GAIN_BIAS_BE4, B_GAIN_BIAS_BW20_BE4,
+ calc.cck_mean_gain_bias, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_GAIN_BIAS_BE4, B_GAIN_BIAS_BW40_BE4,
+ calc.cck_mean_gain_bias, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CCK_RPL_OFST_BE4, B_CCK_RPL_OFST_BE4,
+ calc.cck_rpl_ofst, phy_idx);
+}
+
+static void rtw8922d_calc_rx_gain_normal_ofdm(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx,
+ struct rtw89_phy_calc_efuse_gain *calc)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ s8 rx_gain_offset;
+
+ rx_gain_offset = rtw8922d_get_rx_gain_by_chan(rtwdev, chan, path, false);
+ calc->rssi_ofst = (rx_gain_offset + gain->ref_gain_base[phy_idx]) & 0xff;
+}
+
+static void rtw8922d_set_rx_gain_normal_ofdm(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ static const u32 rssi_ofst_addr[2] = {R_OFDM_OFST_P0_BE4, R_OFDM_OFST_P1_BE4};
+ static const u32 rssi_ofst_addr_m[2] = {B_OFDM_OFST_P0_BE4, B_OFDM_OFST_P1_BE4};
+ static const u32 rpl_bias_comp[2] = {R_OFDM_RPL_BIAS_P0_BE4, R_OFDM_RPL_BIAS_P1_BE4};
+ static const u32 rpl_bias_comp_m[2] = {B_OFDM_RPL_BIAS_P0_BE4, B_OFDM_RPL_BIAS_P1_BE4};
+ struct rtw89_phy_calc_efuse_gain calc = {};
+
+ rtw8922d_calc_rx_gain_normal_ofdm(rtwdev, chan, path, phy_idx, &calc);
+
+ rtw89_phy_write32_idx(rtwdev, rssi_ofst_addr[path], rssi_ofst_addr_m[path],
+ calc.rssi_ofst, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, rpl_bias_comp[path], rpl_bias_comp_m[path], 0, phy_idx);
+}
+
+static void rtw8922d_set_rx_gain_normal(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+
+ if (!gain->offset_valid)
+ return;
+
+ if (chan->band_type == RTW89_BAND_2G)
+ rtw8922d_set_rx_gain_normal_cck(rtwdev, chan, path, phy_idx);
+
+ rtw8922d_set_rx_gain_normal_ofdm(rtwdev, chan, path, phy_idx);
+}
+
+static void rtw8922d_set_cck_parameters(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
+ u8 central_ch = chan->channel;
+
+ if (central_ch == 14) {
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF0_BE4, B_PCOEFF01_BE4, 0x3b13ff, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF2_BE4, B_PCOEFF23_BE4, 0x1c42de, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF4_BE4, B_PCOEFF45_BE4, 0xfdb0ad, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF6_BE4, B_PCOEFF67_BE4, 0xf60f6e, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF8_BE4, B_PCOEFF89_BE4, 0xfd8f92, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF10_BE4, B_PCOEFF10_BE4, 0x2d011, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF12_BE4, B_PCOEFF12_BE4, 0x1c02c, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF14_BE4, B_PCOEFF14_BE4, 0xfff00a, phy_idx);
+
+ return;
+ }
+
+ if (regd == RTW89_FCC) {
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF0_BE4, B_PCOEFF01_BE4, 0x39A3BC, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF2_BE4, B_PCOEFF23_BE4, 0x2AA339, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF4_BE4, B_PCOEFF45_BE4, 0x15B202, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF6_BE4, B_PCOEFF67_BE4, 0x0550C7, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF8_BE4, B_PCOEFF89_BE4, 0xfe0009, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF10_BE4, B_PCOEFF10_BE4, 0xfd7fd3, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF12_BE4, B_PCOEFF12_BE4, 0xfeffe2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF14_BE4, B_PCOEFF14_BE4, 0xffeff8, phy_idx);
+ } else {
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF0_BE4, B_PCOEFF01_BE4, 0x3d23ff, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF2_BE4, B_PCOEFF23_BE4, 0x29b354, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF4_BE4, B_PCOEFF45_BE4, 0xfc1c8, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF6_BE4, B_PCOEFF67_BE4, 0xfdb053, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF8_BE4, B_PCOEFF89_BE4, 0xf86f9a, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF10_BE4, B_PCOEFF10_BE4, 0xfaef92, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF12_BE4, B_PCOEFF12_BE4, 0xfe5fcc, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_PCOEFF14_BE4, B_PCOEFF14_BE4, 0xffdff5, phy_idx);
+ }
+}
+
+static void rtw8922d_ctrl_ch(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u16 central_freq = chan->freq;
+ u8 band = chan->band_type;
+ u8 chan_idx;
+
+ if (!central_freq) {
+ rtw89_warn(rtwdev, "Invalid central_freq\n");
+ return;
+ }
+
+ rtw8922d_ctrl_ch_core(rtwdev, chan, phy_idx);
+
+ chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band);
+ rtw89_phy_write32_idx(rtwdev, R_MAC_PIN_SEL_BE4, B_CH_IDX_SEG0, chan_idx, phy_idx);
+
+ rtw8922d_set_gain(rtwdev, chan, RF_PATH_A, phy_idx);
+ rtw8922d_set_gain(rtwdev, chan, RF_PATH_B, phy_idx);
+
+ rtw8922d_set_rx_gain_normal(rtwdev, chan, RF_PATH_A, phy_idx);
+ rtw8922d_set_rx_gain_normal(rtwdev, chan, RF_PATH_B, phy_idx);
+
+ if (band == RTW89_BAND_2G)
+ rtw8922d_set_cck_parameters(rtwdev, chan, phy_idx);
+}
+
+static void rtw8922d_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_sb, u8 bw,
+ enum rtw89_phy_idx phy_idx)
+{
+ switch (bw) {
+ default:
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_BW_BE4, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_PRISB_BE4, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW_BE4, B_RXBW_BE4, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW6_BE4, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW7_BE4, 0x2, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_BW_BE4, 0x1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_PRISB_BE4, pri_sb, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW_BE4, B_RXBW_BE4, 0x3, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW6_BE4, 0x3, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW7_BE4, 0x3, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_BW_BE4, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_PRISB_BE4, pri_sb, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW_BE4, B_RXBW_BE4, 0x4, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW6_BE4, 0x4, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW7_BE4, 0x4, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_160:
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_BW_BE4, 0x3, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_BW_BE4, B_PRISB_BE4, pri_sb, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW_BE4, B_RXBW_BE4, 0x5, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW6_BE4, 0x5, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RXBW67_BE4, B_RXBW7_BE4, 0x5, phy_idx);
+ break;
+ }
+}
+
+static const u16 spur_nbi_a[] = {6400};
+static const u16 spur_csi[] = {6400};
+
+static u32 rtw8922d_spur_freq(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+ bool nbi_or_csi, enum rtw89_rf_path path)
+{
+ static const u16 cbw[RTW89_CHANNEL_WIDTH_ORDINARY_NUM] = {
+ 20, 40, 80, 160, 320,
+ };
+ u16 freq_lower, freq_upper, freq;
+ const u16 *spur_freq;
+ int spur_freq_nr, i;
+
+ if (rtwdev->hal.aid != RTL8922D_AID7060)
+ return 0;
+
+ if (nbi_or_csi && path == RF_PATH_A) {
+ spur_freq = spur_nbi_a;
+ spur_freq_nr = ARRAY_SIZE(spur_nbi_a);
+ } else if (!nbi_or_csi) {
+ spur_freq = spur_csi;
+ spur_freq_nr = ARRAY_SIZE(spur_csi);
+ } else {
+ return 0;
+ }
+
+ if (chan->band_width >= RTW89_CHANNEL_WIDTH_ORDINARY_NUM)
+ return 0;
+
+ freq_lower = chan->freq - cbw[chan->band_width] / 2;
+ freq_upper = chan->freq + cbw[chan->band_width] / 2;
+
+ for (i = 0; i < spur_freq_nr; i++) {
+ freq = spur_freq[i];
+
+ if (freq >= freq_lower && freq <= freq_upper)
+ return freq;
+ }
+
+ return 0;
+}
+
+#define CARRIER_SPACING_312_5 312500 /* 312.5 kHz */
+#define CARRIER_SPACING_78_125 78125 /* 78.125 kHz */
+#define MAX_TONE_NUM 2048
+
+static void rtw8922d_set_csi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ s32 freq_diff, csi_idx, csi_tone_idx;
+ u32 spur_freq;
+
+ spur_freq = rtw8922d_spur_freq(rtwdev, chan, false, RF_PATH_AB);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_idx(rtwdev, R_CSI_WGT_BE4, B_CSI_WGT_EN_BE4,
+ 0, phy_idx);
+ return;
+ }
+
+ freq_diff = (spur_freq - chan->freq) * 1000000;
+ csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125);
+ s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx);
+
+ rtw89_phy_write32_idx(rtwdev, R_CSI_WGT_BE4, B_CSI_WGT_IDX_BE4,
+ csi_tone_idx, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CSI_WGT_BE4, B_CSI_WGT_EN_BE4, 1, phy_idx);
+}
+
+static const struct rtw89_nbi_reg_def rtw8922d_nbi_reg_def[] = {
+ [RF_PATH_A] = {
+ .notch1_idx = {0x241A0, 0xFF},
+ .notch1_frac_idx = {0x241A0, 0xC00},
+ .notch1_en = {0x241A0, 0x1000},
+ .notch2_idx = {0x241AC, 0xFF},
+ .notch2_frac_idx = {0x241AC, 0xC00},
+ .notch2_en = {0x241AC, 0x1000},
+ },
+ [RF_PATH_B] = {
+ .notch1_idx = {0x245A0, 0xFF},
+ .notch1_frac_idx = {0x241A0, 0xC00},
+ .notch1_en = {0x245A0, 0x1000},
+ .notch2_idx = {0x245AC, 0xFF},
+ .notch2_frac_idx = {0x245AC, 0xC00},
+ .notch2_en = {0x245AC, 0x1000},
+ },
+};
+
+static void rtw8922d_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_nbi_reg_def *nbi = &rtw8922d_nbi_reg_def[path];
+ s32 nbi_frac_idx, nbi_frac_tone_idx;
+ s32 nbi_idx, nbi_tone_idx;
+ bool notch2_chk = false;
+ u32 spur_freq, fc;
+ s32 freq_diff;
+
+ spur_freq = rtw8922d_spur_freq(rtwdev, chan, true, path);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0, phy_idx);
+ return;
+ }
+
+ fc = chan->freq;
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160) {
+ fc = (spur_freq > fc) ? fc + 40 : fc - 40;
+ if ((fc > spur_freq &&
+ chan->channel < chan->primary_channel) ||
+ (fc < spur_freq &&
+ chan->channel > chan->primary_channel))
+ notch2_chk = true;
+ }
+
+ freq_diff = (spur_freq - fc) * 1000000;
+ nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5,
+ &nbi_frac_idx);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_20) {
+ s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx);
+ } else {
+ u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ?
+ 128 : 256;
+
+ s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx);
+ }
+ nbi_frac_tone_idx =
+ s32_div_u32_round_closest(nbi_frac_idx, CARRIER_SPACING_78_125);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_idx.addr,
+ nbi->notch2_idx.mask, nbi_tone_idx, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_frac_idx.addr,
+ nbi->notch2_frac_idx.mask, nbi_frac_tone_idx,
+ phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0, phy_idx);
+ } else {
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_idx.addr,
+ nbi->notch1_idx.mask, nbi_tone_idx, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_frac_idx.addr,
+ nbi->notch1_frac_idx.mask, nbi_frac_tone_idx,
+ phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0, phy_idx);
+ }
+}
+
+static void rtw8922d_spur_elimination(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8922d_set_csi_tone_idx(rtwdev, chan, phy_idx);
+ rtw8922d_set_nbi_tone_idx(rtwdev, chan, RF_PATH_A, phy_idx);
+ rtw8922d_set_nbi_tone_idx(rtwdev, chan, RF_PATH_B, phy_idx);
+}
+
+static void rtw8922d_tssi_reset(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
+ if (phy_idx == RTW89_PHY_0) {
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB0_BE4,
+ B_TXPWR_RSTB0_BE4, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB0_BE4,
+ B_TXPWR_RSTB0_BE4, 0x1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB1_BE4,
+ B_TXPWR_RSTB1_BE4, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB1_BE4,
+ B_TXPWR_RSTB1_BE4, 0x1);
+ }
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB0_BE4, B_TXPWR_RSTB0_BE4, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB0_BE4, B_TXPWR_RSTB0_BE4, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB1_BE4, B_TXPWR_RSTB1_BE4, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB1_BE4, B_TXPWR_RSTB1_BE4, 0x1);
+ }
+}
+
+static void rtw8922d_set_channel_bb(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ bool cck_en = chan->band_type == RTW89_BAND_2G;
+ u8 pri_sb = chan->pri_sb_idx;
+ u32 val;
+
+ rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, phy_idx);
+ rtw8922d_ctrl_ch(rtwdev, chan, phy_idx);
+ rtw8922d_ctrl_bw(rtwdev, pri_sb, chan->band_width, phy_idx);
+ rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(rtwdev, chan, phy_idx);
+
+ if (cck_en)
+ rtw8922d_ctrl_sco_cck(rtwdev, chan->primary_channel,
+ chan->band_width, phy_idx);
+
+ rtw8922d_spur_elimination(rtwdev, chan, phy_idx);
+
+ if (hal->cid == RTL8922D_CID7025) {
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160)
+ val = 0x1f9;
+ else if (chan->band_width == RTW89_CHANNEL_WIDTH_80)
+ val = 0x1f5;
+ else
+ val = 0x1e2;
+
+ rtw89_phy_write32_idx(rtwdev, R_AWGN_DET_BE4, B_AWGN_DET_BE4, val, phy_idx);
+ }
+
+ rtw8922d_tssi_reset(rtwdev, RF_PATH_AB, phy_idx);
+}
+
MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part
2026-03-23 3:25 ` [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part Ping-Ke Shih
@ 2026-03-23 10:53 ` Bitterblue Smith
2026-03-24 0:49 ` Ping-Ke Shih
0 siblings, 1 reply; 10+ messages in thread
From: Bitterblue Smith @ 2026-03-23 10:53 UTC (permalink / raw)
To: Ping-Ke Shih, linux-wireless
On 23/03/2026 05:25, Ping-Ke Shih wrote:
> The set channel of BB part is the main part, which according to channel
> and bandwidth to configure CCK SCO, RX gain of LNA and TIA programmed
> in efuse for CCK and OFDM rate, and spur elimination of CSI and NBI tones.
>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
> ---
> drivers/net/wireless/realtek/rtw89/core.h | 2 +
> drivers/net/wireless/realtek/rtw89/reg.h | 64 +-
> drivers/net/wireless/realtek/rtw89/rtw8922d.c | 820 ++++++++++++++++++
> 3 files changed, 885 insertions(+), 1 deletion(-)
>
[..]
> +
> +static const struct rtw89_nbi_reg_def rtw8922d_nbi_reg_def[] = {
> + [RF_PATH_A] = {
> + .notch1_idx = {0x241A0, 0xFF},
> + .notch1_frac_idx = {0x241A0, 0xC00},
> + .notch1_en = {0x241A0, 0x1000},
> + .notch2_idx = {0x241AC, 0xFF},
> + .notch2_frac_idx = {0x241AC, 0xC00},
> + .notch2_en = {0x241AC, 0x1000},
> + },
> + [RF_PATH_B] = {
> + .notch1_idx = {0x245A0, 0xFF},
> + .notch1_frac_idx = {0x241A0, 0xC00},
Is that supposed to be 0x245A0 ?
> + .notch1_en = {0x245A0, 0x1000},
> + .notch2_idx = {0x245AC, 0xFF},
> + .notch2_frac_idx = {0x245AC, 0xC00},
> + .notch2_en = {0x245AC, 0x1000},
> + },
> +};
> +
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread* RE: [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part
2026-03-23 10:53 ` Bitterblue Smith
@ 2026-03-24 0:49 ` Ping-Ke Shih
0 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-24 0:49 UTC (permalink / raw)
To: Bitterblue Smith, linux-wireless@vger.kernel.org
Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 23/03/2026 05:25, Ping-Ke Shih wrote:
> > The set channel of BB part is the main part, which according to channel
> > and bandwidth to configure CCK SCO, RX gain of LNA and TIA programmed
> > in efuse for CCK and OFDM rate, and spur elimination of CSI and NBI tones.
> >
> > Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
> > ---
> > drivers/net/wireless/realtek/rtw89/core.h | 2 +
> > drivers/net/wireless/realtek/rtw89/reg.h | 64 +-
> > drivers/net/wireless/realtek/rtw89/rtw8922d.c | 820 ++++++++++++++++++
> > 3 files changed, 885 insertions(+), 1 deletion(-)
> >
>
> [..]
>
> > +
> > +static const struct rtw89_nbi_reg_def rtw8922d_nbi_reg_def[] = {
> > + [RF_PATH_A] = {
> > + .notch1_idx = {0x241A0, 0xFF},
> > + .notch1_frac_idx = {0x241A0, 0xC00},
> > + .notch1_en = {0x241A0, 0x1000},
> > + .notch2_idx = {0x241AC, 0xFF},
> > + .notch2_frac_idx = {0x241AC, 0xC00},
> > + .notch2_en = {0x241AC, 0x1000},
> > + },
> > + [RF_PATH_B] = {
> > + .notch1_idx = {0x245A0, 0xFF},
> > + .notch1_frac_idx = {0x241A0, 0xC00},
>
> Is that supposed to be 0x245A0 ?
Thanks for the finding. I'll fix it by v2.
>
> > + .notch1_en = {0x245A0, 0x1000},
> > + .notch2_idx = {0x245AC, 0xFF},
> > + .notch2_frac_idx = {0x245AC, 0xC00},
> > + .notch2_en = {0x245AC, 0x1000},
> > + },
> > +};
> > +
>
> [...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH rtw-next 7/7] wifi: rtw89: 8922d: add set channel of RF part
2026-03-23 3:25 [PATCH rtw-next 0/7] wifi: rtw89: 8922d: add RTL8922D common routine part 1 Ping-Ke Shih
` (5 preceding siblings ...)
2026-03-23 3:25 ` [PATCH rtw-next 6/7] wifi: rtw89: 8922d: add set channel of BB part Ping-Ke Shih
@ 2026-03-23 3:25 ` Ping-Ke Shih
6 siblings, 0 replies; 10+ messages in thread
From: Ping-Ke Shih @ 2026-03-23 3:25 UTC (permalink / raw)
To: linux-wireless
The set channel of RF part is to configure channel and bandwidth on a
register. The function to encode channel and bandwidth into register
value will be implemented by coming patch.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 1 +
.../net/wireless/realtek/rtw89/rtw8922d_rfk.c | 33 +++++++++++++++++++
.../net/wireless/realtek/rtw89/rtw8922d_rfk.h | 14 ++++++++
3 files changed, 48 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index f6b36b90dec8..137e98b8883e 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -8,6 +8,7 @@
#include "phy.h"
#include "reg.h"
#include "rtw8922d.h"
+#include "rtw8922d_rfk.h"
#include "util.h"
#define RTW8922D_FW_FORMAT_MAX 0
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
new file mode 100644
index 000000000000..6b35d196cb81
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2026 Realtek Corporation
+ */
+
+#include "phy.h"
+#include "reg.h"
+#include "rtw8922d.h"
+#include "rtw8922d_rfk.h"
+
+static
+void rtw8922d_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ const struct rtw89_chan *chan)
+{
+ u8 synpath;
+ u32 rf18;
+
+ synpath = rtw89_phy_get_syn_sel(rtwdev, phy);
+ rf18 = rtw89_chip_chan_to_rf18_val(rtwdev, chan);
+
+ rtw89_write_rf(rtwdev, synpath, RR_RSV1, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, synpath, RR_MOD, RFREG_MASK, 0x30000);
+ rtw89_write_rf(rtwdev, synpath, RR_CFGCH, RFREG_MASK, rf18);
+ fsleep(400);
+ rtw89_write_rf(rtwdev, synpath, RR_RSV1, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, synpath, RR_CFGCH_V1, RFREG_MASK, rf18);
+}
+
+void rtw8922d_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8922d_ctl_band_ch_bw(rtwdev, phy_idx, chan);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
new file mode 100644
index 000000000000..03af1f0497ac
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2026 Realtek Corporation
+ */
+
+#ifndef __RTW89_8922D_RFK_H__
+#define __RTW89_8922D_RFK_H__
+
+#include "core.h"
+
+void rtw8922d_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread