blob: bde52412028e8741c4a4204e8b9e8173d90f3c64 [file] [log] [blame]
From cefbd5d7c2c8c2986ed7344e71e6d949d4744da9 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 31 Aug 2022 20:06:52 +0800
Subject: [PATCH 1112/1128] mt76: testmode: add pre-cal support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Change-Id: Ibfbbc3443de994eeb4daa5e364b0a90f5d7d3bcd
---
eeprom.c | 6 +-
mt76.h | 1 +
mt76_connac_mcu.h | 1 +
mt7915/eeprom.h | 34 +++-
mt7915/mcu.c | 27 ++-
mt7915/mt7915.h | 5 +
mt7915/testmode.c | 425 +++++++++++++++++++++++++++++++++++++++++++++-
mt7915/testmode.h | 36 ++++
testmode.c | 15 +-
testmode.h | 17 ++
tools/fields.c | 8 +
11 files changed, 562 insertions(+), 13 deletions(-)
diff --git a/eeprom.c b/eeprom.c
index 25f67760..4c50bfe6 100644
--- a/eeprom.c
+++ b/eeprom.c
@@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
}
#ifdef CONFIG_NL80211_TESTMODE
- dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
- dev->test_mtd.offset = offset;
+ if (len == dev->eeprom.size) {
+ dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
+ dev->test_mtd.offset = offset;
+ }
#endif
out_put_node:
diff --git a/mt76.h b/mt76.h
index e79d74a4..c08b8a47 100644
--- a/mt76.h
+++ b/mt76.h
@@ -625,6 +625,7 @@ struct mt76_testmode_ops {
enum mt76_testmode_state new_state);
int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
+ int (*dump_precal)(struct mt76_phy *phy, struct sk_buff *msg, int flag, int type);
};
struct mt76_testmode_entry_data {
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
index 858a2676..c510b5d4 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -976,6 +976,7 @@ enum {
/* ext event table */
enum {
+ MCU_EXT_EVENT_RF_TEST = 0x4,
MCU_EXT_EVENT_PS_SYNC = 0x5,
MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h
index f3e56817..88aaa16a 100644
--- a/mt7915/eeprom.h
+++ b/mt7915/eeprom.h
@@ -39,10 +39,18 @@ enum mt7915_eeprom_field {
};
#define MT_EE_WIFI_CAL_GROUP BIT(0)
-#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1)
+#define MT_EE_WIFI_CAL_DPD_2G BIT(2)
+#define MT_EE_WIFI_CAL_DPD_5G BIT(1)
+#define MT_EE_WIFI_CAL_DPD_6G BIT(3)
+#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1)
#define MT_EE_CAL_UNIT 1024
-#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16)
-#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT)
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
@@ -155,6 +163,26 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
return val & MT_EE_WIFI_CONF7_TSSI0_5G;
}
+static inline u32
+mt7915_get_cal_group_size(struct mt7915_dev *dev)
+{
+ u8 *eep = dev->mt76.eeprom.data;
+ u32 val;
+
+ if (is_mt7915(&dev->mt76)) {
+ return MT_EE_CAL_GROUP_SIZE_7915;
+ } else if (is_mt7916(&dev->mt76)) {
+ val = eep[MT_EE_WIFI_CONF + 1];
+ val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
+ return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G :
+ MT_EE_CAL_GROUP_SIZE_7916;
+ } else if (mt7915_check_adie(dev, false)) {
+ return MT_EE_CAL_GROUP_SIZE_7976;
+ } else {
+ return MT_EE_CAL_GROUP_SIZE_7975;
+ }
+}
+
extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
#endif
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
index adc14d53..f4285994 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -367,6 +367,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
case MCU_EXT_EVENT_BF_STATUS_READ:
mt7915_tm_txbf_status_read(dev, skb);
break;
+ case MCU_EXT_EVENT_RF_TEST:
+ mt7915_tm_rf_test_event(dev, skb);
+ break;
#endif
default:
break;
@@ -2856,7 +2859,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
u32 total = MT_EE_CAL_GROUP_SIZE;
- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP))
+ if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
return 0;
/*
@@ -2936,11 +2939,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
- u16 total = 2, center_freq = chandef->center_freq1;
+ enum nl80211_band band = chandef->chan->band;
+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
+ u16 center_freq = chandef->center_freq1;
u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
+ u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;
int idx;
- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD))
+ switch (band) {
+ case NL80211_BAND_2GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
+ break;
+ case NL80211_BAND_5GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
+ break;
+ case NL80211_BAND_6GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
+ break;
+ default:
+ dpd_mask = 0;
+ break;
+ }
+
+ if (!(eep[offs] & dpd_mask))
return 0;
idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
index 0217c6c3..e801fa30 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -400,6 +400,10 @@ struct mt7915_dev {
struct rchan *relay_fwlog;
void *cal;
+ u32 cur_prek_offset;
+ u8 dpd_chan_num_2g;
+ u8 dpd_chan_num_5g;
+ u8 dpd_chan_num_6g;
struct {
u8 debug_wm;
@@ -629,6 +633,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
void mt7915_mcu_exit(struct mt7915_dev *dev);
int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb);
static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
{
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
index 8f250db1..b1ce2991 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -5,6 +5,7 @@
#include "mac.h"
#include "mcu.h"
#include "testmode.h"
+#include "eeprom.h"
enum {
TM_CHANGED_TXPOWER,
@@ -1578,17 +1579,15 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
static int
mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
{
-#define TX_CONT_START 0x05
-#define TX_CONT_STOP 0x06
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
struct mt76_testmode_data *td = &phy->mt76->test;
- u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
+ u32 func_idx = en ? RF_TEST_TX_CONT_START : RF_TEST_TX_CONT_STOP;
u8 rate_idx = td->tx_rate_idx, mode;
u16 rateval;
struct mt7915_tm_rf_test req = {
- .action = 1,
+ .action = RF_ACT_IN_RFTEST,
.icap_len = 120,
.op.rf.func_idx = cpu_to_le32(func_idx),
};
@@ -1672,6 +1671,316 @@ out:
sizeof(req), true);
}
+static int
+mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
+{
+ u8 *eeprom;
+ u32 i, group_size, dpd_size, size, offs, *pre_cal;
+ int ret = 0;
+ struct mt7915_dev *dev = phy->dev;
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt7915_tm_rf_test req = {
+ .action = RF_ACT_IN_RFTEST,
+ .icap_len = 8,
+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
+ };
+
+ if (!dev->flash_mode && !dev->bin_file_mode) {
+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
+ return 1;
+ }
+
+ eeprom = mdev->eeprom.data;
+ dev->cur_prek_offset = 0;
+ group_size = mt7915_get_cal_group_size(dev);
+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
+ size = group_size + dpd_size;
+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
+
+ switch (state) {
+ case MT76_TM_STATE_GROUP_PREK:
+ req.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL);
+
+ if (!dev->cal) {
+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
+ if (!dev->cal)
+ return -ENOMEM;
+ }
+
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
+ sizeof(req), true);
+
+ if (!ret)
+ eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
+ break;
+ case MT76_TM_STATE_GROUP_PREK_DUMP:
+ pre_cal = (u32 *)dev->cal;
+ if (!pre_cal) {
+ dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
+ return ret;
+ }
+ dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
+ for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
+ dev_info(dev->mt76.dev, "[0x%08x] 0x%8x 0x%8x 0x%8x 0x%8x\n",
+ i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
+ pre_cal[i + 2], pre_cal[i + 3]);
+ }
+ break;
+ case MT76_TM_STATE_GROUP_PREK_CLEAN:
+ pre_cal = (u32 *)dev->cal;
+ if (!pre_cal)
+ return ret;
+ memset(pre_cal, 0, group_size);
+ eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static int
+mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
+{
+#define DPD_2G_CH_BW20_BITMAP_0 0x444
+#define DPD_5G_CH_BW20_BITMAP_0 0xffffc0ff
+#define DPD_5G_CH_BW20_BITMAP_1 0x3
+#define DPD_5G_CH_BW20_BITMAP_7915_0 0x7dffc0ff
+#define DPD_6G_CH_BW20_BITMAP_0 0xffffffff
+#define DPD_6G_CH_BW20_BITMAP_1 0x07ffffff
+ bool is_set = false;
+ u8 band, do_precal, *eeprom;
+ u16 bw20_size, bw160_size;
+ u32 i, j, *bw160_freq, bw160_5g_freq[] = {5250, 5570, 5815};
+ u32 bw160_6g_freq[] = {6025, 6185, 6345, 6505, 6665, 6825, 6985};
+ u32 shift, freq, group_size, dpd_size, size, offs, *pre_cal, dpd_ch_bw20_bitmap[2] = {0};
+ __le32 func_data = 0;
+ int ret = 0;
+ struct mt7915_dev *dev = phy->dev;
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt76_phy *mphy = phy->mt76;
+ struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
+ struct ieee80211_channel chan_backup, chan, *bw20_ch;
+ struct mt7915_tm_rf_test req = {
+ .action = RF_ACT_IN_RFTEST,
+ .icap_len = 8,
+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
+ };
+
+ if (!dev->flash_mode && !dev->bin_file_mode) {
+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
+ return -EOPNOTSUPP;
+ }
+
+ eeprom = mdev->eeprom.data;
+ dev->cur_prek_offset = 0;
+ group_size = mt7915_get_cal_group_size(dev);
+ dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0);
+ if (is_mt7915(&dev->mt76)) {
+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0);
+ dev->dpd_chan_num_6g = 0;
+ dpd_size = MT_EE_CAL_DPD_SIZE_V1;
+ offs = MT_EE_DO_PRE_CAL;
+ } else {
+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) +
+ hweight32(DPD_5G_CH_BW20_BITMAP_1) +
+ ARRAY_SIZE(bw160_5g_freq);
+ dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) +
+ hweight32(DPD_6G_CH_BW20_BITMAP_1) +
+ ARRAY_SIZE(bw160_6g_freq);
+ dpd_size = MT_EE_CAL_DPD_SIZE_V2;
+ offs = MT_EE_DO_PRE_CAL_V2;
+ }
+ size = group_size + dpd_size;
+
+ switch (state) {
+ case MT76_TM_STATE_DPD_2G:
+ if (!is_set) {
+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
+ dpd_ch_bw20_bitmap[0] = DPD_2G_CH_BW20_BITMAP_0;
+ bw20_ch = mphy->sband_2g.sband.channels;
+ bw160_freq = NULL;
+ bw160_size = 0;
+ band = NL80211_BAND_2GHZ;
+ do_precal = MT_EE_WIFI_CAL_DPD_2G;
+ is_set = true;
+ }
+ fallthrough;
+ case MT76_TM_STATE_DPD_5G:
+ if (!is_set) {
+ if (is_mt7915(&dev->mt76)) {
+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_7915_0;
+ bw160_size = 0;
+ dev->cur_prek_offset -= dev->dpd_chan_num_5g * MT_EE_CAL_UNIT * 2;
+ } else {
+ func_data = cpu_to_le32(RF_DPD_FLAT_5G_CAL);
+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_0;
+ dpd_ch_bw20_bitmap[1] = DPD_5G_CH_BW20_BITMAP_1;
+ bw160_size = ARRAY_SIZE(bw160_5g_freq);
+ }
+ bw20_ch = mphy->sband_5g.sband.channels;
+ bw160_freq = bw160_5g_freq;
+ band = NL80211_BAND_5GHZ;
+ do_precal = MT_EE_WIFI_CAL_DPD_5G;
+ is_set = true;
+ }
+ fallthrough;
+ case MT76_TM_STATE_DPD_6G:
+ if (!is_set) {
+ func_data = cpu_to_le32(RF_DPD_FLAT_6G_CAL);
+ dpd_ch_bw20_bitmap[0] = DPD_6G_CH_BW20_BITMAP_0;
+ dpd_ch_bw20_bitmap[1] = DPD_6G_CH_BW20_BITMAP_1;
+ bw20_ch = mphy->sband_6g.sband.channels;
+ bw160_freq = bw160_6g_freq;
+ bw160_size = ARRAY_SIZE(bw160_6g_freq);
+ band = NL80211_BAND_6GHZ;
+ do_precal = MT_EE_WIFI_CAL_DPD_6G;
+ is_set = true;
+ }
+
+ if (!bw20_ch)
+ return -EOPNOTSUPP;
+ if (!dev->cal) {
+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
+ if (!dev->cal)
+ return -ENOMEM;
+ }
+
+ req.op.rf.param.cal_param.func_data = func_data;
+ req.op.rf.param.cal_param.band_idx = phy->band_idx;
+
+ memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
+ memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
+
+ bw20_size = hweight32(dpd_ch_bw20_bitmap[0]) + hweight32(dpd_ch_bw20_bitmap[1]);
+ for (i = 0, j = 0; i < bw20_size + bw160_size; i++) {
+ if (i < bw20_size) {
+ freq = dpd_ch_bw20_bitmap[0] ? 0 : 1;
+ shift = ffs(dpd_ch_bw20_bitmap[freq]);
+ j += shift;
+ memcpy(&chan, &bw20_ch[j - 1], sizeof(struct ieee80211_channel));
+ chandef->width = NL80211_CHAN_WIDTH_20;
+ dpd_ch_bw20_bitmap[0] >>= shift;
+ } else {
+ freq = bw160_freq[i - bw20_size];
+ chan.center_freq = freq;
+ chan.hw_value = ieee80211_frequency_to_channel(freq);
+ chan.band = band;
+ chandef->width = NL80211_CHAN_WIDTH_160;
+ }
+
+ memcpy(chandef->chan, &chan, sizeof(struct ieee80211_channel));
+ if (is_mt7915(&dev->mt76))
+ mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
+ else
+ mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+
+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
+
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
+ sizeof(req), true);
+ if (ret) {
+ dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
+ break;
+ }
+ }
+ memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
+ memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
+
+ if (!ret)
+ eeprom[offs] |= do_precal;
+
+ break;
+ case MT76_TM_STATE_DPD_DUMP:
+ pre_cal = (u32 *)dev->cal;
+ if (!dev->cal) {
+ dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
+ return ret;
+ }
+ dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
+ for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
+ j = i + (group_size / sizeof(u32));
+ dev_info(dev->mt76.dev, "[0x%08x] 0x%8x 0x%8x 0x%8x 0x%8x\n",
+ j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
+ pre_cal[j + 2], pre_cal[j + 3]);
+ }
+ break;
+ case MT76_TM_STATE_DPD_CLEAN:
+ pre_cal = (u32 *)dev->cal;
+ if (!pre_cal)
+ return ret;
+ memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
+ do_precal = MT_EE_WIFI_CAL_DPD;
+ eeprom[offs] &= ~do_precal;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+void mt7915_tm_re_cal_event(struct mt7915_dev *dev, struct mt7915_tm_rf_test_result *result,
+ struct mt7915_tm_rf_test_data *data)
+{
+#define DPD_PER_CHAN_SIZE_7915 2
+#define DPD_PER_CHAN_SIZE_7986 3
+ u32 base, dpd_offest_2g, dpd_offest_5g, cal_idx = 0, cal_type = 0, len = 0;
+ u8 *pre_cal;
+
+ pre_cal = dev->cal;
+ dpd_offest_5g = dev->dpd_chan_num_6g * DPD_PER_CHAN_SIZE_7986 * MT_EE_CAL_UNIT;
+ dpd_offest_2g = dpd_offest_5g + dev->dpd_chan_num_5g * MT_EE_CAL_UNIT *
+ (is_mt7915(&dev->mt76) ? DPD_PER_CHAN_SIZE_7915 : DPD_PER_CHAN_SIZE_7986);
+ cal_idx = le32_to_cpu(data->cal_idx);
+ cal_type = le32_to_cpu(data->cal_type);
+ len = le32_to_cpu(result->payload_len);
+ len = len - sizeof(struct mt7915_tm_rf_test_data);
+
+ switch (cal_type) {
+ case RF_PRE_CAL:
+ base = 0;
+ break;
+ case RF_DPD_FLAT_CAL:
+ base = mt7915_get_cal_group_size(dev) + dpd_offest_2g;
+ break;
+ case RF_DPD_FLAT_5G_CAL:
+ base = mt7915_get_cal_group_size(dev) + dpd_offest_5g;
+ break;
+ case RF_DPD_FLAT_6G_CAL:
+ base = mt7915_get_cal_group_size(dev);
+ break;
+ default:
+ dev_info(dev->mt76.dev, "Unknown calibration type!\n");
+ return;
+ }
+ pre_cal += (base + dev->cur_prek_offset);
+
+ memcpy(pre_cal, data->data, len);
+ dev->cur_prek_offset += len;
+}
+
+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb)
+{
+ struct mt7915_tm_rf_test_result *result;
+ struct mt7915_tm_rf_test_data *data;
+ static u32 event_type;
+
+ result = (struct mt7915_tm_rf_test_result *)skb->data;
+ data = (struct mt7915_tm_rf_test_data *)result->event;
+
+ event_type = le32_to_cpu(result->func_idx);
+
+ switch (event_type) {
+ case RF_TEST_RE_CAL:
+ mt7915_tm_re_cal_event(dev, result, data);
+ break;
+ default:
+ break;
+ }
+}
+
static void
mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
{
@@ -1711,6 +2020,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
else if (prev_state == MT76_TM_STATE_OFF ||
state == MT76_TM_STATE_OFF)
mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
+ else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
+ return mt7915_tm_group_prek(phy, state);
+ else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
+ return mt7915_tm_dpd_prek(phy, state);
if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
@@ -1872,9 +2185,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
return ret;
}
+static int
+mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
+{
+#define DPD_PER_CHAN_SIZE_MASK GENMASK(31, 24)
+#define DPD_CHAN_NUM_2G_MASK GENMASK(23, 16)
+#define DPD_CHAN_NUM_5G_MASK GENMASK(15, 8)
+#define DPD_CHAN_NUM_6G_MASK GENMASK(7, 0)
+ struct mt7915_phy *phy = mphy->priv;
+ struct mt7915_dev *dev = phy->dev;
+ u32 i, group_size, dpd_size, total_size, dpd_per_chan_size, dpd_info = 0;
+ u32 base, size, total_chan_num, offs, transmit_size = 1000;
+ u8 *pre_cal, *eeprom;
+ void *precal;
+ enum prek_ops {
+ PREK_GET_INFO,
+ PREK_SYNC_ALL,
+ PREK_SYNC_GROUP,
+ PREK_SYNC_DPD_2G,
+ PREK_SYNC_DPD_5G,
+ PREK_SYNC_DPD_6G,
+ PREK_CLEAN_GROUP,
+ PREK_CLEAN_DPD,
+ };
+
+ if (!dev->cal) {
+ dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
+ return 0;
+ }
+
+ group_size = mt7915_get_cal_group_size(dev);
+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
+ dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3;
+ total_size = group_size + dpd_size;
+ pre_cal = dev->cal;
+ eeprom = dev->mt76.eeprom.data;
+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
+
+ total_chan_num = dev->dpd_chan_num_2g + dev->dpd_chan_num_5g + dev->dpd_chan_num_6g;
+
+ switch (type) {
+ case PREK_SYNC_ALL:
+ base = 0;
+ size = total_size;
+ break;
+ case PREK_SYNC_GROUP:
+ base = 0;
+ size = group_size;
+ break;
+ case PREK_SYNC_DPD_6G:
+ base = group_size;
+ size = dpd_size * dev->dpd_chan_num_6g / total_chan_num;
+ break;
+ case PREK_SYNC_DPD_5G:
+ base = group_size + dev->dpd_chan_num_6g * dpd_per_chan_size * MT_EE_CAL_UNIT;
+ size = dpd_size * dev->dpd_chan_num_5g / total_chan_num;
+ break;
+ case PREK_SYNC_DPD_2G:
+ base = group_size + (dev->dpd_chan_num_6g + dev->dpd_chan_num_5g) *
+ dpd_per_chan_size * MT_EE_CAL_UNIT;
+ size = dpd_size * dev->dpd_chan_num_2g / total_chan_num;
+ break;
+ case PREK_GET_INFO:
+ break;
+ default:
+ return 0;
+ }
+
+ if (!flag) {
+ if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
+ dpd_info |= u32_encode_bits(dpd_per_chan_size, DPD_PER_CHAN_SIZE_MASK) |
+ u32_encode_bits(dev->dpd_chan_num_2g, DPD_CHAN_NUM_2G_MASK) |
+ u32_encode_bits(dev->dpd_chan_num_5g, DPD_CHAN_NUM_5G_MASK) |
+ u32_encode_bits(dev->dpd_chan_num_6g, DPD_CHAN_NUM_6G_MASK);
+ }
+ dev->cur_prek_offset = 0;
+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
+ if (!precal)
+ return -ENOMEM;
+ nla_put_u32(msg, 0, group_size);
+ nla_put_u32(msg, 1, dpd_size);
+ nla_put_u32(msg, 2, dpd_info);
+ nla_put_u32(msg, 3, transmit_size);
+ nla_put_u32(msg, 4, eeprom[offs]);
+ nla_nest_end(msg, precal);
+ } else {
+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
+ if (!precal)
+ return -ENOMEM;
+
+ transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
+ transmit_size : (size - dev->cur_prek_offset);
+ for (i = 0; i < transmit_size; i++) {
+ if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
+ return -ENOMEM;
+ }
+ dev->cur_prek_offset += transmit_size;
+
+ nla_nest_end(msg, precal);
+ }
+
+ return 0;
+}
+
const struct mt76_testmode_ops mt7915_testmode_ops = {
.set_state = mt7915_tm_set_state,
.set_params = mt7915_tm_set_params,
.dump_stats = mt7915_tm_dump_stats,
.set_eeprom = mt7915_tm_set_eeprom,
+ .dump_precal = mt7915_tm_dump_precal,
};
diff --git a/mt7915/testmode.h b/mt7915/testmode.h
index 01b08e9e..d500987d 100644
--- a/mt7915/testmode.h
+++ b/mt7915/testmode.h
@@ -81,6 +81,11 @@ struct tm_tx_cont {
u8 txfd_mode;
};
+struct tm_cal_param {
+ __le32 func_data;
+ u8 band_idx;
+};
+
struct mt7915_tm_rf_test {
u8 action;
u8 icap_len;
@@ -96,6 +101,7 @@ struct mt7915_tm_rf_test {
__le32 cal_dump;
struct tm_tx_cont tx_cont;
+ struct tm_cal_param cal_param;
u8 _pad[80];
} param;
@@ -103,6 +109,20 @@ struct mt7915_tm_rf_test {
} op;
} __packed;
+struct mt7915_tm_rf_test_result {
+ struct mt76_connac2_mcu_rxd rxd;
+
+ u32 func_idx;
+ u32 payload_len;
+ u8 event[0];
+} __packed;
+
+struct mt7915_tm_rf_test_data {
+ u32 cal_idx;
+ u32 cal_type;
+ u8 data[0];
+} __packed;
+
enum {
RF_OPER_NORMAL,
RF_OPER_RF_TEST,
@@ -111,6 +131,22 @@ enum {
RF_OPER_WIFI_SPECTRUM,
};
+enum {
+ RF_ACT_SWITCH_MODE,
+ RF_ACT_IN_RFTEST,
+};
+
+enum {
+ RF_TEST_RE_CAL = 0x01,
+ RF_TEST_TX_CONT_START = 0x05,
+ RF_TEST_TX_CONT_STOP = 0x06,
+};
+
+#define RF_DPD_FLAT_CAL BIT(28)
+#define RF_PRE_CAL BIT(29)
+#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28)
+#define RF_DPD_FLAT_6G_CAL (BIT(30) | BIT(28))
+
enum {
TAM_ARB_OP_MODE_NORMAL = 1,
TAM_ARB_OP_MODE_TEST,
diff --git a/testmode.c b/testmode.c
index 7a9ed543..82b8e983 100644
--- a/testmode.c
+++ b/testmode.c
@@ -763,6 +763,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
mutex_lock(&dev->mutex);
+ if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
+ int flag, type;
+
+ err = -EINVAL;
+ flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
+ type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
+ if (dev->test_ops->dump_precal)
+ err = dev->test_ops->dump_precal(phy, msg, flag, type);
+
+ goto out;
+ }
+
if (tb[MT76_TM_ATTR_STATS]) {
err = -EINVAL;
@@ -796,7 +808,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
if (dev->test_mtd.name &&
(nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
+ nla_put_u8(msg, MT76_TM_ATTR_IS_MAIN_PHY, phy == &dev->phy)))
goto out;
if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
diff --git a/testmode.h b/testmode.h
index 57949f2b..e2190e72 100644
--- a/testmode.h
+++ b/testmode.h
@@ -19,6 +19,7 @@
*
* @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
* @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
+ * @MT76_TM_ATTR_IS_MAIN_PHY: Is current phy index the main phy or the ext phy (u8)
*
* @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
* state to MT76_TM_STATE_TX_FRAMES (u32)
@@ -40,6 +41,11 @@
*
* @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
*
+ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
+ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
+ * eeprom cal indicator (u32),
+ * dpd_info = [dpd_per_chan_size, chan_num_2g,
+ * chan_num_5g, chan_num_6g]
* @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
*
* @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
@@ -67,6 +73,7 @@ enum mt76_testmode_attr {
MT76_TM_ATTR_MTD_PART,
MT76_TM_ATTR_MTD_OFFSET,
+ MT76_TM_ATTR_IS_MAIN_PHY,
MT76_TM_ATTR_TX_COUNT,
MT76_TM_ATTR_TX_LENGTH,
@@ -85,6 +92,8 @@ enum mt76_testmode_attr {
MT76_TM_ATTR_FREQ_OFFSET,
MT76_TM_ATTR_STATS,
+ MT76_TM_ATTR_PRECAL,
+ MT76_TM_ATTR_PRECAL_INFO,
MT76_TM_ATTR_TX_SPE_IDX,
@@ -184,6 +193,14 @@ enum mt76_testmode_state {
MT76_TM_STATE_TX_FRAMES,
MT76_TM_STATE_RX_FRAMES,
MT76_TM_STATE_TX_CONT,
+ MT76_TM_STATE_GROUP_PREK,
+ MT76_TM_STATE_GROUP_PREK_DUMP,
+ MT76_TM_STATE_GROUP_PREK_CLEAN,
+ MT76_TM_STATE_DPD_2G,
+ MT76_TM_STATE_DPD_5G,
+ MT76_TM_STATE_DPD_6G,
+ MT76_TM_STATE_DPD_DUMP,
+ MT76_TM_STATE_DPD_CLEAN,
MT76_TM_STATE_ON,
/* keep last */
diff --git a/tools/fields.c b/tools/fields.c
index 6e36ab27..1be1ffd6 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
[MT76_TM_STATE_TX_FRAMES] = "tx_frames",
[MT76_TM_STATE_RX_FRAMES] = "rx_frames",
[MT76_TM_STATE_TX_CONT] = "tx_cont",
+ [MT76_TM_STATE_GROUP_PREK] = "group_prek",
+ [MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
+ [MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
+ [MT76_TM_STATE_DPD_2G] = "dpd_2g",
+ [MT76_TM_STATE_DPD_5G] = "dpd_5g",
+ [MT76_TM_STATE_DPD_6G] = "dpd_6g",
+ [MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
+ [MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
};
static const char * const testmode_tx_mode[] = {
--
2.18.0