]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: 8922d: configure TX/RX path assisting in BT coexistence
authorPing-Ke Shih <pkshih@realtek.com>
Mon, 30 Mar 2026 06:58:43 +0000 (14:58 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 2 Apr 2026 03:17:12 +0000 (11:17 +0800)
The BT coexistence mechanism needs to control TX/RX path to co-work with
BT well, and these helpers are provided by BB to configure path.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260330065847.48946-6-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8922d.c

index 37de1c827814727ecb7cd8f952ebb7dce59ebe50..78f2cf579fa61419a262f86edbdfd33daa7335d9 100644 (file)
 #define B_EMLSR_BB_CLK_BE4 GENMASK(31, 30)
 #define R_CHINFO_SEG_BE4 0x200B4
 #define B_CHINFO_SEG_LEN_BE4 GENMASK(12, 10)
-#define R_STS_HDR2_PARSING_BE4 0x2070C
-#define B_STS_HDR2_PARSING_BE4 BIT(10)
+#define R_SEL_GNT_BT_RX_BE4 0x2010C
+#define B_SEL_GNT_BT_RX_PATH0_BE4 GENMASK(3, 0)
+#define B_SEL_GNT_BT_RX_PATH1_BE4 GENMASK(11, 8)
 #define R_SW_SI_WDATA_BE4 0x20370
 #define B_SW_SI_DATA_PATH_BE4 GENMASK(31, 28)
 #define B_SW_SI_DATA_ADR_BE4 GENMASK(27, 20)
 #define B_ENABLE_CCK0_BE4 BIT(5)
 #define R_RSTB_ASYNC_BE4 0x20704
 #define B_RSTB_ASYNC_BE4 BIT(1)
+#define R_STS_HDR2_PARSING_BE4 0x2070C
+#define B_STS_HDR2_PARSING_BE4 BIT(10)
 #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_SEL_GNT_BT_RXPHY_BE4 0x2079C
+#define B_SEL_GNT_BT_RXPHY_BE4 GENMASK(11, 8)
 #define R_IMR_TX_ERROR_BE4 0x20920
 #define B_IMR_TX_ERROR_BE4 BIT(30)
 #define R_TXINFO_PATH_BE4 0x209A4
index 9c62a5f1296205088570c7605679b2a58cc3de45..cfe9752abddcb858be81d7fb30862ba9939eb994 100644 (file)
@@ -238,6 +238,35 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
        [RTW89_EFUSE_BLOCK_ADIE]                = {.offset = 0x70000, .size = 0x10},
 };
 
+static void rtw8922d_sel_bt_rx_path(struct rtw89_dev *rtwdev, u8 val,
+                                   enum rtw89_rf_path rx_path)
+{
+       if (rx_path == RF_PATH_A)
+               rtw89_phy_write32_mask(rtwdev, R_SEL_GNT_BT_RX_BE4,
+                                      B_SEL_GNT_BT_RX_PATH0_BE4, val);
+       else if (rx_path == RF_PATH_B)
+               rtw89_phy_write32_mask(rtwdev, R_SEL_GNT_BT_RX_BE4,
+                                      B_SEL_GNT_BT_RX_PATH1_BE4, val);
+       else
+               rtw89_warn(rtwdev, "[%s] Not support path = %d\n", __func__, rx_path);
+}
+
+static void rtw8922d_sel_bt_rx_phy(struct rtw89_dev *rtwdev, u8 val,
+                                  enum rtw89_phy_idx phy_idx)
+{
+       rtw89_phy_write32_idx(rtwdev, R_SEL_GNT_BT_RXPHY_BE4,
+                             B_SEL_GNT_BT_RXPHY_BE4, val, phy_idx);
+}
+
+static void rtw8922d_set_gbt_bt_rx_sel(struct rtw89_dev *rtwdev, bool en,
+                                      enum rtw89_phy_idx phy_idx)
+{
+       rtw8922d_sel_bt_rx_path(rtwdev, 0x3, RF_PATH_A);
+       rtw8922d_sel_bt_rx_phy(rtwdev, 0x0, RTW89_PHY_0);
+       rtw8922d_sel_bt_rx_path(rtwdev, 0x3, RF_PATH_B);
+       rtw8922d_sel_bt_rx_phy(rtwdev, 0x0, RTW89_PHY_1);
+}
+
 static int rtw8922d_pwr_on_func(struct rtw89_dev *rtwdev)
 {
        struct rtw89_hal *hal = &rtwdev->hal;
@@ -2437,6 +2466,102 @@ static void rtw8922d_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
        rtw8922d_set_txpwr_ref(rtwdev, chan, phy_idx);
 }
 
+static void rtw8922d_ctrl_trx_path(struct rtw89_dev *rtwdev,
+                                  enum rtw89_rf_path tx_path, u8 tx_nss,
+                                  enum rtw89_rf_path rx_path, u8 rx_nss)
+{
+       enum rtw89_phy_idx phy_idx;
+
+       for (phy_idx = RTW89_PHY_0; phy_idx <= RTW89_PHY_1; phy_idx++) {
+               rtw8922d_ctrl_tx_path_tmac(rtwdev, tx_path, phy_idx);
+               rtw8922d_ctrl_rx_path_tmac(rtwdev, rx_path, phy_idx);
+
+               rtw8922d_tssi_reset(rtwdev, rx_path, phy_idx);
+       }
+}
+
+static void rtw8922d_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
+                                    enum rtw89_phy_idx phy_idx)
+{
+       if (en) {
+               rtw89_phy_write32_idx(rtwdev, R_FORCE_FIR_A, B_FORCE_FIR_A, 0x3, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_RXBY_WBADC_A, B_RXBY_WBADC_A,
+                                     0xf, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_RXBY_WBADC_A, B_BT_RXBY_WBADC_A,
+                                     0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_SHARE_A, B_BT_TRK_OFF_A, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_OP1DB_A, B_OP1DB_A, 0x80, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_OP1DB1_A, B_TIA10_A, 0x8080, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BACKOFF_A, B_LNA_IBADC_A, 0x34, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BKOFF_A, B_BKOFF_IBADC_A, 0x34, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_FORCE_FIR_B, B_FORCE_FIR_B, 0x3, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_RXBY_WBADC_B, B_RXBY_WBADC_B,
+                                     0xf, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_RXBY_WBADC_B, B_BT_RXBY_WBADC_B,
+                                     0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_SHARE_B, B_BT_TRK_OFF_B, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_LNA_TIA, B_TIA1_B, 0x80, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BACKOFF_B, B_LNA_IBADC_B, 0x34, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BKOFF_B, B_BKOFF_IBADC_B, 0x34, phy_idx);
+       } else {
+               rtw89_phy_write32_idx(rtwdev, R_FORCE_FIR_A, B_FORCE_FIR_A, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_RXBY_WBADC_A, B_RXBY_WBADC_A,
+                                     0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_RXBY_WBADC_A, B_BT_RXBY_WBADC_A,
+                                     0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_SHARE_A, B_BT_TRK_OFF_A, 0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_OP1DB_A, B_OP1DB_A, 0x1a, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_OP1DB1_A, B_TIA10_A, 0x2a2a, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BACKOFF_A, B_LNA_IBADC_A, 0x7a6, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BKOFF_A, B_BKOFF_IBADC_A, 0x26, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_FORCE_FIR_B, B_FORCE_FIR_B, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_RXBY_WBADC_B, B_RXBY_WBADC_B,
+                                     0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_RXBY_WBADC_B, B_BT_RXBY_WBADC_B,
+                                     0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BT_SHARE_B, B_BT_TRK_OFF_B, 0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_LNA_TIA, B_TIA1_B, 0x2a, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BACKOFF_B, B_LNA_IBADC_B, 0x7a6, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_BKOFF_B, B_BKOFF_IBADC_B, 0x26, phy_idx);
+       }
+}
+
+static void rtw8922d_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
+{
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
+       enum rtw89_band band = chan->band_type;
+       struct rtw89_hal *hal = &rtwdev->hal;
+       u8 ntx_path = RF_PATH_AB;
+       u8 nrx_path = RF_PATH_AB;
+       u32 tx_en0, tx_en1;
+       u8 rx_nss = 2;
+
+       if (hal->antenna_tx == RF_A)
+               ntx_path = RF_PATH_A;
+       else if (hal->antenna_tx == RF_B)
+               ntx_path = RF_PATH_B;
+
+       if (hal->antenna_rx == RF_A)
+               nrx_path = RF_PATH_A;
+       else if (hal->antenna_rx == RF_B)
+               nrx_path = RF_PATH_B;
+
+       if (nrx_path != RF_PATH_AB)
+               rx_nss = 1;
+
+       rtw8922d_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, true);
+       if (rtwdev->dbcc_en)
+               rtw8922d_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band,
+                                  &tx_en1, true);
+
+       rtw8922d_ctrl_trx_path(rtwdev, ntx_path, 2, nrx_path, rx_nss);
+
+       rtw8922d_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false);
+       if (rtwdev->dbcc_en)
+               rtw8922d_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band,
+                                  &tx_en1, false);
+}
+
 MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
 MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
 MODULE_AUTHOR("Realtek Corporation");