Many ethernet devices use an EEPROM to store various settings, most commonly the device MAC address. But on some devices it can contains a lot more, for example USB device might also have many USB related parameters.
This commit add a set of commands to read/write this EEPROM, write a default configuration and read/write the device MAC address. The defaults command allow priming the EEPROM for devices that need more than just a MAC address in the EEPROM. Signed-off-by: Alban Bedel <alban.be...@avionic-design.de> --- v2: * No changes since v1 v3: * Replace the dedicated 'eth_eeprom' command with a subcommand to the newly introduced 'eth' command --- common/cmd_net.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/net.h | 28 +++++++++++++ net/eth.c | 46 +++++++++++++++++++++ 3 files changed, 195 insertions(+) diff --git a/common/cmd_net.c b/common/cmd_net.c index 9cc0bdf..1c2e254 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -446,6 +446,109 @@ U_BOOT_CMD( #endif /* CONFIG_CMD_LINK_LOCAL */ +#if defined(CONFIG_CMD_ETH_EEPROM) +static int do_eth_eeprom_rw(struct eth_device *dev, + int argc, char * const argv[]) +{ + ulong addr, offset, length = 1; + + if (argc < 3) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + offset = simple_strtoul(argv[2], NULL, 16); + if (argc > 3) + length = simple_strtoul(argv[3], NULL, 16); + + if (!strcmp(argv[0], "write")) { + if (eth_eeprom_write(dev, offset, length, (void *)addr)) { + printf("EEPROM write failed\n"); + return CMD_RET_FAILURE; + } + return CMD_RET_SUCCESS; + } else if (!strcmp(argv[0], "read")) { + if (eth_eeprom_read(dev, offset, length, (void *)addr)) { + printf("EEPROM read failed\n"); + return CMD_RET_FAILURE; + } + return CMD_RET_SUCCESS; + } + + return CMD_RET_USAGE; +} + +static int do_eth_eeprom_defaults(struct eth_device *dev, + int argc, char * const argv[]) +{ + if (eth_eeprom_defaults(dev)) { + printf("EEPROM write failed\n"); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_eth_eeprom_set_mac(struct eth_device *dev, + int argc, char * const argv[]) +{ + u8 mac[6]; + + if (argc < 2) + return CMD_RET_USAGE; + + eth_parse_enetaddr(argv[1], mac); + if (!is_valid_ether_addr(mac)) { + printf("Invalid mac address given\n"); + return CMD_RET_FAILURE; + } + + printf("Writing MAC to EEPROM ....\n"); + if (eth_eeprom_write_mac(dev, mac)) { + printf("EEPROM write failed\n"); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_eth_eeprom_show_mac(struct eth_device *dev, + int argc, char * const argv[]) +{ + u8 data[6]; + + if (eth_eeprom_read_mac(dev, data)) { + printf("EEPROM read failed\n"); + return CMD_RET_FAILURE; + } + + printf("%pM\n", data); + if (!is_valid_ether_addr(data)) + printf("Warning: MAC address is not valid!\n"); + + return CMD_RET_SUCCESS; +} + +static int do_eth_eeprom(struct eth_device *dev, + int argc, char * const argv[]) +{ + if (argc < 2) + return CMD_RET_USAGE; + + if (!strcmp(argv[1], "read") || !strcmp(argv[1], "write")) + return do_eth_eeprom_rw(dev, argc - 1, argv + 1); + if (!strcmp(argv[1], "defaults")) + return do_eth_eeprom_defaults(dev, argc - 1, argv + 1); + if (!strcmp(argv[1], "set_mac")) + return do_eth_eeprom_set_mac(dev, argc - 1, argv + 1); + if (!strcmp(argv[1], "show_mac")) + return do_eth_eeprom_show_mac(dev, argc - 1, argv + 1); + + printf("Unknown eeprom sub command: %s\n", argv[1]); + + return CMD_RET_USAGE; +} +#endif + static int do_eth_show(struct eth_device *dev, int argc, char * const argv[]) { @@ -478,6 +581,10 @@ static int do_eth(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!strcmp(argv[2], "show")) return do_eth_show(dev, argc - 2, argv + 2); +#if defined(CONFIG_CMD_ETH_EEPROM) + if (!strcmp(argv[2], "eeprom")) + return do_eth_eeprom(dev, argc - 2, argv + 2); +#endif printf("Unknown eth sub command: %s\n", argv[2]); @@ -492,4 +599,18 @@ U_BOOT_CMD( "\n" "eth <dev> show\n" " - show basic information about the ethernet device\n" +#if defined(CONFIG_CMD_ETH_EEPROM) + "eth <dev> eeprom <command> [<args>...]\n" + " - access the EEPROM of the ethernet device:\n" + " read <addr> <off> [<size>]\n" + " - read <size> bytes starting at offset <off> to memory address <addr>.\n" + " write <addr> <off> [<size>]\n" + " - write <size> bytes starting at offset <off> from memory address <addr>.\n" + " defaults\n" + " - write default settings in the EEPROM.\n" + " set_mac <mac>\n" + " - set the MAC address in the EEPROM to 'mac'\n" + " show_mac\n" + " - read the MAC address from the EEPROM." +#endif ); diff --git a/include/net.h b/include/net.h index 18d279e..fba7572 100644 --- a/include/net.h +++ b/include/net.h @@ -92,6 +92,25 @@ struct eth_device { int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set); #endif int (*write_hwaddr) (struct eth_device *); +#ifdef CONFIG_CMD_ETH_EEPROM + /* Read data from the ethernet device eeprom */ + int (*eeprom_read)(struct eth_device *, + u32 offset, u32 length, u8 *data); + /* Write data to the ethernet device eeprom */ + int (*eeprom_write)(struct eth_device *, + u32 offset, u32 length, u8 *data); + /* Write the default settings to the eeprom */ + int (*eeprom_defaults)(struct eth_device *); + /* Read the MAC stored in the eeprom, if not implemented + * the MAC is assumed to be at the given offset. */ + int (*eeprom_read_mac)(struct eth_device *, u8 *enetaddr); + /* Write the MAC in the eeprom, if not implemented + * the MAC is assumed to be at the given offset. */ + int (*eeprom_write_mac)(struct eth_device *, u8 *enetaddr); + /* Offset of the MAC address for the default implementation. + * Set to a negative value if the MAC is not in the EEPROM. */ + int eeprom_mac_offset; +#endif struct eth_device *next; int index; void *priv; @@ -172,6 +191,15 @@ int eth_mcast_join(IPaddr_t mcast_addr, u8 join); u32 ether_crc(size_t len, unsigned char const *p); #endif +#ifdef CONFIG_CMD_ETH_EEPROM +int eth_eeprom_read(struct eth_device *dev, u32 offset, + u32 length, u8 *data); +int eth_eeprom_write(struct eth_device *dev, u32 offset, + u32 length, u8 *data); +int eth_eeprom_defaults(struct eth_device *dev); +int eth_eeprom_read_mac(struct eth_device *, u8 *enetaddr); +int eth_eeprom_write_mac(struct eth_device *, u8 *enetaddr); +#endif /**********************************************************************/ /* diff --git a/net/eth.c b/net/eth.c index 76ffa05..2cde72c 100644 --- a/net/eth.c +++ b/net/eth.c @@ -542,3 +542,49 @@ char *eth_get_name(void) { return eth_current ? eth_current->name : "unknown"; } + +#ifdef CONFIG_CMD_ETH_EEPROM +int eth_eeprom_read(struct eth_device *dev, u32 offset, + u32 length, u8 *data) +{ + return dev->eeprom_read ? + dev->eeprom_read(dev, offset, length, data) : + -ENOSYS; +} + +int eth_eeprom_write(struct eth_device *dev, u32 offset, + u32 length, u8 *data) +{ + return dev->eeprom_write ? + dev->eeprom_write(dev, offset, length, data) : + -ENOSYS; +} + +int eth_eeprom_defaults(struct eth_device *dev) +{ + return dev->eeprom_defaults ? dev->eeprom_defaults(dev) : + -ENOSYS; +} + +int eth_eeprom_read_mac(struct eth_device *dev, u8 *enetaddr) +{ + if (dev->eeprom_read_mac) + return dev->eeprom_read_mac(dev, enetaddr); + + return dev->eeprom_mac_offset >= 0 ? + eth_eeprom_read(dev, dev->eeprom_mac_offset, + 6, enetaddr) : + -ENOSYS; +} + +int eth_eeprom_write_mac(struct eth_device *dev, u8 *enetaddr) +{ + if (dev->eeprom_write_mac) + return dev->eeprom_write_mac(dev, enetaddr); + + return dev->eeprom_mac_offset >= 0 ? + eth_eeprom_write(dev, dev->eeprom_mac_offset, + 6, enetaddr) : + -ENOSYS; +} +#endif -- 2.1.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot