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