blob: 6dd4113d5daf831df8bde5967f800f4b60ba663f [file] [log] [blame]
developer22c7ab62022-01-24 11:13:32 +08001#define _GNU_SOURCE
2#include <fcntl.h>
3#include <sys/mman.h>
4#include <sys/stat.h>
5#include <sys/wait.h>
6
7#include "atenl.h"
8
developer8e1f5142023-03-31 17:43:25 +08009#define EEPROM_PART_SIZE 0xFF000
developer2bf395f2022-01-26 20:50:22 +080010char *eeprom_file;
developer22c7ab62022-01-24 11:13:32 +080011
developer0296d8b2022-11-01 11:15:32 +080012static int
13atenl_create_file(struct atenl *an, bool flash_mode)
developer22c7ab62022-01-24 11:13:32 +080014{
developer0296d8b2022-11-01 11:15:32 +080015 char fname[64], buf[1024];
16 ssize_t w, len, max_len, total_len = 0;
17 int fd_ori, fd, ret;
developer22c7ab62022-01-24 11:13:32 +080018
developer0296d8b2022-11-01 11:15:32 +080019 /* reserve space for pre-cal data in flash mode */
20 if (flash_mode) {
developer1042c082023-10-27 19:57:13 +080021 atenl_dbg("%s: init eeprom with flash / binfile mode\n", __func__);
developer0296d8b2022-11-01 11:15:32 +080022 max_len = EEPROM_PART_SIZE;
23 } else {
developer1042c082023-10-27 19:57:13 +080024 atenl_dbg("%s: init eeprom with efuse / default bin mode\n", __func__);
developerbb73fa22022-12-28 22:40:23 +080025 max_len = 0x1e00;
developer22c7ab62022-01-24 11:13:32 +080026 }
developer22c7ab62022-01-24 11:13:32 +080027
developer0296d8b2022-11-01 11:15:32 +080028 snprintf(fname, sizeof(fname),
29 "/sys/kernel/debug/ieee80211/phy%d/mt76/eeprom",
developer86045992024-06-03 16:24:42 +080030 an->main_phy_idx);
developer0296d8b2022-11-01 11:15:32 +080031 fd_ori = open(fname, O_RDONLY);
32 if (fd_ori < 0)
developer22c7ab62022-01-24 11:13:32 +080033 return -1;
developer22c7ab62022-01-24 11:13:32 +080034
developer2bf395f2022-01-26 20:50:22 +080035 fd = open(eeprom_file, O_RDWR | O_CREAT | O_EXCL, 00644);
developer22c7ab62022-01-24 11:13:32 +080036 if (fd < 0)
37 goto out;
38
developer0296d8b2022-11-01 11:15:32 +080039 while ((len = read(fd_ori, buf, sizeof(buf))) > 0) {
developer22c7ab62022-01-24 11:13:32 +080040retry:
41 w = write(fd, buf, len);
developerf30d4472022-05-30 16:40:23 +080042 if (w > 0) {
developer0296d8b2022-11-01 11:15:32 +080043 total_len += len;
developer22c7ab62022-01-24 11:13:32 +080044 continue;
developerf30d4472022-05-30 16:40:23 +080045 }
developer22c7ab62022-01-24 11:13:32 +080046
47 if (errno == EINTR)
48 goto retry;
49
50 perror("write");
developer2bf395f2022-01-26 20:50:22 +080051 unlink(eeprom_file);
developer22c7ab62022-01-24 11:13:32 +080052 close(fd);
53 fd = -1;
54 goto out;
55 }
56
developer0296d8b2022-11-01 11:15:32 +080057 /* reserve space for pre-cal data in flash mode */
58 len = sizeof(buf);
59 memset(buf, 0, len);
60 while (total_len < max_len) {
developer22c7ab62022-01-24 11:13:32 +080061 w = write(fd, buf, len);
developer22c7ab62022-01-24 11:13:32 +080062
developer0296d8b2022-11-01 11:15:32 +080063 if (w > 0) {
64 total_len += len;
65 continue;
66 }
developer22c7ab62022-01-24 11:13:32 +080067
developer0296d8b2022-11-01 11:15:32 +080068 if (errno != EINTR) {
69 perror("write");
70 unlink(eeprom_file);
71 close(fd);
72 fd = -1;
73 goto out;
74 }
developer22c7ab62022-01-24 11:13:32 +080075 }
76
developer0296d8b2022-11-01 11:15:32 +080077
developer22c7ab62022-01-24 11:13:32 +080078 ret = lseek(fd, 0, SEEK_SET);
79 if (ret) {
80 close(fd_ori);
81 close(fd);
82 return ret;
83 }
84
85out:
86 close(fd_ori);
87 return fd;
88}
89
90static bool
91atenl_eeprom_file_exists(void)
92{
93 struct stat st;
94
developer2bf395f2022-01-26 20:50:22 +080095 return stat(eeprom_file, &st) == 0;
developer22c7ab62022-01-24 11:13:32 +080096}
97
98static int
99atenl_eeprom_init_file(struct atenl *an, bool flash_mode)
100{
101 int fd;
102
developer0296d8b2022-11-01 11:15:32 +0800103 if (!atenl_eeprom_file_exists())
104 return atenl_create_file(an, flash_mode);
developer22c7ab62022-01-24 11:13:32 +0800105
developer2bf395f2022-01-26 20:50:22 +0800106 fd = open(eeprom_file, O_RDWR);
developer22c7ab62022-01-24 11:13:32 +0800107 if (fd < 0)
108 perror("open");
109
developer22c7ab62022-01-24 11:13:32 +0800110 return fd;
111}
112
113static void
developerf30d4472022-05-30 16:40:23 +0800114atenl_eeprom_init_chip_id(struct atenl *an)
115{
116 an->chip_id = *(u16 *)an->eeprom_data;
117
118 if (is_mt7915(an)) {
119 an->adie_id = 0x7975;
developerae49e8a2023-10-31 16:53:21 +0800120 } else if (is_mt7916(an) || is_mt7981(an)) {
developerf30d4472022-05-30 16:40:23 +0800121 an->adie_id = 0x7976;
122 } else if (is_mt7986(an)) {
123 bool is_7975 = false;
124 u32 val;
125 u8 sub_id;
126
127 atenl_reg_read(an, 0x18050000, &val);
128
129 switch (val & 0xf) {
130 case MT7975_ONE_ADIE_SINGLE_BAND:
131 is_7975 = true;
132 /* fallthrough */
133 case MT7976_ONE_ADIE_SINGLE_BAND:
134 sub_id = 0xa;
135 break;
136 case MT7976_ONE_ADIE_DBDC:
137 sub_id = 0x7;
138 break;
139 case MT7975_DUAL_ADIE_DBDC:
140 is_7975 = true;
141 /* fallthrough */
142 case MT7976_DUAL_ADIE_DBDC:
143 default:
144 sub_id = 0xf;
145 break;
146 }
147
148 an->sub_chip_id = sub_id;
149 an->adie_id = is_7975 ? 0x7975 : 0x7976;
developerbb73fa22022-12-28 22:40:23 +0800150 } else if (is_mt7996(an)) {
151 /* TODO: parse info if required */
developere2e8ccc2023-10-13 18:41:57 +0800152 } else if (is_mt7992(an)) {
153 /* TODO: parse info if required */
developer9efec3f2024-09-23 13:43:05 +0800154 } else if (is_mt7990(an)) {
155 /* TODO: parse info if required */
developerf30d4472022-05-30 16:40:23 +0800156 }
157}
158
159static void
developer22c7ab62022-01-24 11:13:32 +0800160atenl_eeprom_init_max_size(struct atenl *an)
161{
162 switch (an->chip_id) {
developer9efec3f2024-09-23 13:43:05 +0800163 case MT7915_DEVICE_ID:
developer22c7ab62022-01-24 11:13:32 +0800164 an->eeprom_size = 3584;
developer454c4652022-08-31 20:39:29 +0800165 an->eeprom_prek_offs = 0x62;
developer22c7ab62022-01-24 11:13:32 +0800166 break;
developer9efec3f2024-09-23 13:43:05 +0800167 case MT7916_EEPROM_CHIP_ID:
168 case MT7916_DEVICE_ID:
169 case MT7981_DEVICE_ID:
170 case MT7986_DEVICE_ID:
developer22c7ab62022-01-24 11:13:32 +0800171 an->eeprom_size = 4096;
developer454c4652022-08-31 20:39:29 +0800172 an->eeprom_prek_offs = 0x19a;
developer22c7ab62022-01-24 11:13:32 +0800173 break;
developer9efec3f2024-09-23 13:43:05 +0800174 case MT7996_DEVICE_ID:
175 case MT7992_DEVICE_ID:
176 case MT7990_DEVICE_ID:
developerbb73fa22022-12-28 22:40:23 +0800177 an->eeprom_size = 7680;
178 an->eeprom_prek_offs = 0x1a5;
developer22c7ab62022-01-24 11:13:32 +0800179 default:
180 break;
181 }
182}
183
184static void
185atenl_eeprom_init_band_cap(struct atenl *an)
186{
developerbb73fa22022-12-28 22:40:23 +0800187#define EAGLE_BAND_SEL(index) MT_EE_WIFI_EAGLE_CONF##index##_BAND_SEL
developer22c7ab62022-01-24 11:13:32 +0800188 u8 *eeprom = an->eeprom_data;
189
190 if (is_mt7915(an)) {
191 u8 val = eeprom[MT_EE_WIFI_CONF];
192 u8 band_sel = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
193 struct atenl_band *anb = &an->anb[0];
194
195 /* MT7915A */
196 if (band_sel == MT_EE_BAND_SEL_DEFAULT) {
197 anb->valid = true;
198 anb->cap = BAND_TYPE_2G_5G;
199 return;
200 }
201
202 /* MT7915D */
203 if (band_sel == MT_EE_BAND_SEL_2GHZ) {
204 anb->valid = true;
205 anb->cap = BAND_TYPE_2G;
206 }
207
208 val = eeprom[MT_EE_WIFI_CONF + 1];
209 band_sel = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
210 anb++;
211
212 if (band_sel == MT_EE_BAND_SEL_5GHZ) {
213 anb->valid = true;
214 anb->cap = BAND_TYPE_5G;
215 }
developerae49e8a2023-10-31 16:53:21 +0800216 } else if (is_mt7916(an) || is_mt7981(an) || is_mt7986(an)) {
developer22c7ab62022-01-24 11:13:32 +0800217 struct atenl_band *anb;
218 u8 val, band_sel;
219 int i;
220
221 for (i = 0; i < 2; i++) {
222 val = eeprom[MT_EE_WIFI_CONF + i];
223 band_sel = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
224 anb = &an->anb[i];
225
226 anb->valid = true;
227 switch (band_sel) {
228 case MT_EE_BAND_SEL_2G:
229 anb->cap = BAND_TYPE_2G;
230 break;
231 case MT_EE_BAND_SEL_5G:
232 anb->cap = BAND_TYPE_5G;
233 break;
234 case MT_EE_BAND_SEL_6G:
235 anb->cap = BAND_TYPE_6G;
236 break;
237 case MT_EE_BAND_SEL_5G_6G:
238 anb->cap = BAND_TYPE_5G_6G;
239 break;
240 default:
241 break;
242 }
243 }
developerbb73fa22022-12-28 22:40:23 +0800244 } else if (is_mt7996(an)) {
245 struct atenl_band *anb;
246 u8 val, band_sel;
247 u8 band_sel_mask[3] = {EAGLE_BAND_SEL(0), EAGLE_BAND_SEL(1),
248 EAGLE_BAND_SEL(2)};
249 int i;
250
251 for (i = 0; i < 3; i++) {
252 val = eeprom[MT_EE_WIFI_CONF + i];
253 band_sel = FIELD_GET(band_sel_mask[i], val);
254 anb = &an->anb[i];
255
256 anb->valid = true;
257 switch (band_sel) {
258 case MT_EE_EAGLE_BAND_SEL_2GHZ:
259 anb->cap = BAND_TYPE_2G;
260 break;
developer9efec3f2024-09-23 13:43:05 +0800261 case MT_EE_EAGLE_BAND_SEL_5GHZ_LOW:
262 case MT_EE_EAGLE_BAND_SEL_5GHZ_HIGH:
developerbb73fa22022-12-28 22:40:23 +0800263 case MT_EE_EAGLE_BAND_SEL_5GHZ:
264 anb->cap = BAND_TYPE_5G;
265 break;
developer9efec3f2024-09-23 13:43:05 +0800266 case MT_EE_EAGLE_BAND_SEL_6GHZ_LOW:
267 case MT_EE_EAGLE_BAND_SEL_6GHZ_HIGH:
developerbb73fa22022-12-28 22:40:23 +0800268 case MT_EE_EAGLE_BAND_SEL_6GHZ:
269 anb->cap = BAND_TYPE_6G;
270 break;
developerbb73fa22022-12-28 22:40:23 +0800271 default:
272 break;
273 }
274 }
developer9efec3f2024-09-23 13:43:05 +0800275 } else if (is_mt7992(an) || is_mt7990(an)) {
developere2e8ccc2023-10-13 18:41:57 +0800276 struct atenl_band *anb;
277 u8 val, band_sel;
278 u8 band_sel_mask[2] = {EAGLE_BAND_SEL(0), EAGLE_BAND_SEL(1)};
279 int i;
280
281 for (i = 0; i < 2; i++) {
282 val = eeprom[MT_EE_WIFI_CONF + i];
283 band_sel = FIELD_GET(band_sel_mask[i], val);
284 anb = &an->anb[i];
285
286 anb->valid = true;
287 switch (band_sel) {
288 case MT_EE_EAGLE_BAND_SEL_2GHZ:
289 anb->cap = BAND_TYPE_2G;
290 break;
developer9efec3f2024-09-23 13:43:05 +0800291 case MT_EE_EAGLE_BAND_SEL_5GHZ_LOW:
292 case MT_EE_EAGLE_BAND_SEL_5GHZ_HIGH:
developere2e8ccc2023-10-13 18:41:57 +0800293 case MT_EE_EAGLE_BAND_SEL_5GHZ:
294 anb->cap = BAND_TYPE_5G;
295 break;
developer9efec3f2024-09-23 13:43:05 +0800296 case MT_EE_EAGLE_BAND_SEL_6GHZ_LOW:
297 case MT_EE_EAGLE_BAND_SEL_6GHZ_HIGH:
developere2e8ccc2023-10-13 18:41:57 +0800298 case MT_EE_EAGLE_BAND_SEL_6GHZ:
299 anb->cap = BAND_TYPE_6G;
300 break;
developere2e8ccc2023-10-13 18:41:57 +0800301 default:
302 break;
303 }
304 }
developer22c7ab62022-01-24 11:13:32 +0800305 }
306}
307
308static void
309atenl_eeprom_init_antenna_cap(struct atenl *an)
310{
developere2e8ccc2023-10-13 18:41:57 +0800311 switch (an->chip_id) {
developer9efec3f2024-09-23 13:43:05 +0800312 case MT7915_DEVICE_ID:
developer22c7ab62022-01-24 11:13:32 +0800313 if (an->anb[0].cap == BAND_TYPE_2G_5G)
314 an->anb[0].chainmask = 0xf;
315 else {
316 an->anb[0].chainmask = 0x3;
317 an->anb[1].chainmask = 0xc;
318 }
developere2e8ccc2023-10-13 18:41:57 +0800319 break;
developer9efec3f2024-09-23 13:43:05 +0800320 case MT7916_EEPROM_CHIP_ID:
321 case MT7916_DEVICE_ID:
developer22c7ab62022-01-24 11:13:32 +0800322 an->anb[0].chainmask = 0x3;
323 an->anb[1].chainmask = 0x3;
developere2e8ccc2023-10-13 18:41:57 +0800324 break;
developer9efec3f2024-09-23 13:43:05 +0800325 case MT7981_DEVICE_ID:
developerae49e8a2023-10-31 16:53:21 +0800326 an->anb[0].chainmask = 0x3;
327 an->anb[1].chainmask = 0x7;
328 break;
developer9efec3f2024-09-23 13:43:05 +0800329 case MT7986_DEVICE_ID:
developer22c7ab62022-01-24 11:13:32 +0800330 an->anb[0].chainmask = 0xf;
331 an->anb[1].chainmask = 0xf;
developere2e8ccc2023-10-13 18:41:57 +0800332 break;
developer9efec3f2024-09-23 13:43:05 +0800333 case MT7996_DEVICE_ID:
334 /* TODO: handle 4T5R */
developerbb73fa22022-12-28 22:40:23 +0800335 an->anb[0].chainmask = 0xf;
336 an->anb[1].chainmask = 0xf;
337 an->anb[2].chainmask = 0xf;
developere2e8ccc2023-10-13 18:41:57 +0800338 break;
developer9efec3f2024-09-23 13:43:05 +0800339 case MT7992_DEVICE_ID:
340 /* TODO: handle BE7200 2i5i 5T5R */
developere2e8ccc2023-10-13 18:41:57 +0800341 an->anb[0].chainmask = 0xf;
342 an->anb[1].chainmask = 0xf;
343 break;
developer9efec3f2024-09-23 13:43:05 +0800344 case MT7990_DEVICE_ID:
345 an->anb[0].chainmask = 0x3;
346 an->anb[1].chainmask = 0x7;
347 break;
developere2e8ccc2023-10-13 18:41:57 +0800348 default:
349 break;
developer22c7ab62022-01-24 11:13:32 +0800350 }
351}
352
353int atenl_eeprom_init(struct atenl *an, u8 phy_idx)
354{
355 bool flash_mode;
356 int eeprom_fd;
developer2bf395f2022-01-26 20:50:22 +0800357 char buf[30];
developer22c7ab62022-01-24 11:13:32 +0800358
359 set_band_val(an, 0, phy_idx, phy_idx);
developer22c7ab62022-01-24 11:13:32 +0800360 atenl_nl_check_mtd(an);
361 flash_mode = an->mtd_part != NULL;
362
developerbb73fa22022-12-28 22:40:23 +0800363 // Get the first main phy index for this chip
developer86045992024-06-03 16:24:42 +0800364 an->main_phy_idx = phy_idx - an->band_idx;
365 snprintf(buf, sizeof(buf), "/tmp/atenl-eeprom-phy%u", an->main_phy_idx);
developer454c4652022-08-31 20:39:29 +0800366 eeprom_file = strdup(buf);
367
developer22c7ab62022-01-24 11:13:32 +0800368 eeprom_fd = atenl_eeprom_init_file(an, flash_mode);
369 if (eeprom_fd < 0)
370 return -1;
371
372 an->eeprom_data = mmap(NULL, EEPROM_PART_SIZE, PROT_READ | PROT_WRITE,
developer454c4652022-08-31 20:39:29 +0800373 MAP_SHARED, eeprom_fd, 0);
developer22c7ab62022-01-24 11:13:32 +0800374 if (!an->eeprom_data) {
375 perror("mmap");
376 close(eeprom_fd);
377 return -1;
378 }
379
380 an->eeprom_fd = eeprom_fd;
developerf30d4472022-05-30 16:40:23 +0800381 atenl_eeprom_init_chip_id(an);
developer22c7ab62022-01-24 11:13:32 +0800382 atenl_eeprom_init_max_size(an);
383 atenl_eeprom_init_band_cap(an);
384 atenl_eeprom_init_antenna_cap(an);
385
386 if (get_band_val(an, 1, valid))
387 set_band_val(an, 1, phy_idx, phy_idx + 1);
388
developer86869102023-05-15 13:52:35 +0800389 if (get_band_val(an, 2, valid))
390 set_band_val(an, 2, phy_idx, phy_idx + 2);
391
developer22c7ab62022-01-24 11:13:32 +0800392 return 0;
393}
394
395void atenl_eeprom_close(struct atenl *an)
396{
397 msync(an->eeprom_data, EEPROM_PART_SIZE, MS_SYNC);
398 munmap(an->eeprom_data, EEPROM_PART_SIZE);
399 close(an->eeprom_fd);
400
developerf30d4472022-05-30 16:40:23 +0800401 if (!an->cmd_mode) {
developer2bf395f2022-01-26 20:50:22 +0800402 if (remove(eeprom_file))
developer22c7ab62022-01-24 11:13:32 +0800403 perror("remove");
developer2bf395f2022-01-26 20:50:22 +0800404 }
405
406 free(eeprom_file);
developer22c7ab62022-01-24 11:13:32 +0800407}
408
developer454c4652022-08-31 20:39:29 +0800409int atenl_eeprom_update_precal(struct atenl *an, int write_offs, int size)
410{
411 u32 offs = an->eeprom_prek_offs;
412 u8 cal_indicator, *eeprom, *pre_cal;
413
414 if (!an->cal && !an->cal_info)
415 return 0;
416
417 eeprom = an->eeprom_data;
418 pre_cal = eeprom + an->eeprom_size;
419 cal_indicator = an->cal_info[4];
420
421 memcpy(eeprom + offs, &cal_indicator, sizeof(u8));
422 memcpy(pre_cal, an->cal_info, PRE_CAL_INFO);
423 pre_cal += (PRE_CAL_INFO + write_offs);
424
425 if (an->cal)
426 memcpy(pre_cal, an->cal, size);
427 else
428 memset(pre_cal, 0, size);
429
430 return 0;
431}
432
developer22c7ab62022-01-24 11:13:32 +0800433int atenl_eeprom_write_mtd(struct atenl *an)
434{
developer091f3342023-11-10 11:26:03 +0800435#define TMP_FILE "/tmp/tmp_eeprom.bin"
developer22c7ab62022-01-24 11:13:32 +0800436 pid_t pid;
developer091f3342023-11-10 11:26:03 +0800437 u32 size = an->eeprom_size;
438 u32 *precal_info = an->eeprom_data + an->eeprom_size;
439 u32 precal_size = precal_info[0] + precal_info[1];
440 char cmd[100];
developer22c7ab62022-01-24 11:13:32 +0800441
developer1042c082023-10-27 19:57:13 +0800442 if (an->mtd_part == NULL || !(~an->mtd_offset))
developer22c7ab62022-01-24 11:13:32 +0800443 return 0;
444
developer091f3342023-11-10 11:26:03 +0800445 if (precal_size)
446 size += PRE_CAL_INFO + precal_size;
447
448 sprintf(cmd, "dd if=%s of=%s bs=1 count=%d", eeprom_file, TMP_FILE, size);
449 system(cmd);
450
451 sprintf(cmd, "mtd -p %d write %s %s", an->mtd_offset, TMP_FILE, an->mtd_part);
452 system(cmd);
developer22c7ab62022-01-24 11:13:32 +0800453
developer091f3342023-11-10 11:26:03 +0800454 sprintf(cmd, "rm %s", TMP_FILE);
455 system(cmd);
developer22c7ab62022-01-24 11:13:32 +0800456
457 return 0;
458}
459
developerf30d4472022-05-30 16:40:23 +0800460/* Directly read values from driver's eeprom.
developer22c7ab62022-01-24 11:13:32 +0800461 * It's usally used to get calibrated data from driver.
462 */
463int atenl_eeprom_read_from_driver(struct atenl *an, u32 offset, int len)
464{
465 u8 *eeprom_data = an->eeprom_data + offset;
466 char fname[64], buf[1024];
467 int fd_ori, ret;
468 ssize_t rd;
469
470 snprintf(fname, sizeof(fname),
471 "/sys/kernel/debug/ieee80211/phy%d/mt76/eeprom",
developer86045992024-06-03 16:24:42 +0800472 an->main_phy_idx);
developer22c7ab62022-01-24 11:13:32 +0800473 fd_ori = open(fname, O_RDONLY);
474 if (fd_ori < 0)
475 return -1;
476
477 ret = lseek(fd_ori, offset, SEEK_SET);
478 if (ret < 0)
479 goto out;
480
481 while ((rd = read(fd_ori, buf, sizeof(buf))) > 0 && len) {
482 if (len < rd) {
483 memcpy(eeprom_data, buf, len);
484 break;
485 } else {
486 memcpy(eeprom_data, buf, rd);
487 eeprom_data += rd;
488 len -= rd;
489 }
490 }
491
492 ret = 0;
493out:
494 close(fd_ori);
495 return ret;
496}
497
developerdcf5eb32024-09-03 17:06:32 +0800498/* Update all eeprom values to driver before writing efuse or ext eeprom */
developer22c7ab62022-01-24 11:13:32 +0800499static void
500atenl_eeprom_sync_to_driver(struct atenl *an)
501{
502 int i;
503
developer2bf395f2022-01-26 20:50:22 +0800504 for (i = 0; i < an->eeprom_size; i += 16)
developer22c7ab62022-01-24 11:13:32 +0800505 atenl_nl_write_eeprom(an, i, &an->eeprom_data[i], 16);
506}
507
508void atenl_eeprom_cmd_handler(struct atenl *an, u8 phy_idx, char *cmd)
509{
developer22c7ab62022-01-24 11:13:32 +0800510 an->cmd_mode = true;
511
512 atenl_eeprom_init(an, phy_idx);
developer22c7ab62022-01-24 11:13:32 +0800513
514 if (!strncmp(cmd, "sync eeprom all", 15)) {
515 atenl_eeprom_write_mtd(an);
516 } else if (!strncmp(cmd, "eeprom", 6)) {
517 char *s = strchr(cmd, ' ');
518
519 if (!s) {
developerf30d4472022-05-30 16:40:23 +0800520 atenl_err("eeprom: please type a correct command\n");
developer22c7ab62022-01-24 11:13:32 +0800521 return;
522 }
523
524 s++;
525 if (!strncmp(s, "reset", 5)) {
developer2bf395f2022-01-26 20:50:22 +0800526 unlink(eeprom_file);
developer22c7ab62022-01-24 11:13:32 +0800527 } else if (!strncmp(s, "file", 4)) {
developer2bf395f2022-01-26 20:50:22 +0800528 atenl_info("%s\n", eeprom_file);
developer1042c082023-10-27 19:57:13 +0800529 if (an->mtd_part != NULL)
530 atenl_info("%s mode\n",
531 ~an->mtd_offset == 0 ? "Binfile" : "Flash");
532 else
533 atenl_info("Efuse / Default bin mode\n");
developer22c7ab62022-01-24 11:13:32 +0800534 } else if (!strncmp(s, "set", 3)) {
535 u32 offset, val;
536
537 s = strchr(s, ' ');
538 if (!s)
539 return;
540 s++;
541
542 if (!sscanf(s, "%x=%x", &offset, &val) ||
543 offset > EEPROM_PART_SIZE)
544 return;
545
546 an->eeprom_data[offset] = val;
547 atenl_info("set offset 0x%x to 0x%x\n", offset, val);
developer48fbcb62022-03-10 14:24:55 +0800548 } else if (!strncmp(s, "update buffermode", 17)) {
developer2bf395f2022-01-26 20:50:22 +0800549 atenl_eeprom_sync_to_driver(an);
developer22c7ab62022-01-24 11:13:32 +0800550 atenl_nl_update_buffer_mode(an);
551 } else if (!strncmp(s, "write", 5)) {
552 s = strchr(s, ' ');
553 if (!s)
554 return;
555 s++;
556
developer48fbcb62022-03-10 14:24:55 +0800557 if (!strncmp(s, "flash", 5)) {
developer22c7ab62022-01-24 11:13:32 +0800558 atenl_eeprom_write_mtd(an);
developere2e8ccc2023-10-13 18:41:57 +0800559 } else if (!strncmp(s, "to efuse", 8)) {
560 atenl_eeprom_sync_to_driver(an);
561 atenl_nl_write_efuse_all(an);
developerdcf5eb32024-09-03 17:06:32 +0800562 } else if (!strncmp(s, "to ext", 6)) {
563 atenl_eeprom_sync_to_driver(an);
564 atenl_nl_write_ext_eeprom_all(an);
developere2e8ccc2023-10-13 18:41:57 +0800565 }
developer22c7ab62022-01-24 11:13:32 +0800566 } else if (!strncmp(s, "read", 4)) {
567 u32 offset;
568
569 s = strchr(s, ' ');
570 if (!s)
571 return;
572 s++;
573
574 if (!sscanf(s, "%x", &offset) ||
575 offset > EEPROM_PART_SIZE)
576 return;
577
578 atenl_info("val = 0x%x (%u)\n", an->eeprom_data[offset],
579 an->eeprom_data[offset]);
developer454c4652022-08-31 20:39:29 +0800580 } else if (!strncmp(s, "precal", 6)) {
581 s = strchr(s, ' ');
582 if (!s)
583 return;
584 s++;
585
586 if (!strncmp(s, "sync group", 10)) {
587 atenl_nl_precal_sync_from_driver(an, PREK_SYNC_GROUP);
588 } else if (!strncmp(s, "sync dpd 2g", 11)) {
589 atenl_nl_precal_sync_from_driver(an, PREK_SYNC_DPD_2G);
590 } else if (!strncmp(s, "sync dpd 5g", 11)) {
591 atenl_nl_precal_sync_from_driver(an, PREK_SYNC_DPD_5G);
592 } else if (!strncmp(s, "sync dpd 6g", 11)) {
593 atenl_nl_precal_sync_from_driver(an, PREK_SYNC_DPD_6G);
594 } else if (!strncmp(s, "group clean", 11)) {
595 atenl_nl_precal_sync_from_driver(an, PREK_CLEAN_GROUP);
596 } else if (!strncmp(s, "dpd clean", 9)) {
597 atenl_nl_precal_sync_from_driver(an, PREK_CLEAN_DPD);
598 } else if (!strncmp(s, "sync", 4)) {
599 atenl_nl_precal_sync_from_driver(an, PREK_SYNC_ALL);
600 }
developer25a27292023-07-21 13:42:14 +0800601 } else if (!strncmp(s, "ibf sync", 8)) {
602 atenl_get_ibf_cal_result(an);
developer48fbcb62022-03-10 14:24:55 +0800603 } else {
developer25a27292023-07-21 13:42:14 +0800604 atenl_err("Unknown eeprom command: %s\n", cmd);
605 }
developer22c7ab62022-01-24 11:13:32 +0800606 } else {
607 atenl_err("Unknown command: %s\n", cmd);
608 }
609}