blob: 3ccce52f3d9b0b0f4f99c10d5ca6af388e1048e9 [file] [log] [blame]
developer3f52c302024-04-08 14:36:46 +08001From 2d9fc3393a175ec0b132e6186df69baaad77e428 Mon Sep 17 00:00:00 2001
developer27b55252022-09-05 19:09:45 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 31 Aug 2022 20:06:52 +0800
developer3f52c302024-04-08 14:36:46 +08004Subject: [PATCH 1009/1053] wifi: mt76: testmode: add pre-cal support
developer27b55252022-09-05 19:09:45 +08005
6Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer27b55252022-09-05 19:09:45 +08007---
8 eeprom.c | 6 +-
9 mt76.h | 1 +
10 mt76_connac_mcu.h | 1 +
developer43a264f2024-03-26 14:09:54 +080011 mt7915/mcu.c | 3 +
12 mt7915/mt7915.h | 1 +
developer27b55252022-09-05 19:09:45 +080013 mt7915/testmode.c | 425 +++++++++++++++++++++++++++++++++++++++++++++-
14 mt7915/testmode.h | 36 ++++
15 testmode.c | 15 +-
16 testmode.h | 17 ++
17 tools/fields.c | 8 +
developer43a264f2024-03-26 14:09:54 +080018 10 files changed, 506 insertions(+), 7 deletions(-)
developer27b55252022-09-05 19:09:45 +080019
20diff --git a/eeprom.c b/eeprom.c
developer3f52c302024-04-08 14:36:46 +080021index a267397..3625b16 100644
developer27b55252022-09-05 19:09:45 +080022--- a/eeprom.c
23+++ b/eeprom.c
developerd243af02023-12-21 14:49:33 +080024@@ -94,8 +94,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
developer27b55252022-09-05 19:09:45 +080025 }
26
27 #ifdef CONFIG_NL80211_TESTMODE
28- dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
29- dev->test_mtd.offset = offset;
30+ if (len == dev->eeprom.size) {
31+ dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
32+ dev->test_mtd.offset = offset;
33+ }
34 #endif
35
36 out_put_node:
37diff --git a/mt76.h b/mt76.h
developer3f52c302024-04-08 14:36:46 +080038index 3fe18cd..22d76bb 100644
developer27b55252022-09-05 19:09:45 +080039--- a/mt76.h
40+++ b/mt76.h
developer43a264f2024-03-26 14:09:54 +080041@@ -708,6 +708,7 @@ struct mt76_testmode_ops {
developer27b55252022-09-05 19:09:45 +080042 enum mt76_testmode_state new_state);
43 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
44 int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
45+ int (*dump_precal)(struct mt76_phy *phy, struct sk_buff *msg, int flag, int type);
46 };
47
48 struct mt76_testmode_entry_data {
49diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developer3f52c302024-04-08 14:36:46 +080050index 0972010..b75d340 100644
developer27b55252022-09-05 19:09:45 +080051--- a/mt76_connac_mcu.h
52+++ b/mt76_connac_mcu.h
developer3f52c302024-04-08 14:36:46 +080053@@ -1019,6 +1019,7 @@ enum {
developer27b55252022-09-05 19:09:45 +080054
55 /* ext event table */
56 enum {
57+ MCU_EXT_EVENT_RF_TEST = 0x4,
58 MCU_EXT_EVENT_PS_SYNC = 0x5,
59 MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
60 MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
developer27b55252022-09-05 19:09:45 +080061diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developer3f52c302024-04-08 14:36:46 +080062index 233411c..ad58e3b 100644
developer27b55252022-09-05 19:09:45 +080063--- a/mt7915/mcu.c
64+++ b/mt7915/mcu.c
developerebda9012024-02-22 13:42:45 +080065@@ -482,6 +482,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
developer27b55252022-09-05 19:09:45 +080066 case MCU_EXT_EVENT_BF_STATUS_READ:
67 mt7915_tm_txbf_status_read(dev, skb);
68 break;
69+ case MCU_EXT_EVENT_RF_TEST:
70+ mt7915_tm_rf_test_event(dev, skb);
71+ break;
72 #endif
developerebda9012024-02-22 13:42:45 +080073 case MCU_EXT_EVENT_BSS_ACQ_PKT_CNT:
74 mt7915_mcu_rx_bss_acq_pkt_cnt(dev, skb);
developer27b55252022-09-05 19:09:45 +080075diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developer3f52c302024-04-08 14:36:46 +080076index 1846e2f..dd2e80b 100644
developer27b55252022-09-05 19:09:45 +080077--- a/mt7915/mt7915.h
78+++ b/mt7915/mt7915.h
developer43a264f2024-03-26 14:09:54 +080079@@ -654,6 +654,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
developer27b55252022-09-05 19:09:45 +080080 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
81 void mt7915_mcu_exit(struct mt7915_dev *dev);
82 int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
83+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb);
developerebda9012024-02-22 13:42:45 +080084 void mt7915_mcu_wmm_pbc_work(struct work_struct *work);
developer27b55252022-09-05 19:09:45 +080085
86 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
developer27b55252022-09-05 19:09:45 +080087diff --git a/mt7915/testmode.c b/mt7915/testmode.c
developer3f52c302024-04-08 14:36:46 +080088index 32dc85c..4b34430 100644
developer27b55252022-09-05 19:09:45 +080089--- a/mt7915/testmode.c
90+++ b/mt7915/testmode.c
91@@ -5,6 +5,7 @@
92 #include "mac.h"
93 #include "mcu.h"
94 #include "testmode.h"
95+#include "eeprom.h"
96
97 enum {
98 TM_CHANGED_TXPOWER,
developerd243af02023-12-21 14:49:33 +080099@@ -1604,18 +1605,16 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
developer27b55252022-09-05 19:09:45 +0800100 static int
101 mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
102 {
103-#define TX_CONT_START 0x05
104-#define TX_CONT_STOP 0x06
105 struct mt7915_dev *dev = phy->dev;
106 struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
107 int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
108 struct mt76_testmode_data *td = &phy->mt76->test;
109- u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
110+ u32 func_idx = en ? RF_TEST_TX_CONT_START : RF_TEST_TX_CONT_STOP;
111 u8 rate_idx = td->tx_rate_idx, mode;
developer2458e702022-12-13 15:52:04 +0800112 u8 band = phy->mt76->band_idx;
developer27b55252022-09-05 19:09:45 +0800113 u16 rateval;
114 struct mt7915_tm_rf_test req = {
115- .action = 1,
116+ .action = RF_ACT_IN_RFTEST,
117 .icap_len = 120,
118 .op.rf.func_idx = cpu_to_le32(func_idx),
119 };
developerd243af02023-12-21 14:49:33 +0800120@@ -1700,6 +1699,316 @@ out:
developer27b55252022-09-05 19:09:45 +0800121 sizeof(req), true);
122 }
123
124+static int
125+mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
126+{
127+ u8 *eeprom;
128+ u32 i, group_size, dpd_size, size, offs, *pre_cal;
129+ int ret = 0;
130+ struct mt7915_dev *dev = phy->dev;
131+ struct mt76_dev *mdev = &dev->mt76;
132+ struct mt7915_tm_rf_test req = {
133+ .action = RF_ACT_IN_RFTEST,
134+ .icap_len = 8,
135+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
136+ };
137+
138+ if (!dev->flash_mode && !dev->bin_file_mode) {
139+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
140+ return 1;
141+ }
142+
143+ eeprom = mdev->eeprom.data;
144+ dev->cur_prek_offset = 0;
145+ group_size = mt7915_get_cal_group_size(dev);
146+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
147+ size = group_size + dpd_size;
148+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
149+
150+ switch (state) {
151+ case MT76_TM_STATE_GROUP_PREK:
152+ req.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL);
153+
154+ if (!dev->cal) {
155+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
156+ if (!dev->cal)
157+ return -ENOMEM;
158+ }
159+
160+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
161+ sizeof(req), true);
162+
163+ if (!ret)
164+ eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
165+ break;
166+ case MT76_TM_STATE_GROUP_PREK_DUMP:
167+ pre_cal = (u32 *)dev->cal;
168+ if (!pre_cal) {
169+ dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
170+ return ret;
171+ }
172+ dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
173+ for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
developer2458e702022-12-13 15:52:04 +0800174+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
developer27b55252022-09-05 19:09:45 +0800175+ i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
176+ pre_cal[i + 2], pre_cal[i + 3]);
177+ }
178+ break;
179+ case MT76_TM_STATE_GROUP_PREK_CLEAN:
180+ pre_cal = (u32 *)dev->cal;
181+ if (!pre_cal)
182+ return ret;
183+ memset(pre_cal, 0, group_size);
184+ eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
185+ break;
186+ default:
187+ return -EINVAL;
188+ }
189+ return ret;
190+}
191+
192+static int
193+mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
194+{
195+#define DPD_2G_CH_BW20_BITMAP_0 0x444
196+#define DPD_5G_CH_BW20_BITMAP_0 0xffffc0ff
197+#define DPD_5G_CH_BW20_BITMAP_1 0x3
198+#define DPD_5G_CH_BW20_BITMAP_7915_0 0x7dffc0ff
199+#define DPD_6G_CH_BW20_BITMAP_0 0xffffffff
200+#define DPD_6G_CH_BW20_BITMAP_1 0x07ffffff
201+ bool is_set = false;
202+ u8 band, do_precal, *eeprom;
203+ u16 bw20_size, bw160_size;
204+ u32 i, j, *bw160_freq, bw160_5g_freq[] = {5250, 5570, 5815};
205+ u32 bw160_6g_freq[] = {6025, 6185, 6345, 6505, 6665, 6825, 6985};
206+ u32 shift, freq, group_size, dpd_size, size, offs, *pre_cal, dpd_ch_bw20_bitmap[2] = {0};
207+ __le32 func_data = 0;
208+ int ret = 0;
209+ struct mt7915_dev *dev = phy->dev;
210+ struct mt76_dev *mdev = &dev->mt76;
211+ struct mt76_phy *mphy = phy->mt76;
212+ struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
213+ struct ieee80211_channel chan_backup, chan, *bw20_ch;
214+ struct mt7915_tm_rf_test req = {
215+ .action = RF_ACT_IN_RFTEST,
216+ .icap_len = 8,
217+ .op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
218+ };
219+
220+ if (!dev->flash_mode && !dev->bin_file_mode) {
221+ dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
222+ return -EOPNOTSUPP;
223+ }
224+
225+ eeprom = mdev->eeprom.data;
226+ dev->cur_prek_offset = 0;
227+ group_size = mt7915_get_cal_group_size(dev);
228+ dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0);
229+ if (is_mt7915(&dev->mt76)) {
230+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0);
231+ dev->dpd_chan_num_6g = 0;
232+ dpd_size = MT_EE_CAL_DPD_SIZE_V1;
233+ offs = MT_EE_DO_PRE_CAL;
234+ } else {
235+ dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) +
236+ hweight32(DPD_5G_CH_BW20_BITMAP_1) +
237+ ARRAY_SIZE(bw160_5g_freq);
238+ dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) +
239+ hweight32(DPD_6G_CH_BW20_BITMAP_1) +
240+ ARRAY_SIZE(bw160_6g_freq);
241+ dpd_size = MT_EE_CAL_DPD_SIZE_V2;
242+ offs = MT_EE_DO_PRE_CAL_V2;
243+ }
244+ size = group_size + dpd_size;
245+
246+ switch (state) {
247+ case MT76_TM_STATE_DPD_2G:
248+ if (!is_set) {
249+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
250+ dpd_ch_bw20_bitmap[0] = DPD_2G_CH_BW20_BITMAP_0;
251+ bw20_ch = mphy->sband_2g.sband.channels;
252+ bw160_freq = NULL;
253+ bw160_size = 0;
254+ band = NL80211_BAND_2GHZ;
255+ do_precal = MT_EE_WIFI_CAL_DPD_2G;
256+ is_set = true;
257+ }
258+ fallthrough;
259+ case MT76_TM_STATE_DPD_5G:
260+ if (!is_set) {
261+ if (is_mt7915(&dev->mt76)) {
262+ func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
263+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_7915_0;
264+ bw160_size = 0;
265+ dev->cur_prek_offset -= dev->dpd_chan_num_5g * MT_EE_CAL_UNIT * 2;
266+ } else {
267+ func_data = cpu_to_le32(RF_DPD_FLAT_5G_CAL);
268+ dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_0;
269+ dpd_ch_bw20_bitmap[1] = DPD_5G_CH_BW20_BITMAP_1;
270+ bw160_size = ARRAY_SIZE(bw160_5g_freq);
271+ }
272+ bw20_ch = mphy->sband_5g.sband.channels;
273+ bw160_freq = bw160_5g_freq;
274+ band = NL80211_BAND_5GHZ;
275+ do_precal = MT_EE_WIFI_CAL_DPD_5G;
276+ is_set = true;
277+ }
278+ fallthrough;
279+ case MT76_TM_STATE_DPD_6G:
280+ if (!is_set) {
281+ func_data = cpu_to_le32(RF_DPD_FLAT_6G_CAL);
282+ dpd_ch_bw20_bitmap[0] = DPD_6G_CH_BW20_BITMAP_0;
283+ dpd_ch_bw20_bitmap[1] = DPD_6G_CH_BW20_BITMAP_1;
284+ bw20_ch = mphy->sband_6g.sband.channels;
285+ bw160_freq = bw160_6g_freq;
286+ bw160_size = ARRAY_SIZE(bw160_6g_freq);
287+ band = NL80211_BAND_6GHZ;
288+ do_precal = MT_EE_WIFI_CAL_DPD_6G;
289+ is_set = true;
290+ }
291+
292+ if (!bw20_ch)
293+ return -EOPNOTSUPP;
294+ if (!dev->cal) {
295+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
296+ if (!dev->cal)
297+ return -ENOMEM;
298+ }
299+
300+ req.op.rf.param.cal_param.func_data = func_data;
developer2458e702022-12-13 15:52:04 +0800301+ req.op.rf.param.cal_param.band_idx = phy->mt76->band_idx;
developer27b55252022-09-05 19:09:45 +0800302+
303+ memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
304+ memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
305+
306+ bw20_size = hweight32(dpd_ch_bw20_bitmap[0]) + hweight32(dpd_ch_bw20_bitmap[1]);
307+ for (i = 0, j = 0; i < bw20_size + bw160_size; i++) {
308+ if (i < bw20_size) {
309+ freq = dpd_ch_bw20_bitmap[0] ? 0 : 1;
310+ shift = ffs(dpd_ch_bw20_bitmap[freq]);
311+ j += shift;
312+ memcpy(&chan, &bw20_ch[j - 1], sizeof(struct ieee80211_channel));
313+ chandef->width = NL80211_CHAN_WIDTH_20;
314+ dpd_ch_bw20_bitmap[0] >>= shift;
315+ } else {
316+ freq = bw160_freq[i - bw20_size];
317+ chan.center_freq = freq;
318+ chan.hw_value = ieee80211_frequency_to_channel(freq);
319+ chan.band = band;
320+ chandef->width = NL80211_CHAN_WIDTH_160;
321+ }
322+
323+ memcpy(chandef->chan, &chan, sizeof(struct ieee80211_channel));
324+ if (is_mt7915(&dev->mt76))
325+ mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
326+ else
327+ mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
328+
329+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
330+
331+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
332+ sizeof(req), true);
333+ if (ret) {
334+ dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
335+ break;
336+ }
337+ }
338+ memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
339+ memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
340+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
341+
342+ if (!ret)
343+ eeprom[offs] |= do_precal;
344+
345+ break;
346+ case MT76_TM_STATE_DPD_DUMP:
347+ pre_cal = (u32 *)dev->cal;
348+ if (!dev->cal) {
349+ dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
350+ return ret;
351+ }
352+ dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
353+ for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
354+ j = i + (group_size / sizeof(u32));
developer2458e702022-12-13 15:52:04 +0800355+ dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
developer27b55252022-09-05 19:09:45 +0800356+ j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
357+ pre_cal[j + 2], pre_cal[j + 3]);
358+ }
359+ break;
360+ case MT76_TM_STATE_DPD_CLEAN:
361+ pre_cal = (u32 *)dev->cal;
362+ if (!pre_cal)
363+ return ret;
364+ memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
365+ do_precal = MT_EE_WIFI_CAL_DPD;
366+ eeprom[offs] &= ~do_precal;
367+ break;
368+ default:
369+ return -EINVAL;
370+ }
371+ return ret;
372+}
373+
374+void mt7915_tm_re_cal_event(struct mt7915_dev *dev, struct mt7915_tm_rf_test_result *result,
375+ struct mt7915_tm_rf_test_data *data)
376+{
377+#define DPD_PER_CHAN_SIZE_7915 2
378+#define DPD_PER_CHAN_SIZE_7986 3
379+ u32 base, dpd_offest_2g, dpd_offest_5g, cal_idx = 0, cal_type = 0, len = 0;
380+ u8 *pre_cal;
381+
382+ pre_cal = dev->cal;
383+ dpd_offest_5g = dev->dpd_chan_num_6g * DPD_PER_CHAN_SIZE_7986 * MT_EE_CAL_UNIT;
384+ dpd_offest_2g = dpd_offest_5g + dev->dpd_chan_num_5g * MT_EE_CAL_UNIT *
385+ (is_mt7915(&dev->mt76) ? DPD_PER_CHAN_SIZE_7915 : DPD_PER_CHAN_SIZE_7986);
386+ cal_idx = le32_to_cpu(data->cal_idx);
387+ cal_type = le32_to_cpu(data->cal_type);
388+ len = le32_to_cpu(result->payload_len);
389+ len = len - sizeof(struct mt7915_tm_rf_test_data);
390+
391+ switch (cal_type) {
392+ case RF_PRE_CAL:
393+ base = 0;
394+ break;
395+ case RF_DPD_FLAT_CAL:
396+ base = mt7915_get_cal_group_size(dev) + dpd_offest_2g;
397+ break;
398+ case RF_DPD_FLAT_5G_CAL:
399+ base = mt7915_get_cal_group_size(dev) + dpd_offest_5g;
400+ break;
401+ case RF_DPD_FLAT_6G_CAL:
402+ base = mt7915_get_cal_group_size(dev);
403+ break;
404+ default:
405+ dev_info(dev->mt76.dev, "Unknown calibration type!\n");
406+ return;
407+ }
408+ pre_cal += (base + dev->cur_prek_offset);
409+
410+ memcpy(pre_cal, data->data, len);
411+ dev->cur_prek_offset += len;
412+}
413+
414+void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb)
415+{
416+ struct mt7915_tm_rf_test_result *result;
417+ struct mt7915_tm_rf_test_data *data;
418+ static u32 event_type;
419+
420+ result = (struct mt7915_tm_rf_test_result *)skb->data;
421+ data = (struct mt7915_tm_rf_test_data *)result->event;
422+
423+ event_type = le32_to_cpu(result->func_idx);
424+
425+ switch (event_type) {
426+ case RF_TEST_RE_CAL:
427+ mt7915_tm_re_cal_event(dev, result, data);
428+ break;
429+ default:
430+ break;
431+ }
432+}
433+
434 static void
435 mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
436 {
developerd243af02023-12-21 14:49:33 +0800437@@ -1750,6 +2059,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
developer27b55252022-09-05 19:09:45 +0800438 else if (prev_state == MT76_TM_STATE_OFF ||
439 state == MT76_TM_STATE_OFF)
440 mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
441+ else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
442+ return mt7915_tm_group_prek(phy, state);
443+ else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
444+ return mt7915_tm_dpd_prek(phy, state);
445
446 if ((state == MT76_TM_STATE_IDLE &&
447 prev_state == MT76_TM_STATE_OFF) ||
developerd243af02023-12-21 14:49:33 +0800448@@ -1930,9 +2243,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
developer27b55252022-09-05 19:09:45 +0800449 return ret;
450 }
451
452+static int
453+mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
454+{
developer32b0e0f2023-04-11 13:34:56 +0800455+#define DPD_PER_CHAN_SIZE_MASK GENMASK(31, 30)
456+#define DPD_CHAN_NUM_2G_MASK GENMASK(29, 20)
457+#define DPD_CHAN_NUM_5G_MASK GENMASK(19, 10)
458+#define DPD_CHAN_NUM_6G_MASK GENMASK(9, 0)
developer27b55252022-09-05 19:09:45 +0800459+ struct mt7915_phy *phy = mphy->priv;
460+ struct mt7915_dev *dev = phy->dev;
461+ u32 i, group_size, dpd_size, total_size, dpd_per_chan_size, dpd_info = 0;
462+ u32 base, size, total_chan_num, offs, transmit_size = 1000;
463+ u8 *pre_cal, *eeprom;
464+ void *precal;
465+ enum prek_ops {
466+ PREK_GET_INFO,
467+ PREK_SYNC_ALL,
468+ PREK_SYNC_GROUP,
469+ PREK_SYNC_DPD_2G,
470+ PREK_SYNC_DPD_5G,
471+ PREK_SYNC_DPD_6G,
472+ PREK_CLEAN_GROUP,
473+ PREK_CLEAN_DPD,
474+ };
475+
476+ if (!dev->cal) {
477+ dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
478+ return 0;
479+ }
480+
481+ group_size = mt7915_get_cal_group_size(dev);
482+ dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
483+ dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3;
484+ total_size = group_size + dpd_size;
485+ pre_cal = dev->cal;
486+ eeprom = dev->mt76.eeprom.data;
487+ offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
488+
489+ total_chan_num = dev->dpd_chan_num_2g + dev->dpd_chan_num_5g + dev->dpd_chan_num_6g;
490+
491+ switch (type) {
492+ case PREK_SYNC_ALL:
493+ base = 0;
494+ size = total_size;
495+ break;
496+ case PREK_SYNC_GROUP:
497+ base = 0;
498+ size = group_size;
499+ break;
500+ case PREK_SYNC_DPD_6G:
501+ base = group_size;
502+ size = dpd_size * dev->dpd_chan_num_6g / total_chan_num;
503+ break;
504+ case PREK_SYNC_DPD_5G:
505+ base = group_size + dev->dpd_chan_num_6g * dpd_per_chan_size * MT_EE_CAL_UNIT;
506+ size = dpd_size * dev->dpd_chan_num_5g / total_chan_num;
507+ break;
508+ case PREK_SYNC_DPD_2G:
509+ base = group_size + (dev->dpd_chan_num_6g + dev->dpd_chan_num_5g) *
510+ dpd_per_chan_size * MT_EE_CAL_UNIT;
511+ size = dpd_size * dev->dpd_chan_num_2g / total_chan_num;
512+ break;
513+ case PREK_GET_INFO:
514+ break;
515+ default:
516+ return 0;
517+ }
518+
519+ if (!flag) {
520+ if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
521+ dpd_info |= u32_encode_bits(dpd_per_chan_size, DPD_PER_CHAN_SIZE_MASK) |
522+ u32_encode_bits(dev->dpd_chan_num_2g, DPD_CHAN_NUM_2G_MASK) |
523+ u32_encode_bits(dev->dpd_chan_num_5g, DPD_CHAN_NUM_5G_MASK) |
524+ u32_encode_bits(dev->dpd_chan_num_6g, DPD_CHAN_NUM_6G_MASK);
525+ }
526+ dev->cur_prek_offset = 0;
527+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
528+ if (!precal)
529+ return -ENOMEM;
530+ nla_put_u32(msg, 0, group_size);
531+ nla_put_u32(msg, 1, dpd_size);
532+ nla_put_u32(msg, 2, dpd_info);
533+ nla_put_u32(msg, 3, transmit_size);
534+ nla_put_u32(msg, 4, eeprom[offs]);
535+ nla_nest_end(msg, precal);
536+ } else {
537+ precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
538+ if (!precal)
539+ return -ENOMEM;
540+
541+ transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
542+ transmit_size : (size - dev->cur_prek_offset);
543+ for (i = 0; i < transmit_size; i++) {
544+ if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
545+ return -ENOMEM;
546+ }
547+ dev->cur_prek_offset += transmit_size;
548+
549+ nla_nest_end(msg, precal);
550+ }
551+
552+ return 0;
553+}
554+
555 const struct mt76_testmode_ops mt7915_testmode_ops = {
556 .set_state = mt7915_tm_set_state,
557 .set_params = mt7915_tm_set_params,
558 .dump_stats = mt7915_tm_dump_stats,
559 .set_eeprom = mt7915_tm_set_eeprom,
560+ .dump_precal = mt7915_tm_dump_precal,
561 };
562diff --git a/mt7915/testmode.h b/mt7915/testmode.h
developer3f52c302024-04-08 14:36:46 +0800563index eb0e043..7569826 100644
developer27b55252022-09-05 19:09:45 +0800564--- a/mt7915/testmode.h
565+++ b/mt7915/testmode.h
566@@ -81,6 +81,11 @@ struct tm_tx_cont {
567 u8 txfd_mode;
568 };
569
570+struct tm_cal_param {
571+ __le32 func_data;
572+ u8 band_idx;
573+};
574+
575 struct mt7915_tm_rf_test {
576 u8 action;
577 u8 icap_len;
578@@ -96,6 +101,7 @@ struct mt7915_tm_rf_test {
579 __le32 cal_dump;
580
581 struct tm_tx_cont tx_cont;
582+ struct tm_cal_param cal_param;
583
584 u8 _pad[80];
585 } param;
586@@ -103,6 +109,20 @@ struct mt7915_tm_rf_test {
587 } op;
588 } __packed;
589
590+struct mt7915_tm_rf_test_result {
591+ struct mt76_connac2_mcu_rxd rxd;
592+
593+ u32 func_idx;
594+ u32 payload_len;
595+ u8 event[0];
596+} __packed;
597+
598+struct mt7915_tm_rf_test_data {
599+ u32 cal_idx;
600+ u32 cal_type;
601+ u8 data[0];
602+} __packed;
603+
604 enum {
605 RF_OPER_NORMAL,
606 RF_OPER_RF_TEST,
607@@ -111,6 +131,22 @@ enum {
608 RF_OPER_WIFI_SPECTRUM,
609 };
610
611+enum {
612+ RF_ACT_SWITCH_MODE,
613+ RF_ACT_IN_RFTEST,
614+};
615+
616+enum {
617+ RF_TEST_RE_CAL = 0x01,
618+ RF_TEST_TX_CONT_START = 0x05,
619+ RF_TEST_TX_CONT_STOP = 0x06,
620+};
621+
622+#define RF_DPD_FLAT_CAL BIT(28)
623+#define RF_PRE_CAL BIT(29)
624+#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28)
625+#define RF_DPD_FLAT_6G_CAL (BIT(30) | BIT(28))
626+
627 enum {
628 TAM_ARB_OP_MODE_NORMAL = 1,
629 TAM_ARB_OP_MODE_TEST,
630diff --git a/testmode.c b/testmode.c
developer3f52c302024-04-08 14:36:46 +0800631index 7587047..070b296 100644
developer27b55252022-09-05 19:09:45 +0800632--- a/testmode.c
633+++ b/testmode.c
developere35b8e42023-10-16 11:04:00 +0800634@@ -771,6 +771,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer27b55252022-09-05 19:09:45 +0800635
636 mutex_lock(&dev->mutex);
637
638+ if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
639+ int flag, type;
640+
641+ err = -EINVAL;
642+ flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
643+ type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
644+ if (dev->test_ops->dump_precal)
645+ err = dev->test_ops->dump_precal(phy, msg, flag, type);
646+
647+ goto out;
648+ }
649+
650 if (tb[MT76_TM_ATTR_STATS]) {
651 err = -EINVAL;
652
developere35b8e42023-10-16 11:04:00 +0800653@@ -804,7 +816,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer27b55252022-09-05 19:09:45 +0800654
655 if (dev->test_mtd.name &&
656 (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
657- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
658+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
developerb9a96602023-01-10 19:53:25 +0800659+ nla_put_u8(msg, MT76_TM_ATTR_BAND_IDX, phy->band_idx)))
developer27b55252022-09-05 19:09:45 +0800660 goto out;
661
662 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
663diff --git a/testmode.h b/testmode.h
developer3f52c302024-04-08 14:36:46 +0800664index 7a68625..e4c1b52 100644
developer27b55252022-09-05 19:09:45 +0800665--- a/testmode.h
666+++ b/testmode.h
667@@ -19,6 +19,7 @@
668 *
669 * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
670 * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
developerb9a96602023-01-10 19:53:25 +0800671+ * @MT76_TM_ATTR_BAND_IDX: band idx of the chip (u8)
developer27b55252022-09-05 19:09:45 +0800672 *
developere35b8e42023-10-16 11:04:00 +0800673 * @MT76_TM_ATTR_SKU_EN: config txpower sku is enabled or disabled in testmode (u8)
developer27b55252022-09-05 19:09:45 +0800674 * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
developere35b8e42023-10-16 11:04:00 +0800675@@ -41,6 +42,11 @@
developer27b55252022-09-05 19:09:45 +0800676 *
677 * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
678 *
679+ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
680+ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
681+ * eeprom cal indicator (u32),
682+ * dpd_info = [dpd_per_chan_size, chan_num_2g,
683+ * chan_num_5g, chan_num_6g]
684 * @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
685 *
686 * @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
developere35b8e42023-10-16 11:04:00 +0800687@@ -68,6 +74,7 @@ enum mt76_testmode_attr {
developer27b55252022-09-05 19:09:45 +0800688
689 MT76_TM_ATTR_MTD_PART,
690 MT76_TM_ATTR_MTD_OFFSET,
developerb9a96602023-01-10 19:53:25 +0800691+ MT76_TM_ATTR_BAND_IDX,
developer27b55252022-09-05 19:09:45 +0800692
developere35b8e42023-10-16 11:04:00 +0800693 MT76_TM_ATTR_SKU_EN,
developer27b55252022-09-05 19:09:45 +0800694 MT76_TM_ATTR_TX_COUNT,
developere35b8e42023-10-16 11:04:00 +0800695@@ -87,6 +94,8 @@ enum mt76_testmode_attr {
developer27b55252022-09-05 19:09:45 +0800696 MT76_TM_ATTR_FREQ_OFFSET,
697
698 MT76_TM_ATTR_STATS,
699+ MT76_TM_ATTR_PRECAL,
700+ MT76_TM_ATTR_PRECAL_INFO,
701
702 MT76_TM_ATTR_TX_SPE_IDX,
703
developere35b8e42023-10-16 11:04:00 +0800704@@ -188,6 +197,14 @@ enum mt76_testmode_state {
developer27b55252022-09-05 19:09:45 +0800705 MT76_TM_STATE_TX_FRAMES,
706 MT76_TM_STATE_RX_FRAMES,
707 MT76_TM_STATE_TX_CONT,
708+ MT76_TM_STATE_GROUP_PREK,
709+ MT76_TM_STATE_GROUP_PREK_DUMP,
710+ MT76_TM_STATE_GROUP_PREK_CLEAN,
711+ MT76_TM_STATE_DPD_2G,
712+ MT76_TM_STATE_DPD_5G,
713+ MT76_TM_STATE_DPD_6G,
714+ MT76_TM_STATE_DPD_DUMP,
715+ MT76_TM_STATE_DPD_CLEAN,
716 MT76_TM_STATE_ON,
717
718 /* keep last */
719diff --git a/tools/fields.c b/tools/fields.c
developer3f52c302024-04-08 14:36:46 +0800720index 406ba77..27801db 100644
developer27b55252022-09-05 19:09:45 +0800721--- a/tools/fields.c
722+++ b/tools/fields.c
723@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
724 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
725 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
726 [MT76_TM_STATE_TX_CONT] = "tx_cont",
727+ [MT76_TM_STATE_GROUP_PREK] = "group_prek",
728+ [MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
729+ [MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
730+ [MT76_TM_STATE_DPD_2G] = "dpd_2g",
731+ [MT76_TM_STATE_DPD_5G] = "dpd_5g",
732+ [MT76_TM_STATE_DPD_6G] = "dpd_6g",
733+ [MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
734+ [MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
735 };
736
737 static const char * const testmode_tx_mode[] = {
738--
developere35b8e42023-10-16 11:04:00 +08007392.18.0
developer27b55252022-09-05 19:09:45 +0800740