]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: phy: add {read,write}_rf_v3 for RTL8922D
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 14 Jan 2026 01:39:40 +0000 (09:39 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 22 Jan 2026 01:32:12 +0000 (09:32 +0800)
Implement to access RF registers for RTL8922D.

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

index 0b72d3dcf66689c4c015fdb1ed3e2a428bd5c7b9..20d3f3a42b4bee877d0ccbdf969862dfc4b9fd4a 100644 (file)
@@ -1036,6 +1036,68 @@ u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 }
 EXPORT_SYMBOL(rtw89_phy_read_rf_v2);
 
+static u32 rtw89_phy_read_full_rf_v3_a(struct rtw89_dev *rtwdev,
+                                      enum rtw89_rf_path rf_path, u32 addr)
+{
+       bool done;
+       u32 busy;
+       int ret;
+       u32 val;
+
+       ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
+                                      1, 30, false,
+                                      rtwdev, R_SW_SI_DATA_BE4,
+                                      B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
+       if (ret) {
+               rtw89_warn(rtwdev, "poll HWSI is busy\n");
+               return INV_RF_DATA;
+       }
+
+       val = u32_encode_bits(rf_path, GENMASK(10, 8)) |
+             u32_encode_bits(addr, GENMASK(7, 0));
+
+       rtw89_phy_write32_mask(rtwdev, R_SW_SI_READ_ADDR_BE4, B_SW_SI_READ_ADDR_BE4, val);
+
+       ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
+                                      1, 30, false,
+                                      rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_DONE_BE4);
+       if (ret) {
+               rtw89_warn(rtwdev, "read HWSI is busy\n");
+               return INV_RF_DATA;
+       }
+
+       val = rtw89_phy_read32_mask(rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_BE4);
+
+       return val;
+}
+
+static u32 rtw89_phy_read_rf_v3_a(struct rtw89_dev *rtwdev,
+                                 enum rtw89_rf_path rf_path, u32 addr, u32 mask)
+{
+       u32 val;
+
+       val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
+
+       return (val & mask) >> __ffs(mask);
+}
+
+u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                        u32 addr, u32 mask)
+{
+       bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
+
+       if (rf_path >= rtwdev->chip->rf_path_num) {
+               rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+               return INV_RF_DATA;
+       }
+
+       if (ad_sel)
+               return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
+       else
+               return rtw89_phy_read_rf_v3_a(rtwdev, rf_path, addr, mask);
+}
+EXPORT_SYMBOL(rtw89_phy_read_rf_v3);
+
 bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                        u32 addr, u32 mask, u32 data)
 {
@@ -1175,6 +1237,66 @@ bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 }
 EXPORT_SYMBOL(rtw89_phy_write_rf_v2);
 
+static
+bool rtw89_phy_write_full_rf_v3_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                                 u32 addr, u32 data)
+{
+       u32 busy;
+       u32 val;
+       int ret;
+
+       ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
+                                      1, 30, false,
+                                      rtwdev, R_SW_SI_DATA_BE4,
+                                      B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
+       if (ret) {
+               rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
+               return false;
+       }
+
+       val = u32_encode_bits(rf_path, B_SW_SI_DATA_PATH_BE4) |
+             u32_encode_bits(addr, B_SW_SI_DATA_ADR_BE4) |
+             u32_encode_bits(data, B_SW_SI_DATA_DAT_BE4);
+
+       rtw89_phy_write32(rtwdev, R_SW_SI_WDATA_BE4, val);
+
+       return true;
+}
+
+static
+bool rtw89_phy_write_rf_a_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                            u32 addr, u32 mask, u32 data)
+{
+       u32 val;
+
+       if (mask == RFREG_MASK) {
+               val = data;
+       } else {
+               val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
+               val &= ~mask;
+               val |= (data << __ffs(mask)) & mask;
+       }
+
+       return rtw89_phy_write_full_rf_v3_a(rtwdev, rf_path, addr, val);
+}
+
+bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                          u32 addr, u32 mask, u32 data)
+{
+       bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
+
+       if (rf_path >= rtwdev->chip->rf_path_num) {
+               rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+               return INV_RF_DATA;
+       }
+
+       if (ad_sel)
+               return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
+       else
+               return rtw89_phy_write_rf_a_v3(rtwdev, rf_path, addr, mask, data);
+}
+EXPORT_SYMBOL(rtw89_phy_write_rf_v3);
+
 static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
 {
        return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
index 9caacffd0af8682ee4300b43b1600a2f66470de7..444b4ff86ebc85b064fb986f1e8432a4d50c60f2 100644 (file)
@@ -823,12 +823,16 @@ u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                         u32 addr, u32 mask);
 u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                         u32 addr, u32 mask);
+u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                        u32 addr, u32 mask);
 bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                        u32 addr, u32 mask, u32 data);
 bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                           u32 addr, u32 mask, u32 data);
 bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                           u32 addr, u32 mask, u32 data);
+bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+                          u32 addr, u32 mask, u32 data);
 void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
 void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev);
 void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
index df0866ba1d1721e66baea6bbb24a1f412ab405f3..bb991e7450bf536f4644e77398e90be3dee87a7a 100644 (file)
 #define R_TSSI_K_P1 0xE7A0
 #define B_TSSI_K_OFDM_P1 GENMASK(29, 20)
 
+#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_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_SW_SI_DATA_BE4 0x2CF4C
+#define B_SW_SI_READ_DATA_BE4 GENMASK(19, 0)
+#define B_SW_SI_W_BUSY_BE4 BIT(24)
+#define B_SW_SI_R_BUSY_BE4 BIT(25)
+#define B_SW_SI_READ_DATA_DONE_BE4 BIT(26)
+
 /* WiFi CPU local domain */
 #define R_AX_WDT_CTRL 0x0040
 #define B_AX_WDT_EN BIT(31)