blob: e185c117bacbcda99c50bb7afb83978f470cd010 [file] [log] [blame]
developer064da3c2023-06-13 15:57:26 +08001From 47c64d6cac5ed78fab15cd4173ae8935605a3fca Mon Sep 17 00:00:00 2001
2From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Fri, 31 Mar 2023 11:27:24 +0800
4Subject: [PATCH 1006/1015] wifi: mt76: testmode: add testmode pre-calibration
5 support
6
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
8Change-Id: If8a6cc02fa20e35f079c826e0571e8c04c3f9c7e
9---
10 mac80211.c | 21 ---
11 mt76.h | 22 +++
12 mt76_connac_mcu.h | 2 +
13 mt7996/eeprom.c | 66 +++++++
14 mt7996/eeprom.h | 47 +++++
15 mt7996/mcu.c | 5 +
16 mt7996/mt7996.h | 7 +
17 mt7996/testmode.c | 437 ++++++++++++++++++++++++++++++++++++++++++++++
18 mt7996/testmode.h | 20 ++-
19 testmode.c | 12 ++
20 testmode.h | 8 +
21 tools/fields.c | 8 +
22 12 files changed, 632 insertions(+), 23 deletions(-)
23
24diff --git a/mac80211.c b/mac80211.c
25index 501325e9..6430e6ee 100644
26--- a/mac80211.c
27+++ b/mac80211.c
28@@ -7,27 +7,6 @@
29 #include <net/page_pool.h>
30 #include "mt76.h"
31
32-#define CHAN2G(_idx, _freq) { \
33- .band = NL80211_BAND_2GHZ, \
34- .center_freq = (_freq), \
35- .hw_value = (_idx), \
36- .max_power = 30, \
37-}
38-
39-#define CHAN5G(_idx, _freq) { \
40- .band = NL80211_BAND_5GHZ, \
41- .center_freq = (_freq), \
42- .hw_value = (_idx), \
43- .max_power = 30, \
44-}
45-
46-#define CHAN6G(_idx, _freq) { \
47- .band = NL80211_BAND_6GHZ, \
48- .center_freq = (_freq), \
49- .hw_value = (_idx), \
50- .max_power = 30, \
51-}
52-
53 static const struct ieee80211_channel mt76_channels_2ghz[] = {
54 CHAN2G(1, 2412),
55 CHAN2G(2, 2417),
56diff --git a/mt76.h b/mt76.h
57index 31d5dc37..3341720c 100644
58--- a/mt76.h
59+++ b/mt76.h
60@@ -18,6 +18,27 @@
61 #include "util.h"
62 #include "testmode.h"
63
64+#define CHAN2G(_idx, _freq) { \
65+ .band = NL80211_BAND_2GHZ, \
66+ .center_freq = (_freq), \
67+ .hw_value = (_idx), \
68+ .max_power = 30, \
69+}
70+
71+#define CHAN5G(_idx, _freq) { \
72+ .band = NL80211_BAND_5GHZ, \
73+ .center_freq = (_freq), \
74+ .hw_value = (_idx), \
75+ .max_power = 30, \
76+}
77+
78+#define CHAN6G(_idx, _freq) { \
79+ .band = NL80211_BAND_6GHZ, \
80+ .center_freq = (_freq), \
81+ .hw_value = (_idx), \
82+ .max_power = 30, \
83+}
84+
85 #define MT_MCU_RING_SIZE 32
86 #define MT_RX_BUF_SIZE 2048
87 #define MT_SKB_HEAD_LEN 256
88@@ -654,6 +675,7 @@ struct mt76_testmode_ops {
89 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
90 void (*reset_rx_stats)(struct mt76_phy *phy);
91 void (*tx_stop)(struct mt76_phy *phy);
92+ int (*dump_precal)(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type);
93 };
94
95 #define MT_TM_FW_RX_COUNT BIT(0)
96diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
97index e62f17ad..262abf88 100644
98--- a/mt76_connac_mcu.h
99+++ b/mt76_connac_mcu.h
100@@ -1011,6 +1011,8 @@ enum {
101 MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
102 MCU_UNI_EVENT_RDD_REPORT = 0x11,
103 MCU_UNI_EVENT_THERMAL = 0x35,
104+ MCU_UNI_EVENT_BF = 0x33,
105+ MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
106 };
107
108 #define MCU_UNI_CMD_EVENT BIT(1)
109diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
110index be0a34ae..60e98463 100644
111--- a/mt7996/eeprom.c
112+++ b/mt7996/eeprom.c
113@@ -12,6 +12,42 @@ static bool testmode_enable;
114 module_param(testmode_enable, bool, 0644);
115 MODULE_PARM_DESC(testmode_enable, "Enable testmode");
116
117+const struct ieee80211_channel dpd_2g_ch_list_bw20[] = {
118+ CHAN2G(3, 2422),
119+ CHAN2G(7, 2442),
120+ CHAN2G(11, 2462)
121+};
122+
123+const struct ieee80211_channel dpd_5g_ch_list_bw160[] = {
124+ CHAN5G(50, 5250),
125+ CHAN5G(114, 5570),
126+ CHAN5G(163, 5815)
127+};
128+
129+const struct ieee80211_channel dpd_6g_ch_list_bw160[] = {
130+ CHAN6G(15, 6025),
131+ CHAN6G(47, 6185),
132+ CHAN6G(79, 6345),
133+ CHAN6G(111, 6505),
134+ CHAN6G(143, 6665),
135+ CHAN6G(175, 6825),
136+ CHAN6G(207, 6985)
137+};
138+
139+const struct ieee80211_channel dpd_6g_ch_list_bw320[] = {
140+ CHAN6G(31, 6105),
141+ CHAN6G(63, 6265),
142+ CHAN6G(95, 6425),
143+ CHAN6G(127, 6585),
144+ CHAN6G(159, 6745),
145+ CHAN6G(191, 6905)
146+};
147+
148+const u32 dpd_2g_bw20_ch_num = ARRAY_SIZE(dpd_2g_ch_list_bw20);
149+const u32 dpd_5g_bw160_ch_num = ARRAY_SIZE(dpd_5g_ch_list_bw160);
150+const u32 dpd_6g_bw160_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw160);
151+const u32 dpd_6g_bw320_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw320);
152+
153 static int mt7996_check_eeprom(struct mt7996_dev *dev)
154 {
155 u8 *eeprom = dev->mt76.eeprom.data;
156@@ -34,6 +70,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
157 return MT7996_EEPROM_DEFAULT;
158 }
159
160+int
161+mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band)
162+{
163+ /* handle different sku */
164+ static const u8 band_to_idx[] = {
165+ [NL80211_BAND_2GHZ] = MT_BAND0,
166+ [NL80211_BAND_5GHZ] = MT_BAND1,
167+ [NL80211_BAND_6GHZ] = MT_BAND2,
168+ };
169+ struct mt7996_phy *phy = __mt7996_phy(dev, band_to_idx[band]);
170+ struct mt76_phy *mphy;
171+ int dpd_size;
172+
173+ if (!phy)
174+ return 0;
175+
176+ mphy = phy->mt76;
177+
178+ if (band == NL80211_BAND_2GHZ)
179+ dpd_size = dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
180+ else if (band == NL80211_BAND_5GHZ)
181+ dpd_size = mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
182+ dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
183+ else
184+ dpd_size = mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
185+ (dpd_6g_bw160_ch_num + dpd_6g_bw320_ch_num) * DPD_PER_CH_GT_BW20_SIZE;
186+
187+ return dpd_size;
188+}
189+
190 static int
191 mt7996_eeprom_load_default(struct mt7996_dev *dev)
192 {
193diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
194index 343e65e1..7ff290f4 100644
195--- a/mt7996/eeprom.h
196+++ b/mt7996/eeprom.h
197@@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
198 MT_EE_MAC_ADDR = 0x004,
199 MT_EE_MAC_ADDR2 = 0x00a,
200 MT_EE_WIFI_CONF = 0x190,
201+ MT_EE_DO_PRE_CAL = 0x1a5,
202 MT_EE_TESTMODE_EN = 0x1af,
203 MT_EE_MAC_ADDR3 = 0x2c0,
204 MT_EE_RATE_DELTA_2G = 0x1400,
205@@ -31,6 +32,52 @@ enum mt7996_eeprom_field {
206 #define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(5, 3)
207 #define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0)
208
209+#define MT_EE_WIFI_CAL_GROUP_2G BIT(0)
210+#define MT_EE_WIFI_CAL_GROUP_5G BIT(1)
211+#define MT_EE_WIFI_CAL_GROUP_6G BIT(2)
212+#define MT_EE_WIFI_CAL_GROUP GENMASK(2, 0)
213+#define MT_EE_WIFI_CAL_DPD_2G BIT(3)
214+#define MT_EE_WIFI_CAL_DPD_5G BIT(4)
215+#define MT_EE_WIFI_CAL_DPD_6G BIT(5)
216+#define MT_EE_WIFI_CAL_DPD GENMASK(5, 3)
217+
218+#define MT_EE_CAL_UNIT 1024
219+#define MT_EE_CAL_GROUP_SIZE_2G (4 * MT_EE_CAL_UNIT)
220+#define MT_EE_CAL_GROUP_SIZE_5G (45 * MT_EE_CAL_UNIT)
221+#define MT_EE_CAL_GROUP_SIZE_6G (125 * MT_EE_CAL_UNIT)
222+#define MT_EE_CAL_ADCDCOC_SIZE_2G (4 * 4)
223+#define MT_EE_CAL_ADCDCOC_SIZE_5G (4 * 4)
224+#define MT_EE_CAL_ADCDCOC_SIZE_6G (4 * 5)
225+#define MT_EE_CAL_GROUP_SIZE (MT_EE_CAL_GROUP_SIZE_2G + \
226+ MT_EE_CAL_GROUP_SIZE_5G + \
227+ MT_EE_CAL_GROUP_SIZE_6G + \
228+ MT_EE_CAL_ADCDCOC_SIZE_2G + \
229+ MT_EE_CAL_ADCDCOC_SIZE_5G + \
230+ MT_EE_CAL_ADCDCOC_SIZE_6G)
231+
232+#define DPD_PER_CH_LEGACY_SIZE (4 * MT_EE_CAL_UNIT)
233+#define DPD_PER_CH_MEM_SIZE (13 * MT_EE_CAL_UNIT)
234+#define DPD_PER_CH_OTFG0_SIZE (2 * MT_EE_CAL_UNIT)
235+#define DPD_PER_CH_BW20_SIZE (DPD_PER_CH_LEGACY_SIZE + DPD_PER_CH_OTFG0_SIZE)
236+#define DPD_PER_CH_GT_BW20_SIZE (DPD_PER_CH_MEM_SIZE + DPD_PER_CH_OTFG0_SIZE)
237+#define MT_EE_CAL_DPD_SIZE (780 * MT_EE_CAL_UNIT)
238+
239+extern const struct ieee80211_channel dpd_2g_ch_list_bw20[];
240+extern const u32 dpd_2g_bw20_ch_num;
241+extern const struct ieee80211_channel dpd_5g_ch_list_bw160[];
242+extern const u32 dpd_5g_bw160_ch_num;
243+extern const struct ieee80211_channel dpd_6g_ch_list_bw160[];
244+extern const u32 dpd_6g_bw160_ch_num;
245+extern const struct ieee80211_channel dpd_6g_ch_list_bw320[];
246+extern const u32 dpd_6g_bw320_ch_num;
247+
248+#define RF_DPD_FLAT_CAL BIT(28)
249+#define RF_PRE_CAL BIT(29)
250+#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28)
251+#define RF_DPD_FLAT_5G_MEM_CAL (BIT(30) | BIT(28))
252+#define RF_DPD_FLAT_6G_CAL GENMASK(30, 28)
253+#define RF_DPD_FLAT_6G_MEM_CAL (BIT(31) | BIT(28))
254+
255 #define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
256 #define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
257 #define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
258diff --git a/mt7996/mcu.c b/mt7996/mcu.c
259index 91f3103a..1fb7bae1 100644
260--- a/mt7996/mcu.c
261+++ b/mt7996/mcu.c
262@@ -523,6 +523,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
263 case MCU_UNI_EVENT_THERMAL:
264 mt7996_mcu_rx_thermal_notify(dev, skb);
265 break;
266+#ifdef CONFIG_NL80211_TESTMODE
267+ case MCU_UNI_EVENT_TESTMODE_CTRL:
268+ mt7996_tm_rf_test_event(dev, skb);
269+ break;
270+#endif
271 default:
272 break;
273 }
274diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
275index dc44edc1..9ab86eaf 100644
276--- a/mt7996/mt7996.h
277+++ b/mt7996/mt7996.h
278@@ -390,6 +390,9 @@ struct mt7996_dev {
279 struct dentry *debugfs_dir;
280 struct rchan *relay_fwlog;
281
282+ void *cal;
283+ u32 cur_prek_offset;
284+
285 struct {
286 u8 table_mask;
287 u8 n_agrt;
288@@ -522,6 +525,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
289 int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
290 struct ieee80211_channel *chan);
291 s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
292+int mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band);
293 int mt7996_dma_init(struct mt7996_dev *dev);
294 void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
295 void mt7996_dma_prefetch(struct mt7996_dev *dev);
296@@ -602,6 +606,9 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
297 int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
298 int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
299 void mt7996_mcu_scs_sta_poll(struct work_struct *work);
300+#ifdef CONFIG_NL80211_TESTMODE
301+void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
302+#endif
303
304 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
305 {
306diff --git a/mt7996/testmode.c b/mt7996/testmode.c
307index 43eca4ef..7d36902e 100644
308--- a/mt7996/testmode.c
309+++ b/mt7996/testmode.c
310@@ -7,6 +7,8 @@
311 #include "mac.h"
312 #include "mcu.h"
313 #include "testmode.h"
314+#include "eeprom.h"
315+#include "mtk_mcu.h"
316
317 enum {
318 TM_CHANGED_TXPOWER,
319@@ -397,6 +399,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
320 }
321 }
322
323+static int
324+mt7996_tm_group_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
325+{
326+ u8 *eeprom;
327+ u32 i, group_size, dpd_size, size, offs, *pre_cal;
328+ int ret = 0;
329+ struct mt7996_dev *dev = phy->dev;
330+ struct mt76_dev *mdev = &dev->mt76;
331+ struct mt7996_tm_req req = {
332+ .rf_test = {
333+ .tag = cpu_to_le16(UNI_RF_TEST_CTRL),
334+ .len = cpu_to_le16(sizeof(req.rf_test)),
335+ .action = RF_ACTION_IN_RF_TEST,
336+ .icap_len = RF_TEST_ICAP_LEN,
337+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
338+ .op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL),
339+ .op.rf.param.cal_param.band_idx = phy->mt76->band_idx,
340+ },
341+ };
342+
343+ if (!dev->flash_mode) {
344+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN FILE mode, return!\n");
345+ return -EOPNOTSUPP;
346+ }
347+
348+ eeprom = mdev->eeprom.data;
349+ dev->cur_prek_offset = 0;
350+ group_size = MT_EE_CAL_GROUP_SIZE;
351+ dpd_size = MT_EE_CAL_DPD_SIZE;
352+ size = group_size + dpd_size;
353+ offs = MT_EE_DO_PRE_CAL;
354+
355+ switch (state) {
356+ case MT76_TM_STATE_GROUP_PREK:
357+ if (!dev->cal) {
358+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
359+ if (!dev->cal)
360+ return -ENOMEM;
361+ }
362+
363+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), &req,
364+ sizeof(req), false);
365+ wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == group_size,
366+ 30 * HZ);
367+
368+ if (ret) {
369+ dev_err(dev->mt76.dev, "Group Pre-cal: mcu send msg failed!\n");
370+ return ret;
371+ }
372+
373+ if (!ret)
374+ eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
375+ break;
376+ case MT76_TM_STATE_GROUP_PREK_DUMP:
377+ pre_cal = (u32 *)dev->cal;
378+ if (!pre_cal) {
379+ dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
380+ return ret;
381+ }
382+ dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
383+ for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
384+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
385+ i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
386+ pre_cal[i + 2], pre_cal[i + 3]);
387+ }
388+ break;
389+ case MT76_TM_STATE_GROUP_PREK_CLEAN:
390+ pre_cal = (u32 *)dev->cal;
391+ if (!pre_cal)
392+ return ret;
393+ memset(pre_cal, 0, group_size);
394+ eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
395+ break;
396+ default:
397+ return -EINVAL;
398+ }
399+
400+ return ret;
401+}
402+
403+static int
404+mt7996_tm_dpd_prek_send_req(struct mt7996_phy *phy, struct mt7996_tm_req *req,
405+ const struct ieee80211_channel *chan_list, u32 channel_size,
406+ enum nl80211_chan_width width, u32 func_data)
407+{
408+ struct mt7996_dev *dev = phy->dev;
409+ struct mt76_phy *mphy = phy->mt76;
410+ struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
411+ struct ieee80211_channel chan_backup;
412+ int i, ret;
413+
414+ if (!chan_list)
415+ return -EOPNOTSUPP;
416+
417+ req->rf_test.op.rf.param.cal_param.func_data = cpu_to_le32(func_data);
418+
419+ memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
420+ memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
421+
422+ for (i = 0; i < channel_size; i++) {
423+ memcpy(chandef->chan, &chan_list[i], sizeof(struct ieee80211_channel));
424+ chandef->width = width;
425+
426+ /* set channel switch reason */
427+ mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
428+ mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
429+
430+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), req,
431+ sizeof(*req), false);
432+ if (ret) {
433+ dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
434+ goto out;
435+ }
436+ }
437+
438+out:
439+ mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
440+ memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
441+ memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
442+ mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
443+
444+ return ret;
445+}
446+
447+static int
448+mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
449+{
450+ struct mt7996_dev *dev = phy->dev;
451+ struct mt76_dev *mdev = &dev->mt76;
452+ struct mt76_phy *mphy = phy->mt76;
453+ struct mt7996_tm_req req = {
454+ .rf_test = {
455+ .tag = cpu_to_le16(UNI_RF_TEST_CTRL),
456+ .len = cpu_to_le16(sizeof(req.rf_test)),
457+ .action = RF_ACTION_IN_RF_TEST,
458+ .icap_len = RF_TEST_ICAP_LEN,
459+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
460+ .op.rf.param.cal_param.band_idx = phy->mt76->band_idx,
461+ },
462+ };
463+ u32 i, j, group_size, dpd_size, size, offs, *pre_cal;
464+ u32 wait_on_prek_offset = 0;
465+ u8 do_precal, *eeprom;
466+ int ret = 0;
467+
468+ if (!dev->flash_mode) {
469+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN FILE mode, return!\n");
470+ return -EOPNOTSUPP;
471+ }
472+
473+ eeprom = mdev->eeprom.data;
474+ dev->cur_prek_offset = 0;
475+ group_size = MT_EE_CAL_GROUP_SIZE;
476+ dpd_size = MT_EE_CAL_DPD_SIZE;
477+ size = group_size + dpd_size;
478+ offs = MT_EE_DO_PRE_CAL;
479+
480+ if (!dev->cal && state < MT76_TM_STATE_DPD_DUMP) {
481+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
482+ if (!dev->cal)
483+ return -ENOMEM;
484+ }
485+
486+ switch (state) {
487+ case MT76_TM_STATE_DPD_2G:
488+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_2g_ch_list_bw20,
489+ dpd_2g_bw20_ch_num,
490+ NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_CAL);
491+ wait_on_prek_offset += dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
492+ wait_event_timeout(mdev->mcu.wait,
493+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
494+
495+ do_precal = MT_EE_WIFI_CAL_DPD_2G;
496+ break;
497+ case MT76_TM_STATE_DPD_5G:
498+ /* 5g channel bw20 calibration */
499+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, mphy->sband_5g.sband.channels,
500+ mphy->sband_5g.sband.n_channels,
501+ NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_5G_CAL);
502+ if (ret)
503+ return ret;
504+ wait_on_prek_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
505+ wait_event_timeout(mdev->mcu.wait,
506+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
507+
508+ /* 5g channel bw160 calibration */
509+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_5g_ch_list_bw160,
510+ dpd_5g_bw160_ch_num,
511+ NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_5G_MEM_CAL);
512+ wait_on_prek_offset += dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
513+ wait_event_timeout(mdev->mcu.wait,
514+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
515+
516+ do_precal = MT_EE_WIFI_CAL_DPD_5G;
517+ break;
518+ case MT76_TM_STATE_DPD_6G:
519+ /* 6g channel bw20 calibration */
520+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, mphy->sband_6g.sband.channels,
521+ mphy->sband_6g.sband.n_channels,
522+ NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_6G_CAL);
523+ if (ret)
524+ return ret;
525+ wait_on_prek_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
526+ wait_event_timeout(mdev->mcu.wait,
527+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
528+
529+ /* 6g channel bw160 calibration */
530+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw160,
531+ dpd_6g_bw160_ch_num,
532+ NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_6G_MEM_CAL);
533+ if (ret)
534+ return ret;
535+ wait_on_prek_offset += dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
536+ wait_event_timeout(mdev->mcu.wait,
537+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
538+
539+ /* 6g channel bw320 calibration */
540+ ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw320,
541+ dpd_6g_bw320_ch_num,
542+ NL80211_CHAN_WIDTH_320, RF_DPD_FLAT_6G_MEM_CAL);
543+ wait_on_prek_offset += dpd_6g_bw320_ch_num * DPD_PER_CH_GT_BW20_SIZE;
544+ wait_event_timeout(mdev->mcu.wait,
545+ dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
546+
547+ do_precal = MT_EE_WIFI_CAL_DPD_6G;
548+ break;
549+ case MT76_TM_STATE_DPD_DUMP:
550+ if (!dev->cal) {
551+ dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
552+ return ret;
553+ }
554+ pre_cal = (u32 *)dev->cal;
555+ dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
556+ for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
557+ j = i + (group_size / sizeof(u32));
558+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
559+ j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
560+ pre_cal[j + 2], pre_cal[j + 3]);
561+ }
562+ return 0;
563+ case MT76_TM_STATE_DPD_CLEAN:
564+ pre_cal = (u32 *)dev->cal;
565+ if (!pre_cal)
566+ return ret;
567+ memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
568+ do_precal = MT_EE_WIFI_CAL_DPD;
569+ eeprom[offs] &= ~do_precal;
570+ return 0;
571+ default:
572+ return -EINVAL;
573+ }
574+
575+ if (!ret)
576+ eeprom[offs] |= do_precal;
577+
578+ return ret;
579+}
580+
581+static int
582+mt7996_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
583+{
584+#define DPD_PER_CHAN_SIZE_MASK GENMASK(31, 30)
585+#define DPD_2G_RATIO_MASK GENMASK(29, 20)
586+#define DPD_5G_RATIO_MASK GENMASK(19, 10)
587+#define DPD_6G_RATIO_MASK GENMASK(9, 0)
588+ struct mt7996_phy *phy = mphy->priv;
589+ struct mt7996_dev *dev = phy->dev;
590+ u32 i, group_size, dpd_size, total_size, size, dpd_info = 0;
591+ u32 dpd_size_2g, dpd_size_5g, dpd_size_6g;
592+ u32 base, offs, transmit_size = 1000;
593+ u8 *pre_cal, *eeprom;
594+ void *precal;
595+ enum prek_ops {
596+ PREK_GET_INFO,
597+ PREK_SYNC_ALL,
598+ PREK_SYNC_GROUP,
599+ PREK_SYNC_DPD_2G,
600+ PREK_SYNC_DPD_5G,
601+ PREK_SYNC_DPD_6G,
602+ PREK_CLEAN_GROUP,
603+ PREK_CLEAN_DPD,
604+ };
605+
606+ if (!dev->cal) {
607+ dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
608+ return 0;
609+ }
610+
611+ group_size = MT_EE_CAL_GROUP_SIZE;
612+ dpd_size = MT_EE_CAL_DPD_SIZE;
613+ total_size = group_size + dpd_size;
614+ pre_cal = dev->cal;
615+ eeprom = dev->mt76.eeprom.data;
616+ offs = MT_EE_DO_PRE_CAL;
617+
618+ dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
619+ dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
620+ dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
621+
622+ switch (type) {
623+ case PREK_SYNC_ALL:
624+ base = 0;
625+ size = total_size;
626+ break;
627+ case PREK_SYNC_GROUP:
628+ base = 0;
629+ size = group_size;
630+ break;
631+ case PREK_SYNC_DPD_2G:
632+ base = group_size;
633+ size = dpd_size_2g;
634+ break;
635+ case PREK_SYNC_DPD_5G:
636+ base = group_size + dpd_size_2g;
637+ size = dpd_size_5g;
638+ break;
639+ case PREK_SYNC_DPD_6G:
640+ base = group_size + dpd_size_2g + dpd_size_5g;
641+ size = dpd_size_6g;
642+ break;
643+ case PREK_GET_INFO:
644+ break;
645+ default:
646+ return 0;
647+ }
648+
649+ if (!flag) {
650+ if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
651+ dpd_info |= u32_encode_bits(1, DPD_PER_CHAN_SIZE_MASK) |
652+ u32_encode_bits(dpd_size_2g / MT_EE_CAL_UNIT,
653+ DPD_2G_RATIO_MASK) |
654+ u32_encode_bits(dpd_size_5g / MT_EE_CAL_UNIT,
655+ DPD_5G_RATIO_MASK) |
656+ u32_encode_bits(dpd_size_6g / MT_EE_CAL_UNIT,
657+ DPD_6G_RATIO_MASK);
658+ }
659+ dev->cur_prek_offset = 0;
660+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
661+ if (!precal)
662+ return -ENOMEM;
663+ nla_put_u32(msg, 0, group_size);
664+ nla_put_u32(msg, 1, dpd_size);
665+ nla_put_u32(msg, 2, dpd_info);
666+ nla_put_u32(msg, 3, transmit_size);
667+ nla_put_u32(msg, 4, eeprom[offs]);
668+ nla_nest_end(msg, precal);
669+ } else {
670+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
671+ if (!precal)
672+ return -ENOMEM;
673+
674+ transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
675+ transmit_size : (size - dev->cur_prek_offset);
676+ for (i = 0; i < transmit_size; i++) {
677+ if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
678+ return -ENOMEM;
679+ }
680+ dev->cur_prek_offset += transmit_size;
681+
682+ nla_nest_end(msg, precal);
683+ }
684+
685+ return 0;
686+}
687+
688+static void
689+mt7996_tm_re_cal_event(struct mt7996_dev *dev, struct mt7996_tm_rf_test_result *result,
690+ struct mt7996_tm_rf_test_data *data)
691+{
692+ u32 base, dpd_size_2g, dpd_size_5g, dpd_size_6g, cal_idx, cal_type, len = 0;
693+ u8 *pre_cal;
694+
695+ pre_cal = dev->cal;
696+ dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
697+ dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
698+ dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
699+
700+ cal_idx = le32_to_cpu(data->cal_idx);
701+ cal_type = le32_to_cpu(data->cal_type);
702+ len = le32_to_cpu(result->payload_length);
703+ len = len - sizeof(struct mt7996_tm_rf_test_data);
704+
705+ switch (cal_type) {
706+ case RF_PRE_CAL:
707+ base = 0;
708+ break;
709+ case RF_DPD_FLAT_CAL:
710+ base = MT_EE_CAL_GROUP_SIZE;
711+ break;
712+ case RF_DPD_FLAT_5G_CAL:
713+ case RF_DPD_FLAT_5G_MEM_CAL:
714+ base = MT_EE_CAL_GROUP_SIZE + dpd_size_2g;
715+ break;
716+ case RF_DPD_FLAT_6G_CAL:
717+ case RF_DPD_FLAT_6G_MEM_CAL:
718+ base = MT_EE_CAL_GROUP_SIZE + dpd_size_2g + dpd_size_5g;
719+ break;
720+ default:
721+ dev_info(dev->mt76.dev, "Unknown calibration type!\n");
722+ return;
723+ }
724+ pre_cal += (base + dev->cur_prek_offset);
725+
726+ memcpy(pre_cal, data->cal_data, len);
727+ dev->cur_prek_offset += len;
728+}
729+
730+void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
731+{
732+ struct mt7996_tm_event *event;
733+ struct mt7996_tm_rf_test_result *result;
734+ struct mt7996_tm_rf_test_data *data;
735+ static u32 event_type;
736+
737+ skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
738+ event = (struct mt7996_tm_event *)skb->data;
739+ result = (struct mt7996_tm_rf_test_result *)&event->result;
740+ data = (struct mt7996_tm_rf_test_data *)result->data;
741+
742+ event_type = le32_to_cpu(result->func_idx);
743+
744+ switch (event_type) {
745+ case RF_TEST_RE_CAL:
746+ mt7996_tm_re_cal_event(dev, result, data);
747+ break;
748+ default:
749+ break;
750+ }
751+}
752+
753 static void
754 mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
755 {
756@@ -447,6 +879,10 @@ mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
757 else if (prev_state == MT76_TM_STATE_OFF ||
758 state == MT76_TM_STATE_OFF)
759 mt7996_tm_init(phy, !(state == MT76_TM_STATE_OFF));
760+ else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
761+ return mt7996_tm_group_prek(phy, state);
762+ else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
763+ return mt7996_tm_dpd_prek(phy, state);
764
765 if ((state == MT76_TM_STATE_IDLE &&
766 prev_state == MT76_TM_STATE_OFF) ||
767@@ -655,4 +1091,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
768 .dump_stats = mt7996_tm_dump_stats,
769 .reset_rx_stats = mt7996_tm_reset_trx_stats,
770 .tx_stop = mt7996_tm_tx_stop,
771+ .dump_precal = mt7996_tm_dump_precal,
772 };
773diff --git a/mt7996/testmode.h b/mt7996/testmode.h
774index f00e51f4..778c9bc6 100644
775--- a/mt7996/testmode.h
776+++ b/mt7996/testmode.h
777@@ -34,6 +34,12 @@ enum bw_mapping_method {
778 NUM_BW_MAP,
779 };
780
781+struct tm_cal_param {
782+ __le32 func_data;
783+ u8 band_idx;
784+ u8 rsv[3];
785+};
786+
787 struct mt7996_tm_rf_test {
788 __le16 tag;
789 __le16 len;
790@@ -50,7 +56,7 @@ struct mt7996_tm_rf_test {
791 union {
792 __le32 func_data;
793 __le32 cal_dump;
794-
795+ struct tm_cal_param cal_param;
796 u8 _pad[80];
797 } param;
798 } rf;
799@@ -63,10 +69,16 @@ struct mt7996_tm_req {
800 struct mt7996_tm_rf_test rf_test;
801 } __packed;
802
803+struct mt7996_tm_rf_test_data {
804+ __le32 cal_idx;
805+ __le32 cal_type;
806+ u8 cal_data[0];
807+} __packed;
808+
809 struct mt7996_tm_rf_test_result {
810 __le32 func_idx;
811 __le32 payload_length;
812- u8 event[0];
813+ u8 data[0];
814 };
815
816 struct mt7996_tm_event {
817@@ -77,6 +89,8 @@ struct mt7996_tm_event {
818 struct mt7996_tm_rf_test_result result;
819 } __packed;
820
821+#define RF_TEST_RE_CAL 0x01
822+
823 enum {
824 RF_ACTION_SWITCH_TO_RF_TEST,
825 RF_ACTION_IN_RF_TEST,
826@@ -84,6 +98,8 @@ enum {
827 RF_ACTION_GET,
828 };
829
830+#define RF_TEST_ICAP_LEN 120
831+
832 enum {
833 RF_OPER_NORMAL,
834 RF_OPER_RF_TEST,
835diff --git a/testmode.c b/testmode.c
836index fc68c2af..74bb26fa 100644
837--- a/testmode.c
838+++ b/testmode.c
839@@ -626,6 +626,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
840
841 mutex_lock(&dev->mutex);
842
843+ if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
844+ int flag, type;
845+
846+ err = -EINVAL;
847+ flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
848+ type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
849+ if (dev->test_ops->dump_precal)
850+ err = dev->test_ops->dump_precal(phy, msg, flag, type);
851+
852+ goto out;
853+ }
854+
855 if (tb[MT76_TM_ATTR_STATS]) {
856 err = -EINVAL;
857
858diff --git a/testmode.h b/testmode.h
859index 8d0b9702..0c3b1393 100644
860--- a/testmode.h
861+++ b/testmode.h
862@@ -215,6 +215,14 @@ enum mt76_testmode_state {
863 MT76_TM_STATE_TX_FRAMES,
864 MT76_TM_STATE_RX_FRAMES,
865 MT76_TM_STATE_TX_CONT,
866+ MT76_TM_STATE_GROUP_PREK,
867+ MT76_TM_STATE_GROUP_PREK_DUMP,
868+ MT76_TM_STATE_GROUP_PREK_CLEAN,
869+ MT76_TM_STATE_DPD_2G,
870+ MT76_TM_STATE_DPD_5G,
871+ MT76_TM_STATE_DPD_6G,
872+ MT76_TM_STATE_DPD_DUMP,
873+ MT76_TM_STATE_DPD_CLEAN,
874 MT76_TM_STATE_ON,
875
876 /* keep last */
877diff --git a/tools/fields.c b/tools/fields.c
878index e5cf7c53..b22b3fc8 100644
879--- a/tools/fields.c
880+++ b/tools/fields.c
881@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
882 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
883 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
884 [MT76_TM_STATE_TX_CONT] = "tx_cont",
885+ [MT76_TM_STATE_GROUP_PREK] = "group_prek",
886+ [MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
887+ [MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
888+ [MT76_TM_STATE_DPD_2G] = "dpd_2g",
889+ [MT76_TM_STATE_DPD_5G] = "dpd_5g",
890+ [MT76_TM_STATE_DPD_6G] = "dpd_6g",
891+ [MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
892+ [MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
893 };
894
895 static const char * const testmode_tx_mode[] = {
896--
8972.39.2
898