mirror of
https://github.com/torvalds/linux.git
synced 2024-12-07 11:31:41 +00:00
rtw88: 8822c: add CFO tracking
Add CFO tracking, which stands for central frequency offset tracking, to adjust oscillator to align central frequency of connected AP. Then, it can yield better performance. Signed-off-by: Po-Hao Huang <phhuang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20210416030901.7099-1-pkshih@realtek.com
This commit is contained in:
parent
c544d89b0d
commit
fb8517f4fa
@ -406,4 +406,12 @@ void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
|
||||
void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type);
|
||||
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);
|
||||
|
||||
static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
|
||||
return coex_stat->bt_disabled;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@ enum rtw_debug_mask {
|
||||
RTW_DBG_PS = 0x00000400,
|
||||
RTW_DBG_BF = 0x00000800,
|
||||
RTW_DBG_WOW = 0x00001000,
|
||||
RTW_DBG_CFO = 0x00002000,
|
||||
|
||||
RTW_DBG_ALL = 0xffffffff
|
||||
};
|
||||
|
@ -625,6 +625,7 @@ struct rtw_rx_pkt_stat {
|
||||
|
||||
struct rtw_sta_info *si;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_hdr *hdr;
|
||||
};
|
||||
|
||||
DECLARE_EWMA(tp, 10, 2);
|
||||
@ -838,6 +839,8 @@ struct rtw_chip_ops {
|
||||
struct ieee80211_bss_conf *conf);
|
||||
void (*cfg_csi_rate)(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
|
||||
u8 fixrate_en, u8 *new_rate);
|
||||
void (*cfo_init)(struct rtw_dev *rtwdev);
|
||||
void (*cfo_track)(struct rtw_dev *rtwdev);
|
||||
|
||||
/* for coex */
|
||||
void (*coex_set_init)(struct rtw_dev *rtwdev);
|
||||
@ -1499,6 +1502,15 @@ struct rtw_iqk_info {
|
||||
} result;
|
||||
};
|
||||
|
||||
struct rtw_cfo_track {
|
||||
bool is_adjust;
|
||||
u8 crystal_cap;
|
||||
s32 cfo_tail[RTW_RF_PATH_MAX];
|
||||
s32 cfo_cnt[RTW_RF_PATH_MAX];
|
||||
u32 packet_count;
|
||||
u32 packet_count_pre;
|
||||
};
|
||||
|
||||
#define RRSR_INIT_2G 0x15f
|
||||
#define RRSR_INIT_5G 0x150
|
||||
|
||||
@ -1552,6 +1564,7 @@ struct rtw_dm_info {
|
||||
u8 dack_dck[RTW_RF_PATH_MAX][2][DACK_DCK_BACKUP_NUM];
|
||||
|
||||
struct rtw_dpk_info dpk_info;
|
||||
struct rtw_cfo_track cfo_track;
|
||||
|
||||
/* [bandwidth 0:20M/1:40M][number of path] */
|
||||
u8 cck_pd_lv[2][RTW_RF_PATH_MAX];
|
||||
|
@ -119,6 +119,14 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev)
|
||||
dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
|
||||
}
|
||||
|
||||
static void rtw_phy_cfo_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->cfo_init)
|
||||
chip->ops->cfo_init(rtwdev);
|
||||
}
|
||||
|
||||
void rtw_phy_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
@ -140,6 +148,7 @@ void rtw_phy_init(struct rtw_dev *rtwdev)
|
||||
rtw_phy_cck_pd_init(rtwdev);
|
||||
|
||||
dm_info->iqk.done = false;
|
||||
rtw_phy_cfo_init(rtwdev);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_phy_init);
|
||||
|
||||
@ -528,6 +537,62 @@ static void rtw_phy_dpk_track(struct rtw_dev *rtwdev)
|
||||
chip->ops->dpk_track(rtwdev);
|
||||
}
|
||||
|
||||
struct rtw_rx_addr_match_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct rtw_rx_pkt_stat *pkt_stat;
|
||||
u8 *bssid;
|
||||
};
|
||||
|
||||
static void rtw_phy_parsing_cfo_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_rx_addr_match_data *iter_data = data;
|
||||
struct rtw_dev *rtwdev = iter_data->rtwdev;
|
||||
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 *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++) {
|
||||
cfo->cfo_tail[i] += pkt_stat->cfo_tail[i];
|
||||
cfo->cfo_cnt[i]++;
|
||||
}
|
||||
|
||||
cfo->packet_count++;
|
||||
}
|
||||
|
||||
void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev,
|
||||
struct rtw_rx_pkt_stat *pkt_stat)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = pkt_stat->hdr;
|
||||
struct rtw_rx_addr_match_data data = {};
|
||||
|
||||
if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status ||
|
||||
ieee80211_is_ctl(hdr->frame_control))
|
||||
return;
|
||||
|
||||
data.rtwdev = rtwdev;
|
||||
data.hdr = hdr;
|
||||
data.pkt_stat = pkt_stat;
|
||||
data.bssid = get_hdr_bssid(hdr);
|
||||
|
||||
rtw_iterate_vifs_atomic(rtwdev, rtw_phy_parsing_cfo_iter, &data);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_phy_parsing_cfo);
|
||||
|
||||
static void rtw_phy_cfo_track(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->cfo_track)
|
||||
chip->ops->cfo_track(rtwdev);
|
||||
}
|
||||
|
||||
#define CCK_PD_FA_LV1_MIN 1000
|
||||
#define CCK_PD_FA_LV0_MAX 500
|
||||
|
||||
@ -630,6 +695,7 @@ void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev)
|
||||
rtw_phy_dig(rtwdev);
|
||||
rtw_phy_cck_pd(rtwdev);
|
||||
rtw_phy_ra_track(rtwdev);
|
||||
rtw_phy_cfo_track(rtwdev);
|
||||
rtw_phy_dpk_track(rtwdev);
|
||||
rtw_phy_pwr_track(rtwdev);
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev);
|
||||
bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev);
|
||||
void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
|
||||
struct rtw_swing_table *swing_table);
|
||||
void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev,
|
||||
struct rtw_rx_pkt_stat *pkt_stat);
|
||||
|
||||
struct rtw_txpwr_lmt_cfg_pair {
|
||||
u8 regd;
|
||||
|
@ -516,6 +516,7 @@
|
||||
#define BIT_RFE_BUF_EN BIT(3)
|
||||
|
||||
#define REG_ANAPAR_XTAL_0 0x1040
|
||||
#define BIT_XCAP_0 GENMASK(23, 10)
|
||||
#define REG_CPU_DMEM_CON 0x1080
|
||||
#define BIT_WL_PLATFORM_RST BIT(16)
|
||||
#define BIT_WL_SECURITY_CLK BIT(15)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "util.h"
|
||||
#include "bf.h"
|
||||
#include "efuse.h"
|
||||
#include "coex.h"
|
||||
|
||||
#define IQK_DONE_8822C 0xaa
|
||||
|
||||
@ -39,7 +40,7 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
|
||||
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 & XCAP_MASK;
|
||||
efuse->channel_plan = map->channel_plan;
|
||||
efuse->country_code[0] = map->country_code[0];
|
||||
efuse->country_code[1] = map->country_code[1];
|
||||
@ -1866,6 +1867,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
|
||||
}
|
||||
dm_info->rx_evm_dbm[path] = evm_dbm;
|
||||
}
|
||||
rtw_phy_parsing_cfo(rtwdev, pkt_stat);
|
||||
}
|
||||
|
||||
static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
|
||||
@ -1921,6 +1923,7 @@ static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
|
||||
pkt_stat->drv_info_sz);
|
||||
pkt_stat->hdr = hdr;
|
||||
if (pkt_stat->phy_status) {
|
||||
phy_status = rx_desc + desc_sz + pkt_stat->shift;
|
||||
query_phy_status(rtwdev, phy_status, pkt_stat);
|
||||
@ -3436,6 +3439,128 @@ static void rtw8822c_dpk_track(struct rtw_dev *rtwdev)
|
||||
}
|
||||
}
|
||||
|
||||
#define XCAP_EXTEND(val) ({typeof(val) _v = (val); _v | _v << 7; })
|
||||
static void rtw8822c_set_crystal_cap_reg(struct rtw_dev *rtwdev, u8 crystal_cap)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
u32 val = 0;
|
||||
|
||||
val = XCAP_EXTEND(crystal_cap);
|
||||
cfo->crystal_cap = crystal_cap;
|
||||
rtw_write32_mask(rtwdev, REG_ANAPAR_XTAL_0, BIT_XCAP_0, val);
|
||||
}
|
||||
|
||||
static void rtw8822c_set_crystal_cap(struct rtw_dev *rtwdev, u8 crystal_cap)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
|
||||
if (cfo->crystal_cap == crystal_cap)
|
||||
return;
|
||||
|
||||
rtw8822c_set_crystal_cap_reg(rtwdev, crystal_cap);
|
||||
}
|
||||
|
||||
static void rtw8822c_cfo_tracking_reset(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
|
||||
cfo->is_adjust = true;
|
||||
|
||||
if (cfo->crystal_cap > rtwdev->efuse.crystal_cap)
|
||||
rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap - 1);
|
||||
else if (cfo->crystal_cap < rtwdev->efuse.crystal_cap)
|
||||
rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap + 1);
|
||||
}
|
||||
|
||||
static void rtw8822c_cfo_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
|
||||
cfo->crystal_cap = rtwdev->efuse.crystal_cap;
|
||||
cfo->is_adjust = true;
|
||||
}
|
||||
|
||||
#define REPORT_TO_KHZ(val) ({typeof(val) _v = (val); (_v << 1) + (_v >> 1); })
|
||||
static s32 rtw8822c_cfo_calc_avg(struct rtw_dev *rtwdev, u8 path_num)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
s32 cfo_avg, cfo_path_sum = 0, cfo_rpt_sum;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < path_num; i++) {
|
||||
cfo_rpt_sum = REPORT_TO_KHZ(cfo->cfo_tail[i]);
|
||||
|
||||
if (cfo->cfo_cnt[i])
|
||||
cfo_avg = cfo_rpt_sum / cfo->cfo_cnt[i];
|
||||
else
|
||||
cfo_avg = 0;
|
||||
|
||||
cfo_path_sum += cfo_avg;
|
||||
}
|
||||
|
||||
for (i = 0; i < path_num; i++) {
|
||||
cfo->cfo_tail[i] = 0;
|
||||
cfo->cfo_cnt[i] = 0;
|
||||
}
|
||||
|
||||
return cfo_path_sum / path_num;
|
||||
}
|
||||
|
||||
static void rtw8822c_cfo_need_adjust(struct rtw_dev *rtwdev, s32 cfo_avg)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_cfo_track *cfo = &dm_info->cfo_track;
|
||||
|
||||
if (!cfo->is_adjust) {
|
||||
if (abs(cfo_avg) > CFO_TRK_ENABLE_TH)
|
||||
cfo->is_adjust = true;
|
||||
} else {
|
||||
if (abs(cfo_avg) <= CFO_TRK_STOP_TH)
|
||||
cfo->is_adjust = false;
|
||||
}
|
||||
|
||||
if (!rtw_coex_disabled(rtwdev)) {
|
||||
cfo->is_adjust = false;
|
||||
rtw8822c_set_crystal_cap(rtwdev, rtwdev->efuse.crystal_cap);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw8822c_cfo_track(struct rtw_dev *rtwdev)
|
||||
{
|
||||
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;
|
||||
s8 crystal_cap = cfo->crystal_cap;
|
||||
s32 cfo_avg = 0;
|
||||
|
||||
if (rtwdev->sta_cnt != 1) {
|
||||
rtw8822c_cfo_tracking_reset(rtwdev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfo->packet_count == cfo->packet_count_pre)
|
||||
return;
|
||||
|
||||
cfo->packet_count_pre = cfo->packet_count;
|
||||
cfo_avg = rtw8822c_cfo_calc_avg(rtwdev, path_num);
|
||||
rtw8822c_cfo_need_adjust(rtwdev, cfo_avg);
|
||||
|
||||
if (cfo->is_adjust) {
|
||||
if (cfo_avg > CFO_TRK_ADJ_TH)
|
||||
crystal_cap++;
|
||||
else if (cfo_avg < -CFO_TRK_ADJ_TH)
|
||||
crystal_cap--;
|
||||
|
||||
crystal_cap = clamp_t(s8, crystal_cap, 0, XCAP_MASK);
|
||||
rtw8822c_set_crystal_cap(rtwdev, (u8)crystal_cap);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct rtw_phy_cck_pd_reg
|
||||
rtw8822c_cck_pd_reg[RTW_CHANNEL_WIDTH_40 + 1][RTW_RF_PATH_MAX] = {
|
||||
{
|
||||
@ -4016,6 +4141,8 @@ static struct rtw_chip_ops rtw8822c_ops = {
|
||||
.config_bfee = rtw8822c_bf_config_bfee,
|
||||
.set_gid_table = rtw_bf_set_gid_table,
|
||||
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
|
||||
.cfo_init = rtw8822c_cfo_init,
|
||||
.cfo_track = rtw8822c_cfo_track,
|
||||
|
||||
.coex_set_init = rtw8822c_coex_cfg_init,
|
||||
.coex_set_ant_switch = NULL,
|
||||
|
@ -165,6 +165,11 @@ const struct rtw_table name ## _tbl = { \
|
||||
#define REG_ANAPARLDO_POW_MAC 0x0029
|
||||
#define BIT_LDOE25_PON BIT(0)
|
||||
|
||||
#define XCAP_MASK GENMASK(6, 0)
|
||||
#define CFO_TRK_ENABLE_TH 20
|
||||
#define CFO_TRK_STOP_TH 10
|
||||
#define CFO_TRK_ADJ_TH 10
|
||||
|
||||
#define REG_TXDFIR0 0x808
|
||||
#define REG_DFIRBW 0x810
|
||||
#define REG_ANTMAP0 0x820
|
||||
|
Loading…
Reference in New Issue
Block a user