[U-Boot] [PATCH 00/12] Introduce layout aware eeprom commands

This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr eeprom update [-l <layout_version>] bus_num device_addr <field_name> <field_value>
The series starts with importing the code in a way that is very separated from the existing eeprom command code (it uses its own parsing function and its own command execution code, but does reuse the eeprom_read and eeprom_write functions), then activates the feature for all Compulab boards, and finally merges the layout aware code with the layout unaware code so that there is one parsing function, and one command execution function.
Features: - print EEPROM layout in a human readable way (field names and formatted data) - update EEPROM data by specifying the field name and the new data in a human readable format (same format as shown by the print command) - Layout can be either auto detected, or manually selected with the -l option - Completely optional and backwards compatible with current eeprom command
Tested on cm-t43 and cm-fx6. Final result compile tested on arm.
Example of use:
CM-T43 # eeprom print 0 0x50 Major Revision 1.04 Minor Revision 0.00 1st MAC Address 01:02:03:04:05:06 2nd MAC Address ff:ff:ff:ff:ff:ff Production Date 01/Jan/2016 Serial Number 0000000000000005a0387754 3rd MAC Address (WIFI) ff:ff:ff:ff:ff:ff 4th MAC Address (Bluetooth) ff:ff:ff:ff:ff:ff Layout Version 02 Reserved fields (83 bytes) Product Name CM-T43 Product Options #1 C1000M-D1G-N4G- Product Options #2 E2-A-WB Product Options #3 Reserved fields (64 bytes)
CM-T43 # eeprom update 0 0x50 "Major Revision" 2.30 CM-T43 # eeprom update 0 0x50 "Product Name" CM-T54 CM-T43 # eeprom update 0 0x50 "Productuction Date" 10/Feb/2017 No such field 'Productuction Date' CM-T43 # eeprom update 0 0x50 "Production Date" 10/Feb/2017
CM-T43 # eeprom print 0 0x50 Major Revision 2.30 Minor Revision 0.00 1st MAC Address 01:02:03:04:05:06 2nd MAC Address ff:ff:ff:ff:ff:ff Production Date 10/Feb/2017 Serial Number 0000000000000005a0387754 3rd MAC Address (WIFI) ff:ff:ff:ff:ff:ff 4th MAC Address (Bluetooth) ff:ff:ff:ff:ff:ff Layout Version 02 Reserved fields (83 bytes) Product Name CM-T54 Product Options #1 C1000M-D1G-N4G- Product Options #2 E2-A-WB Product Options #3 Reserved fields (64 bytes)
CM-T43 # eeprom print -l legacy 0 0x50 MAC address e6:00:ff:ff:01:02 Board Revision 0304 Serial Number 0506ffffffffffff Board Configuration �Tw8� Reserved fields (176 bytes) CM-T43 #
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com
Nikita Kiryanov (12): cmd: eeprom: add bus switching support for all i2c drivers cmd: eeprom: add support for layout aware commands compulab: add support for layout aware eeprom commands arm: cm-fx6: add support for eeprom layout comands arm: cm-t335: add support for eeprom layout comands arm: cm-t54: add support for eeprom layout comands arm: cm-t3517: add support for eeprom layout comands arm: cm-t35: add support for eeprom layout comands arm: cm-t43: add support for eeprom layout comands eeprom: refactor i2c bus and devaddr parsing eeprom: use eeprom_execute_command for all eeprom functions eeprom: merge cmdline parsing of eeprom commands
README | 1 + board/compulab/common/eeprom.c | 344 +++++++++++++++++++++++++++++++++++++++++ cmd/eeprom.c | 251 +++++++++++++++++++++++++----- common/Makefile | 3 + common/eeprom/eeprom_field.c | 250 ++++++++++++++++++++++++++++++ common/eeprom/eeprom_layout.c | 125 +++++++++++++++ include/configs/cm_fx6.h | 11 ++ include/configs/cm_t335.h | 11 ++ include/configs/cm_t35.h | 11 ++ include/configs/cm_t3517.h | 11 ++ include/configs/cm_t43.h | 11 ++ include/configs/cm_t54.h | 11 ++ include/eeprom_field.h | 39 +++++ include/eeprom_layout.h | 33 ++++ 14 files changed, 1077 insertions(+), 35 deletions(-) create mode 100644 common/eeprom/eeprom_field.c create mode 100644 common/eeprom/eeprom_layout.c create mode 100644 include/eeprom_field.h create mode 100644 include/eeprom_layout.h

The i2c_init function is always provided when CONFIG_SYS_I2C is defined. No need to limit ourselves to just one supported I2C driver (soft_i2c). Update the #ifdef conditions to support bus switching for all I2C drivers.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- cmd/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 571240a..75def98 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -68,7 +68,7 @@ void eeprom_init(int bus) #endif
/* I2C EEPROM */ -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT) +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) #if defined(CONFIG_SYS_I2C) if (bus >= 0) i2c_set_bus_num(bus);

On Sat, Apr 16, 2016 at 05:55:02PM +0300, Nikita Kiryanov wrote:
The i2c_init function is always provided when CONFIG_SYS_I2C is defined. No need to limit ourselves to just one supported I2C driver (soft_i2c). Update the #ifdef conditions to support bus switching for all I2C drivers.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Introduce the (optional) eeprom print and eeprom update commands.
These commands are eeprom layout aware: * The eeprom print command prints the contents of the eeprom in a human readable way (eeprom layout fields, and data formatted to be fit for human consumption). * The eeprom update command allows user to update eeprom fields by specifying the field name, and providing the new data in a human readable format (same format as displayed by the eeprom print command). * Both commands can either auto detect the layout, or be told which layout to use.
New CONFIG options: CONFIG_CMD_EEPROM_LAYOUT - enables commands. CONFIG_EEPROM_LAYOUT_HELP_STRING - tells user what layout names are supported
Feature API: __weak int parse_layout_version(char *str) - override to provide your own layout name parsing __weak void __eeprom_layout_assign(struct eeprom_layout *layout, int layout_version); - override to setup the layout metadata based on the version __weak int eeprom_layout_detect(unsigned char *data) - override to provide your own algorithm for detecting layout version eeprom_field.c - contains various printing and updating functions for common types of eeprom fields. Can be used for defining custom layouts.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- README | 1 + cmd/eeprom.c | 148 ++++++++++++++++++++++++- common/Makefile | 3 + common/eeprom/eeprom_field.c | 250 ++++++++++++++++++++++++++++++++++++++++++ common/eeprom/eeprom_layout.c | 125 +++++++++++++++++++++ include/eeprom_field.h | 39 +++++++ include/eeprom_layout.h | 33 ++++++ 7 files changed, 598 insertions(+), 1 deletion(-) create mode 100644 common/eeprom/eeprom_field.c create mode 100644 common/eeprom/eeprom_layout.c create mode 100644 include/eeprom_field.h create mode 100644 include/eeprom_layout.h
diff --git a/README b/README index 88ff837..ddb6fba 100644 --- a/README +++ b/README @@ -1003,6 +1003,7 @@ The following options need to be configured: CONFIG_CMD_ECHO echo arguments CONFIG_CMD_EDITENV edit env variable CONFIG_CMD_EEPROM * EEPROM read/write support + CONFIG_CMD_EEPROM_LAYOUT* EEPROM layout aware commands CONFIG_CMD_ELF * bootelf, bootvx CONFIG_CMD_ENV_CALLBACK * display details about env callbacks CONFIG_CMD_ENV_FLAGS * display details about env flags diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 75def98..114d68f 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -203,6 +203,131 @@ int eeprom_write(unsigned dev_addr, unsigned offset, return ret; }
+#ifdef CONFIG_CMD_EEPROM_LAYOUT +#include <eeprom_layout.h> + +__weak int eeprom_parse_layout_version(char *str) +{ + return LAYOUT_VERSION_UNRECOGNIZED; +} + +static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; + +#ifndef CONFIG_EEPROM_LAYOUT_HELP_STRING +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "<not defined>" +#endif + +enum eeprom_action { + EEPROM_PRINT, + EEPROM_UPDATE, + EEPROM_ACTION_INVALID, +}; + +static enum eeprom_action parse_action(char *cmd) +{ + if (!strncmp(cmd, "print", 5)) + return EEPROM_PRINT; + if (!strncmp(cmd, "update", 6)) + return EEPROM_UPDATE; + + return EEPROM_ACTION_INVALID; +} + +static int parse_numeric_param(char *str) +{ + char *endptr; + int value = simple_strtol(str, &endptr, 16); + + return (*endptr != '\0') ? -1 : value; +} + +static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, + int i2c_addr, int layout_ver, char *key, + char *value) +{ + int rcode; + struct eeprom_layout layout; + + if (action == EEPROM_ACTION_INVALID) + return CMD_RET_USAGE; + + eeprom_init(i2c_bus); + rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); + if (rcode < 0) + return rcode; + + eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE, + layout_ver); + + if (action == EEPROM_PRINT) { + layout.print(&layout); + return 0; + } + + layout.update(&layout, key, value); + + rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); + + return rcode; +} + +#define NEXT_PARAM(argc, index) { (argc)--; (index)++; } +static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int layout_ver = LAYOUT_VERSION_AUTODETECT; + enum eeprom_action action = EEPROM_ACTION_INVALID; + int i2c_bus = -1, i2c_addr = -1, index = 0; + char *field_name = ""; + char *field_value = ""; + + if (argc <= 1) + return CMD_RET_USAGE; + + NEXT_PARAM(argc, index); /* Skip program name */ + + action = parse_action(argv[index]); + NEXT_PARAM(argc, index); + + if (argc <= 1) + return CMD_RET_USAGE; + + if (!strcmp(argv[index], "-l")) { + NEXT_PARAM(argc, index); + + layout_ver = eeprom_parse_layout_version(argv[index]); + NEXT_PARAM(argc, index); + } + + if (argc <= 1) + return CMD_RET_USAGE; + + i2c_bus = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + + i2c_addr = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + + if (action == EEPROM_PRINT) + goto done; + + if (argc) { + field_name = argv[index]; + NEXT_PARAM(argc, index); + } + + if (argc) { + field_value = argv[index]; + NEXT_PARAM(argc, index); + } + +done: + return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, + field_name, field_value); +} + +#endif + static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const char *const fmt = @@ -212,6 +337,13 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong dev_addr, addr, off, cnt; int bus_addr;
+#ifdef CONFIG_CMD_EEPROM_LAYOUT + if (argc >= 2) { + if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print")) + return do_eeprom_layout(cmdtp, flag, argc, argv); + } +#endif + switch (argc) { #ifdef CONFIG_SYS_DEF_EEPROM_ADDR case 5: @@ -257,9 +389,23 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }
U_BOOT_CMD( - eeprom, 7, 1, do_eeprom, + eeprom, 8, 1, do_eeprom, "EEPROM sub-system", "read <bus> <devaddr> addr off cnt\n" "eeprom write <bus> <devaddr> addr off cnt\n" " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" +#ifdef CONFIG_CMD_EEPROM_LAYOUT + "\n" + "eeprom print [-l <layout_version>] bus devaddr\n" + " - Print layout fields and their data in human readable format\n" + "eeprom update [-l <layout_version>] bus devaddr <field_name> <field_value>\n" + " - Update a specific eeprom field with new data.\n" + " The new data must be written in the same human readable format as shown by the print command.\n" + "\n" + "LAYOUT VERSIONS\n" + "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n" + "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n" + "The values which can be provided with the -l option are:\n" + CONFIG_EEPROM_LAYOUT_HELP_STRING"\n" +#endif ) diff --git a/common/Makefile b/common/Makefile index 9a4b817..4634fdd 100644 --- a/common/Makefile +++ b/common/Makefile @@ -149,6 +149,9 @@ obj-y += fb_nand.o endif endif
+ifdef CONFIG_CMD_EEPROM_LAYOUT +obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o +endif # We always have this since drivers/ddr/fs/interactive.c needs it obj-$(CONFIG_CMDLINE) += cli_simple.o
diff --git a/common/eeprom/eeprom_field.c b/common/eeprom/eeprom_field.c new file mode 100644 index 0000000..7f095a6 --- /dev/null +++ b/common/eeprom/eeprom_field.c @@ -0,0 +1,250 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov nikita@compulab.co.il + * Igor Grinberg grinberg@compulab.co.il + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/string.h> +#include <eeprom_field.h> + +static void __eeprom_field_print_bin(const struct eeprom_field *field, + char *delimiter, bool reverse) +{ + int i; + int from = reverse ? field->size - 1 : 0; + int to = reverse ? 0 : field->size - 1; + + printf(PRINT_FIELD_SEGMENT, field->name); + for (i = from; i != to; reverse ? i-- : i++) + printf("%02x%s", field->buf[i], delimiter); + + printf("%02x\n", field->buf[i]); +} + +static int __eeprom_field_update_bin(struct eeprom_field *field, + const char *value, bool reverse) +{ + int len = strlen(value); + int k, j, i = reverse ? len - 1 : 0; + unsigned char byte; + char *endptr; + + /* each two characters in the string fit in one byte */ + if (len > field->size * 2) + return -1; + + memset(field->buf, 0, field->size); + + /* i - string iterator, j - buf iterator */ + for (j = 0; j < field->size; j++) { + byte = 0; + char tmp[3] = { 0, 0, 0 }; + + if ((reverse && i < 0) || (!reverse && i >= len)) + break; + + for (k = 0; k < 2; k++) { + if (reverse && i == 0) { + tmp[k] = value[i]; + break; + } + + tmp[k] = value[reverse ? i - 1 + k : i + k]; + } + + byte = simple_strtoul(tmp, &endptr, 0); + if (*endptr != '\0' || byte < 0) + return -1; + + field->buf[j] = byte; + i = reverse ? i - 2 : i + 2; + } + + return 0; +} + +static int __eeprom_field_update_bin_delim(struct eeprom_field *field, + char *value, char *delimiter) +{ + int count = 0; + int i, val; + const char *tmp = value; + char *tok; + char *endptr; + + tmp = strstr(tmp, delimiter); + while (tmp != NULL) { + count++; + tmp++; + tmp = strstr(tmp, delimiter); + } + + if (count > field->size) + return -1; + + tok = strtok(value, delimiter); + for (i = 0; tok && i < field->size; i++) { + val = simple_strtoul(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + /* here we assume that each tok is no more than byte long */ + field->buf[i] = (unsigned char)val; + tok = strtok(NULL, delimiter); + } + + return 0; +} + +/** + * eeprom_field_print_bin() - print a field which contains binary data + * + * Treat the field data as simple binary data, and print it as two digit + * hexadecimal values. + * Sample output: + * Field Name 0102030405060708090a + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, "", false); +} + +/** + * eeprom_field_update_bin() - Update field with new data in binary form + * + * @field: an initialized field + * @value: a string of values (i.e. "10b234a") + */ +int eeprom_field_update_bin(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin(field, value, false); +} + +/** + * eeprom_field_update_reserved() - Update reserved field with new data in + * binary form + * + * @field: an initialized field + * @value: a space delimited string of byte values (i.e. "1 02 3 0x4") + */ +int eeprom_field_update_reserved(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin_delim(field, value, " "); +} + +/** + * eeprom_field_print_bin_rev() - print a field which contains binary data in + * reverse order + * + * Treat the field data as simple binary data, and print it in reverse order + * as two digit hexadecimal values. + * + * Data in field: + * 0102030405060708090a + * Sample output: + * Field Name 0a090807060504030201 + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin_rev(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, "", true); +} + +/** + * eeprom_field_update_bin_rev() - Update field with new data in binary form, + * storing it in reverse + * + * This function takes a string of byte values, and stores them + * in the field in the reverse order. i.e. if the input string was "1234", + * "3412" will be written to the field. + * + * @field: an initialized field + * @value: a string of byte values + */ +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin(field, value, true); +} + +/** + * eeprom_field_print_mac_addr() - print a field which contains a mac address + * + * Treat the field data as simple binary data, and print it formatted as a MAC + * address. + * Sample output: + * Field Name 01:02:03:04:05:06 + * + * @field: an initialized field to print + */ +void eeprom_field_print_mac(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, ":", false); +} + +/** + * eeprom_field_update_mac() - Update a mac address field which contains binary + * data + * + * @field: an initialized field + * @value: a colon delimited string of byte values (i.e. "1:02:3:ff") + */ +int eeprom_field_update_mac(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin_delim(field, value, ":"); +} + +/** + * eeprom_field_print_ascii() - print a field which contains ASCII data + * @field: an initialized field to print + */ +void eeprom_field_print_ascii(const struct eeprom_field *field) +{ + char format[8]; + + sprintf(format, "%%.%ds\n", field->size); + printf(PRINT_FIELD_SEGMENT, field->name); + printf(format, field->buf); +} + +/** + * eeprom_field_update_ascii() - Update field with new data in ASCII form + * @field: an initialized field + * @value: the new string data + * + * Returns 0 on success, -1 of failure (new string too long). + */ +int eeprom_field_update_ascii(struct eeprom_field *field, char *value) +{ + if (strlen(value) >= field->size) { + printf("%s: new data too long\n", field->name); + return -1; + } + + strncpy((char *)field->buf, value, field->size - 1); + field->buf[field->size - 1] = '\0'; + + return 0; +} + +/** + * eeprom_field_print_reserved() - print the "Reserved fields" field + * + * Print a notice that the following field_size bytes are reserved. + * + * Sample output: + * Reserved fields (64 bytes) + * + * @field: an initialized field to print + */ +void eeprom_field_print_reserved(const struct eeprom_field *field) +{ + printf(PRINT_FIELD_SEGMENT, "Reserved fields\t"); + printf("(%d bytes)\n", field->size); +} diff --git a/common/eeprom/eeprom_layout.c b/common/eeprom/eeprom_layout.c new file mode 100644 index 0000000..c059233 --- /dev/null +++ b/common/eeprom/eeprom_layout.c @@ -0,0 +1,125 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov nikita@compulab.co.il + * Igor Grinberg grinberg@compulab.co.il + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/kernel.h> +#include <eeprom_layout.h> +#include <eeprom_field.h> + +#define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n" + +struct eeprom_field layout_unknown[1] = { + { NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin, + eeprom_field_update_bin }, +}; + +/* + * eeprom_layout_detect() - detect layout based on the contents of the data. + * @data: Pointer to the data to be analyzed. + * + * Returns: the detected layout version. + */ +__weak int eeprom_layout_detect(unsigned char *data) +{ + return LAYOUT_VERSION_UNRECOGNIZED; +} + +/* + * __eeprom_layout_assign() - set the layout fields + * @layout: A pointer to an existing struct layout. + * @layout_version: The version number of the desired layout + */ +__weak void __eeprom_layout_assign(struct eeprom_layout *layout, + int layout_version) +{ + layout->fields = layout_unknown; + layout->num_of_fields = ARRAY_SIZE(layout_unknown); +} +void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \ + __attribute__((weak, alias("__eeprom_layout_assign"))); + +/* + * eeprom_layout_print() - print the layout and the data which is assigned to it + * @layout: A pointer to an existing struct layout. + */ +static void eeprom_layout_print(const struct eeprom_layout *layout) +{ + int i; + struct eeprom_field *fields = layout->fields; + + for (i = 0; i < layout->num_of_fields; i++) + fields[i].print(&fields[i]); +} + +/* + * eeprom_layout_update_field() - update a single field in the layout data. + * @layout: A pointer to an existing struct layout. + * @field_name: The name of the field to update. + * @new_data: The new field data (a string. Format depends on the field) + * + * Returns: 0 on success, negative error value on failure. + */ +static int eeprom_layout_update_field(struct eeprom_layout *layout, + char *field_name, char *new_data) +{ + int i, err; + struct eeprom_field *fields = layout->fields; + + if (new_data == NULL) + return 0; + + if (field_name == NULL) + return -1; + + for (i = 0; i < layout->num_of_fields; i++) { + if (fields[i].name == RESERVED_FIELDS || + strcmp(fields[i].name, field_name)) + continue; + + err = fields[i].update(&fields[i], new_data); + if (err) + printf("Invalid data for field %s\n", field_name); + + return err; + } + + printf("No such field '%s'\n", field_name); + + return -1; +} + +/* + * eeprom_layout_setup() - setup layout struct with the layout data and + * metadata as dictated by layout_version + * @layout: A pointer to an existing struct layout. + * @buf: A buffer initialized with the eeprom data. + * @buf_size: Size of buf in bytes. + * @layout version: The version number of the layout. + */ +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf, + unsigned int buf_size, int layout_version) +{ + int i; + + if (layout_version == LAYOUT_VERSION_AUTODETECT) + layout->layout_version = eeprom_layout_detect(buf); + else + layout->layout_version = layout_version; + + eeprom_layout_assign(layout, layout_version); + layout->data = buf; + for (i = 0; i < layout->num_of_fields; i++) { + layout->fields[i].buf = buf; + buf += layout->fields[i].size; + } + + layout->data_size = buf_size; + layout->print = eeprom_layout_print; + layout->update = eeprom_layout_update_field; +} diff --git a/include/eeprom_field.h b/include/eeprom_field.h new file mode 100644 index 0000000..94e259f --- /dev/null +++ b/include/eeprom_field.h @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov nikita@compulab.co.il + * Igor Grinberg grinberg@compulab.co.il + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FIELD_ +#define _FIELD_ + +#define PRINT_FIELD_SEGMENT "%-30s" + +struct eeprom_field { + char *name; + int size; + unsigned char *buf; + + void (*print)(const struct eeprom_field *eeprom_field); + int (*update)(struct eeprom_field *eeprom_field, char *value); +}; + +void eeprom_field_print_bin(const struct eeprom_field *field); +int eeprom_field_update_bin(struct eeprom_field *field, char *value); + +void eeprom_field_print_bin_rev(const struct eeprom_field *field); +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value); + +void eeprom_field_print_mac(const struct eeprom_field *field); +int eeprom_field_update_mac(struct eeprom_field *field, char *value); + +void eeprom_field_print_ascii(const struct eeprom_field *field); +int eeprom_field_update_ascii(struct eeprom_field *field, char *value); + +void eeprom_field_print_reserved(const struct eeprom_field *field); +int eeprom_field_update_reserved(struct eeprom_field *field, char *value); + +#endif diff --git a/include/eeprom_layout.h b/include/eeprom_layout.h new file mode 100644 index 0000000..459b99d --- /dev/null +++ b/include/eeprom_layout.h @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov nikita@compulab.co.il + * Igor Grinberg grinberg@compulab.co.il + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _LAYOUT_ +#define _LAYOUT_ + +#define RESERVED_FIELDS NULL +#define LAYOUT_VERSION_UNRECOGNIZED -1 +#define LAYOUT_VERSION_AUTODETECT -2 + +struct eeprom_layout { + struct eeprom_field *fields; + int num_of_fields; + int layout_version; + unsigned char *data; + int data_size; + void (*print)(const struct eeprom_layout *eeprom_layout); + int (*update)(struct eeprom_layout *eeprom_layout, char *field_name, + char *new_data); +}; + +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf, + unsigned int buf_size, int layout_version); +__weak void __eeprom_layout_assign(struct eeprom_layout *layout, + int layout_version); + +#endif

On Sat, Apr 16, 2016 at 05:55:03PM +0300, Nikita Kiryanov wrote:
Introduce the (optional) eeprom print and eeprom update commands.
These commands are eeprom layout aware:
- The eeprom print command prints the contents of the eeprom in a human readable way (eeprom layout fields, and data formatted to be fit for human consumption).
- The eeprom update command allows user to update eeprom fields by specifying the field name, and providing the new data in a human readable format (same format as displayed by the eeprom print command).
- Both commands can either auto detect the layout, or be told which layout to use.
New CONFIG options: CONFIG_CMD_EEPROM_LAYOUT - enables commands. CONFIG_EEPROM_LAYOUT_HELP_STRING - tells user what layout names are supported
Feature API: __weak int parse_layout_version(char *str)
- override to provide your own layout name parsing
__weak void __eeprom_layout_assign(struct eeprom_layout *layout, int layout_version);
- override to setup the layout metadata based on the version
__weak int eeprom_layout_detect(unsigned char *data)
- override to provide your own algorithm for detecting layout version
eeprom_field.c
- contains various printing and updating functions for common types of eeprom fields. Can be used for defining custom layouts.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add layout definitions and implement functions for field printing/updating, layout detection, layout assignment, and layout parsing.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- board/compulab/common/eeprom.c | 344 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+)
diff --git a/board/compulab/common/eeprom.c b/board/compulab/common/eeprom.c index 6304468..b5f1aa6 100644 --- a/board/compulab/common/eeprom.c +++ b/board/compulab/common/eeprom.c @@ -9,6 +9,9 @@
#include <common.h> #include <i2c.h> +#include <eeprom_layout.h> +#include <eeprom_field.h> +#include <linux/kernel.h> #include "eeprom.h"
#ifndef CONFIG_SYS_I2C_EEPROM_ADDR @@ -181,3 +184,344 @@ int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus)
return err; } + +#ifdef CONFIG_CMD_EEPROM_LAYOUT +/** + * eeprom_field_print_bin_ver() - print a "version field" which contains binary + * data + * + * Treat the field data as simple binary data, and print it formatted as a + * version number (2 digits after decimal point). + * The field size must be exactly 2 bytes. + * + * Sample output: + * Field Name 123.45 + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin_ver(const struct eeprom_field *field) +{ + if ((field->buf[0] == 0xff) && (field->buf[1] == 0xff)) { + field->buf[0] = 0; + field->buf[1] = 0; + } + + printf(PRINT_FIELD_SEGMENT, field->name); + int major = (field->buf[1] << 8 | field->buf[0]) / 100; + int minor = (field->buf[1] << 8 | field->buf[0]) - major * 100; + printf("%d.%02d\n", major, minor); +} + +/** + * eeprom_field_update_bin_ver() - update a "version field" which contains + * binary data + * + * This function takes a version string in the form of x.y (x and y are both + * decimal values, y is limited to two digits), translates it to the binary + * form, then writes it to the field. The field size must be exactly 2 bytes. + * + * This function strictly enforces the data syntax, and will not update the + * field if there's any deviation from it. It also protects from overflow. + * + * @field: an initialized field + * @value: a version string + * + * Returns 0 on success, -1 on failure. + */ +int eeprom_field_update_bin_ver(struct eeprom_field *field, char *value) +{ + char *endptr; + char *tok = strtok(value, "."); + if (tok == NULL) + return -1; + + int num = simple_strtol(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + tok = strtok(NULL, ""); + if (tok == NULL) + return -1; + + int remainder = simple_strtol(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + num = num * 100 + remainder; + if (num >> 16) + return -1; + + field->buf[0] = (unsigned char)num; + field->buf[1] = num >> 8; + + return 0; +} + +char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +/** + * eeprom_field_print_date() - print a field which contains date data + * + * Treat the field data as simple binary data, and print it formatted as a date. + * Sample output: + * Field Name 07/Feb/2014 + * Field Name 56/BAD/9999 + * + * @field: an initialized field to print + */ +void eeprom_field_print_date(const struct eeprom_field *field) +{ + printf(PRINT_FIELD_SEGMENT, field->name); + printf("%02d/", field->buf[0]); + if (field->buf[1] >= 1 && field->buf[1] <= 12) + printf("%s", months[field->buf[1] - 1]); + else + printf("BAD"); + + printf("/%d\n", field->buf[3] << 8 | field->buf[2]); +} + +static int validate_date(unsigned char day, unsigned char month, + unsigned int year) +{ + int days_in_february; + + switch (month) { + case 0: + case 2: + case 4: + case 6: + case 7: + case 9: + case 11: + if (day > 31) + return -1; + break; + case 3: + case 5: + case 8: + case 10: + if (day > 30) + return -1; + break; + case 1: + days_in_february = 28; + if (year % 4 == 0) { + if (year % 100 != 0) + days_in_february = 29; + else if (year % 400 == 0) + days_in_february = 29; + } + + if (day > days_in_february) + return -1; + + break; + default: + return -1; + } + + return 0; +} + +/** + * eeprom_field_update_date() - update a date field which contains binary data + * + * This function takes a date string in the form of x/Mon/y (x and y are both + * decimal values), translates it to the binary representation, then writes it + * to the field. + * + * This function strictly enforces the data syntax, and will not update the + * field if there's any deviation from it. It also protects from overflow in the + * year value, and checks the validity of the date. + * + * @field: an initialized field + * @value: a date string + * + * Returns 0 on success, -1 on failure. + */ +int eeprom_field_update_date(struct eeprom_field *field, char *value) +{ + char *endptr; + char *tok1 = strtok(value, "/"); + char *tok2 = strtok(NULL, "/"); + char *tok3 = strtok(NULL, "/"); + + if (tok1 == NULL || tok2 == NULL || tok3 == NULL) { + printf("%s: syntax error\n", field->name); + return -1; + } + + unsigned char day = (unsigned char)simple_strtol(tok1, &endptr, 0); + if (*endptr != '\0' || day == 0) { + printf("%s: invalid day\n", field->name); + return -1; + } + + unsigned char month; + for (month = 1; month <= 12; month++) + if (!strcmp(tok2, months[month - 1])) + break; + + unsigned int year = simple_strtol(tok3, &endptr, 0); + if (*endptr != '\0') { + printf("%s: invalid year\n", field->name); + return -1; + } + + if (validate_date(day, month - 1, year)) { + printf("%s: invalid date\n", field->name); + return -1; + } + + if (year >> 16) { + printf("%s: year overflow\n", field->name); + return -1; + } + + field->buf[0] = day; + field->buf[1] = month; + field->buf[2] = (unsigned char)year; + field->buf[3] = (unsigned char)(year >> 8); + + return 0; +} + +#define LAYOUT_VERSION_LEGACY 1 +#define LAYOUT_VERSION_VER1 2 +#define LAYOUT_VERSION_VER2 3 +#define LAYOUT_VERSION_VER3 4 + +extern struct eeprom_field layout_unknown[1]; + +#define DEFINE_PRINT_UPDATE(x) eeprom_field_print_##x, eeprom_field_update_##x + +#ifdef CONFIG_CM_T3X +struct eeprom_field layout_legacy[5] = { + { "MAC address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Board Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "Serial Number", 8, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "Board Configuration", 64, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 176, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; +#else +#define layout_legacy layout_unknown +#endif + +#if defined(CONFIG_CM_T3X) || defined(CONFIG_CM_T3517) +struct eeprom_field layout_v1[12] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { RESERVED_FIELDS, 96, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; +#else +#define layout_v1 layout_unknown +#endif + +struct eeprom_field layout_v2[15] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) }, + { RESERVED_FIELDS, 83, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; + +struct eeprom_field layout_v3[16] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "CompuLab EEPROM ID", 3, NULL, DEFINE_PRINT_UPDATE(bin) }, + { RESERVED_FIELDS, 80, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; + +void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) +{ + switch (layout->layout_version) { + case LAYOUT_VERSION_LEGACY: + layout->fields = layout_legacy; + layout->num_of_fields = ARRAY_SIZE(layout_legacy); + break; + case LAYOUT_VERSION_VER1: + layout->fields = layout_v1; + layout->num_of_fields = ARRAY_SIZE(layout_v1); + break; + case LAYOUT_VERSION_VER2: + layout->fields = layout_v2; + layout->num_of_fields = ARRAY_SIZE(layout_v2); + break; + case LAYOUT_VERSION_VER3: + layout->fields = layout_v3; + layout->num_of_fields = ARRAY_SIZE(layout_v3); + break; + default: + __eeprom_layout_assign(layout, layout_version); + } +} + +int eeprom_parse_layout_version(char *str) +{ + if (!strcmp(str, "legacy")) + return LAYOUT_VERSION_LEGACY; + else if (!strcmp(str, "v1")) + return LAYOUT_VERSION_VER1; + else if (!strcmp(str, "v2")) + return LAYOUT_VERSION_VER2; + else if (!strcmp(str, "v3")) + return LAYOUT_VERSION_VER3; + else + return LAYOUT_VERSION_UNRECOGNIZED; +} + +int eeprom_layout_detect(unsigned char *data) +{ + switch (data[EEPROM_LAYOUT_VER_OFFSET]) { + case 0xff: + case 0: + return LAYOUT_VERSION_VER1; + case 2: + return LAYOUT_VERSION_VER2; + case 3: + return LAYOUT_VERSION_VER3; + } + + if (data[EEPROM_LAYOUT_VER_OFFSET] >= 0x20) + return LAYOUT_VERSION_LEGACY; + + return LAYOUT_VERSION_UNRECOGNIZED; +} +#endif

On Sat, Apr 16, 2016 at 05:55:04PM +0300, Nikita Kiryanov wrote:
Add layout definitions and implement functions for field printing/updating, layout detection, layout assignment, and layout parsing.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-FX6.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_fx6.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h index b36ba14..3e6c228 100644 --- a/include/configs/cm_fx6.h +++ b/include/configs/cm_fx6.h @@ -256,4 +256,15 @@ #define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_BMP_LOGO
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #endif /* __CONFIG_CM_FX6_H */

On Sat, Apr 16, 2016 at 05:55:05PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-FX6.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-T335.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_t335.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_t335.h b/include/configs/cm_t335.h index adf05b1..d8d49d7 100644 --- a/include/configs/cm_t335.h +++ b/include/configs/cm_t335.h @@ -167,6 +167,17 @@ #define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 2) #define STATUS_LED_BOOT 0
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #ifndef CONFIG_SPL_BUILD /* * Enable PCA9555 at I2C0-0x26.

On Sat, Apr 16, 2016 at 05:55:06PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-T335.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-T54.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_t54.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h index c8c67c4..8e48128 100644 --- a/include/configs/cm_t54.h +++ b/include/configs/cm_t54.h @@ -84,6 +84,17 @@ #define CONFIG_CMD_DHCP /* DHCP Support */ #define CONFIG_CMD_PING
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + /* USB Networking options */ #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX

On Sat, Apr 16, 2016 at 05:55:07PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-T54.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-T3517.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_t3517.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_t3517.h b/include/configs/cm_t3517.h index d8a29f0..08582f6 100644 --- a/include/configs/cm_t3517.h +++ b/include/configs/cm_t3517.h @@ -317,4 +317,15 @@
#define CONFIG_OMAP3_SPI
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v1, v2, v3" + #endif /* __CONFIG_H */

On Sat, Apr 16, 2016 at 05:55:08PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-T3517.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-T35.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_t35.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h index 3910b46..9496e24 100644 --- a/include/configs/cm_t35.h +++ b/include/configs/cm_t35.h @@ -372,4 +372,15 @@ #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "legacy, v1, v2, v3" + #endif /* __CONFIG_H */

On Sat, Apr 16, 2016 at 05:55:09PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-T35.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Add support for EEPROM and EEPROM layout commands for CM-T43.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- include/configs/cm_t43.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h index 1c1951c..598e7c1 100644 --- a/include/configs/cm_t43.h +++ b/include/configs/cm_t43.h @@ -172,4 +172,15 @@ #define CONFIG_SPL_I2C_SUPPORT #define CONFIG_SPL_POWER_SUPPORT
+/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #endif /* __CONFIG_CM_T43_H */

On Sat, Apr 16, 2016 at 05:55:10PM +0300, Nikita Kiryanov wrote:
Add support for EEPROM and EEPROM layout commands for CM-T43.
Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Introduce parse_i2c_bus_addr() to generalize the parsing of i2c bus number and i2c device address. This is done in preparation for merging layout aware and layout unaware command parsing into one function.
No functional changes.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- cmd/eeprom.c | 79 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 26 deletions(-)
diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 114d68f..27daf59 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -203,6 +203,56 @@ int eeprom_write(unsigned dev_addr, unsigned offset, return ret; }
+static int parse_numeric_param(char *str) +{ + char *endptr; + int value = simple_strtol(str, &endptr, 16); + + return (*endptr != '\0') ? -1 : value; +} + +/** + * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters + * + * @i2c_bus: address to store the i2c bus + * @i2c_addr: address to store the device i2c address + * @argc: count of command line arguments left to parse + * @argv: command line arguments left to parse + * @argc_no_bus_addr: argc value we expect to see when bus & addr aren't given + * + * @returns: number of arguments parsed or CMD_RET_USAGE if error + */ +static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc, + char * const argv[], int argc_no_bus_addr) +{ + int argc_no_bus = argc_no_bus_addr + 1; + int argc_bus_addr = argc_no_bus_addr + 2; + +#ifdef CONFIG_SYS_DEF_EEPROM_ADDR + if (argc == argc_no_bus_addr) { + *i2c_bus = -1; + *i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR; + + return 0; + } +#endif + if (argc == argc_no_bus) { + *i2c_bus = -1; + *i2c_addr = parse_numeric_param(argv[0]); + + return 1; + } + + if (argc == argc_bus_addr) { + *i2c_bus = parse_numeric_param(argv[0]); + *i2c_addr = parse_numeric_param(argv[1]); + + return 2; + } + + return CMD_RET_USAGE; +} + #ifdef CONFIG_CMD_EEPROM_LAYOUT #include <eeprom_layout.h>
@@ -233,14 +283,6 @@ static enum eeprom_action parse_action(char *cmd) return EEPROM_ACTION_INVALID; }
-static int parse_numeric_param(char *str) -{ - char *endptr; - int value = simple_strtol(str, &endptr, 16); - - return (*endptr != '\0') ? -1 : value; -} - static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, int i2c_addr, int layout_ver, char *key, char *value) @@ -344,24 +386,9 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif
- switch (argc) { -#ifdef CONFIG_SYS_DEF_EEPROM_ADDR - case 5: - bus_addr = -1; - dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR; - break; -#endif - case 6: - bus_addr = -1; - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - case 7: - bus_addr = simple_strtoul(*args++, NULL, 16); - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - default: - return CMD_RET_USAGE; - } + rcode = parse_i2c_bus_addr(&bus_addr, &dev_addr, argc - 2, argv + 2, 3); + if (rcode == CMD_RET_USAGE) + return rcode;
addr = simple_strtoul(*args++, NULL, 16); off = simple_strtoul(*args++, NULL, 16);

On Sat, Apr 16, 2016 at 05:55:11PM +0300, Nikita Kiryanov wrote:
Introduce parse_i2c_bus_addr() to generalize the parsing of i2c bus number and i2c device address. This is done in preparation for merging layout aware and layout unaware command parsing into one function.
No functional changes.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Update eeprom_execute_command() and related code to accommodate both layout aware and layout unaware functions.
No functional changes.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- cmd/eeprom.c | 59 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 27daf59..cc973ca 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -24,6 +24,7 @@ #include <config.h> #include <command.h> #include <i2c.h> +#include <eeprom_layout.h>
#ifndef CONFIG_SYS_I2C_SPEED #define CONFIG_SYS_I2C_SPEED 50000 @@ -254,7 +255,6 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc, }
#ifdef CONFIG_CMD_EEPROM_LAYOUT -#include <eeprom_layout.h>
__weak int eeprom_parse_layout_version(char *str) { @@ -267,12 +267,17 @@ static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; #define CONFIG_EEPROM_LAYOUT_HELP_STRING "<not defined>" #endif
+#endif + enum eeprom_action { + EEPROM_READ, + EEPROM_WRITE, EEPROM_PRINT, EEPROM_UPDATE, EEPROM_ACTION_INVALID, };
+#ifdef CONFIG_CMD_EEPROM_LAYOUT static enum eeprom_action parse_action(char *cmd) { if (!strncmp(cmd, "print", 5)) @@ -282,18 +287,40 @@ static enum eeprom_action parse_action(char *cmd)
return EEPROM_ACTION_INVALID; } +#endif
static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, int i2c_addr, int layout_ver, char *key, - char *value) + char *value, ulong addr, ulong off, ulong cnt) { - int rcode; + int rcode = 0; + const char *const fmt = + "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; +#ifdef CONFIG_CMD_EEPROM_LAYOUT struct eeprom_layout layout; +#endif
if (action == EEPROM_ACTION_INVALID) return CMD_RET_USAGE;
eeprom_init(i2c_bus); + if (action == EEPROM_READ) { + printf(fmt, i2c_addr, "read", addr, off, cnt); + + rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } else if (action == EEPROM_WRITE) { + printf(fmt, i2c_addr, "write", addr, off, cnt); + + rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } + +#ifdef CONFIG_CMD_EEPROM_LAYOUT rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); if (rcode < 0) return rcode; @@ -309,10 +336,12 @@ static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, layout.update(&layout, key, value);
rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); +#endif
return rcode; }
+#ifdef CONFIG_CMD_EEPROM_LAYOUT #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -365,15 +394,13 @@ static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc,
done: return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, - field_name, field_value); + field_name, field_value, 0, 0, 0); }
#endif
static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - const char *const fmt = - "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; char * const *args = &argv[2]; int rcode; ulong dev_addr, addr, off, cnt; @@ -394,22 +421,14 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) off = simple_strtoul(*args++, NULL, 16); cnt = simple_strtoul(*args++, NULL, 16);
- eeprom_init(bus_addr); - if (strcmp(argv[1], "read") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; + return eeprom_execute_command(EEPROM_READ, bus_addr, dev_addr, + LAYOUT_VERSION_UNRECOGNIZED, + NULL, NULL, addr, off, cnt); } else if (strcmp(argv[1], "write") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; + return eeprom_execute_command(EEPROM_WRITE, bus_addr, dev_addr, + LAYOUT_VERSION_UNRECOGNIZED, + NULL, NULL, addr, off, cnt); }
return CMD_RET_USAGE;

On Sat, Apr 16, 2016 at 05:55:12PM +0300, Nikita Kiryanov wrote:
Update eeprom_execute_command() and related code to accommodate both layout aware and layout unaware functions.
No functional changes.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

Merge the parsing of layout aware and layout unaware eeprom commands into one parsing function. With this change, layout aware commands now follow the eeprom read and eeprom write conventions of making i2c bus and i2c address parameters optional.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il --- cmd/eeprom.c | 117 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 53 insertions(+), 64 deletions(-)
diff --git a/cmd/eeprom.c b/cmd/eeprom.c index cc973ca..b35f5f9 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -277,17 +277,21 @@ enum eeprom_action { EEPROM_ACTION_INVALID, };
-#ifdef CONFIG_CMD_EEPROM_LAYOUT static enum eeprom_action parse_action(char *cmd) { + if (!strncmp(cmd, "read", 4)) + return EEPROM_READ; + if (!strncmp(cmd, "write", 5)) + return EEPROM_WRITE; +#ifdef CONFIG_CMD_EEPROM_LAYOUT if (!strncmp(cmd, "print", 5)) return EEPROM_PRINT; if (!strncmp(cmd, "update", 6)) return EEPROM_UPDATE; +#endif
return EEPROM_ACTION_INVALID; } -#endif
static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, int i2c_addr, int layout_ver, char *key, @@ -341,14 +345,14 @@ static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, return rcode; }
-#ifdef CONFIG_CMD_EEPROM_LAYOUT #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } -static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) +int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int layout_ver = LAYOUT_VERSION_AUTODETECT; enum eeprom_action action = EEPROM_ACTION_INVALID; - int i2c_bus = -1, i2c_addr = -1, index = 0; + int i2c_bus = -1, index = 0; + ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0; + int ret; char *field_name = ""; char *field_value = "";
@@ -360,78 +364,63 @@ static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, action = parse_action(argv[index]); NEXT_PARAM(argc, index);
- if (argc <= 1) + if (action == EEPROM_ACTION_INVALID) return CMD_RET_USAGE;
- if (!strcmp(argv[index], "-l")) { - NEXT_PARAM(argc, index); - - layout_ver = eeprom_parse_layout_version(argv[index]); - NEXT_PARAM(argc, index); +#ifdef CONFIG_CMD_EEPROM_LAYOUT + if (action == EEPROM_PRINT || action == EEPROM_UPDATE) { + if (!strcmp(argv[index], "-l")) { + NEXT_PARAM(argc, index); + layout_ver = eeprom_parse_layout_version(argv[index]); + NEXT_PARAM(argc, index); + } } +#endif
- if (argc <= 1) + switch (action) { + case EEPROM_READ: + case EEPROM_WRITE: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 3); + break; + case EEPROM_PRINT: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 0); + break; + case EEPROM_UPDATE: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 2); + break; + default: + /* Get compiler to stop whining */ return CMD_RET_USAGE; + }
- i2c_bus = parse_numeric_param(argv[index]); - NEXT_PARAM(argc, index); - - i2c_addr = parse_numeric_param(argv[index]); - NEXT_PARAM(argc, index); - - if (action == EEPROM_PRINT) - goto done; + if (ret == CMD_RET_USAGE) + return ret;
- if (argc) { - field_name = argv[index]; + while (ret--) NEXT_PARAM(argc, index); - }
- if (argc) { - field_value = argv[index]; + if (action == EEPROM_READ || action == EEPROM_WRITE) { + addr = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + off = parse_numeric_param(argv[index]); NEXT_PARAM(argc, index); + cnt = parse_numeric_param(argv[index]); }
-done: - return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, - field_name, field_value, 0, 0, 0); -} - -#endif - -static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char * const *args = &argv[2]; - int rcode; - ulong dev_addr, addr, off, cnt; - int bus_addr; - #ifdef CONFIG_CMD_EEPROM_LAYOUT - if (argc >= 2) { - if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print")) - return do_eeprom_layout(cmdtp, flag, argc, argv); + if (action == EEPROM_UPDATE) { + field_name = argv[index]; + NEXT_PARAM(argc, index); + field_value = argv[index]; + NEXT_PARAM(argc, index); } #endif
- rcode = parse_i2c_bus_addr(&bus_addr, &dev_addr, argc - 2, argv + 2, 3); - if (rcode == CMD_RET_USAGE) - return rcode; - - addr = simple_strtoul(*args++, NULL, 16); - off = simple_strtoul(*args++, NULL, 16); - cnt = simple_strtoul(*args++, NULL, 16); - - if (strcmp(argv[1], "read") == 0) { - return eeprom_execute_command(EEPROM_READ, bus_addr, dev_addr, - LAYOUT_VERSION_UNRECOGNIZED, - NULL, NULL, addr, off, cnt); - } else if (strcmp(argv[1], "write") == 0) { - return eeprom_execute_command(EEPROM_WRITE, bus_addr, dev_addr, - LAYOUT_VERSION_UNRECOGNIZED, - NULL, NULL, addr, off, cnt); - } - - return CMD_RET_USAGE; + return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, + field_name, field_value, addr, off, cnt); }
U_BOOT_CMD( @@ -442,9 +431,9 @@ U_BOOT_CMD( " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" #ifdef CONFIG_CMD_EEPROM_LAYOUT "\n" - "eeprom print [-l <layout_version>] bus devaddr\n" + "eeprom print [-l <layout_version>] <bus> <devaddr>\n" " - Print layout fields and their data in human readable format\n" - "eeprom update [-l <layout_version>] bus devaddr <field_name> <field_value>\n" + "eeprom update [-l <layout_version>] <bus> <devaddr> field_name field_value\n" " - Update a specific eeprom field with new data.\n" " The new data must be written in the same human readable format as shown by the print command.\n" "\n"

On Sat, Apr 16, 2016 at 05:55:13PM +0300, Nikita Kiryanov wrote:
Merge the parsing of layout aware and layout unaware eeprom commands into one parsing function. With this change, layout aware commands now follow the eeprom read and eeprom write conventions of making i2c bus and i2c address parameters optional.
Cc: Heiko Schocher hs@denx.de Cc: Marek Vasut marex@denx.de Cc: Simon Glass sjg@chromium.org Cc: Igor Grinberg grinberg@compulab.co.il Cc: Tom Rini trini@konsulko.com Signed-off-by: Nikita Kiryanov nikita@compulab.co.il
Applied to u-boot/master, thanks!

On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Best regards, Marek Vasut

Hi Marek,
On Sun, Apr 17, 2016 at 11:47:23AM +0200, Marek Vasut wrote:
On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Are you referring to the fact that the command allows the user to not specify the bus number (relying on a default value instead)? If so, I agree with you that it is problematic. If I had my way I would've made it a mendatory parameter along with the device address, but that will hurt backwards compatibility. I'll be more than happy to redo the last 3 patches if we agree that we are willing to pay that price.
Best regards, Marek Vasut

On 04/17/2016 12:33 PM, Nikita Kiryanov wrote:
Hi Marek,
On Sun, Apr 17, 2016 at 11:47:23AM +0200, Marek Vasut wrote:
On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Are you referring to the fact that the command allows the user to not specify the bus number (relying on a default value instead)?
No, just using the bus number and device address doesn't seem right anymore.
If so, I agree with you that it is problematic. If I had my way I would've made it a mendatory parameter along with the device address, but that will hurt backwards compatibility.
But this is new feature, there is no backward compatibility.
I'll be more than happy to redo the last 3 patches if we agree that we are willing to pay that price.
Best regards, Marek Vasut

On Sun, Apr 17, 2016 at 11:00:09PM +0200, Marek Vasut wrote:
On 04/17/2016 12:33 PM, Nikita Kiryanov wrote:
Hi Marek,
On Sun, Apr 17, 2016 at 11:47:23AM +0200, Marek Vasut wrote:
On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Are you referring to the fact that the command allows the user to not specify the bus number (relying on a default value instead)?
No, just using the bus number and device address doesn't seem right anymore.
How so? Both are properties of the hardware, and they should be addressable as such. I feel like I'm missing something, can you elaborate on what you think the problem is?
If so, I agree with you that it is problematic. If I had my way I would've made it a mendatory parameter along with the device address, but that will hurt backwards compatibility.
But this is new feature, there is no backward compatibility.
I meant making this change for the eeprom read and write commands as well, not just the new commands. I think that the new commands should follow the conventions of the original commands for consistency, I just wish the current conventions were less ambiguous than they are now (it's not possible to figure out what ommision of these parameters does without looking at the source code).
I'll be more than happy to redo the last 3 patches if we agree that we are willing to pay that price.
Best regards, Marek Vasut
-- Best regards, Marek Vasut

On 04/18/2016 10:22 AM, Nikita Kiryanov wrote:
On Sun, Apr 17, 2016 at 11:00:09PM +0200, Marek Vasut wrote:
On 04/17/2016 12:33 PM, Nikita Kiryanov wrote:
Hi Marek,
On Sun, Apr 17, 2016 at 11:47:23AM +0200, Marek Vasut wrote:
On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Are you referring to the fact that the command allows the user to not specify the bus number (relying on a default value instead)?
No, just using the bus number and device address doesn't seem right anymore.
How so? Both are properties of the hardware, and they should be addressable as such. I feel like I'm missing something, can you elaborate on what you think the problem is?
The bus number is not really an exact identifier in the system anymore because the number changes depending on the number and order of registered buses in DM case. This works for now and is backwards compatible, but I am tempted to push for user API which would be more exact. You might want Simon's opinion on this too.
If so, I agree with you that it is problematic. If I had my way I would've made it a mendatory parameter along with the device address, but that will hurt backwards compatibility.
But this is new feature, there is no backward compatibility.
I meant making this change for the eeprom read and write commands as well, not just the new commands. I think that the new commands should follow the conventions of the original commands for consistency, I just wish the current conventions were less ambiguous than they are now (it's not possible to figure out what ommision of these parameters does without looking at the source code).
The EEPROM code is in horrible state, indeed. If you want to clean it up some more, I'd be real happy.
I'll be more than happy to redo the last 3 patches if we agree that we are willing to pay that price.
Best regards, Marek Vasut
-- Best regards, Marek Vasut

Hi Tom, Marek,
For the time being I do not wish to make additional refactoring to the code as I think it is better to wait until an alternative to the bus number is found. My changes follow the current implementation of the eeprom command, so if there are no additional comments, can this be applied?
On Mon, Apr 18, 2016 at 01:21:30PM +0200, Marek Vasut wrote:
On 04/18/2016 10:22 AM, Nikita Kiryanov wrote:
On Sun, Apr 17, 2016 at 11:00:09PM +0200, Marek Vasut wrote:
On 04/17/2016 12:33 PM, Nikita Kiryanov wrote:
Hi Marek,
On Sun, Apr 17, 2016 at 11:47:23AM +0200, Marek Vasut wrote:
On 04/16/2016 04:55 PM, Nikita Kiryanov wrote:
This series introduces eeprom layout aware capabilities to the existing eeprom command, and then enables this feature on Compulab boards. It is an import of the Compulab eeprom-utility (https://github.com/compulab/eeprom-util), and it introduces 2 new options to the eeprom command:
eeprom print [-l <layout_version>] bus_num device_addr
The bus number starts to become a problem, esp. when used with DM and where the bus number can change between boots.
Are you referring to the fact that the command allows the user to not specify the bus number (relying on a default value instead)?
No, just using the bus number and device address doesn't seem right anymore.
How so? Both are properties of the hardware, and they should be addressable as such. I feel like I'm missing something, can you elaborate on what you think the problem is?
The bus number is not really an exact identifier in the system anymore because the number changes depending on the number and order of registered buses in DM case. This works for now and is backwards compatible, but I am tempted to push for user API which would be more exact. You might want Simon's opinion on this too.
If so, I agree with you that it is problematic. If I had my way I would've made it a mendatory parameter along with the device address, but that will hurt backwards compatibility.
But this is new feature, there is no backward compatibility.
I meant making this change for the eeprom read and write commands as well, not just the new commands. I think that the new commands should follow the conventions of the original commands for consistency, I just wish the current conventions were less ambiguous than they are now (it's not possible to figure out what ommision of these parameters does without looking at the source code).
The EEPROM code is in horrible state, indeed. If you want to clean it up some more, I'd be real happy.
I'll be more than happy to redo the last 3 patches if we agree that we are willing to pay that price.
Best regards, Marek Vasut
-- Best regards, Marek Vasut
-- Best regards, Marek Vasut

On Wed, May 11, 2016 at 12:56:07PM +0300, Nikita Kiryanov wrote:
Hi Tom, Marek,
For the time being I do not wish to make additional refactoring to the code as I think it is better to wait until an alternative to the bus number is found. My changes follow the current implementation of the eeprom command, so if there are no additional comments, can this be applied?
I will give it a good hard look and think next week when I open up the merge window, thanks.
participants (3)
-
Marek Vasut
-
Nikita Kiryanov
-
Tom Rini