blob: 61dedbf6a343d796c4ff3f618bf49da7fa161eca [file] [log] [blame]
developer1f55fcf2024-10-17 14:52:33 +08001From 2e68a34aa076b06b96614e3a1db37967909d8f2c Mon Sep 17 00:00:00 2001
developerd0c89452024-10-11 16:53:27 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Thu, 22 Aug 2024 23:22:46 +0800
developer1f55fcf2024-10-17 14:52:33 +08004Subject: [PATCH 188/193] mtk: mt76: mt7996: add external eeprom support
developerd0c89452024-10-11 16:53:27 +08005
6Add external eeprom support
7For Kite and Griffin, efuse mode is not supported due to the lack of
8space in efuse.
9So, an additional external eeprom is added for user to store their
10golden eeprom.
11
12Note that the FW currently has some issues with writing to the ext
13eeprom, so the write back function of ext eeprom is not yet linked
14to any command.
15A write back command will be added once the FW fixes the issue.
16
17Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
18Change-Id: Ie36469700f9620806e6513ffaf076338841ba7c3
19---
20 debugfs.c | 2 +
21 mt76.h | 1 +
22 mt76_connac_mcu.h | 1 +
23 mt7996/debugfs.c | 57 ++++++++++++++++++-
24 mt7996/eeprom.c | 35 +++++++-----
25 mt7996/eeprom.h | 7 ---
26 mt7996/init.c | 3 +-
27 mt7996/mcu.c | 130 ++++++++++++++++++++++++++++++++++---------
28 mt7996/mcu.h | 35 +++++++++++-
29 mt7996/mt7996.h | 30 +++++++++-
30 mt7996/mtk_debugfs.c | 3 +
31 mt7996/testmode.c | 39 ++++++++-----
32 testmode.h | 2 +
33 13 files changed, 277 insertions(+), 68 deletions(-)
34
35diff --git a/debugfs.c b/debugfs.c
developer1f55fcf2024-10-17 14:52:33 +080036index ac5207e..2ded5c0 100644
developerd0c89452024-10-11 16:53:27 +080037--- a/debugfs.c
38+++ b/debugfs.c
39@@ -121,6 +121,8 @@ mt76_register_debugfs_fops(struct mt76_phy *phy,
40 debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom);
41 if (dev->otp.data)
42 debugfs_create_blob("otp", 0400, dir, &dev->otp);
43+ if (dev->ext_eeprom.data)
44+ debugfs_create_blob("ext_eeprom", 0400, dir, &dev->ext_eeprom);
45 debugfs_create_devm_seqfile(dev->dev, "rx-queues", dir,
46 mt76_rx_queues_read);
47
48diff --git a/mt76.h b/mt76.h
developer1f55fcf2024-10-17 14:52:33 +080049index a465785..c319ba2 100644
developerd0c89452024-10-11 16:53:27 +080050--- a/mt76.h
51+++ b/mt76.h
52@@ -1065,6 +1065,7 @@ struct mt76_dev {
53
54 struct debugfs_blob_wrapper eeprom;
55 struct debugfs_blob_wrapper otp;
56+ struct debugfs_blob_wrapper ext_eeprom;
57
58 char alpha2[3];
59 enum nl80211_dfs_regions region;
60diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developer1f55fcf2024-10-17 14:52:33 +080061index 68d7c31..25d5f9f 100644
developerd0c89452024-10-11 16:53:27 +080062--- a/mt76_connac_mcu.h
63+++ b/mt76_connac_mcu.h
64@@ -1325,6 +1325,7 @@ enum {
65 MCU_UNI_CMD_PER_STA_INFO = 0x6d,
66 MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
67 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
68+ MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
69 MCU_UNI_CMD_PTA_3WIRE_CTRL = 0x78,
70 MCU_UNI_CMD_MLD = 0x82,
71 MCU_UNI_CMD_PEER_MLD = 0x83,
72diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
developer1f55fcf2024-10-17 14:52:33 +080073index 240c6d4..d06fb58 100644
developerd0c89452024-10-11 16:53:27 +080074--- a/mt7996/debugfs.c
75+++ b/mt7996/debugfs.c
76@@ -972,7 +972,9 @@ mt7996_efuse_get(struct file *file, char __user *user_buf,
77 block_num = DIV_ROUND_UP(mdev->otp.size, MT7996_EEPROM_BLOCK_SIZE);
78 for (i = 0; i < block_num; i++) {
79 buff = mdev->otp.data + i * MT7996_EEPROM_BLOCK_SIZE;
80- ret = mt7996_mcu_get_eeprom(dev, i * MT7996_EEPROM_BLOCK_SIZE, buff);
81+ ret = mt7996_mcu_get_eeprom(dev, i * MT7996_EEPROM_BLOCK_SIZE,
82+ buff, MT7996_EEPROM_BLOCK_SIZE,
83+ EFUSE_MODE);
84 if (ret && ret != -EINVAL)
85 return ret;
86 }
87@@ -989,6 +991,58 @@ static const struct file_operations mt7996_efuse_ops = {
88 .llseek = default_llseek,
89 };
90
91+static ssize_t
92+mt7996_ext_eeprom_get(struct file *file, char __user *user_buf,
93+ size_t count, loff_t *ppos)
94+{
95+ struct mt7996_dev *dev = file->private_data;
96+ struct mt76_dev *mdev = &dev->mt76;
97+ u8 *buff = mdev->ext_eeprom.data;
98+ u32 block_num, block_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
99+ int i;
100+ ssize_t ret;
101+
102+ if (!mt7996_has_ext_eeprom(dev)) {
103+ dev_info(dev->mt76.dev, "No external eeprom device found\n");
104+ return 0;
105+ }
106+
107+ mdev->ext_eeprom.size = MT7996_EEPROM_SIZE;
108+
109+ if (!mdev->ext_eeprom.data) {
110+ mdev->ext_eeprom.data = devm_kzalloc(mdev->dev,
111+ mdev->ext_eeprom.size,
112+ GFP_KERNEL);
113+ if (!mdev->ext_eeprom.data)
114+ return -ENOMEM;
115+
116+ block_num = DIV_ROUND_UP(mdev->ext_eeprom.size, block_size);
117+ for (i = 0; i < block_num; i++) {
118+ u32 buf_len = block_size;
119+ u32 offset = i * block_size;
120+
121+ if (offset + block_size > mdev->ext_eeprom.size)
122+ buf_len = mdev->ext_eeprom.size % block_size;
123+ buff = mdev->ext_eeprom.data + offset;
124+ ret = mt7996_mcu_get_eeprom(dev, offset, buff, buf_len,
125+ EXT_EEPROM_MODE);
126+ if (ret && ret != -EINVAL)
127+ return ret;
128+ }
129+ }
130+
131+ ret = simple_read_from_buffer(user_buf, count, ppos,
132+ mdev->ext_eeprom.data, mdev->ext_eeprom.size);
133+
134+ return ret;
135+}
136+
137+static const struct file_operations mt7996_ext_eeprom_ops = {
138+ .read = mt7996_ext_eeprom_get,
139+ .open = simple_open,
140+ .llseek = default_llseek,
141+};
142+
143 static int
144 mt7996_vow_info_read(struct seq_file *s, void *data)
145 {
146@@ -1133,6 +1187,7 @@ int mt7996_init_dev_debugfs(struct mt7996_phy *phy)
147 mt7996_twt_stats);
148 debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
149 debugfs_create_file("otp", 0400, dir, dev, &mt7996_efuse_ops);
150+ debugfs_create_file("ext_eeprom", 0400, dir, dev, &mt7996_ext_eeprom_ops);
151 debugfs_create_devm_seqfile(dev->mt76.dev, "vow_info", dir,
152 mt7996_vow_info_read);
153 debugfs_create_devm_seqfile(dev->mt76.dev, "airtime", dir,
154diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
developer1f55fcf2024-10-17 14:52:33 +0800155index 327a36b..db98db2 100644
developerd0c89452024-10-11 16:53:27 +0800156--- a/mt7996/eeprom.c
157+++ b/mt7996/eeprom.c
158@@ -315,43 +315,52 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
159
160 /* flash or bin file mode eeprom is loaded before mcu init */
161 if (!dev->flash_mode) {
162- u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
163- u32 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
164+ u32 eeprom_blk_size, block_num;
165 u8 free_block_num;
166 int i;
167
168 memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
169- ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);
170- if (ret < 0)
171- return ret;
172-
173- /* efuse info isn't enough */
174- if (free_block_num >= 59) {
175- use_default = true;
176- goto out;
177+ if (!mt7996_has_ext_eeprom(dev)) {
178+ /* efuse mode */
179+ dev->eeprom_mode = EFUSE_MODE;
180+ eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
181+ ret = mt7996_mcu_get_efuse_free_block(dev, &free_block_num);
182+ if (ret < 0)
183+ return ret;
184+
185+ /* efuse info isn't enough */
186+ if (free_block_num >= 59) {
187+ use_default = true;
188+ goto out;
189+ }
190+ } else {
191+ /* external eeprom mode */
192+ dev->eeprom_mode = EXT_EEPROM_MODE;
193+ eeprom_blk_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
194 }
195
196 /* check if eeprom data from fw is valid */
197- if (mt7996_mcu_get_eeprom(dev, 0, NULL, 0) ||
198+ if (mt7996_mcu_get_eeprom(dev, 0, NULL, eeprom_blk_size,
199+ dev->eeprom_mode) ||
200 mt7996_check_eeprom(dev)) {
201 use_default = true;
202 goto out;
203 }
204
205 /* read eeprom data from fw */
206+ block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
207 for (i = 1; i < block_num; i++) {
208 u32 len = eeprom_blk_size;
209
210 if (i == block_num - 1)
211 len = MT7996_EEPROM_SIZE % eeprom_blk_size;
212 ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size,
213- NULL, len);
214+ NULL, len, dev->eeprom_mode);
215 if (ret && ret != -EINVAL) {
216 use_default = true;
217 goto out;
218 }
219 }
220- dev->eeprom_mode = EFUSE_MODE;
221 }
222
223 out:
224diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
developer1f55fcf2024-10-17 14:52:33 +0800225index 788c33c..15b6620 100644
developerd0c89452024-10-11 16:53:27 +0800226--- a/mt7996/eeprom.h
227+++ b/mt7996/eeprom.h
228@@ -151,13 +151,6 @@ enum mt7996_eeprom_band {
229 MT_EE_BAND_SEL_6GHZ,
230 };
231
232-enum mt7915_eeprom_mode {
233- DEFAULT_BIN_MODE,
234- EFUSE_MODE,
235- FLASH_MODE,
236- BIN_FILE_MODE,
237-};
238-
239 static inline int
240 mt7996_get_channel_group_5g(int channel)
241 {
242diff --git a/mt7996/init.c b/mt7996/init.c
developer1f55fcf2024-10-17 14:52:33 +0800243index 9f80143..604d015 100644
developerd0c89452024-10-11 16:53:27 +0800244--- a/mt7996/init.c
245+++ b/mt7996/init.c
developer1f55fcf2024-10-17 14:52:33 +0800246@@ -1235,7 +1235,8 @@ static int mt7996_variant_fem_init(struct mt7996_dev *dev)
developerd0c89452024-10-11 16:53:27 +0800247 if (ret)
248 return ret;
249
250- ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf));
251+ ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf),
252+ EFUSE_MODE);
253 if (ret && ret != -EINVAL)
254 return ret;
255
256diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer1f55fcf2024-10-17 14:52:33 +0800257index 6d4765b..b584a0e 100644
developerd0c89452024-10-11 16:53:27 +0800258--- a/mt7996/mcu.c
259+++ b/mt7996/mcu.c
260@@ -5259,7 +5259,7 @@ int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
261 #define MAX_PAGE_IDX_MASK GENMASK(7, 5)
262 #define PAGE_IDX_MASK GENMASK(4, 2)
263 #define PER_PAGE_SIZE 0x400
264- struct mt7996_mcu_eeprom req = {
265+ struct mt7996_mcu_eeprom_update req = {
266 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
267 .buffer_mode = EE_MODE_BUFFER
268 };
269@@ -5301,7 +5301,7 @@ int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
270
271 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
272 {
273- struct mt7996_mcu_eeprom req = {
274+ struct mt7996_mcu_eeprom_update req = {
275 .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
276 .len = cpu_to_le16(sizeof(req) - 4),
277 .buffer_mode = EE_MODE_EFUSE,
278@@ -5309,7 +5309,7 @@ int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
279 };
280 int ret;
281
282- if (dev->flash_mode)
283+ if (dev->flash_mode || mt7996_has_ext_eeprom(dev))
284 ret = mt7996_mcu_set_eeprom_flash(dev);
285 else
286 ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
287@@ -5320,36 +5320,64 @@ int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
288 return mt7996_mcu_set_cal_free_data(dev);
289 }
290
291-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len)
292+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
293+ enum mt7996_eeprom_mode mode)
294 {
295- struct mt7996_mcu_eeprom_info req = {
296- .tag = cpu_to_le16(UNI_EFUSE_ACCESS),
297- .len = cpu_to_le16(sizeof(req) - 4),
298- .addr = cpu_to_le32(round_down(offset,
299- MT7996_EEPROM_BLOCK_SIZE)),
300- };
301+ struct mt7996_mcu_eeprom_access req;
302+ struct mt7996_mcu_eeprom_access_event *event;
303 struct sk_buff *skb;
304- bool valid;
305- int ret;
306+ int ret, cmd;
307
308- ret = mt76_mcu_send_and_get_msg(&dev->mt76,
309- MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
310- &req, sizeof(req), true, &skb);
311+ switch (mode) {
312+ case EFUSE_MODE:
313+ req.info.tag = cpu_to_le16(UNI_EFUSE_ACCESS);
314+ req.info.len = cpu_to_le16(sizeof(req) - 4);
315+ req.info.addr = cpu_to_le32(round_down(offset, MT7996_EEPROM_BLOCK_SIZE));
316+ cmd = MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL);
317+ break;
318+ case EXT_EEPROM_MODE:
319+ req.info.tag = cpu_to_le16(UNI_EXT_EEPROM_ACCESS);
320+ req.info.len = cpu_to_le16(sizeof(req) - 4);
321+ req.info.addr = cpu_to_le32(round_down(offset, MT7996_EXT_EEPROM_BLOCK_SIZE));
322+ req.eeprom.ext_eeprom.data_len = cpu_to_le32(buf_len);
323+ cmd = MCU_WM_UNI_CMD_QUERY(EXT_EEPROM_CTRL);
324+ break;
325+ default:
326+ return -EINVAL;
327+ }
328+
329+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, cmd, &req,
330+ sizeof(req), true, &skb);
331 if (ret)
332 return ret;
333
334- valid = le32_to_cpu(*(__le32 *)(skb->data + 16));
335- if (valid) {
336- u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
337-
338- if (!buf)
339- buf = (u8 *)dev->mt76.eeprom.data + addr;
340+ event = (struct mt7996_mcu_eeprom_access_event *)skb->data;
341+ if (event->valid) {
342+ u32 addr = le32_to_cpu(event->addr);
343+ u32 ret_len = le32_to_cpu(event->eeprom.ext_eeprom.data_len);
344
345- if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
346- buf_len = MT7996_EEPROM_BLOCK_SIZE;
347+ switch (mode) {
348+ case EFUSE_MODE:
349+ if (!buf)
350+ buf = (u8 *)dev->mt76.eeprom.data + addr;
351+ if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
352+ buf_len = MT7996_EEPROM_BLOCK_SIZE;
353
354- skb_pull(skb, 48);
355- memcpy(buf, skb->data, buf_len);
356+ memcpy(buf, event->eeprom.efuse, buf_len);
357+ break;
358+ case EXT_EEPROM_MODE:
359+ if (!buf)
360+ buf = (u8 *)dev->mt76.ext_eeprom.data + addr;
361+ if (!buf_len || buf_len > MT7996_EXT_EEPROM_BLOCK_SIZE)
362+ buf_len = MT7996_EXT_EEPROM_BLOCK_SIZE;
363+
364+ memcpy(buf, event->eeprom.ext_eeprom.data,
365+ ret_len < buf_len ? ret_len : buf_len);
366+ break;
367+ default:
368+ ret = -EINVAL;
369+ break;
370+ }
371 } else {
372 ret = -EINVAL;
373 }
374@@ -5359,7 +5387,57 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_l
375 return ret;
376 }
377
378-int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
379+int
380+mt7996_mcu_write_ext_eeprom(struct mt7996_dev *dev, u32 offset,
381+ u32 data_len, u8 *write_buf)
382+{
383+ struct mt7996_mcu_eeprom_access req = {
384+ .info.tag = cpu_to_le16(UNI_EXT_EEPROM_ACCESS),
385+ .info.len = cpu_to_le16(sizeof(req) - 4 +
386+ MT7996_EXT_EEPROM_BLOCK_SIZE),
387+ };
388+ u32 block_num, block_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
389+ u8 *buf = write_buf;
390+ int i, ret = -EINVAL;
391+ int msg_len = sizeof(req) + block_size;
392+
393+ if (!mt7996_has_ext_eeprom(dev))
394+ return ret;
395+
396+ if (!buf)
397+ buf = (u8 *)dev->mt76.eeprom.data + offset;
398+
399+ block_num = DIV_ROUND_UP(data_len, block_size);
400+ for (i = 0; i < block_num; i++) {
401+ struct sk_buff *skb;
402+ u32 buf_len = block_size;
403+ u32 block_offs = i * block_size;
404+
405+ if (block_offs + block_size > data_len)
406+ buf_len = data_len % block_size;
407+
408+ req.info.addr = cpu_to_le32(offset + block_offs);
409+ req.eeprom.ext_eeprom.data_len = cpu_to_le32(buf_len);
410+
411+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, msg_len);
412+ if (!skb)
413+ return -ENOMEM;
414+
415+ skb_put_data(skb, &req, sizeof(req));
416+ skb_put_data(skb, buf, buf_len);
417+
418+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
419+ MCU_WM_UNI_CMD(EXT_EEPROM_CTRL), false);
420+ if (ret)
421+ return ret;
422+
423+ buf += buf_len;
424+ }
425+
426+ return 0;
427+}
428+
429+int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num)
430 {
431 struct {
432 u8 _rsv[4];
433diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer1f55fcf2024-10-17 14:52:33 +0800434index 33ba377..f405b0c 100644
developerd0c89452024-10-11 16:53:27 +0800435--- a/mt7996/mcu.h
436+++ b/mt7996/mcu.h
437@@ -161,7 +161,7 @@ struct mt7996_mcu_background_chain_ctrl {
438 u8 rsv[2];
439 } __packed;
440
441-struct mt7996_mcu_eeprom {
442+struct mt7996_mcu_eeprom_update {
443 u8 _rsv[4];
444
445 __le16 tag;
446@@ -171,6 +171,14 @@ struct mt7996_mcu_eeprom {
447 __le16 buf_len;
448 } __packed;
449
450+union eeprom_data {
451+ struct {
452+ __le32 data_len;
453+ DECLARE_FLEX_ARRAY(u8, data);
454+ } ext_eeprom;
455+ DECLARE_FLEX_ARRAY(u8, efuse);
456+} __packed;
457+
458 struct mt7996_mcu_eeprom_info {
459 u8 _rsv[4];
460
461@@ -178,7 +186,26 @@ struct mt7996_mcu_eeprom_info {
462 __le16 len;
463 __le32 addr;
464 __le32 valid;
465- u8 data[MT7996_EEPROM_BLOCK_SIZE];
466+} __packed;
467+
468+struct mt7996_mcu_eeprom_access {
469+ struct mt7996_mcu_eeprom_info info;
470+ union eeprom_data eeprom;
471+} __packed;
472+
473+struct mt7996_mcu_eeprom_access_event {
474+ u8 _rsv[4];
475+
476+ __le16 tag;
477+ __le16 len;
478+ __le32 version;
479+ __le32 addr;
480+ __le32 valid;
481+ __le32 size;
482+ __le32 magic_no;
483+ __le32 type;
484+ __le32 rsv[4];
485+ union eeprom_data eeprom;
486 } __packed;
487
488 struct mt7996_mcu_phy_rx_info {
489@@ -1091,6 +1118,10 @@ enum {
490 UNI_EFUSE_PATCH,
491 };
492
493+enum {
494+ UNI_EXT_EEPROM_ACCESS = 1,
495+};
496+
497 enum {
498 UNI_VOW_DRR_CTRL,
499 UNI_VOW_FEATURE_CTRL,
500diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer1f55fcf2024-10-17 14:52:33 +0800501index b841cc2..e65d2a6 100644
developerd0c89452024-10-11 16:53:27 +0800502--- a/mt7996/mt7996.h
503+++ b/mt7996/mt7996.h
504@@ -74,7 +74,8 @@
505 #define MT7992_EEPROM_DEFAULT_24 "mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
506
507 #define MT7996_EEPROM_SIZE 7680
508-#define MT7996_EEPROM_BLOCK_SIZE 16
509+#define MT7996_EEPROM_BLOCK_SIZE 16
510+#define MT7996_EXT_EEPROM_BLOCK_SIZE 1024
511 #define MT7996_TOKEN_SIZE 16384
512 #define MT7996_HW_TOKEN_SIZE 8192
513 #define MT7996_SW_TOKEN_SIZE 15360
514@@ -171,6 +172,14 @@ enum mt7996_fem_type {
515 MT7996_FEM_MIX,
516 };
517
518+enum mt7996_eeprom_mode {
519+ DEFAULT_BIN_MODE,
520+ EFUSE_MODE,
521+ FLASH_MODE,
522+ BIN_FILE_MODE,
523+ EXT_EEPROM_MODE,
524+};
525+
526 enum mt7996_coredump_state {
527 MT7996_COREDUMP_IDLE = 0,
528 MT7996_COREDUMP_MANUAL_WA,
529@@ -973,6 +982,18 @@ mt7996_has_background_radar(struct mt7996_dev *dev)
530 return true;
531 }
532
533+static inline bool
534+mt7996_has_ext_eeprom(struct mt7996_dev *dev)
535+{
536+ switch (mt76_chip(&dev->mt76)) {
537+ case 0x7990:
538+ return false;
539+ case 0x7992:
540+ default:
541+ return true;
542+ }
543+}
544+
545 static inline struct mt7996_phy *
546 mt7996_band_phy(struct ieee80211_hw *hw, enum nl80211_band band)
547 {
548@@ -1154,8 +1175,11 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
549 struct mt7996_link_sta *mlink, void *data,
550 u32 field);
551 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
552-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
553-int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
554+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
555+ enum mt7996_eeprom_mode mode);
556+int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num);
557+int mt7996_mcu_write_ext_eeprom(struct mt7996_dev *dev, u32 offset,
558+ u32 data_len, u8 *write_buf);
559 int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
560 int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
561 int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);
562diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
developer1f55fcf2024-10-17 14:52:33 +0800563index 5338d0b..4996774 100644
developerd0c89452024-10-11 16:53:27 +0800564--- a/mt7996/mtk_debugfs.c
565+++ b/mt7996/mtk_debugfs.c
566@@ -2829,6 +2829,9 @@ static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
567 case BIN_FILE_MODE:
568 seq_printf(s, " bin file mode\n filename = %s\n", dev->mt76.bin_file_name);
569 break;
570+ case EXT_EEPROM_MODE:
571+ seq_printf(s, " external eeprom mode\n");
572+ break;
573 default:
574 break;
575 }
576diff --git a/mt7996/testmode.c b/mt7996/testmode.c
developer1f55fcf2024-10-17 14:52:33 +0800577index 1674e12..b369263 100644
developerd0c89452024-10-11 16:53:27 +0800578--- a/mt7996/testmode.c
579+++ b/mt7996/testmode.c
580@@ -2138,37 +2138,43 @@ mt7996_tm_write_back_to_efuse(struct mt7996_dev *dev)
581 {
582 struct mt7996_mcu_eeprom_info req = {
583 .tag = cpu_to_le16(UNI_EFUSE_ACCESS),
584- .len = cpu_to_le16(sizeof(req) - 4),
585+ .len = cpu_to_le16(sizeof(req) - 4 +
586+ MT76_TM_EEPROM_BLOCK_SIZE),
587 };
588 u8 read_buf[MT76_TM_EEPROM_BLOCK_SIZE], *eeprom = dev->mt76.eeprom.data;
589+ int msg_len = sizeof(req) + MT76_TM_EEPROM_BLOCK_SIZE;
590 int i, ret = -EINVAL;
591
592 /* prevent from damaging chip id in efuse */
593 if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
594- goto out;
595+ return ret;
596
597 for (i = 0; i < MT7996_EEPROM_SIZE; i += MT76_TM_EEPROM_BLOCK_SIZE) {
598- req.addr = cpu_to_le32(i);
599- memcpy(req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
600+ struct sk_buff *skb;
601
602- ret = mt7996_mcu_get_eeprom(dev, i, read_buf, sizeof(read_buf));
603- if (ret) {
604- if (ret != -EINVAL)
605- return ret;
606-
607- memset(read_buf, 0, MT76_TM_EEPROM_BLOCK_SIZE);
608- }
609+ memset(read_buf, 0, MT76_TM_EEPROM_BLOCK_SIZE);
610+ ret = mt7996_mcu_get_eeprom(dev, i, read_buf, sizeof(read_buf),
611+ EFUSE_MODE);
612+ if (ret && ret != -EINVAL)
613+ return ret;
614
615- if (!memcmp(req.data, read_buf, MT76_TM_EEPROM_BLOCK_SIZE))
616+ if (!memcmp(eeprom + i, read_buf, MT76_TM_EEPROM_BLOCK_SIZE))
617 continue;
618
619- ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
620- &req, sizeof(req), true);
621+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, msg_len);
622+ if (!skb)
623+ return -ENOMEM;
624+
625+ req.addr = cpu_to_le32(i);
626+ skb_put_data(skb, &req, sizeof(req));
627+ skb_put_data(skb, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
628+
629+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
630+ MCU_WM_UNI_CMD(EFUSE_CTRL), true);
631 if (ret)
632 return ret;
633 }
634
635-out:
636 return ret;
637 }
638
639@@ -2193,6 +2199,9 @@ mt7996_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
640 case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
641 ret = mt7996_tm_write_back_to_efuse(dev);
642 break;
643+ case MT76_TM_EEPROM_ACTION_WRITE_TO_EXT_EEPROM:
644+ ret = mt7996_mcu_write_ext_eeprom(dev, 0, MT7996_EEPROM_SIZE, NULL);
645+ break;
646 default:
647 break;
648 }
649diff --git a/testmode.h b/testmode.h
developer1f55fcf2024-10-17 14:52:33 +0800650index 44f9984..8e751bb 100644
developerd0c89452024-10-11 16:53:27 +0800651--- a/testmode.h
652+++ b/testmode.h
653@@ -281,11 +281,13 @@ enum mt76_testmode_tx_mode {
654 * eeprom data block
655 * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
656 * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
657+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EXT_EEPROM: write eeprom data back to external eeprom
658 */
659 enum mt76_testmode_eeprom_action {
660 MT76_TM_EEPROM_ACTION_UPDATE_DATA,
661 MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
662 MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
663+ MT76_TM_EEPROM_ACTION_WRITE_TO_EXT_EEPROM,
664
665 /* keep last */
666 NUM_MT76_TM_EEPROM_ACTION,
667--
6682.45.2
669