wifi: rtw89: 8852bt: add set_channel_rf
Add RF part of set_channel() is to configure RF registers, and then hardware can TX/RX on specified frequency and bandwidth. Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20240720021340.12102-2-pkshih@realtek.com
This commit is contained in:
@@ -4017,3 +4017,229 @@ void rtw8852bt_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
|
||||
else
|
||||
rtw8852bt_tssi_default_txagc(rtwdev, phy_idx, false);
|
||||
}
|
||||
|
||||
static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
|
||||
enum rtw89_bandwidth bw, bool dav)
|
||||
{
|
||||
u32 rf_reg18;
|
||||
u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
|
||||
|
||||
rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
|
||||
if (rf_reg18 == INV_RF_DATA) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[RFK]Invalid RF_0x18 for Path-%d\n", path);
|
||||
return;
|
||||
}
|
||||
rf_reg18 &= ~RR_CFGCH_BW;
|
||||
|
||||
switch (bw) {
|
||||
case RTW89_CHANNEL_WIDTH_5:
|
||||
case RTW89_CHANNEL_WIDTH_10:
|
||||
case RTW89_CHANNEL_WIDTH_20:
|
||||
rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_20M);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_40M);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_80M);
|
||||
break;
|
||||
default:
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]Fail to set CH\n");
|
||||
}
|
||||
|
||||
rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
|
||||
RR_CFGCH_BW2) & RFREG_MASK;
|
||||
rf_reg18 |= RR_CFGCH_BW2;
|
||||
rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set %x at path%d, %x =0x%x\n",
|
||||
bw, path, reg18_addr,
|
||||
rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
|
||||
}
|
||||
|
||||
static void _ctrl_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_bandwidth bw)
|
||||
{
|
||||
_bw_setting(rtwdev, RF_PATH_A, bw, true);
|
||||
_bw_setting(rtwdev, RF_PATH_B, bw, true);
|
||||
_bw_setting(rtwdev, RF_PATH_A, bw, false);
|
||||
_bw_setting(rtwdev, RF_PATH_B, bw, false);
|
||||
}
|
||||
|
||||
static bool _set_s0_arfc18(struct rtw89_dev *rtwdev, u32 val)
|
||||
{
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK, val);
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp == 0, 1, 1000,
|
||||
false, rtwdev, RF_PATH_A, RR_LPF, RR_LPF_BUSY);
|
||||
if (ret)
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]LCK timeout\n");
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
static void _lck_check(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN MMD reset\n");
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x1);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x0);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x1);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x0);
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
|
||||
if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]re-set RF 0x18\n");
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
|
||||
tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
|
||||
_set_s0_arfc18(rtwdev, tmp);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
|
||||
}
|
||||
|
||||
if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN off/on\n");
|
||||
|
||||
tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK, tmp);
|
||||
tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK, tmp);
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x1);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x0);
|
||||
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
|
||||
tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
|
||||
_set_s0_arfc18(rtwdev, tmp);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]0xb2=%x, 0xc5=%x\n",
|
||||
rtw89_read_rf(rtwdev, RF_PATH_A, RR_VCO, RFREG_MASK),
|
||||
rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RFREG_MASK));
|
||||
}
|
||||
}
|
||||
|
||||
static void _set_ch(struct rtw89_dev *rtwdev, u32 val)
|
||||
{
|
||||
bool timeout;
|
||||
u32 bak;
|
||||
|
||||
bak = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RR_LDO_SEL, 0x1);
|
||||
timeout = _set_s0_arfc18(rtwdev, val);
|
||||
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK, bak);
|
||||
if (!timeout)
|
||||
_lck_check(rtwdev);
|
||||
}
|
||||
|
||||
static void _ch_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
|
||||
u8 central_ch, bool dav)
|
||||
{
|
||||
u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
|
||||
bool is_2g_ch = central_ch <= 14;
|
||||
u32 rf_reg18;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
|
||||
|
||||
rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
|
||||
rf_reg18 &= ~(RR_CFGCH_BAND1 | RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH |
|
||||
RR_CFGCH_BCN | RR_CFGCH_BAND0 | RR_CFGCH_CH);
|
||||
rf_reg18 |= FIELD_PREP(RR_CFGCH_CH, central_ch);
|
||||
|
||||
if (!is_2g_ch)
|
||||
rf_reg18 |= FIELD_PREP(RR_CFGCH_BAND1, CFGCH_BAND1_5G) |
|
||||
FIELD_PREP(RR_CFGCH_BAND0, CFGCH_BAND0_5G);
|
||||
|
||||
rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
|
||||
RR_CFGCH_BW2) & RFREG_MASK;
|
||||
rf_reg18 |= RR_CFGCH_BW2;
|
||||
|
||||
if (path == RF_PATH_A && dav)
|
||||
_set_ch(rtwdev, rf_reg18);
|
||||
else
|
||||
rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
|
||||
|
||||
rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 0);
|
||||
rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 1);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[RFK]CH: %d for Path-%d, reg0x%x = 0x%x\n",
|
||||
central_ch, path, reg18_addr,
|
||||
rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
|
||||
}
|
||||
|
||||
static void _ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch)
|
||||
{
|
||||
_ch_setting(rtwdev, RF_PATH_A, central_ch, true);
|
||||
_ch_setting(rtwdev, RF_PATH_B, central_ch, true);
|
||||
_ch_setting(rtwdev, RF_PATH_A, central_ch, false);
|
||||
_ch_setting(rtwdev, RF_PATH_B, central_ch, false);
|
||||
}
|
||||
|
||||
static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_bandwidth bw,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1);
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0x12);
|
||||
|
||||
if (bw == RTW89_CHANNEL_WIDTH_20)
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x1b);
|
||||
else if (bw == RTW89_CHANNEL_WIDTH_40)
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x13);
|
||||
else if (bw == RTW89_CHANNEL_WIDTH_80)
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0xb);
|
||||
else
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x3);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set S%d RXBB BW 0x3F = 0x%x\n",
|
||||
path, rtw89_read_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB));
|
||||
|
||||
rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0);
|
||||
}
|
||||
|
||||
static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_bandwidth bw)
|
||||
{
|
||||
u8 kpath, path;
|
||||
|
||||
kpath = _kpath(rtwdev, phy);
|
||||
|
||||
for (path = 0; path < RF_PATH_NUM_8852BT; path++) {
|
||||
if (!(kpath & BIT(path)))
|
||||
continue;
|
||||
|
||||
_set_rxbb_bw(rtwdev, bw, path);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw8852bt_ctrl_bw_ch(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy, u8 central_ch,
|
||||
enum rtw89_band band, enum rtw89_bandwidth bw)
|
||||
{
|
||||
_ctrl_ch(rtwdev, central_ch);
|
||||
_ctrl_bw(rtwdev, phy, bw);
|
||||
_rxbb_bw(rtwdev, phy, bw);
|
||||
}
|
||||
|
||||
void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852bt_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type,
|
||||
chan->band_width);
|
||||
}
|
||||
|
||||
@@ -18,5 +18,8 @@ void rtw8852bt_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_
|
||||
void rtw8852bt_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
|
||||
void rtw8852bt_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user