Implement to access RF registers for RTL8922D. Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/phy.c | 122 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/phy.h | 4 + drivers/net/wireless/realtek/rtw89/reg.h | 13 +++ 3 files changed, 139 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index d29fbc9cb5ac..a7ae8b277dd5 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -1028,6 +1028,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) { @@ -1167,6 +1229,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; diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 9caacffd0af8..444b4ff86ebc 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -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); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index edf0223b28a3..c06723fdb4d3 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -9893,6 +9893,19 @@ #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) -- 2.25.1