]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: rtw89: 8852bt: add set_channel_rf
authorPing-Ke Shih <pkshih@realtek.com>
Sat, 20 Jul 2024 02:13:34 +0000 (10:13 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 31 Jul 2024 05:48:00 +0000 (13:48 +0800)
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
drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h

index 5bdabb45e9686c560234208c75ea7957c96f894b..0f2a74269b981174d4a5814d91c9fcc0631cfbd1 100644 (file)
@@ -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);
+}
index 09918835c6e85d7a2c059d8abf40abca4ceb6e7c..ef3d98f804007854125437e459423b9d756f0ed2 100644 (file)
@@ -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