blob: ac7b1216409eea5501eb7b5ec62eca5e51a51394 [file] [log] [blame]
developerbbd45e12023-05-19 08:22:06 +08001From 0b10a07db9b3c9dd93861d71da449c521e228b3e Mon Sep 17 00:00:00 2001
developer071927d2022-08-31 20:39:29 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 31 Aug 2022 20:06:52 +0800
developerbbd45e12023-05-19 08:22:06 +08004Subject: [PATCH 1011/1033] wifi: mt76: testmode: add pre-cal support
developer071927d2022-08-31 20:39:29 +08005
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
developer1d9da7d2023-04-15 12:45:34 +080023index 90d36c8..aa88925 100644
developer071927d2022-08-31 20:39:29 +080024--- 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
developerbbd45e12023-05-19 08:22:06 +080040index 3191626..c632852 100644
developer071927d2022-08-31 20:39:29 +080041--- a/mt76.h
42+++ b/mt76.h
developer5bea7322023-04-13 18:50:55 +080043@@ -647,6 +647,7 @@ struct mt76_testmode_ops {
developer071927d2022-08-31 20:39:29 +080044 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
developerbbd45e12023-05-19 08:22:06 +080052index 79416e6..df7e50b 100644
developer071927d2022-08-31 20:39:29 +080053--- a/mt76_connac_mcu.h
54+++ b/mt76_connac_mcu.h
developerc9233442023-04-04 06:06:17 +080055@@ -992,6 +992,7 @@ enum {
developer071927d2022-08-31 20:39:29 +080056
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
developer1d9da7d2023-04-15 12:45:34 +080064index f3e5681..88aaa16 100644
developer071927d2022-08-31 20:39:29 +080065--- 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)
developerc226de82022-10-03 12:24:57 +080089@@ -155,6 +163,26 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
developer071927d2022-08-31 20:39:29 +080090 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
developerbbd45e12023-05-19 08:22:06 +0800117index e4ab3e0..abb54eb 100644
developer071927d2022-08-31 20:39:29 +0800118--- a/mt7915/mcu.c
119+++ b/mt7915/mcu.c
developerbbd45e12023-05-19 08:22:06 +0800120@@ -391,6 +391,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
developer071927d2022-08-31 20:39:29 +0800121 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;
developerbbd45e12023-05-19 08:22:06 +0800130@@ -2887,7 +2890,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
developer071927d2022-08-31 20:39:29 +0800131 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 /*
developerbbd45e12023-05-19 08:22:06 +0800139@@ -2967,11 +2970,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
developer071927d2022-08-31 20:39:29 +0800140 {
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
developerbbd45e12023-05-19 08:22:06 +0800172index 83743cd..54e8944 100644
developer071927d2022-08-31 20:39:29 +0800173--- a/mt7915/mt7915.h
174+++ b/mt7915/mt7915.h
developerbbd45e12023-05-19 08:22:06 +0800175@@ -406,6 +406,10 @@ struct mt7915_dev {
developer071927d2022-08-31 20:39:29 +0800176 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;
developerbbd45e12023-05-19 08:22:06 +0800186@@ -642,6 +646,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
developer071927d2022-08-31 20:39:29 +0800187 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
developerbbd45e12023-05-19 08:22:06 +0800195index c44f13f..146c4d3 100644
developer071927d2022-08-31 20:39:29 +0800196--- 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,
developereb6a0182022-12-12 18:53:32 +0800206@@ -1580,18 +1581,16 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
developer071927d2022-08-31 20:39:29 +0800207 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;
developereb6a0182022-12-12 18:53:32 +0800219 u8 band = phy->mt76->band_idx;
developer071927d2022-08-31 20:39:29 +0800220 u16 rateval;
221 struct mt7915_tm_rf_test req = {
222- .action = 1,
223+ .action = RF_ACT_IN_RFTEST,
224 .icap_len = 120,
225 .op.rf.func_idx = cpu_to_le32(func_idx),
226 };
developereb6a0182022-12-12 18:53:32 +0800227@@ -1676,6 +1675,316 @@ out:
developer071927d2022-08-31 20:39:29 +0800228 sizeof(req), true);
229 }
230
231+static int
232+mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
233+{
234+ u8 *eeprom;
235+ u32 i, group_size, dpd_size, size, offs, *pre_cal;
236+ int ret = 0;
237+ struct mt7915_dev *dev = phy->dev;
238+ struct mt76_dev *mdev = &dev->mt76;
239+ struct mt7915_tm_rf_test req = {
240+ .action = RF_ACT_IN_RFTEST,
241+ .icap_len = 8,
242+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
243+ };
244+
245+ if (!dev->flash_mode && !dev->bin_file_mode) {
246+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
247+ return 1;
248+ }
249+
250+ eeprom = mdev->eeprom.data;
251+ dev->cur_prek_offset = 0;
252+ group_size = mt7915_get_cal_group_size(dev);
253+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
254+ size = group_size + dpd_size;
255+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
256+
257+ switch (state) {
258+ case MT76_TM_STATE_GROUP_PREK:
259+ req.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL);
260+
261+ if (!dev->cal) {
262+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
263+ if (!dev->cal)
264+ return -ENOMEM;
265+ }
266+
267+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
268+ sizeof(req), true);
269+
270+ if (!ret)
271+ eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
272+ break;
273+ case MT76_TM_STATE_GROUP_PREK_DUMP:
274+ pre_cal = (u32 *)dev->cal;
275+ if (!pre_cal) {
276+ dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
277+ return ret;
278+ }
279+ dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
280+ for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
developereb6a0182022-12-12 18:53:32 +0800281+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
developer071927d2022-08-31 20:39:29 +0800282+ i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
283+ pre_cal[i + 2], pre_cal[i + 3]);
284+ }
285+ break;
286+ case MT76_TM_STATE_GROUP_PREK_CLEAN:
287+ pre_cal = (u32 *)dev->cal;
288+ if (!pre_cal)
289+ return ret;
290+ memset(pre_cal, 0, group_size);
291+ eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
292+ break;
293+ default:
294+ return -EINVAL;
295+ }
296+ return ret;
297+}
298+
299+static int
300+mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
301+{
302+#define DPD_2G_CH_BW20_BITMAP_0 0x444
303+#define DPD_5G_CH_BW20_BITMAP_0 0xffffc0ff
304+#define DPD_5G_CH_BW20_BITMAP_1 0x3
305+#define DPD_5G_CH_BW20_BITMAP_7915_0 0x7dffc0ff
306+#define DPD_6G_CH_BW20_BITMAP_0 0xffffffff
307+#define DPD_6G_CH_BW20_BITMAP_1 0x07ffffff
308+ bool is_set = false;
309+ u8 band, do_precal, *eeprom;
310+ u16 bw20_size, bw160_size;
311+ u32 i, j, *bw160_freq, bw160_5g_freq[] = {5250, 5570, 5815};
312+ u32 bw160_6g_freq[] = {6025, 6185, 6345, 6505, 6665, 6825, 6985};
313+ u32 shift, freq, group_size, dpd_size, size, offs, *pre_cal, dpd_ch_bw20_bitmap[2] = {0};
314+ __le32 func_data = 0;
315+ int ret = 0;
316+ struct mt7915_dev *dev = phy->dev;
317+ struct mt76_dev *mdev = &dev->mt76;
318+ struct mt76_phy *mphy = phy->mt76;
319+ struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
320+ struct ieee80211_channel chan_backup, chan, *bw20_ch;
321+ struct mt7915_tm_rf_test req = {
322+ .action = RF_ACT_IN_RFTEST,
323+ .icap_len = 8,
324+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
325+ };
326+
327+ if (!dev->flash_mode && !dev->bin_file_mode) {
328+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
329+ return -EOPNOTSUPP;
330+ }
331+
332+ eeprom = mdev->eeprom.data;
333+ dev->cur_prek_offset = 0;
334+ group_size = mt7915_get_cal_group_size(dev);
335+ dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0);
336+ if (is_mt7915(&dev->mt76)) {
337+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0);
338+ dev->dpd_chan_num_6g = 0;
339+ dpd_size = MT_EE_CAL_DPD_SIZE_V1;
340+ offs = MT_EE_DO_PRE_CAL;
341+ } else {
342+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) +
343+ hweight32(DPD_5G_CH_BW20_BITMAP_1) +
344+ ARRAY_SIZE(bw160_5g_freq);
345+ dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) +
346+ hweight32(DPD_6G_CH_BW20_BITMAP_1) +
347+ ARRAY_SIZE(bw160_6g_freq);
348+ dpd_size = MT_EE_CAL_DPD_SIZE_V2;
349+ offs = MT_EE_DO_PRE_CAL_V2;
350+ }
351+ size = group_size + dpd_size;
352+
353+ switch (state) {
354+ case MT76_TM_STATE_DPD_2G:
355+ if (!is_set) {
356+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
357+ dpd_ch_bw20_bitmap[0] = DPD_2G_CH_BW20_BITMAP_0;
358+ bw20_ch = mphy->sband_2g.sband.channels;
359+ bw160_freq = NULL;
360+ bw160_size = 0;
361+ band = NL80211_BAND_2GHZ;
362+ do_precal = MT_EE_WIFI_CAL_DPD_2G;
363+ is_set = true;
364+ }
365+ fallthrough;
366+ case MT76_TM_STATE_DPD_5G:
367+ if (!is_set) {
368+ if (is_mt7915(&dev->mt76)) {
369+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
370+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_7915_0;
371+ bw160_size = 0;
372+ dev->cur_prek_offset -= dev->dpd_chan_num_5g * MT_EE_CAL_UNIT * 2;
373+ } else {
374+ func_data = cpu_to_le32(RF_DPD_FLAT_5G_CAL);
375+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_0;
376+ dpd_ch_bw20_bitmap[1] = DPD_5G_CH_BW20_BITMAP_1;
377+ bw160_size = ARRAY_SIZE(bw160_5g_freq);
378+ }
379+ bw20_ch = mphy->sband_5g.sband.channels;
380+ bw160_freq = bw160_5g_freq;
381+ band = NL80211_BAND_5GHZ;
382+ do_precal = MT_EE_WIFI_CAL_DPD_5G;
383+ is_set = true;
384+ }
385+ fallthrough;
386+ case MT76_TM_STATE_DPD_6G:
387+ if (!is_set) {
388+ func_data = cpu_to_le32(RF_DPD_FLAT_6G_CAL);
389+ dpd_ch_bw20_bitmap[0] = DPD_6G_CH_BW20_BITMAP_0;
390+ dpd_ch_bw20_bitmap[1] = DPD_6G_CH_BW20_BITMAP_1;
391+ bw20_ch = mphy->sband_6g.sband.channels;
392+ bw160_freq = bw160_6g_freq;
393+ bw160_size = ARRAY_SIZE(bw160_6g_freq);
394+ band = NL80211_BAND_6GHZ;
395+ do_precal = MT_EE_WIFI_CAL_DPD_6G;
396+ is_set = true;
397+ }
398+
399+ if (!bw20_ch)
400+ return -EOPNOTSUPP;
401+ if (!dev->cal) {
402+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
403+ if (!dev->cal)
404+ return -ENOMEM;
405+ }
406+
407+ req.op.rf.param.cal_param.func_data = func_data;
developereb6a0182022-12-12 18:53:32 +0800408+ req.op.rf.param.cal_param.band_idx = phy->mt76->band_idx;
developer071927d2022-08-31 20:39:29 +0800409+
410+ memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
411+ memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
412+
413+ bw20_size = hweight32(dpd_ch_bw20_bitmap[0]) + hweight32(dpd_ch_bw20_bitmap[1]);
414+ for (i = 0, j = 0; i < bw20_size + bw160_size; i++) {
415+ if (i < bw20_size) {
416+ freq = dpd_ch_bw20_bitmap[0] ? 0 : 1;
417+ shift = ffs(dpd_ch_bw20_bitmap[freq]);
418+ j += shift;
419+ memcpy(&chan, &bw20_ch[j - 1], sizeof(struct ieee80211_channel));
420+ chandef->width = NL80211_CHAN_WIDTH_20;
421+ dpd_ch_bw20_bitmap[0] >>= shift;
422+ } else {
423+ freq = bw160_freq[i - bw20_size];
424+ chan.center_freq = freq;
425+ chan.hw_value = ieee80211_frequency_to_channel(freq);
426+ chan.band = band;
427+ chandef->width = NL80211_CHAN_WIDTH_160;
428+ }
429+
430+ memcpy(chandef->chan, &chan, sizeof(struct ieee80211_channel));
431+ if (is_mt7915(&dev->mt76))
432+ mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
433+ else
434+ mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
435+
436+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
437+
438+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
439+ sizeof(req), true);
440+ if (ret) {
441+ dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
442+ break;
443+ }
444+ }
445+ memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
446+ memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
447+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
448+
449+ if (!ret)
450+ eeprom[offs] |= do_precal;
451+
452+ break;
453+ case MT76_TM_STATE_DPD_DUMP:
454+ pre_cal = (u32 *)dev->cal;
455+ if (!dev->cal) {
456+ dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
457+ return ret;
458+ }
459+ dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
460+ for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
461+ j = i + (group_size / sizeof(u32));
developereb6a0182022-12-12 18:53:32 +0800462+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
developer071927d2022-08-31 20:39:29 +0800463+ j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
464+ pre_cal[j + 2], pre_cal[j + 3]);
465+ }
466+ break;
467+ case MT76_TM_STATE_DPD_CLEAN:
468+ pre_cal = (u32 *)dev->cal;
469+ if (!pre_cal)
470+ return ret;
471+ memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
472+ do_precal = MT_EE_WIFI_CAL_DPD;
473+ eeprom[offs] &= ~do_precal;
474+ break;
475+ default:
476+ return -EINVAL;
477+ }
478+ return ret;
479+}
480+
481+void mt7915_tm_re_cal_event(struct mt7915_dev *dev, struct mt7915_tm_rf_test_result *result,
482+ struct mt7915_tm_rf_test_data *data)
483+{
484+#define DPD_PER_CHAN_SIZE_7915 2
485+#define DPD_PER_CHAN_SIZE_7986 3
486+ u32 base, dpd_offest_2g, dpd_offest_5g, cal_idx = 0, cal_type = 0, len = 0;
487+ u8 *pre_cal;
488+
489+ pre_cal = dev->cal;
490+ dpd_offest_5g = dev->dpd_chan_num_6g * DPD_PER_CHAN_SIZE_7986 * MT_EE_CAL_UNIT;
491+ dpd_offest_2g = dpd_offest_5g + dev->dpd_chan_num_5g * MT_EE_CAL_UNIT *
492+ (is_mt7915(&dev->mt76) ? DPD_PER_CHAN_SIZE_7915 : DPD_PER_CHAN_SIZE_7986);
493+ cal_idx = le32_to_cpu(data->cal_idx);
494+ cal_type = le32_to_cpu(data->cal_type);
495+ len = le32_to_cpu(result->payload_len);
496+ len = len - sizeof(struct mt7915_tm_rf_test_data);
497+
498+ switch (cal_type) {
499+ case RF_PRE_CAL:
500+ base = 0;
501+ break;
502+ case RF_DPD_FLAT_CAL:
503+ base = mt7915_get_cal_group_size(dev) + dpd_offest_2g;
504+ break;
505+ case RF_DPD_FLAT_5G_CAL:
506+ base = mt7915_get_cal_group_size(dev) + dpd_offest_5g;
507+ break;
508+ case RF_DPD_FLAT_6G_CAL:
509+ base = mt7915_get_cal_group_size(dev);
510+ break;
511+ default:
512+ dev_info(dev->mt76.dev, "Unknown calibration type!\n");
513+ return;
514+ }
515+ pre_cal += (base + dev->cur_prek_offset);
516+
517+ memcpy(pre_cal, data->data, len);
518+ dev->cur_prek_offset += len;
519+}
520+
521+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb)
522+{
523+ struct mt7915_tm_rf_test_result *result;
524+ struct mt7915_tm_rf_test_data *data;
525+ static u32 event_type;
526+
527+ result = (struct mt7915_tm_rf_test_result *)skb->data;
528+ data = (struct mt7915_tm_rf_test_data *)result->event;
529+
530+ event_type = le32_to_cpu(result->func_idx);
531+
532+ switch (event_type) {
533+ case RF_TEST_RE_CAL:
534+ mt7915_tm_re_cal_event(dev, result, data);
535+ break;
536+ default:
537+ break;
538+ }
539+}
540+
541 static void
542 mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
543 {
developer287ee9f2023-03-02 20:13:34 +0800544@@ -1720,6 +2029,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
developer071927d2022-08-31 20:39:29 +0800545 else if (prev_state == MT76_TM_STATE_OFF ||
546 state == MT76_TM_STATE_OFF)
547 mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
548+ else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
549+ return mt7915_tm_group_prek(phy, state);
550+ else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
551+ return mt7915_tm_dpd_prek(phy, state);
552
553 if ((state == MT76_TM_STATE_IDLE &&
554 prev_state == MT76_TM_STATE_OFF) ||
developer2324aa22023-04-12 11:30:15 +0800555@@ -1888,9 +2201,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
developer071927d2022-08-31 20:39:29 +0800556 return ret;
557 }
558
559+static int
560+mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
561+{
developer99b75a82023-03-31 17:44:08 +0800562+#define DPD_PER_CHAN_SIZE_MASK GENMASK(31, 30)
563+#define DPD_CHAN_NUM_2G_MASK GENMASK(29, 20)
564+#define DPD_CHAN_NUM_5G_MASK GENMASK(19, 10)
565+#define DPD_CHAN_NUM_6G_MASK GENMASK(9, 0)
developer071927d2022-08-31 20:39:29 +0800566+ struct mt7915_phy *phy = mphy->priv;
567+ struct mt7915_dev *dev = phy->dev;
568+ u32 i, group_size, dpd_size, total_size, dpd_per_chan_size, dpd_info = 0;
569+ u32 base, size, total_chan_num, offs, transmit_size = 1000;
570+ u8 *pre_cal, *eeprom;
571+ void *precal;
572+ enum prek_ops {
573+ PREK_GET_INFO,
574+ PREK_SYNC_ALL,
575+ PREK_SYNC_GROUP,
576+ PREK_SYNC_DPD_2G,
577+ PREK_SYNC_DPD_5G,
578+ PREK_SYNC_DPD_6G,
579+ PREK_CLEAN_GROUP,
580+ PREK_CLEAN_DPD,
581+ };
582+
583+ if (!dev->cal) {
584+ dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
585+ return 0;
586+ }
587+
588+ group_size = mt7915_get_cal_group_size(dev);
589+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
590+ dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3;
591+ total_size = group_size + dpd_size;
592+ pre_cal = dev->cal;
593+ eeprom = dev->mt76.eeprom.data;
594+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
595+
596+ total_chan_num = dev->dpd_chan_num_2g + dev->dpd_chan_num_5g + dev->dpd_chan_num_6g;
597+
598+ switch (type) {
599+ case PREK_SYNC_ALL:
600+ base = 0;
601+ size = total_size;
602+ break;
603+ case PREK_SYNC_GROUP:
604+ base = 0;
605+ size = group_size;
606+ break;
607+ case PREK_SYNC_DPD_6G:
608+ base = group_size;
609+ size = dpd_size * dev->dpd_chan_num_6g / total_chan_num;
610+ break;
611+ case PREK_SYNC_DPD_5G:
612+ base = group_size + dev->dpd_chan_num_6g * dpd_per_chan_size * MT_EE_CAL_UNIT;
613+ size = dpd_size * dev->dpd_chan_num_5g / total_chan_num;
614+ break;
615+ case PREK_SYNC_DPD_2G:
616+ base = group_size + (dev->dpd_chan_num_6g + dev->dpd_chan_num_5g) *
617+ dpd_per_chan_size * MT_EE_CAL_UNIT;
618+ size = dpd_size * dev->dpd_chan_num_2g / total_chan_num;
619+ break;
620+ case PREK_GET_INFO:
621+ break;
622+ default:
623+ return 0;
624+ }
625+
626+ if (!flag) {
627+ if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
628+ dpd_info |= u32_encode_bits(dpd_per_chan_size, DPD_PER_CHAN_SIZE_MASK) |
629+ u32_encode_bits(dev->dpd_chan_num_2g, DPD_CHAN_NUM_2G_MASK) |
630+ u32_encode_bits(dev->dpd_chan_num_5g, DPD_CHAN_NUM_5G_MASK) |
631+ u32_encode_bits(dev->dpd_chan_num_6g, DPD_CHAN_NUM_6G_MASK);
632+ }
633+ dev->cur_prek_offset = 0;
634+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
635+ if (!precal)
636+ return -ENOMEM;
637+ nla_put_u32(msg, 0, group_size);
638+ nla_put_u32(msg, 1, dpd_size);
639+ nla_put_u32(msg, 2, dpd_info);
640+ nla_put_u32(msg, 3, transmit_size);
641+ nla_put_u32(msg, 4, eeprom[offs]);
642+ nla_nest_end(msg, precal);
643+ } else {
644+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
645+ if (!precal)
646+ return -ENOMEM;
647+
648+ transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
649+ transmit_size : (size - dev->cur_prek_offset);
650+ for (i = 0; i < transmit_size; i++) {
651+ if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
652+ return -ENOMEM;
653+ }
654+ dev->cur_prek_offset += transmit_size;
655+
656+ nla_nest_end(msg, precal);
657+ }
658+
659+ return 0;
660+}
661+
662 const struct mt76_testmode_ops mt7915_testmode_ops = {
663 .set_state = mt7915_tm_set_state,
664 .set_params = mt7915_tm_set_params,
665 .dump_stats = mt7915_tm_dump_stats,
666 .set_eeprom = mt7915_tm_set_eeprom,
667+ .dump_precal = mt7915_tm_dump_precal,
668 };
669diff --git a/mt7915/testmode.h b/mt7915/testmode.h
developer1d9da7d2023-04-15 12:45:34 +0800670index 01b08e9..d500987 100644
developer071927d2022-08-31 20:39:29 +0800671--- a/mt7915/testmode.h
672+++ b/mt7915/testmode.h
673@@ -81,6 +81,11 @@ struct tm_tx_cont {
674 u8 txfd_mode;
675 };
676
677+struct tm_cal_param {
678+ __le32 func_data;
679+ u8 band_idx;
680+};
681+
682 struct mt7915_tm_rf_test {
683 u8 action;
684 u8 icap_len;
685@@ -96,6 +101,7 @@ struct mt7915_tm_rf_test {
686 __le32 cal_dump;
687
688 struct tm_tx_cont tx_cont;
689+ struct tm_cal_param cal_param;
690
691 u8 _pad[80];
692 } param;
693@@ -103,6 +109,20 @@ struct mt7915_tm_rf_test {
694 } op;
695 } __packed;
696
697+struct mt7915_tm_rf_test_result {
698+ struct mt76_connac2_mcu_rxd rxd;
699+
700+ u32 func_idx;
701+ u32 payload_len;
702+ u8 event[0];
703+} __packed;
704+
705+struct mt7915_tm_rf_test_data {
706+ u32 cal_idx;
707+ u32 cal_type;
708+ u8 data[0];
709+} __packed;
710+
711 enum {
712 RF_OPER_NORMAL,
713 RF_OPER_RF_TEST,
714@@ -111,6 +131,22 @@ enum {
715 RF_OPER_WIFI_SPECTRUM,
716 };
717
718+enum {
719+ RF_ACT_SWITCH_MODE,
720+ RF_ACT_IN_RFTEST,
721+};
722+
723+enum {
724+ RF_TEST_RE_CAL = 0x01,
725+ RF_TEST_TX_CONT_START = 0x05,
726+ RF_TEST_TX_CONT_STOP = 0x06,
727+};
728+
729+#define RF_DPD_FLAT_CAL BIT(28)
730+#define RF_PRE_CAL BIT(29)
731+#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28)
732+#define RF_DPD_FLAT_6G_CAL (BIT(30) | BIT(28))
733+
734 enum {
735 TAM_ARB_OP_MODE_NORMAL = 1,
736 TAM_ARB_OP_MODE_TEST,
737diff --git a/testmode.c b/testmode.c
developer1d9da7d2023-04-15 12:45:34 +0800738index fd3b9b2..b5a919a 100644
developer071927d2022-08-31 20:39:29 +0800739--- a/testmode.c
740+++ b/testmode.c
developerc9233442023-04-04 06:06:17 +0800741@@ -766,6 +766,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer071927d2022-08-31 20:39:29 +0800742
743 mutex_lock(&dev->mutex);
744
745+ if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
746+ int flag, type;
747+
748+ err = -EINVAL;
749+ flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
750+ type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
751+ if (dev->test_ops->dump_precal)
752+ err = dev->test_ops->dump_precal(phy, msg, flag, type);
753+
754+ goto out;
755+ }
756+
757 if (tb[MT76_TM_ATTR_STATS]) {
758 err = -EINVAL;
759
developerc9233442023-04-04 06:06:17 +0800760@@ -799,7 +811,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer071927d2022-08-31 20:39:29 +0800761
762 if (dev->test_mtd.name &&
763 (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
764- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
765+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
developerf90c9af2022-12-28 22:40:23 +0800766+ nla_put_u8(msg, MT76_TM_ATTR_BAND_IDX, phy->band_idx)))
developer071927d2022-08-31 20:39:29 +0800767 goto out;
768
769 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
770diff --git a/testmode.h b/testmode.h
developer1d9da7d2023-04-15 12:45:34 +0800771index 57949f2..34936e5 100644
developer071927d2022-08-31 20:39:29 +0800772--- a/testmode.h
773+++ b/testmode.h
774@@ -19,6 +19,7 @@
775 *
776 * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
777 * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
developerf90c9af2022-12-28 22:40:23 +0800778+ * @MT76_TM_ATTR_BAND_IDX: band idx of the chip (u8)
developer071927d2022-08-31 20:39:29 +0800779 *
780 * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
781 * state to MT76_TM_STATE_TX_FRAMES (u32)
782@@ -40,6 +41,11 @@
783 *
784 * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
785 *
786+ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
787+ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
788+ * eeprom cal indicator (u32),
789+ * dpd_info = [dpd_per_chan_size, chan_num_2g,
790+ * chan_num_5g, chan_num_6g]
791 * @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
792 *
793 * @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
794@@ -67,6 +73,7 @@ enum mt76_testmode_attr {
795
796 MT76_TM_ATTR_MTD_PART,
797 MT76_TM_ATTR_MTD_OFFSET,
developerf90c9af2022-12-28 22:40:23 +0800798+ MT76_TM_ATTR_BAND_IDX,
developer071927d2022-08-31 20:39:29 +0800799
800 MT76_TM_ATTR_TX_COUNT,
801 MT76_TM_ATTR_TX_LENGTH,
802@@ -85,6 +92,8 @@ enum mt76_testmode_attr {
803 MT76_TM_ATTR_FREQ_OFFSET,
804
805 MT76_TM_ATTR_STATS,
806+ MT76_TM_ATTR_PRECAL,
807+ MT76_TM_ATTR_PRECAL_INFO,
808
809 MT76_TM_ATTR_TX_SPE_IDX,
810
811@@ -184,6 +193,14 @@ enum mt76_testmode_state {
812 MT76_TM_STATE_TX_FRAMES,
813 MT76_TM_STATE_RX_FRAMES,
814 MT76_TM_STATE_TX_CONT,
815+ MT76_TM_STATE_GROUP_PREK,
816+ MT76_TM_STATE_GROUP_PREK_DUMP,
817+ MT76_TM_STATE_GROUP_PREK_CLEAN,
818+ MT76_TM_STATE_DPD_2G,
819+ MT76_TM_STATE_DPD_5G,
820+ MT76_TM_STATE_DPD_6G,
821+ MT76_TM_STATE_DPD_DUMP,
822+ MT76_TM_STATE_DPD_CLEAN,
823 MT76_TM_STATE_ON,
824
825 /* keep last */
826diff --git a/tools/fields.c b/tools/fields.c
developer1d9da7d2023-04-15 12:45:34 +0800827index 7e564a3..3ca5cd1 100644
developer071927d2022-08-31 20:39:29 +0800828--- a/tools/fields.c
829+++ b/tools/fields.c
830@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
831 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
832 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
833 [MT76_TM_STATE_TX_CONT] = "tx_cont",
834+ [MT76_TM_STATE_GROUP_PREK] = "group_prek",
835+ [MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
836+ [MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
837+ [MT76_TM_STATE_DPD_2G] = "dpd_2g",
838+ [MT76_TM_STATE_DPD_5G] = "dpd_5g",
839+ [MT76_TM_STATE_DPD_6G] = "dpd_6g",
840+ [MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
841+ [MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
842 };
843
844 static const char * const testmode_tx_mode[] = {
845--
developer2324aa22023-04-12 11:30:15 +08008462.18.0
developer071927d2022-08-31 20:39:29 +0800847