blob: 7ecdd8b553845e1c75be90e4f9531f93bc3a9637 [file] [log] [blame]
developer27b55252022-09-05 19:09:45 +08001From 3e0328c381fcaaa6e5fcf50494934c770d9ade49 Mon Sep 17 00:00:00 2001
2From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 31 Aug 2022 20:06:52 +0800
4Subject: [PATCH 1112/1121] mt76: testmode: add pre-cal support
5
6Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
7Change-Id: Ibfbbc3443de994eeb4daa5e364b0a90f5d7d3bcd
8---
9 eeprom.c | 6 +-
10 mt76.h | 1 +
11 mt76_connac_mcu.h | 1 +
12 mt7915/eeprom.h | 34 +++-
13 mt7915/mcu.c | 27 ++-
14 mt7915/mt7915.h | 5 +
15 mt7915/testmode.c | 425 +++++++++++++++++++++++++++++++++++++++++++++-
16 mt7915/testmode.h | 36 ++++
17 testmode.c | 15 +-
18 testmode.h | 17 ++
19 tools/fields.c | 8 +
20 11 files changed, 562 insertions(+), 13 deletions(-)
21
22diff --git a/eeprom.c b/eeprom.c
23index 1e41b94..e083964 100644
24--- a/eeprom.c
25+++ b/eeprom.c
26@@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
27 }
28
29 #ifdef CONFIG_NL80211_TESTMODE
30- dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
31- dev->test_mtd.offset = offset;
32+ if (len == dev->eeprom.size) {
33+ dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
34+ dev->test_mtd.offset = offset;
35+ }
36 #endif
37
38 out_put_node:
39diff --git a/mt76.h b/mt76.h
40index d03f312..0ed4188 100644
41--- a/mt76.h
42+++ b/mt76.h
43@@ -611,6 +611,7 @@ struct mt76_testmode_ops {
44 enum mt76_testmode_state new_state);
45 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
46 int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
47+ int (*dump_precal)(struct mt76_phy *phy, struct sk_buff *msg, int flag, int type);
48 };
49
50 struct mt76_testmode_entry_data {
51diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
52index cb1e94a..9789380 100644
53--- a/mt76_connac_mcu.h
54+++ b/mt76_connac_mcu.h
55@@ -963,6 +963,7 @@ enum {
56
57 /* ext event table */
58 enum {
59+ MCU_EXT_EVENT_RF_TEST = 0x4,
60 MCU_EXT_EVENT_PS_SYNC = 0x5,
61 MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
62 MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
63diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h
64index 7578ac6..b980342 100644
65--- a/mt7915/eeprom.h
66+++ b/mt7915/eeprom.h
67@@ -39,10 +39,18 @@ enum mt7915_eeprom_field {
68 };
69
70 #define MT_EE_WIFI_CAL_GROUP BIT(0)
71-#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1)
72+#define MT_EE_WIFI_CAL_DPD_2G BIT(2)
73+#define MT_EE_WIFI_CAL_DPD_5G BIT(1)
74+#define MT_EE_WIFI_CAL_DPD_6G BIT(3)
75+#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1)
76 #define MT_EE_CAL_UNIT 1024
77-#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16)
78-#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT)
79+#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16)
80+#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16)
81+#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16)
82+#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16)
83+#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16)
84+#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT)
85+#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT)
86
87 #define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
88 #define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
89@@ -160,6 +168,26 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
90 return val & MT_EE_WIFI_CONF7_TSSI0_5G;
91 }
92
93+static inline u32
94+mt7915_get_cal_group_size(struct mt7915_dev *dev)
95+{
96+ u8 *eep = dev->mt76.eeprom.data;
97+ u32 val;
98+
99+ if (is_mt7915(&dev->mt76)) {
100+ return MT_EE_CAL_GROUP_SIZE_7915;
101+ } else if (is_mt7916(&dev->mt76)) {
102+ val = eep[MT_EE_WIFI_CONF + 1];
103+ val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
104+ return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G :
105+ MT_EE_CAL_GROUP_SIZE_7916;
106+ } else if (mt7915_check_adie(dev, false)) {
107+ return MT_EE_CAL_GROUP_SIZE_7976;
108+ } else {
109+ return MT_EE_CAL_GROUP_SIZE_7975;
110+ }
111+}
112+
113 extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
114
115 #endif
116diff --git a/mt7915/mcu.c b/mt7915/mcu.c
117index ecdc4fb..42b1abc 100644
118--- a/mt7915/mcu.c
119+++ b/mt7915/mcu.c
120@@ -438,6 +438,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
121 case MCU_EXT_EVENT_BF_STATUS_READ:
122 mt7915_tm_txbf_status_read(dev, skb);
123 break;
124+ case MCU_EXT_EVENT_RF_TEST:
125+ mt7915_tm_rf_test_event(dev, skb);
126+ break;
127 #endif
128 default:
129 break;
130@@ -2925,7 +2928,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
131 u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
132 u32 total = MT_EE_CAL_GROUP_SIZE;
133
134- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP))
135+ if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
136 return 0;
137
138 /*
139@@ -3005,11 +3008,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
140 {
141 struct mt7915_dev *dev = phy->dev;
142 struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
143- u16 total = 2, center_freq = chandef->center_freq1;
144+ enum nl80211_band band = chandef->chan->band;
145+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
146+ u16 center_freq = chandef->center_freq1;
147 u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
148+ u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;
149 int idx;
150
151- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD))
152+ switch (band) {
153+ case NL80211_BAND_2GHZ:
154+ dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
155+ break;
156+ case NL80211_BAND_5GHZ:
157+ dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
158+ break;
159+ case NL80211_BAND_6GHZ:
160+ dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
161+ break;
162+ default:
163+ dpd_mask = 0;
164+ break;
165+ }
166+
167+ if (!(eep[offs] & dpd_mask))
168 return 0;
169
170 idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
171diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
172index 99f364c..fc0621e 100644
173--- a/mt7915/mt7915.h
174+++ b/mt7915/mt7915.h
175@@ -381,6 +381,10 @@ struct mt7915_dev {
176 struct rchan *relay_fwlog;
177
178 void *cal;
179+ u32 cur_prek_offset;
180+ u8 dpd_chan_num_2g;
181+ u8 dpd_chan_num_5g;
182+ u8 dpd_chan_num_6g;
183
184 struct {
185 u8 debug_wm;
186@@ -617,6 +621,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
187 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
188 void mt7915_mcu_exit(struct mt7915_dev *dev);
189 int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
190+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb);
191
192 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
193 {
194diff --git a/mt7915/testmode.c b/mt7915/testmode.c
195index bc4cd80..7a49608 100644
196--- a/mt7915/testmode.c
197+++ b/mt7915/testmode.c
198@@ -5,6 +5,7 @@
199 #include "mac.h"
200 #include "mcu.h"
201 #include "testmode.h"
202+#include "eeprom.h"
203
204 enum {
205 TM_CHANGED_TXPOWER,
206@@ -1578,17 +1579,15 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
207 static int
208 mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
209 {
210-#define TX_CONT_START 0x05
211-#define TX_CONT_STOP 0x06
212 struct mt7915_dev *dev = phy->dev;
213 struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
214 int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
215 struct mt76_testmode_data *td = &phy->mt76->test;
216- u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
217+ u32 func_idx = en ? RF_TEST_TX_CONT_START : RF_TEST_TX_CONT_STOP;
218 u8 rate_idx = td->tx_rate_idx, mode;
219 u16 rateval;
220 struct mt7915_tm_rf_test req = {
221- .action = 1,
222+ .action = RF_ACT_IN_RFTEST,
223 .icap_len = 120,
224 .op.rf.func_idx = cpu_to_le32(func_idx),
225 };
226@@ -1672,6 +1671,316 @@ out:
227 sizeof(req), true);
228 }
229
230+static int
231+mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
232+{
233+ u8 *eeprom;
234+ u32 i, group_size, dpd_size, size, offs, *pre_cal;
235+ int ret = 0;
236+ struct mt7915_dev *dev = phy->dev;
237+ struct mt76_dev *mdev = &dev->mt76;
238+ struct mt7915_tm_rf_test req = {
239+ .action = RF_ACT_IN_RFTEST,
240+ .icap_len = 8,
241+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
242+ };
243+
244+ if (!dev->flash_mode && !dev->bin_file_mode) {
245+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
246+ return 1;
247+ }
248+
249+ eeprom = mdev->eeprom.data;
250+ dev->cur_prek_offset = 0;
251+ group_size = mt7915_get_cal_group_size(dev);
252+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
253+ size = group_size + dpd_size;
254+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
255+
256+ switch (state) {
257+ case MT76_TM_STATE_GROUP_PREK:
258+ req.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL);
259+
260+ if (!dev->cal) {
261+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
262+ if (!dev->cal)
263+ return -ENOMEM;
264+ }
265+
266+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
267+ sizeof(req), true);
268+
269+ if (!ret)
270+ eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
271+ break;
272+ case MT76_TM_STATE_GROUP_PREK_DUMP:
273+ pre_cal = (u32 *)dev->cal;
274+ if (!pre_cal) {
275+ dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
276+ return ret;
277+ }
278+ dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
279+ for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
280+ dev_info(dev->mt76.dev, "[0x%08x] 0x%8x 0x%8x 0x%8x 0x%8x\n",
281+ i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
282+ pre_cal[i + 2], pre_cal[i + 3]);
283+ }
284+ break;
285+ case MT76_TM_STATE_GROUP_PREK_CLEAN:
286+ pre_cal = (u32 *)dev->cal;
287+ if (!pre_cal)
288+ return ret;
289+ memset(pre_cal, 0, group_size);
290+ eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
291+ break;
292+ default:
293+ return -EINVAL;
294+ }
295+ return ret;
296+}
297+
298+static int
299+mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
300+{
301+#define DPD_2G_CH_BW20_BITMAP_0 0x444
302+#define DPD_5G_CH_BW20_BITMAP_0 0xffffc0ff
303+#define DPD_5G_CH_BW20_BITMAP_1 0x3
304+#define DPD_5G_CH_BW20_BITMAP_7915_0 0x7dffc0ff
305+#define DPD_6G_CH_BW20_BITMAP_0 0xffffffff
306+#define DPD_6G_CH_BW20_BITMAP_1 0x07ffffff
307+ bool is_set = false;
308+ u8 band, do_precal, *eeprom;
309+ u16 bw20_size, bw160_size;
310+ u32 i, j, *bw160_freq, bw160_5g_freq[] = {5250, 5570, 5815};
311+ u32 bw160_6g_freq[] = {6025, 6185, 6345, 6505, 6665, 6825, 6985};
312+ u32 shift, freq, group_size, dpd_size, size, offs, *pre_cal, dpd_ch_bw20_bitmap[2] = {0};
313+ __le32 func_data = 0;
314+ int ret = 0;
315+ struct mt7915_dev *dev = phy->dev;
316+ struct mt76_dev *mdev = &dev->mt76;
317+ struct mt76_phy *mphy = phy->mt76;
318+ struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
319+ struct ieee80211_channel chan_backup, chan, *bw20_ch;
320+ struct mt7915_tm_rf_test req = {
321+ .action = RF_ACT_IN_RFTEST,
322+ .icap_len = 8,
323+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
324+ };
325+
326+ if (!dev->flash_mode && !dev->bin_file_mode) {
327+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
328+ return -EOPNOTSUPP;
329+ }
330+
331+ eeprom = mdev->eeprom.data;
332+ dev->cur_prek_offset = 0;
333+ group_size = mt7915_get_cal_group_size(dev);
334+ dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0);
335+ if (is_mt7915(&dev->mt76)) {
336+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0);
337+ dev->dpd_chan_num_6g = 0;
338+ dpd_size = MT_EE_CAL_DPD_SIZE_V1;
339+ offs = MT_EE_DO_PRE_CAL;
340+ } else {
341+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) +
342+ hweight32(DPD_5G_CH_BW20_BITMAP_1) +
343+ ARRAY_SIZE(bw160_5g_freq);
344+ dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) +
345+ hweight32(DPD_6G_CH_BW20_BITMAP_1) +
346+ ARRAY_SIZE(bw160_6g_freq);
347+ dpd_size = MT_EE_CAL_DPD_SIZE_V2;
348+ offs = MT_EE_DO_PRE_CAL_V2;
349+ }
350+ size = group_size + dpd_size;
351+
352+ switch (state) {
353+ case MT76_TM_STATE_DPD_2G:
354+ if (!is_set) {
355+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
356+ dpd_ch_bw20_bitmap[0] = DPD_2G_CH_BW20_BITMAP_0;
357+ bw20_ch = mphy->sband_2g.sband.channels;
358+ bw160_freq = NULL;
359+ bw160_size = 0;
360+ band = NL80211_BAND_2GHZ;
361+ do_precal = MT_EE_WIFI_CAL_DPD_2G;
362+ is_set = true;
363+ }
364+ fallthrough;
365+ case MT76_TM_STATE_DPD_5G:
366+ if (!is_set) {
367+ if (is_mt7915(&dev->mt76)) {
368+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
369+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_7915_0;
370+ bw160_size = 0;
371+ dev->cur_prek_offset -= dev->dpd_chan_num_5g * MT_EE_CAL_UNIT * 2;
372+ } else {
373+ func_data = cpu_to_le32(RF_DPD_FLAT_5G_CAL);
374+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_0;
375+ dpd_ch_bw20_bitmap[1] = DPD_5G_CH_BW20_BITMAP_1;
376+ bw160_size = ARRAY_SIZE(bw160_5g_freq);
377+ }
378+ bw20_ch = mphy->sband_5g.sband.channels;
379+ bw160_freq = bw160_5g_freq;
380+ band = NL80211_BAND_5GHZ;
381+ do_precal = MT_EE_WIFI_CAL_DPD_5G;
382+ is_set = true;
383+ }
384+ fallthrough;
385+ case MT76_TM_STATE_DPD_6G:
386+ if (!is_set) {
387+ func_data = cpu_to_le32(RF_DPD_FLAT_6G_CAL);
388+ dpd_ch_bw20_bitmap[0] = DPD_6G_CH_BW20_BITMAP_0;
389+ dpd_ch_bw20_bitmap[1] = DPD_6G_CH_BW20_BITMAP_1;
390+ bw20_ch = mphy->sband_6g.sband.channels;
391+ bw160_freq = bw160_6g_freq;
392+ bw160_size = ARRAY_SIZE(bw160_6g_freq);
393+ band = NL80211_BAND_6GHZ;
394+ do_precal = MT_EE_WIFI_CAL_DPD_6G;
395+ is_set = true;
396+ }
397+
398+ if (!bw20_ch)
399+ return -EOPNOTSUPP;
400+ if (!dev->cal) {
401+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
402+ if (!dev->cal)
403+ return -ENOMEM;
404+ }
405+
406+ req.op.rf.param.cal_param.func_data = func_data;
407+ req.op.rf.param.cal_param.band_idx = phy->band_idx;
408+
409+ memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
410+ memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
411+
412+ bw20_size = hweight32(dpd_ch_bw20_bitmap[0]) + hweight32(dpd_ch_bw20_bitmap[1]);
413+ for (i = 0, j = 0; i < bw20_size + bw160_size; i++) {
414+ if (i < bw20_size) {
415+ freq = dpd_ch_bw20_bitmap[0] ? 0 : 1;
416+ shift = ffs(dpd_ch_bw20_bitmap[freq]);
417+ j += shift;
418+ memcpy(&chan, &bw20_ch[j - 1], sizeof(struct ieee80211_channel));
419+ chandef->width = NL80211_CHAN_WIDTH_20;
420+ dpd_ch_bw20_bitmap[0] >>= shift;
421+ } else {
422+ freq = bw160_freq[i - bw20_size];
423+ chan.center_freq = freq;
424+ chan.hw_value = ieee80211_frequency_to_channel(freq);
425+ chan.band = band;
426+ chandef->width = NL80211_CHAN_WIDTH_160;
427+ }
428+
429+ memcpy(chandef->chan, &chan, sizeof(struct ieee80211_channel));
430+ if (is_mt7915(&dev->mt76))
431+ mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
432+ else
433+ mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
434+
435+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
436+
437+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
438+ sizeof(req), true);
439+ if (ret) {
440+ dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
441+ break;
442+ }
443+ }
444+ memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
445+ memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
446+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
447+
448+ if (!ret)
449+ eeprom[offs] |= do_precal;
450+
451+ break;
452+ case MT76_TM_STATE_DPD_DUMP:
453+ pre_cal = (u32 *)dev->cal;
454+ if (!dev->cal) {
455+ dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
456+ return ret;
457+ }
458+ dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
459+ for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
460+ j = i + (group_size / sizeof(u32));
461+ dev_info(dev->mt76.dev, "[0x%08x] 0x%8x 0x%8x 0x%8x 0x%8x\n",
462+ j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
463+ pre_cal[j + 2], pre_cal[j + 3]);
464+ }
465+ break;
466+ case MT76_TM_STATE_DPD_CLEAN:
467+ pre_cal = (u32 *)dev->cal;
468+ if (!pre_cal)
469+ return ret;
470+ memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
471+ do_precal = MT_EE_WIFI_CAL_DPD;
472+ eeprom[offs] &= ~do_precal;
473+ break;
474+ default:
475+ return -EINVAL;
476+ }
477+ return ret;
478+}
479+
480+void mt7915_tm_re_cal_event(struct mt7915_dev *dev, struct mt7915_tm_rf_test_result *result,
481+ struct mt7915_tm_rf_test_data *data)
482+{
483+#define DPD_PER_CHAN_SIZE_7915 2
484+#define DPD_PER_CHAN_SIZE_7986 3
485+ u32 base, dpd_offest_2g, dpd_offest_5g, cal_idx = 0, cal_type = 0, len = 0;
486+ u8 *pre_cal;
487+
488+ pre_cal = dev->cal;
489+ dpd_offest_5g = dev->dpd_chan_num_6g * DPD_PER_CHAN_SIZE_7986 * MT_EE_CAL_UNIT;
490+ dpd_offest_2g = dpd_offest_5g + dev->dpd_chan_num_5g * MT_EE_CAL_UNIT *
491+ (is_mt7915(&dev->mt76) ? DPD_PER_CHAN_SIZE_7915 : DPD_PER_CHAN_SIZE_7986);
492+ cal_idx = le32_to_cpu(data->cal_idx);
493+ cal_type = le32_to_cpu(data->cal_type);
494+ len = le32_to_cpu(result->payload_len);
495+ len = len - sizeof(struct mt7915_tm_rf_test_data);
496+
497+ switch (cal_type) {
498+ case RF_PRE_CAL:
499+ base = 0;
500+ break;
501+ case RF_DPD_FLAT_CAL:
502+ base = mt7915_get_cal_group_size(dev) + dpd_offest_2g;
503+ break;
504+ case RF_DPD_FLAT_5G_CAL:
505+ base = mt7915_get_cal_group_size(dev) + dpd_offest_5g;
506+ break;
507+ case RF_DPD_FLAT_6G_CAL:
508+ base = mt7915_get_cal_group_size(dev);
509+ break;
510+ default:
511+ dev_info(dev->mt76.dev, "Unknown calibration type!\n");
512+ return;
513+ }
514+ pre_cal += (base + dev->cur_prek_offset);
515+
516+ memcpy(pre_cal, data->data, len);
517+ dev->cur_prek_offset += len;
518+}
519+
520+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb)
521+{
522+ struct mt7915_tm_rf_test_result *result;
523+ struct mt7915_tm_rf_test_data *data;
524+ static u32 event_type;
525+
526+ result = (struct mt7915_tm_rf_test_result *)skb->data;
527+ data = (struct mt7915_tm_rf_test_data *)result->event;
528+
529+ event_type = le32_to_cpu(result->func_idx);
530+
531+ switch (event_type) {
532+ case RF_TEST_RE_CAL:
533+ mt7915_tm_re_cal_event(dev, result, data);
534+ break;
535+ default:
536+ break;
537+ }
538+}
539+
540 static void
541 mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
542 {
543@@ -1711,6 +2020,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
544 else if (prev_state == MT76_TM_STATE_OFF ||
545 state == MT76_TM_STATE_OFF)
546 mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
547+ else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
548+ return mt7915_tm_group_prek(phy, state);
549+ else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
550+ return mt7915_tm_dpd_prek(phy, state);
551
552 if ((state == MT76_TM_STATE_IDLE &&
553 prev_state == MT76_TM_STATE_OFF) ||
554@@ -1872,9 +2185,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
555 return ret;
556 }
557
558+static int
559+mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
560+{
561+#define DPD_PER_CHAN_SIZE_MASK GENMASK(31, 24)
562+#define DPD_CHAN_NUM_2G_MASK GENMASK(23, 16)
563+#define DPD_CHAN_NUM_5G_MASK GENMASK(15, 8)
564+#define DPD_CHAN_NUM_6G_MASK GENMASK(7, 0)
565+ struct mt7915_phy *phy = mphy->priv;
566+ struct mt7915_dev *dev = phy->dev;
567+ u32 i, group_size, dpd_size, total_size, dpd_per_chan_size, dpd_info = 0;
568+ u32 base, size, total_chan_num, offs, transmit_size = 1000;
569+ u8 *pre_cal, *eeprom;
570+ void *precal;
571+ enum prek_ops {
572+ PREK_GET_INFO,
573+ PREK_SYNC_ALL,
574+ PREK_SYNC_GROUP,
575+ PREK_SYNC_DPD_2G,
576+ PREK_SYNC_DPD_5G,
577+ PREK_SYNC_DPD_6G,
578+ PREK_CLEAN_GROUP,
579+ PREK_CLEAN_DPD,
580+ };
581+
582+ if (!dev->cal) {
583+ dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
584+ return 0;
585+ }
586+
587+ group_size = mt7915_get_cal_group_size(dev);
588+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
589+ dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3;
590+ total_size = group_size + dpd_size;
591+ pre_cal = dev->cal;
592+ eeprom = dev->mt76.eeprom.data;
593+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
594+
595+ total_chan_num = dev->dpd_chan_num_2g + dev->dpd_chan_num_5g + dev->dpd_chan_num_6g;
596+
597+ switch (type) {
598+ case PREK_SYNC_ALL:
599+ base = 0;
600+ size = total_size;
601+ break;
602+ case PREK_SYNC_GROUP:
603+ base = 0;
604+ size = group_size;
605+ break;
606+ case PREK_SYNC_DPD_6G:
607+ base = group_size;
608+ size = dpd_size * dev->dpd_chan_num_6g / total_chan_num;
609+ break;
610+ case PREK_SYNC_DPD_5G:
611+ base = group_size + dev->dpd_chan_num_6g * dpd_per_chan_size * MT_EE_CAL_UNIT;
612+ size = dpd_size * dev->dpd_chan_num_5g / total_chan_num;
613+ break;
614+ case PREK_SYNC_DPD_2G:
615+ base = group_size + (dev->dpd_chan_num_6g + dev->dpd_chan_num_5g) *
616+ dpd_per_chan_size * MT_EE_CAL_UNIT;
617+ size = dpd_size * dev->dpd_chan_num_2g / total_chan_num;
618+ break;
619+ case PREK_GET_INFO:
620+ break;
621+ default:
622+ return 0;
623+ }
624+
625+ if (!flag) {
626+ if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
627+ dpd_info |= u32_encode_bits(dpd_per_chan_size, DPD_PER_CHAN_SIZE_MASK) |
628+ u32_encode_bits(dev->dpd_chan_num_2g, DPD_CHAN_NUM_2G_MASK) |
629+ u32_encode_bits(dev->dpd_chan_num_5g, DPD_CHAN_NUM_5G_MASK) |
630+ u32_encode_bits(dev->dpd_chan_num_6g, DPD_CHAN_NUM_6G_MASK);
631+ }
632+ dev->cur_prek_offset = 0;
633+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
634+ if (!precal)
635+ return -ENOMEM;
636+ nla_put_u32(msg, 0, group_size);
637+ nla_put_u32(msg, 1, dpd_size);
638+ nla_put_u32(msg, 2, dpd_info);
639+ nla_put_u32(msg, 3, transmit_size);
640+ nla_put_u32(msg, 4, eeprom[offs]);
641+ nla_nest_end(msg, precal);
642+ } else {
643+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
644+ if (!precal)
645+ return -ENOMEM;
646+
647+ transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
648+ transmit_size : (size - dev->cur_prek_offset);
649+ for (i = 0; i < transmit_size; i++) {
650+ if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
651+ return -ENOMEM;
652+ }
653+ dev->cur_prek_offset += transmit_size;
654+
655+ nla_nest_end(msg, precal);
656+ }
657+
658+ return 0;
659+}
660+
661 const struct mt76_testmode_ops mt7915_testmode_ops = {
662 .set_state = mt7915_tm_set_state,
663 .set_params = mt7915_tm_set_params,
664 .dump_stats = mt7915_tm_dump_stats,
665 .set_eeprom = mt7915_tm_set_eeprom,
666+ .dump_precal = mt7915_tm_dump_precal,
667 };
668diff --git a/mt7915/testmode.h b/mt7915/testmode.h
669index 01b08e9..d500987 100644
670--- a/mt7915/testmode.h
671+++ b/mt7915/testmode.h
672@@ -81,6 +81,11 @@ struct tm_tx_cont {
673 u8 txfd_mode;
674 };
675
676+struct tm_cal_param {
677+ __le32 func_data;
678+ u8 band_idx;
679+};
680+
681 struct mt7915_tm_rf_test {
682 u8 action;
683 u8 icap_len;
684@@ -96,6 +101,7 @@ struct mt7915_tm_rf_test {
685 __le32 cal_dump;
686
687 struct tm_tx_cont tx_cont;
688+ struct tm_cal_param cal_param;
689
690 u8 _pad[80];
691 } param;
692@@ -103,6 +109,20 @@ struct mt7915_tm_rf_test {
693 } op;
694 } __packed;
695
696+struct mt7915_tm_rf_test_result {
697+ struct mt76_connac2_mcu_rxd rxd;
698+
699+ u32 func_idx;
700+ u32 payload_len;
701+ u8 event[0];
702+} __packed;
703+
704+struct mt7915_tm_rf_test_data {
705+ u32 cal_idx;
706+ u32 cal_type;
707+ u8 data[0];
708+} __packed;
709+
710 enum {
711 RF_OPER_NORMAL,
712 RF_OPER_RF_TEST,
713@@ -111,6 +131,22 @@ enum {
714 RF_OPER_WIFI_SPECTRUM,
715 };
716
717+enum {
718+ RF_ACT_SWITCH_MODE,
719+ RF_ACT_IN_RFTEST,
720+};
721+
722+enum {
723+ RF_TEST_RE_CAL = 0x01,
724+ RF_TEST_TX_CONT_START = 0x05,
725+ RF_TEST_TX_CONT_STOP = 0x06,
726+};
727+
728+#define RF_DPD_FLAT_CAL BIT(28)
729+#define RF_PRE_CAL BIT(29)
730+#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28)
731+#define RF_DPD_FLAT_6G_CAL (BIT(30) | BIT(28))
732+
733 enum {
734 TAM_ARB_OP_MODE_NORMAL = 1,
735 TAM_ARB_OP_MODE_TEST,
736diff --git a/testmode.c b/testmode.c
737index 7a9ed54..82b8e98 100644
738--- a/testmode.c
739+++ b/testmode.c
740@@ -763,6 +763,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
741
742 mutex_lock(&dev->mutex);
743
744+ if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
745+ int flag, type;
746+
747+ err = -EINVAL;
748+ flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
749+ type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
750+ if (dev->test_ops->dump_precal)
751+ err = dev->test_ops->dump_precal(phy, msg, flag, type);
752+
753+ goto out;
754+ }
755+
756 if (tb[MT76_TM_ATTR_STATS]) {
757 err = -EINVAL;
758
759@@ -796,7 +808,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
760
761 if (dev->test_mtd.name &&
762 (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
763- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
764+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
765+ nla_put_u8(msg, MT76_TM_ATTR_IS_MAIN_PHY, phy == &dev->phy)))
766 goto out;
767
768 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
769diff --git a/testmode.h b/testmode.h
770index 57949f2..e2190e7 100644
771--- a/testmode.h
772+++ b/testmode.h
773@@ -19,6 +19,7 @@
774 *
775 * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
776 * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
777+ * @MT76_TM_ATTR_IS_MAIN_PHY: Is current phy index the main phy or the ext phy (u8)
778 *
779 * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
780 * state to MT76_TM_STATE_TX_FRAMES (u32)
781@@ -40,6 +41,11 @@
782 *
783 * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
784 *
785+ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
786+ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
787+ * eeprom cal indicator (u32),
788+ * dpd_info = [dpd_per_chan_size, chan_num_2g,
789+ * chan_num_5g, chan_num_6g]
790 * @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
791 *
792 * @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
793@@ -67,6 +73,7 @@ enum mt76_testmode_attr {
794
795 MT76_TM_ATTR_MTD_PART,
796 MT76_TM_ATTR_MTD_OFFSET,
797+ MT76_TM_ATTR_IS_MAIN_PHY,
798
799 MT76_TM_ATTR_TX_COUNT,
800 MT76_TM_ATTR_TX_LENGTH,
801@@ -85,6 +92,8 @@ enum mt76_testmode_attr {
802 MT76_TM_ATTR_FREQ_OFFSET,
803
804 MT76_TM_ATTR_STATS,
805+ MT76_TM_ATTR_PRECAL,
806+ MT76_TM_ATTR_PRECAL_INFO,
807
808 MT76_TM_ATTR_TX_SPE_IDX,
809
810@@ -184,6 +193,14 @@ enum mt76_testmode_state {
811 MT76_TM_STATE_TX_FRAMES,
812 MT76_TM_STATE_RX_FRAMES,
813 MT76_TM_STATE_TX_CONT,
814+ MT76_TM_STATE_GROUP_PREK,
815+ MT76_TM_STATE_GROUP_PREK_DUMP,
816+ MT76_TM_STATE_GROUP_PREK_CLEAN,
817+ MT76_TM_STATE_DPD_2G,
818+ MT76_TM_STATE_DPD_5G,
819+ MT76_TM_STATE_DPD_6G,
820+ MT76_TM_STATE_DPD_DUMP,
821+ MT76_TM_STATE_DPD_CLEAN,
822 MT76_TM_STATE_ON,
823
824 /* keep last */
825diff --git a/tools/fields.c b/tools/fields.c
826index 6e36ab2..1be1ffd 100644
827--- a/tools/fields.c
828+++ b/tools/fields.c
829@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
830 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
831 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
832 [MT76_TM_STATE_TX_CONT] = "tx_cont",
833+ [MT76_TM_STATE_GROUP_PREK] = "group_prek",
834+ [MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
835+ [MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
836+ [MT76_TM_STATE_DPD_2G] = "dpd_2g",
837+ [MT76_TM_STATE_DPD_5G] = "dpd_5g",
838+ [MT76_TM_STATE_DPD_6G] = "dpd_6g",
839+ [MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
840+ [MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
841 };
842
843 static const char * const testmode_tx_mode[] = {
844--
8452.18.0
846