]> Git Repo - J-u-boot.git/blobdiff - cmd/eeprom.c
Merge patch series "Add OPP_LOW support for J7200"
[J-u-boot.git] / cmd / eeprom.c
index 26f3750a80adb02ec26fb3af6e82ee3bb357e99b..cf89cfce3e4d1e71b9b2d066b2644871c6a38ca6 100644 (file)
 
 #include <config.h>
 #include <command.h>
+#include <dm.h>
 #include <eeprom.h>
 #include <i2c.h>
+#include <i2c_eeprom.h>
 #include <eeprom_layout.h>
 #include <vsprintf.h>
 #include <linux/delay.h>
@@ -208,41 +210,95 @@ static long parse_numeric_param(char *str)
        return (*endptr != '\0') ? -1 : value;
 }
 
+struct eeprom_dev_spec {
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       struct udevice *dev;
+#endif
+       int i2c_bus;
+       ulong i2c_addr;
+};
+
+static void eeprom_dev_spec_init(struct eeprom_dev_spec *dev)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (!dev->dev)
+#endif
+               eeprom_init(dev->i2c_bus);
+}
+
+static int eeprom_dev_spec_read(struct eeprom_dev_spec *dev,
+                               unsigned offset, uchar *buffer, unsigned cnt)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (dev->dev)
+               return i2c_eeprom_read(dev->dev, offset, buffer, cnt);
+#endif
+       return eeprom_read(dev->i2c_addr, offset, buffer, cnt);
+}
+
+static int eeprom_dev_spec_write(struct eeprom_dev_spec *dev,
+                                unsigned offset, uchar *buffer, unsigned cnt)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (dev->dev)
+               return i2c_eeprom_write(dev->dev, offset, buffer, cnt);
+#endif
+       return eeprom_write(dev->i2c_addr, offset, buffer, cnt);
+}
+
 /**
- * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters
+ * parse_eeprom_dev_spec - parse the eeprom device specifier
  *
- * @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
+ * @dev:       pointer to eeprom device specifier
+ * @argc:      count of command line arguments that can be used to parse
+ *             the device specifier
  * @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)
+static int parse_eeprom_dev_spec(struct eeprom_dev_spec *dev, int argc,
+                                char *const argv[])
 {
-       int argc_no_bus = argc_no_bus_addr + 1;
-       int argc_bus_addr = argc_no_bus_addr + 2;
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (argc == 0) {
+               if (!uclass_first_device_err(UCLASS_I2C_EEPROM, &dev->dev))
+                       return 0;
+       }
+
+       if (argc == 1) {
+               if (!uclass_get_device_by_name(UCLASS_I2C_EEPROM, argv[0],
+                                              &dev->dev))
+                       return 1;
+
+               /*
+                * If we could not find the device by name and the parameter is
+                * not numeric (and so won't be handled later), fail.
+                */
+               if (parse_numeric_param(argv[0]) == -1) {
+                       printf("Can't get eeprom device: %s\n", argv[0]);
+                       return CMD_RET_USAGE;
+               }
+       }
+#endif
 
 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR
-       if (argc == argc_no_bus_addr) {
-               *i2c_bus = -1;
-               *i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
+       if (argc == 0) {
+               dev->i2c_bus = -1;
+               dev->i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
 
                return 0;
        }
 #endif
-       if (argc == argc_no_bus) {
-               *i2c_bus = -1;
-               *i2c_addr = parse_numeric_param(argv[0]);
+       if (argc == 1) {
+               dev->i2c_bus = -1;
+               dev->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]);
+       if (argc == 2) {
+               dev->i2c_bus = parse_numeric_param(argv[0]);
+               dev->i2c_addr = parse_numeric_param(argv[1]);
 
                return 2;
        }
@@ -252,16 +308,19 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
 
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
 
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
 __weak int eeprom_parse_layout_version(char *str)
 {
        return LAYOUT_VERSION_UNRECOGNIZED;
 }
+#endif
 
 static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
 
 #endif
 
 enum eeprom_action {
+       EEPROM_LIST,
        EEPROM_READ,
        EEPROM_WRITE,
        EEPROM_PRINT,
@@ -271,6 +330,10 @@ enum eeprom_action {
 
 static enum eeprom_action parse_action(char *cmd)
 {
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (!strncmp(cmd, "list", 4))
+               return EEPROM_LIST;
+#endif
        if (!strncmp(cmd, "read", 4))
                return EEPROM_READ;
        if (!strncmp(cmd, "write", 5))
@@ -285,68 +348,115 @@ static enum eeprom_action parse_action(char *cmd)
        return EEPROM_ACTION_INVALID;
 }
 
-static int eeprom_execute_command(enum eeprom_action action, int i2c_bus,
-                                 ulong i2c_addr, int layout_ver, char *key,
-                                 char *value, ulong addr, ulong off, ulong cnt)
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+static int do_eeprom_list(void)
+{
+       struct udevice *dev;
+       struct uclass *uc;
+       int err;
+
+       err = uclass_get(UCLASS_I2C_EEPROM, &uc);
+       if (err)
+               return CMD_RET_FAILURE;
+
+       uclass_foreach_dev(dev, uc)
+               printf("%s (%s)\n", dev->name, dev->driver->name);
+
+       return CMD_RET_SUCCESS;
+}
+#endif
+
+static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool read,
+                       ulong addr, ulong off, ulong cnt)
 {
-       int rcode = 0;
        const char *const fmt =
                "\nEEPROM @0x%lX %s: addr 0x%08lx  off 0x%04lx  count %ld ... ";
+       uchar *memloc = (uchar *)addr;
+       int ret;
+
+       printf(fmt, dev->i2c_addr, read ? "read" : "write", addr, off, cnt);
+       if (read)
+               ret = eeprom_dev_spec_read(dev, off, memloc, cnt);
+       else
+               ret = eeprom_dev_spec_write(dev, off, memloc, cnt);
+       puts("done\n");
+
+       return ret;
+}
+
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
-       struct eeprom_layout layout;
-#endif
 
-       if (action == EEPROM_ACTION_INVALID)
-               return CMD_RET_USAGE;
+static int do_eeprom_layout(struct eeprom_dev_spec *dev, int layout_ver,
+                           struct eeprom_layout *layout)
+{
+       eeprom_layout_setup(layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
+                           layout_ver);
 
-       eeprom_init(i2c_bus);
-       if (action == EEPROM_READ) {
-               printf(fmt, i2c_addr, "read", addr, off, cnt);
+       return eeprom_dev_spec_read(dev, 0, eeprom_buf, layout->data_size);
+}
 
-               rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt);
+static int do_eeprom_print(struct eeprom_dev_spec *dev, int layout_ver)
+{
+       struct eeprom_layout layout;
+       int ret;
 
-               puts("done\n");
-               return rcode;
-       } else if (action == EEPROM_WRITE) {
-               printf(fmt, i2c_addr, "write", addr, off, cnt);
+       ret = do_eeprom_layout(dev, layout_ver, &layout);
+       if (ret)
+               return ret;
 
-               rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt);
+       layout.print(&layout);
 
-               puts("done\n");
-               return rcode;
-       }
+       return 0;
+}
 
-#ifdef CONFIG_CMD_EEPROM_LAYOUT
-       rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
-       if (rcode < 0)
-               return rcode;
+static int do_eeprom_update(struct eeprom_dev_spec *dev, int layout_ver,
+                           char *key, char *value)
+{
+       struct eeprom_layout layout;
+       int ret;
 
-       eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
-                           layout_ver);
+       ret = do_eeprom_layout(dev, layout_ver, &layout);
+       if (ret)
+               return ret;
 
-       if (action == EEPROM_PRINT) {
-               layout.print(&layout);
-               return 0;
-       }
+       ret = layout.update(&layout, key, value);
+       if (ret)
+               return CMD_RET_FAILURE;
 
-       layout.update(&layout, key, value);
+       return eeprom_dev_spec_write(dev, 0, layout.data, layout.data_size);
+}
 
-       rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE);
 #endif
 
-       return rcode;
+static int eeprom_action_expected_argc(enum eeprom_action action)
+{
+       switch (action) {
+       case EEPROM_LIST:
+               return 0;
+       case EEPROM_READ:
+       case EEPROM_WRITE:
+               return 3;
+       case EEPROM_PRINT:
+               return 0;
+       case EEPROM_UPDATE:
+               return 2;
+       default:
+               return CMD_RET_USAGE;
+       }
 }
 
 #define NEXT_PARAM(argc, index)        { (argc)--; (index)++; }
 int do_eeprom(struct cmd_tbl *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, index = 0;
-       ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0;
-       int ret;
+       struct eeprom_dev_spec dev;
+       ulong addr = 0, cnt = 0, off = 0;
+       int ret, index = 0;
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
        char *field_name = "";
        char *field_value = "";
+       int layout_ver = LAYOUT_VERSION_AUTODETECT;
+#endif
 
        if (argc <= 1)
                return CMD_RET_USAGE;
@@ -359,7 +469,12 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        if (action == EEPROM_ACTION_INVALID)
                return CMD_RET_USAGE;
 
-#ifdef CONFIG_CMD_EEPROM_LAYOUT
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       if (action == EEPROM_LIST)
+               return do_eeprom_list();
+#endif
+
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
        if (action == EEPROM_PRINT || action == EEPROM_UPDATE) {
                if (!strcmp(argv[index], "-l")) {
                        NEXT_PARAM(argc, index);
@@ -369,25 +484,9 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        }
 #endif
 
-       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;
-       }
-
+       ret = parse_eeprom_dev_spec(&dev,
+                                   argc - eeprom_action_expected_argc(action),
+                                   argv + index);
        if (ret == CMD_RET_USAGE)
                return ret;
 
@@ -411,24 +510,64 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        }
 #endif
 
-       return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver,
-                                     field_name, field_value, addr, off, cnt);
+       eeprom_dev_spec_init(&dev);
+
+       switch (action) {
+       case EEPROM_READ:
+       case EEPROM_WRITE:
+               return do_eeprom_rw(&dev, action == EEPROM_READ,
+                                   addr, off, cnt);
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+       case EEPROM_PRINT:
+               return do_eeprom_print(&dev, layout_ver);
+       case EEPROM_UPDATE:
+               return do_eeprom_update(&dev, layout_ver,
+                                       field_name, field_value);
+#endif
+       default:
+               return CMD_RET_USAGE;
+       }
 }
 
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
+#define EEPROM_LAYOUT_SPEC     "[-l <layout_version>] "
+#else
+#define EEPROM_LAYOUT_SPEC     ""
+#endif
+
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+# define EEPROM_DEV_SPEC       "[device_specifier]"
+#else
+# define EEPROM_DEV_SPEC       "[[bus] devaddr]"
+#endif
+
 U_BOOT_CMD(
        eeprom, 8,      1,      do_eeprom,
        "EEPROM sub-system",
-       "read  <bus> <devaddr> addr off cnt\n"
-       "eeprom write <bus> <devaddr> addr off cnt\n"
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       "list\n"
+       "eeprom "
+#endif
+       "read  " EEPROM_DEV_SPEC " addr off cnt\n"
+       "eeprom write " EEPROM_DEV_SPEC " 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"
+       "eeprom print " EEPROM_LAYOUT_SPEC EEPROM_DEV_SPEC "\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 " EEPROM_LAYOUT_SPEC EEPROM_DEV_SPEC " 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"
+       "         The new data must be written in the same human readable format as shown by the print command."
+#endif
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+       "\n\n"
+       "DEVICE SPECIFIER - the eeprom device can be specified\n"
+       "  [dev_name] - by device name (devices can listed with the eeprom list command)\n"
+       "  [[bus] devaddr] - or by I2C bus and I2C device address\n"
+       "If no device specifier is given, the first driver-model found device is used."
+#endif
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
+       "\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"
This page took 0.037208 seconds and 4 git commands to generate.