From: Ho Jie Feng <hjf3108@gmail.com>
To: Ping-Ke Shih <pkshih@realtek.com>
Cc: linux-wireless@vger.kernel.org, Ho Jie Feng <hjf3108@gmail.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH rtw-next v2 5/7] wifi: rtw88: 88xxa: correct carrier-frequency offset
Date: Sat, 31 Oct 2026 15:09:45 +0800 [thread overview]
Message-ID: <20261031070950.425176-6-hjf3108@gmail.com> (raw)
In-Reply-To: <20261031070950.425176-1-hjf3108@gmail.com>
Use the newly promoted helpers to implement support for 88xxa
Signed-off-by: Ho Jie Feng <hjf3108@gmail.com>
---
drivers/net/wireless/realtek/rtw88/phy.c | 5 +-
drivers/net/wireless/realtek/rtw88/rtw8812a.c | 2 +
drivers/net/wireless/realtek/rtw88/rtw8814a.c | 31 ++++++++++--
drivers/net/wireless/realtek/rtw88/rtw8821a.c | 2 +
drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 47 +++++++++++++++----
drivers/net/wireless/realtek/rtw88/rtw88xxa.h | 1 +
6 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index d0c1fb65be9563c5fc29a7d18a1c9e8589730b10..69998c0d7c1f851bb30d2702233d62e14b305bf0 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -687,13 +687,14 @@ static void rtw_phy_parsing_cfo_iter(void *data, u8 *mac,
struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
+ u8 path_num = min_t(u8, rtwdev->hal.rf_path_num, 2);
u8 *bssid = iter_data->bssid;
u8 i;
if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
return;
- for (i = 0; i < rtwdev->hal.rf_path_num; i++) {
+ for (i = 0; i < path_num; i++) {
cfo->cfo_tail[i] += pkt_stat->cfo_tail[i];
cfo->cfo_cnt[i]++;
}
@@ -794,7 +795,7 @@ u8 rtw_phy_cfo_xcap_track(struct rtw_dev *rtwdev, u8 xcap_max, bool bt_hold)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
- u8 path_num = rtwdev->hal.rf_path_num;
+ u8 path_num = min_t(u8, rtwdev->hal.rf_path_num, 2);
s8 crystal_cap = cfo->crystal_cap;
s32 cfo_avg = 0;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
index 5d58dff4fcee7c4b3194794266cb48cd472014f9..c8008cf43da9df68a8c1dfb277d529a1191bda01 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
@@ -943,6 +943,8 @@ static const struct rtw_chip_ops rtw8812a_ops = {
.coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type,
.coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power,
.coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
+ .cfo_init = rtw_phy_cfo_xcap_init,
+ .cfo_track = rtw88xxa_cfo_track,
};
static const struct rtw_page_table page_table_8812a[] = {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814a.c b/drivers/net/wireless/realtek/rtw88/rtw8814a.c
index 2db05a83766d65123edc95f50a40d3f93bfb1dba..3c65cd838ce15f0149852cd488e88f78e709efe1 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8814a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8814a.c
@@ -145,7 +145,7 @@ static int rtw8814a_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(4));
efuse->rfe_option = map->rfe_option;
efuse->rf_board_option = map->rf_board_option;
- efuse->crystal_cap = map->xtal_k;
+ efuse->crystal_cap = map->xtal_k & 0x3f;
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
efuse->country_code[1] = map->country_code[1];
@@ -284,9 +284,15 @@ static void rtw8814a_config_cck_rx_antenna_init(struct rtw_dev *rtwdev)
rtw_write32_mask(rtwdev, REG_CCKTX, BIT_CMB_CCA_2R, 1);
}
+static void rtw8814a_set_crystal_cap(struct rtw_dev *rtwdev, u8 crystal_cap)
+{
+ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x07ff8000,
+ crystal_cap | (crystal_cap << 6));
+}
+
static void rtw8814a_phy_set_param(struct rtw_dev *rtwdev)
{
- u32 crystal_cap, val32;
+ u32 val32;
u8 val8, rf_path;
/* power on BB/RF domain */
@@ -308,9 +314,7 @@ static void rtw8814a_phy_set_param(struct rtw_dev *rtwdev)
rtw_load_table(rtwdev, rtwdev->chip->bb_tbl);
rtw_load_table(rtwdev, rtwdev->chip->agc_tbl);
- crystal_cap = rtwdev->efuse.crystal_cap & 0x3F;
- crystal_cap |= crystal_cap << 6;
- rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x07ff8000, crystal_cap);
+ rtw8814a_set_crystal_cap(rtwdev, rtwdev->efuse.crystal_cap);
rtw8814a_config_trx_path(rtwdev);
@@ -1269,6 +1273,8 @@ static void rtw8814a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
pkt_stat->cfo_tail[i] = cfo[i];
dm_info->cfo_tail[i] = (cfo[i] * 5) >> 1;
}
+
+ rtw_phy_parsing_cfo(rtwdev, pkt_stat);
}
}
@@ -2068,6 +2074,19 @@ static void rtw8814a_bf_config_bfee(struct rtw_dev *rtwdev,
rtw_bf_remove_bfee_su(rtwdev, bfee);
}
+static void rtw8814a_cfo_track(struct rtw_dev *rtwdev)
+{
+ struct rtw_cfo_track *cfo = &rtwdev->dm_info.cfo_track;
+ u8 crystal_cap;
+
+ crystal_cap = rtw_phy_cfo_xcap_track(rtwdev, 0x3f, false);
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ cfo->crystal_cap = crystal_cap;
+ rtw8814a_set_crystal_cap(rtwdev, crystal_cap);
+}
+
static void rtw8814a_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
@@ -2102,6 +2121,8 @@ static const struct rtw_chip_ops rtw8814a_ops = {
.cfg_csi_rate = NULL,
.led_set = rtw8814a_led_set,
.fill_txdesc_checksum = rtw8814a_fill_txdesc_checksum,
+ .cfo_init = rtw_phy_cfo_xcap_init,
+ .cfo_track = rtw8814a_cfo_track,
.coex_set_init = rtw8814a_coex_cfg_init,
.coex_set_ant_switch = rtw8814a_coex_cfg_ant_switch,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
index 6d106ae70d9142b45337057311dc423158e7dabc..17d3677ca463cf633d8c138612deaa676bc02986 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
@@ -889,6 +889,8 @@ static const struct rtw_chip_ops rtw8821a_ops = {
.coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type,
.coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power,
.coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
+ .cfo_init = rtw_phy_cfo_xcap_init,
+ .cfo_track = rtw88xxa_cfo_track,
};
static const struct rtw_page_table page_table_8821a[] = {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
index 87253fffe78cd6f5b58a325eef42b58b968e2d46..851d198f76f3b10d5ba77c7e07e4be9d7fd54e4b 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
@@ -279,6 +279,7 @@ int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
efuse->crystal_cap = map->xtal_k;
if (efuse->crystal_cap == 0xff)
efuse->crystal_cap = 0x20;
+ efuse->crystal_cap &= 0x3F;
efuse->pa_type_2g = map->pa_type;
efuse->pa_type_5g = map->pa_type;
efuse->lna_type_2g = map->lna_type_2g;
@@ -632,9 +633,19 @@ static void rtw88xxa_init_beacon_parameters(struct rtw_dev *rtwdev)
rtw_write16(rtwdev, REG_BCNTCFG, 0x4413);
}
+static void rtw88xxa_set_crystal_cap(struct rtw_dev *rtwdev, u8 crystal_cap)
+{
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
+ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x7FF80000,
+ crystal_cap | (crystal_cap << 6));
+ else
+ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x00FFF000,
+ crystal_cap | (crystal_cap << 6));
+}
+
static void rtw88xxa_phy_bb_config(struct rtw_dev *rtwdev)
{
- u8 val8, crystal_cap;
+ u8 val8;
/* power on BB/RF domain */
val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN);
@@ -653,13 +664,7 @@ static void rtw88xxa_phy_bb_config(struct rtw_dev *rtwdev)
rtw_load_table(rtwdev, rtwdev->chip->bb_tbl);
rtw_load_table(rtwdev, rtwdev->chip->agc_tbl);
- crystal_cap = rtwdev->efuse.crystal_cap & 0x3F;
- if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
- rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x7FF80000,
- crystal_cap | (crystal_cap << 6));
- else
- rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x00FFF000,
- crystal_cap | (crystal_cap << 6));
+ rtw88xxa_set_crystal_cap(rtwdev, rtwdev->efuse.crystal_cap & 0x3F);
}
static void rtw88xxa_phy_rf_config(struct rtw_dev *rtwdev)
@@ -1621,6 +1626,17 @@ void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
power_b = power_a;
pkt_stat->signal_power = max3(power_a, power_b, min_rx_power);
+
+ pkt_stat->cfo_tail[RF_PATH_A] =
+ (s8)le32_get_bits(rpt->w2, RTW_JGRPHY_W2_CFO_TAIL_A);
+ pkt_stat->cfo_tail[RF_PATH_B] =
+ (s8)le32_get_bits(rpt->w2, RTW_JGRPHY_W2_CFO_TAIL_B);
+
+ /* convert to kHz (used only for debugfs) */
+ for (i = RF_PATH_A; i < rtwdev->hal.rf_path_num; i++)
+ dm_info->cfo_tail[i] = (pkt_stat->cfo_tail[i] * 5) >> 1;
+
+ rtw_phy_parsing_cfo(rtwdev, pkt_stat);
}
}
EXPORT_SYMBOL(rtw88xxa_query_phy_status);
@@ -2009,6 +2025,21 @@ void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
}
EXPORT_SYMBOL(rtw88xxa_phy_pwrtrack);
+void rtw88xxa_cfo_track(struct rtw_dev *rtwdev)
+{
+ struct rtw_cfo_track *cfo = &rtwdev->dm_info.cfo_track;
+ bool bt_hold = rtwdev->efuse.btcoex && !rtw_coex_disabled(rtwdev);
+ u8 crystal_cap;
+
+ crystal_cap = rtw_phy_cfo_xcap_track(rtwdev, 0x3F, bt_hold);
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ cfo->crystal_cap = crystal_cap;
+ rtw88xxa_set_crystal_cap(rtwdev, crystal_cap);
+}
+EXPORT_SYMBOL(rtw88xxa_cfo_track);
+
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a common code");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
index 0aaf7aa4aafdd396bff25a8fcd880a5514e589ba..09b72d33f62e1e99a2ac5af23ac1630dabb38ef9 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
@@ -172,5 +172,6 @@ void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
void (*do_iqk)(struct rtw_dev *rtwdev));
void rtw88xxa_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee, bool enable);
+void rtw88xxa_cfo_track(struct rtw_dev *rtwdev);
#endif
--
2.55.0
next prev parent reply other threads:[~2026-10-31 7:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 7:09 [PATCH rtw-next v2 0/7] wifi: rtw88: extend 88xxA support Ho Jie Feng
2026-10-31 7:09 ` [PATCH rtw-next v2 1/7] wifi: rtw88: 8812a, 8814a: enable STBC for HT transmissions Ho Jie Feng
2026-10-31 7:09 ` [PATCH rtw-next v2 2/7] wifi: rtw88: 88xxa: receive VHT SU beamformed transmissions Ho Jie Feng
2026-10-31 7:09 ` [PATCH rtw-next v2 3/7] wifi: rtw88: correctly expose beamformee capabilities Ho Jie Feng
2026-10-31 7:09 ` [PATCH rtw-next v2 4/7] wifi: rtw88: prepare frequency-offset correction for more chips Ho Jie Feng
2026-10-31 7:09 ` Ho Jie Feng [this message]
2026-10-31 7:09 ` [PATCH rtw-next v2 6/7] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain Ho Jie Feng
2026-10-31 7:09 ` [PATCH rtw-next v2 7/7] wifi: rtw88: 8812a, 8821a: respect peer A-MPDU size limits Ho Jie Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261031070950.425176-6-hjf3108@gmail.com \
--to=hjf3108@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=pkshih@realtek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.