summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZong-Zhe Yang <kevin_yang@realtek.com>2025-07-10 12:24:21 +0800
committerPing-Ke Shih <pkshih@realtek.com>2025-07-15 09:51:18 +0800
commit21911ad80512f9e4e642b9e8ecd7130e32cb63d3 (patch)
tree313d7c5aa11f343695b4dc9a08365c265327d2c5
parent868676662b08f43cd26a2bc3492d6a7fa1eb3414 (diff)
downloadlinux-21911ad80512f9e4e642b9e8ecd7130e32cb63d3.tar.gz
linux-21911ad80512f9e4e642b9e8ecd7130e32cb63d3.zip
wifi: rtw89: 8852bt: implement RFK multi-channel handling and support chanctx up to 2
To support multiple channels, 2 for this case, RFK requires to record each calibration result for each channel in different RFK tables, and also needs to notify FW. Then, when FW runs in MCC (multi-channel concurrency), it can switch to the corresponding calibration result according to the channel. Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20250710042423.73617-13-pkshih@realtek.com
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt.c12
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c69
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h3
3 files changed, 65 insertions, 19 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 10d09c12f318..06a06c190553 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -533,8 +533,11 @@ static void rtw8852bt_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev)
{
+ struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+
rtwdev->is_tssi_mode[RF_PATH_A] = false;
rtwdev->is_tssi_mode[RF_PATH_B] = false;
+ memset(rfk_mcc, 0, sizeof(*rfk_mcc));
rtw8852bt_dpk_init(rtwdev);
rtw8852bt_rck(rtwdev);
@@ -548,6 +551,7 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
+ rtw8852bt_mcc_get_ch_info(rtwdev, phy_idx);
rtw89_btc_ntfy_conn_rfk(rtwdev, true);
rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx);
@@ -558,6 +562,7 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev,
rtw8852bt_dpk(rtwdev, phy_idx, chanctx_idx);
rtw89_btc_ntfy_conn_rfk(rtwdev, false);
+ rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
}
static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev,
@@ -727,6 +732,10 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
.btc_set_policy = rtw89_btc_set_policy_v1,
};
+static const struct rtw89_chanctx_listener rtw8852bt_chanctx_listener = {
+ .callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852bt_rfk_chanctx_cb,
+};
+
#ifdef CONFIG_PM
static const struct wiphy_wowlan_support rtw_wowlan_stub_8852bt = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
@@ -769,6 +778,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.nctl_post_table = NULL,
.dflt_parms = NULL,
.rfe_parms_conf = NULL,
+ .chanctx_listener = &rtw8852bt_chanctx_listener,
.txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
@@ -777,7 +787,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.tssi_dbw_table = NULL,
.support_macid_num = RTW89_MAX_MAC_ID_NUM,
.support_link_num = 0,
- .support_chanctx_num = 1,
+ .support_chanctx_num = 2,
.support_rnr = false,
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c
index 6e6889eea9a0..d0e299803225 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2024 Realtek Corporation
*/
+#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "fw.h"
@@ -1529,26 +1530,11 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, u
enum rtw89_chanctx_idx chanctx_idx)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx);
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
- u8 get_empty_table = false;
+ u8 idx = rfk_mcc->table_idx;
u32 reg_rf18;
u32 reg_35c;
- u8 idx;
-
- for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
- if (iqk_info->iqk_mcc_ch[idx][path] == 0) {
- get_empty_table = true;
- break;
- }
- }
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (1)idx = %x\n", idx);
-
- if (!get_empty_table) {
- idx = iqk_info->iqk_table_idx[path] + 1;
- if (idx > 1)
- idx = 0;
- }
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (2)idx = %x\n", idx);
reg_rf18 = rtw89_read_rf(rtwdev, path, RR_CFGCH, RFREG_MASK);
reg_35c = rtw89_phy_read32_mask(rtwdev, R_CIRST, B_CIRST_SYN);
@@ -1640,7 +1626,8 @@ static void _iqk_afebb_restore(struct rtw89_dev *rtwdev,
static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path)
{
- u8 idx = 0;
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
+ u8 idx = rfk_mcc->table_idx;
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL + (path << 8), 0x00000001, idx);
rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), 0x00000008, idx);
@@ -4252,3 +4239,49 @@ void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev,
rtw8852bt_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type,
chan->band_width);
}
+
+void rtw8852bt_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, 0);
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
+ struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {};
+ u8 idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(desc); idx++) {
+ struct rtw89_rfk_chan_desc *p = &desc[idx];
+
+ p->ch = rfk_mcc->ch[idx];
+
+ p->has_band = true;
+ p->band = rfk_mcc->band[idx];
+ }
+
+ idx = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
+
+ rfk_mcc->ch[idx] = chan->channel;
+ rfk_mcc->band[idx] = chan->band_type;
+ rfk_mcc->table_idx = idx;
+}
+
+void rtw8852bt_rfk_chanctx_cb(struct rtw89_dev *rtwdev,
+ enum rtw89_chanctx_state state)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 path;
+
+ switch (state) {
+ case RTW89_CHANCTX_STATE_MCC_START:
+ dpk->is_dpk_enable = false;
+ for (path = 0; path < RTW8852BT_SS; path++)
+ _dpk_onoff(rtwdev, path, false);
+ break;
+ case RTW89_CHANCTX_STATE_MCC_STOP:
+ dpk->is_dpk_enable = true;
+ for (path = 0; path < RTW8852BT_SS; path++)
+ _dpk_onoff(rtwdev, path, false);
+ rtw8852bt_dpk(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h
index e34560b4905f..a663bbda4075 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h
@@ -27,5 +27,8 @@ void rtw8852bt_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
+void rtw8852bt_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw8852bt_rfk_chanctx_cb(struct rtw89_dev *rtwdev,
+ enum rtw89_chanctx_state state);
#endif