blob: 838f41e41bd4fd8c82e84f01865562cd52e38a7f [file] [log] [blame]
Yanhong Wang39331e42023-06-15 17:36:48 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 StarFive Technology Co., Ltd.
4 * Author: Yanhong Wang<yanhong.wang@starfivetech.com>
5 */
6
Yanhong Wang39331e42023-06-15 17:36:48 +08007#include <command.h>
8#include <env.h>
9#include <i2c.h>
10#include <init.h>
11#include <u-boot/crc.h>
12#include <linux/delay.h>
13
14#define FORMAT_VERSION 0x2
15#define PCB_VERSION 0xB1
16#define BOM_VERSION 'A'
17/*
18 * BYTES_PER_EEPROM_PAGE: the 24FC04H datasheet says that data can
19 * only be written in page mode, which means 16 bytes at a time:
20 * 16-Byte Page Write Buffer
21 */
22#define BYTES_PER_EEPROM_PAGE 16
23
24/*
25 * EEPROM_WRITE_DELAY_MS: the 24FC04H datasheet says it takes up to
26 * 5ms to complete a given write:
27 * Write Cycle Time (byte or page) ro Page Write Time 5 ms, Maximum
28 */
29#define EEPROM_WRITE_DELAY_MS 5000
30/*
31 * StarFive OUI. Registration Date is 20xx-xx-xx
32 */
33#define STARFIVE_OUI_PREFIX "6C:CF:39:"
34#define STARFIVE_DEFAULT_MAC0 "6C:CF:39:6C:DE:AD"
35#define STARFIVE_DEFAULT_MAC1 "6C:CF:39:6C:DE:AE"
36
37/* Magic number at the first four bytes of EEPROM HATs */
38#define STARFIVE_EEPROM_HATS_SIG "SFVF" /* StarFive VisionFive */
39
40#define STARFIVE_EEPROM_HATS_SIZE_MAX 256 /* Header + Atom1&4(v1) */
41#define STARFIVE_EEPROM_WP_OFFSET 0 /* Read only field */
42#define STARFIVE_EEPROM_ATOM1_PSTR "VF7110A1-2228-D008E000-00000001\0"
43#define STARFIVE_EEPROM_ATOM1_PSTR_SIZE 32
44#define STARFIVE_EEPROM_ATOM1_SN_OFFSET 23
45#define STARFIVE_EEPROM_ATOM1_VSTR "StarFive Technology Co., Ltd.\0\0\0"
46#define STARFIVE_EEPROM_ATOM1_VSTR_SIZE 32
47
48#define MAGIC_NUMBER_BYTES 4
49#define MAC_ADDR_BYTES 6
50#define MAC_ADDR_STRLEN 17
51
52/*
53 * Atom Types
54 * 0x0000 = invalid
55 * 0x0001 = vendor info
56 * 0x0002 = GPIO map
57 * 0x0003 = Linux device tree blob
58 * 0x0004 = manufacturer custom data
59 * 0x0005-0xfffe = reserved for future use
60 * 0xffff = invalid
61 */
62
63#define HATS_ATOM_INVALID 0x0000
64#define HATS_ATOM_VENDOR 0x0001
65#define HATS_ATOM_GPIO 0x0002
66#define HATS_ATOM_DTB 0x0003
67#define HATS_ATOM_CUSTOM 0x0004
68#define HATS_ATOM_INVALID_END 0xffff
69
70struct eeprom_header {
71 char signature[MAGIC_NUMBER_BYTES]; /* ASCII table signature */
72 u8 version; /* EEPROM data format version */
73 /* (0x00 reserved, 0x01 = first version) */
74 u8 reversed; /* 0x00, Reserved field */
75 u16 numatoms; /* total atoms in EEPROM */
76 u32 eeplen; /* total length in bytes of all eeprom data */
77 /* (including this header) */
78};
79
80struct eeprom_atom_header {
81 u16 type;
82 u16 count;
83 u32 dlen;
84};
85
86struct eeprom_atom1_data {
87 u8 uuid[16];
88 u16 pid;
89 u16 pver;
90 u8 vslen;
91 u8 pslen;
92 uchar vstr[STARFIVE_EEPROM_ATOM1_VSTR_SIZE];
93 uchar pstr[STARFIVE_EEPROM_ATOM1_PSTR_SIZE]; /* product SN */
94};
95
96struct starfive_eeprom_atom1 {
97 struct eeprom_atom_header header;
98 struct eeprom_atom1_data data;
99 u16 crc;
100};
101
102struct eeprom_atom4_data {
103 u16 version;
104 u8 pcb_revision; /* PCB version */
105 u8 bom_revision; /* BOM version */
106 u8 mac0_addr[MAC_ADDR_BYTES]; /* Ethernet0 MAC */
107 u8 mac1_addr[MAC_ADDR_BYTES]; /* Ethernet1 MAC */
108 u8 reserved[2];
109};
110
111struct starfive_eeprom_atom4 {
112 struct eeprom_atom_header header;
113 struct eeprom_atom4_data data;
114 u16 crc;
115};
116
117struct starfive_eeprom {
118 struct eeprom_header header;
119 struct starfive_eeprom_atom1 atom1;
120 struct starfive_eeprom_atom4 atom4;
121};
122
123static union {
124 struct starfive_eeprom eeprom;
125 uchar buf[STARFIVE_EEPROM_HATS_SIZE_MAX];
126} pbuf __section(".data");
127
128/* Set to 1 if we've read EEPROM into memory */
129static int has_been_read __section(".data");
130
131static inline int is_match_magic(void)
132{
133 return strncmp(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG,
134 MAGIC_NUMBER_BYTES);
135}
136
137/* Calculate the current CRC */
138static inline u32 calculate_crc16(struct eeprom_atom_header *head)
139{
140 uint len = sizeof(struct eeprom_atom_header) + head->dlen - sizeof(u16);
141
142 return crc16(0, (void *)head, len);
143}
144
145/* This function should be called after each update to the EEPROM structure */
146static inline void update_crc(void)
147{
148 pbuf.eeprom.atom1.crc = calculate_crc16(&pbuf.eeprom.atom1.header);
149 pbuf.eeprom.atom4.crc = calculate_crc16(&pbuf.eeprom.atom4.header);
150}
151
152static void dump_raw_eeprom(void)
153{
154 unsigned int i;
155 u32 len;
156
157 len = sizeof(struct starfive_eeprom);
158 for (i = 0; i < len; i++) {
159 if ((i % 16) == 0)
160 printf("%02X: ", i);
161 printf("%02X ", ((u8 *)pbuf.buf)[i]);
162 if (((i % 16) == 15) || (i == len - 1))
163 printf("\n");
164 }
165}
166
167/**
168 * show_eeprom - display the contents of the EEPROM
169 */
170static void show_eeprom(void)
171{
172 if (has_been_read != 1)
173 return;
174
175 printf("\n--------EEPROM INFO--------\n");
176 printf("Vendor : %s\n", pbuf.eeprom.atom1.data.vstr);
177 printf("Product full SN: %s\n", pbuf.eeprom.atom1.data.pstr);
178 printf("data version: 0x%x\n", pbuf.eeprom.atom4.data.version);
179 if (pbuf.eeprom.atom4.data.version == 2) {
180 printf("PCB revision: 0x%x\n", pbuf.eeprom.atom4.data.pcb_revision);
181 printf("BOM revision: %c\n", pbuf.eeprom.atom4.data.bom_revision);
182 printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
183 pbuf.eeprom.atom4.data.mac0_addr[0], pbuf.eeprom.atom4.data.mac0_addr[1],
184 pbuf.eeprom.atom4.data.mac0_addr[2], pbuf.eeprom.atom4.data.mac0_addr[3],
185 pbuf.eeprom.atom4.data.mac0_addr[4], pbuf.eeprom.atom4.data.mac0_addr[5]);
186 printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
187 pbuf.eeprom.atom4.data.mac1_addr[0], pbuf.eeprom.atom4.data.mac1_addr[1],
188 pbuf.eeprom.atom4.data.mac1_addr[2], pbuf.eeprom.atom4.data.mac1_addr[3],
189 pbuf.eeprom.atom4.data.mac1_addr[4], pbuf.eeprom.atom4.data.mac1_addr[5]);
190 } else {
191 printf("Custom data v%d is not Supported\n", pbuf.eeprom.atom4.data.version);
Heinrich Schuchardtab23ee42023-09-30 14:01:46 +0200192 dump_raw_eeprom();
Yanhong Wang39331e42023-06-15 17:36:48 +0800193 }
194 printf("--------EEPROM INFO--------\n\n");
195}
196
197/**
198 * set_mac_address() - stores a MAC address into the local EEPROM copy
199 *
200 * This function takes a pointer to MAC address string
201 * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number),
202 * stores it in the MAC address field of the EEPROM local copy, and
203 * updates the local copy of the CRC.
204 */
205static void set_mac_address(char *string, int index)
206{
207 u8 i;
208 u8 *mac;
209
210 if (strncasecmp(STARFIVE_OUI_PREFIX, string,
211 strlen(STARFIVE_OUI_PREFIX))) {
212 printf("The MAC address doesn't match StarFive OUI %s\n",
213 STARFIVE_OUI_PREFIX);
214 return;
215 }
216 mac = (index == 0) ? pbuf.eeprom.atom4.data.mac0_addr :
217 pbuf.eeprom.atom4.data.mac1_addr;
218
219 for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) {
220 mac[i] = hextoul(string, &string);
221
222 if (*string == ':')
223 string++;
224 }
225
226 update_crc();
227}
228
229/**
230 * init_local_copy() - initialize the in-memory EEPROM copy
231 *
232 * Initialize the in-memory EEPROM copy with the magic number. Must
233 * be done when preparing to initialize a blank EEPROM, or overwrite
234 * one with a corrupted magic number.
235 */
236static void init_local_copy(void)
237{
238 memset((void *)pbuf.buf, 0, sizeof(struct starfive_eeprom));
239 memcpy(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG,
240 strlen(STARFIVE_EEPROM_HATS_SIG));
241 pbuf.eeprom.header.version = FORMAT_VERSION;
242 pbuf.eeprom.header.numatoms = 2;
243 pbuf.eeprom.header.eeplen = sizeof(struct starfive_eeprom);
244
245 pbuf.eeprom.atom1.header.type = HATS_ATOM_VENDOR;
246 pbuf.eeprom.atom1.header.count = 1;
247 pbuf.eeprom.atom1.header.dlen = sizeof(struct eeprom_atom1_data) + sizeof(u16);
248 pbuf.eeprom.atom1.data.vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE;
249 pbuf.eeprom.atom1.data.pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE;
250 memcpy(pbuf.eeprom.atom1.data.vstr, STARFIVE_EEPROM_ATOM1_VSTR,
251 strlen(STARFIVE_EEPROM_ATOM1_VSTR));
252 memcpy(pbuf.eeprom.atom1.data.pstr, STARFIVE_EEPROM_ATOM1_PSTR,
253 strlen(STARFIVE_EEPROM_ATOM1_PSTR));
254
255 pbuf.eeprom.atom4.header.type = HATS_ATOM_CUSTOM;
256 pbuf.eeprom.atom4.header.count = 2;
257 pbuf.eeprom.atom4.header.dlen = sizeof(struct eeprom_atom4_data) + sizeof(u16);
258 pbuf.eeprom.atom4.data.version = FORMAT_VERSION;
259 pbuf.eeprom.atom4.data.pcb_revision = PCB_VERSION;
260 pbuf.eeprom.atom4.data.bom_revision = BOM_VERSION;
261 set_mac_address(STARFIVE_DEFAULT_MAC0, 0);
262 set_mac_address(STARFIVE_DEFAULT_MAC1, 1);
263}
264
265/**
266 * prog_eeprom() - write the EEPROM from memory
267 */
268static int prog_eeprom(unsigned int size)
269{
270 unsigned int i;
271 void *p;
272 uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
273 struct udevice *dev;
274 int ret;
275
276 if (is_match_magic()) {
277 printf("MAGIC ERROR, Please check the data@%p.\n", pbuf.buf);
278 return -1;
279 }
280
281 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
282 CONFIG_SYS_I2C_EEPROM_ADDR,
283 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
284 &dev);
285 if (ret) {
286 printf("Get i2c bus:%d addr:%d fail.\n", CONFIG_SYS_EEPROM_BUS_NUM,
287 CONFIG_SYS_I2C_EEPROM_ADDR);
288 return ret;
289 }
290
291 for (i = 0, p = (u8 *)pbuf.buf; i < size; ) {
292 if (!ret)
293 ret = dm_i2c_write(dev, i, p, min((int)(size - i),
294 BYTES_PER_EEPROM_PAGE));
295 if (ret)
296 break;
297
298 udelay(EEPROM_WRITE_DELAY_MS);
299 i += BYTES_PER_EEPROM_PAGE;
300 p += BYTES_PER_EEPROM_PAGE;
301 }
302
303 if (!ret) {
304 /* Verify the write by reading back the EEPROM and comparing */
305 ret = dm_i2c_read(dev,
306 STARFIVE_EEPROM_WP_OFFSET,
307 tmp_buff,
308 STARFIVE_EEPROM_HATS_SIZE_MAX);
309 if (!ret && memcmp((void *)pbuf.buf, (void *)tmp_buff,
310 STARFIVE_EEPROM_HATS_SIZE_MAX))
311 ret = -1;
312 }
313
314 if (ret) {
315 has_been_read = -1;
316 printf("Programming failed.\n");
317 return -1;
318 }
319
320 printf("Programming passed.\n");
321 return 0;
322}
323
324/**
325 * read_eeprom() - read the EEPROM into memory, if it hasn't been read already
326 */
327static int read_eeprom(void)
328{
329 int ret;
330 struct udevice *dev;
331
332 if (has_been_read == 1)
333 return 0;
334
335 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
336 CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
337 if (!ret)
338 ret = dm_i2c_read(dev, 0, (u8 *)pbuf.buf,
339 STARFIVE_EEPROM_HATS_SIZE_MAX);
340
341 has_been_read = (ret == 0) ? 1 : 0;
342
343 return ret;
344}
345
346/**
347 * set_pcb_revision() - stores a StarFive PCB revision into the local EEPROM copy
348 *
349 * Takes a pointer to a string representing the numeric PCB revision in
350 * decimal ("0" - "255"), stores it in the pcb_revision field of the
351 * EEPROM local copy, and updates the CRC of the local copy.
352 */
353static void set_pcb_revision(char *string)
354{
355 u32 p;
356
357 p = simple_strtoul(string, &string, 16);
358 if (p > U8_MAX) {
359 printf("%s must not be greater than %d\n", "PCB revision",
360 U8_MAX);
361 return;
362 }
363
364 pbuf.eeprom.atom4.data.pcb_revision = p;
365
366 update_crc();
367}
368
369/**
370 * set_bom_revision() - stores a StarFive BOM revision into the local EEPROM copy
371 *
372 * Takes a pointer to a uppercase ASCII character representing the BOM
373 * revision ("A" - "Z"), stores it in the bom_revision field of the
374 * EEPROM local copy, and updates the CRC of the local copy.
375 */
376static void set_bom_revision(char *string)
377{
378 if (string[0] < 'A' || string[0] > 'Z') {
379 printf("BOM revision must be an uppercase letter between A and Z\n");
380 return;
381 }
382
383 pbuf.eeprom.atom4.data.bom_revision = string[0];
384
385 update_crc();
386}
387
388/**
389 * set_product_id() - stores a StarFive product ID into the local EEPROM copy
390 *
391 * Takes a pointer to a string representing the numeric product ID in
392 * string ("VF7100A1-2150-D008E000-00000001\0"), stores it in the product string
393 * field of the EEPROM local copy, and updates the CRC of the local copy.
394 */
395static void set_product_id(char *string)
396{
397 u32 len;
398
399 len = (strlen(string) > STARFIVE_EEPROM_ATOM1_PSTR_SIZE) ?
400 STARFIVE_EEPROM_ATOM1_PSTR_SIZE : strlen(string);
401
402 memcpy((void *)pbuf.eeprom.atom1.data.pstr, (void *)string, len);
403
404 update_crc();
405}
406
Heinrich Schuchardt4e144fa2024-05-12 06:25:26 +0200407/**
408 * set_vendor() - set vendor name
409 *
410 * Takes a pointer to a string representing the vendor name, e.g.
411 * "StarFive Technology Co., Ltd.", stores it in the vendor field
412 * of the EEPROM local copy, and updates the CRC of the local copy.
413 */
414static void set_vendor(char *string)
415{
416 memset(pbuf.eeprom.atom1.data.vstr, 0,
417 sizeof(pbuf.eeprom.atom1.data.vstr));
418
419 strncpy(pbuf.eeprom.atom1.data.vstr,
420 string, sizeof(pbuf.eeprom.atom1.data.vstr) - 1);
421
422 update_crc();
423}
424
Heinrich Schuchardtf560f0f2024-04-02 10:49:08 +0200425const char *get_product_id_from_eeprom(void)
426{
427 if (read_eeprom())
428 return NULL;
429
430 return pbuf.eeprom.atom1.data.pstr;
431}
432
Yanhong Wang39331e42023-06-15 17:36:48 +0800433int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
434{
435 char *cmd;
436
437 if (argc == 1) {
438 show_eeprom();
439 return 0;
440 }
441
442 if (argc > 3)
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200443 return CMD_RET_USAGE;
Yanhong Wang39331e42023-06-15 17:36:48 +0800444
445 cmd = argv[1];
446
447 /* Commands with no argument */
448 if (!strcmp(cmd, "read_eeprom")) {
449 has_been_read = 0;
450 return read_eeprom();
451 } else if (!strcmp(cmd, "initialize")) {
452 init_local_copy();
453 return 0;
454 } else if (!strcmp(cmd, "write_eeprom")) {
455 return prog_eeprom(STARFIVE_EEPROM_HATS_SIZE_MAX);
Heinrich Schuchardt6b4bb9a2023-09-30 14:01:47 +0200456 } else if (!strcmp(cmd, "raw")) {
457 dump_raw_eeprom();
458 return 0;
Yanhong Wang39331e42023-06-15 17:36:48 +0800459 }
460
461 if (argc != 3)
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200462 return CMD_RET_USAGE;
Yanhong Wang39331e42023-06-15 17:36:48 +0800463
464 if (is_match_magic()) {
465 printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
466 return 0;
467 }
468
469 if (!strcmp(cmd, "mac0_address")) {
470 set_mac_address(argv[2], 0);
471 return 0;
472 } else if (!strcmp(cmd, "mac1_address")) {
473 set_mac_address(argv[2], 1);
474 return 0;
475 } else if (!strcmp(cmd, "pcb_revision")) {
476 set_pcb_revision(argv[2]);
477 return 0;
478 } else if (!strcmp(cmd, "bom_revision")) {
479 set_bom_revision(argv[2]);
480 return 0;
481 } else if (!strcmp(cmd, "product_id")) {
482 set_product_id(argv[2]);
483 return 0;
Heinrich Schuchardt4e144fa2024-05-12 06:25:26 +0200484 } else if (!strcmp(cmd, "vendor")) {
485 set_vendor(argv[2]);
486 return 0;
Yanhong Wang39331e42023-06-15 17:36:48 +0800487 }
488
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200489 return CMD_RET_USAGE;
Yanhong Wang39331e42023-06-15 17:36:48 +0800490}
491
492/**
493 * mac_read_from_eeprom() - read the MAC address & the serial number in EEPROM
494 *
495 * This function reads the MAC address and the serial number from EEPROM and
496 * sets the appropriate environment variables for each one read.
497 *
498 * The environment variables are only set if they haven't been set already.
499 * This ensures that any user-saved variables are never overwritten.
500 *
501 * If CONFIG_ID_EEPROM is enabled, this function will be called in
502 * "static init_fnc_t init_sequence_r[]" of u-boot/common/board_r.c.
503 */
504int mac_read_from_eeprom(void)
505{
506 /**
507 * try to fill the buff from EEPROM,
508 * always return SUCCESS, even some error happens.
509 */
510 if (read_eeprom()) {
511 dump_raw_eeprom();
512 return 0;
513 }
514
515 // 1, setup ethaddr env
Seung-Woo Kimd414b7b2023-08-11 16:12:25 +0900516 eth_env_set_enetaddr("ethaddr", pbuf.eeprom.atom4.data.mac0_addr);
Yanhong Wang39331e42023-06-15 17:36:48 +0800517 eth_env_set_enetaddr("eth1addr", pbuf.eeprom.atom4.data.mac1_addr);
518
519 /**
520 * 2, setup serial# env, reference to hifive-platform-i2c-eeprom.c,
521 * serial# can be a ASCII string, but not just a hex number, so we
522 * setup serial# in the 32Byte format:
523 * "VF7100A1-2201-D008E000-00000001;"
524 * "<product>-<date>-<DDR&eMMC>-<serial_number>"
525 * <date>: 4Byte, should be the output of `date +%y%W`
526 * <DDR&eMMC>: 8Byte, "D008" means 8GB, "D01T" means 1TB;
Michal Simekcc046dc2024-04-16 08:55:19 +0200527 * "E000" means no eMMC, "E032" means 32GB, "E01T" means 1TB.
Yanhong Wang39331e42023-06-15 17:36:48 +0800528 * <serial_number>: 8Byte, the Unique Identifier of board in hex.
529 */
530 if (!env_get("serial#"))
531 env_set("serial#", pbuf.eeprom.atom1.data.pstr);
532
533 printf("StarFive EEPROM format v%u\n", pbuf.eeprom.header.version);
534 show_eeprom();
535 return 0;
536}
537
538/**
539 * get_pcb_revision_from_eeprom - get the PCB revision
540 *
541 * 1.2A return 'A'/'a', 1.3B return 'B'/'b',other values are illegal
542 */
543u8 get_pcb_revision_from_eeprom(void)
544{
545 u8 pv = 0xFF;
546
547 if (read_eeprom())
548 return pv;
549
550 return pbuf.eeprom.atom1.data.pstr[6];
551}
552
553/**
554 * get_ddr_size_from_eeprom - get the DDR size
555 * pstr: VF7110A1-2228-D008E000-00000001
556 * VF7110A1/VF7110B1 : VisionFive JH7110A /VisionFive JH7110B
Michal Simekcc046dc2024-04-16 08:55:19 +0200557 * D008: 8GB LPDDR4
Yanhong Wang39331e42023-06-15 17:36:48 +0800558 * E000: No emmc device, ECxx: include emmc device, xx: Capacity size[GB]
559 * return: the field of 'D008E000'
560 */
561
562u32 get_ddr_size_from_eeprom(void)
563{
564 u32 pv = 0xFFFFFFFF;
565
566 if (read_eeprom())
567 return pv;
568
569 return hextoul(&pbuf.eeprom.atom1.data.pstr[14], NULL);
570}
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200571
Heinrich Schuchardt89ef0342024-05-12 06:25:22 +0200572u32 get_mmc_size_from_eeprom(void)
573{
574 u32 size;
575
576 if (IS_ENABLED(CONFIG_STARFIVE_NO_EMMC))
577 return 0;
578
579 if (read_eeprom())
580 return 0;
581
582 size = dectoul(&pbuf.eeprom.atom1.data.pstr[19], NULL);
583
584 if (pbuf.eeprom.atom1.data.pstr[21] == 'T')
585 size <<= 10;
586
587 return size;
588}
589
Tom Rini03f146c2023-10-07 15:13:08 -0400590U_BOOT_LONGHELP(mac,
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200591 "\n"
592 " - display EEPROM content\n"
593 "mac read_eeprom\n"
594 " - read EEPROM content into memory data structure\n"
595 "mac write_eeprom\n"
596 " - save memory data structure to the EEPROM\n"
597 "mac initialize\n"
598 " - initialize the in-memory EEPROM copy with default data\n"
Heinrich Schuchardt6b4bb9a2023-09-30 14:01:47 +0200599 "mac raw\n"
600 " - hexdump memory data structure\n"
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200601 "mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
602 " - stores a MAC0 address into the local EEPROM copy\n"
603 "mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
604 " - stores a MAC1 address into the local EEPROM copy\n"
605 "mac pcb_revision <?>\n"
606 " - stores a StarFive PCB revision into the local EEPROM copy\n"
607 "mac bom_revision <A>\n"
608 " - stores a StarFive BOM revision into the local EEPROM copy\n"
609 "mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
Heinrich Schuchardt4e144fa2024-05-12 06:25:26 +0200610 " - stores a StarFive product ID into the local EEPROM copy\n"
611 "mac vendor <Vendor Name>\n"
612 " - set vendor string\n");
Heinrich Schuchardta3cf2362023-09-30 14:01:45 +0200613
614U_BOOT_CMD(
615 mac, 3, 1, do_mac,
616 "display and program the board revision and MAC address in EEPROM",
Tom Rini03f146c2023-10-07 15:13:08 -0400617 mac_help_text);