Commit 88d1f9b2 authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo
Browse files

wifi: rtw89: 8922a: add RF read/write v2



Implement indirect interface v2 to read/write RF registers via PHY
registers for 8922A.

Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240124033637.12330-5-pkshih@realtek.com
parent 1ba63a8a
Loading
Loading
Loading
Loading
+125 −0
Original line number Diff line number Diff line
@@ -796,6 +796,71 @@ u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
}
EXPORT_SYMBOL(rtw89_phy_read_rf_v1);

static u32 rtw89_phy_read_full_rf_v2_a(struct rtw89_dev *rtwdev,
				       enum rtw89_rf_path rf_path, u32 addr)
{
	static const u16 r_addr_ofst[2] = {0x2C24, 0x2D24};
	static const u16 addr_ofst[2] = {0x2ADC, 0x2BDC};
	bool busy, done;
	int ret;
	u32 val;

	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_CTL_MASK, 0x1);
	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
				       1, 3800, false,
				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_BUSY);
	if (ret) {
		rtw89_warn(rtwdev, "poll HWSI is busy\n");
		return INV_RF_DATA;
	}

	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_MASK, addr);
	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_RD, 0x1);
	udelay(2);

	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
				       1, 3800, false,
				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_RDONE);
	if (ret) {
		rtw89_warn(rtwdev, "read HWSI is busy\n");
		val = INV_RF_DATA;
		goto out;
	}

	val = rtw89_phy_read32_mask(rtwdev, r_addr_ofst[rf_path], RFREG_MASK);
out:
	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_POLL_MASK, 0);

	return val;
}

static u32 rtw89_phy_read_rf_v2_a(struct rtw89_dev *rtwdev,
				  enum rtw89_rf_path rf_path, u32 addr, u32 mask)
{
	u32 val;

	val = rtw89_phy_read_full_rf_v2_a(rtwdev, rf_path, addr);

	return (val & mask) >> __ffs(mask);
}

u32 rtw89_phy_read_rf_v2(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_v2_a(rtwdev, rf_path, addr, mask);
}
EXPORT_SYMBOL(rtw89_phy_read_rf_v2);

bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
			u32 addr, u32 mask, u32 data)
{
@@ -875,6 +940,66 @@ bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
}
EXPORT_SYMBOL(rtw89_phy_write_rf_v1);

static
bool rtw89_phy_write_full_rf_v2_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
				  u32 addr, u32 data)
{
	static const u32 addr_is_idle[2] = {0x2C24, 0x2D24};
	static const u32 addr_ofst[2] = {0x2AE0, 0x2BE0};
	bool busy;
	u32 val;
	int ret;

	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
				       1, 3800, false,
				       rtwdev, addr_is_idle[rf_path], BIT(29));
	if (ret) {
		rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
		return false;
	}

	val = u32_encode_bits(addr, B_HWSI_DATA_ADDR) |
	      u32_encode_bits(data, B_HWSI_DATA_VAL);

	rtw89_phy_write32(rtwdev, addr_ofst[rf_path], val);

	return true;
}

static
bool rtw89_phy_write_rf_a_v2(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_v2_a(rtwdev, rf_path, addr);
		val &= ~mask;
		val |= (data << __ffs(mask)) & mask;
	}

	return rtw89_phy_write_full_rf_v2_a(rtwdev, rf_path, addr, val);
}

bool rtw89_phy_write_rf_v2(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_v2(rtwdev, rf_path, addr, mask, data);
}
EXPORT_SYMBOL(rtw89_phy_write_rf_v2);

static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
{
	return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
+4 −0
Original line number Diff line number Diff line
@@ -781,10 +781,14 @@ u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
		      u32 addr, u32 mask);
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);
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);
void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
+15 −0
Original line number Diff line number Diff line
@@ -7997,6 +7997,21 @@
#define B_AFEDAC1 GENMASK(2, 0)
#define R_IQKDPK_HC 0x2AB8
#define B_IQKDPK_HC BIT(28)
#define R_HWSI_ADD0 0x2ADC
#define R_HWSI_ADD1 0x2BDC
#define B_HWSI_ADD_MASK GENMASK(11, 4)
#define B_HWSI_ADD_CTL_MASK GENMASK(2, 0)
#define B_HWSI_ADD_RD BIT(2)
#define B_HWSI_ADD_POLL_MASK GENMASK(1, 0)
#define B_HWSI_ADD_RUN BIT(1)
#define B_HWSI_ADD_BUSY BIT(0)
#define R_HWSI_DATA 0x2AE0
#define B_HWSI_DATA_VAL GENMASK(27, 8)
#define B_HWSI_DATA_ADDR GENMASK(7, 0)
#define R_HWSI_VAL0 0x2C24
#define R_HWSI_VAL1 0x2D24
#define B_HWSI_VAL_RDONE BIT(31)
#define B_HWSI_VAL_BUSY BIT(29)
#define R_P1_EN_SOUND_WO_NDP 0x2D7C
#define B_P1_EN_SOUND_WO_NDP BIT(1)
#define R_EDCCA_RPT_A_BE 0x2E38
+2 −0
Original line number Diff line number Diff line
@@ -1594,6 +1594,8 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
	.bb_postinit		= rtw8922a_bb_postinit,
	.bb_reset		= rtw8922a_bb_reset,
	.bb_sethw		= rtw8922a_bb_sethw,
	.read_rf		= rtw89_phy_read_rf_v2,
	.write_rf		= rtw89_phy_write_rf_v2,
	.set_channel		= rtw8922a_set_channel,
	.read_efuse		= rtw8922a_read_efuse,
	.read_phycap		= rtw8922a_read_phycap,