[PATCH 11/11] cmd: eeprom: Extend to EEPROMs probed via driver model

Marek Behún kabel at kernel.org
Tue May 21 09:13:35 CEST 2024


Extend the 'eeprom' command to allow accessing EEPROMs probed via
driver model, uclass UCLASS_I2C_EEPROM.

When the CONFIG_I2C_EEPROM config option is enabled (and so the
i2c-eeprom driver is built), the 'eeprom' command now accepts driver
model device name as EEPROM specifier for the 'eeprom' command, in
addition to the legacy [[bus] devaddr] specifier.

Moreover if no device specifier is given, then the first
UCLASS_I2C_EEPROM device is used, if found.

Signed-off-by: Marek Behún <kabel at kernel.org>
---
 cmd/eeprom.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 112 insertions(+), 10 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 9c4af88738..a39fc5ffdc 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -22,8 +22,10 @@
 #include <common.h>
 #include <config.h>
 #include <command.h>
+#include <dm.h>
 #include <eeprom.h>
 #include <i2c.h>
+#include <i2c_eeprom.h>
 #include <eeprom_layout.h>
 #include <linux/delay.h>
 
@@ -209,10 +211,41 @@ static long parse_numeric_param(char *str)
 }
 
 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_eeprom_dev_spec - parse the eeprom device specifier
  *
@@ -226,6 +259,28 @@ struct eeprom_dev_spec {
 static int parse_eeprom_dev_spec(struct eeprom_dev_spec *dev, int argc,
 				 char *const argv[])
 {
+#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 == 0) {
 		dev->i2c_bus = -1;
@@ -265,6 +320,7 @@ static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
 #endif
 
 enum eeprom_action {
+	EEPROM_LIST,
 	EEPROM_READ,
 	EEPROM_WRITE,
 	EEPROM_PRINT,
@@ -274,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))
@@ -288,6 +348,24 @@ static enum eeprom_action parse_action(char *cmd)
 	return EEPROM_ACTION_INVALID;
 }
 
+#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)
 {
@@ -298,9 +376,9 @@ static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool read,
 
 	printf(fmt, dev->i2c_addr, read ? "read" : "write", addr, off, cnt);
 	if (read)
-		ret = eeprom_read(dev->i2c_addr, off, memloc, cnt);
+		ret = eeprom_dev_spec_read(dev, off, memloc, cnt);
 	else
-		ret = eeprom_write(dev->i2c_addr, off, memloc, cnt);
+		ret = eeprom_dev_spec_write(dev, off, memloc, cnt);
 	puts("done\n");
 
 	return ret;
@@ -314,7 +392,7 @@ static int do_eeprom_layout(struct eeprom_dev_spec *dev, int layout_ver,
 	eeprom_layout_setup(layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
 			    layout_ver);
 
-	return eeprom_read(dev->i2c_addr, 0, eeprom_buf, layout->data_size);
+	return eeprom_dev_spec_read(dev, 0, eeprom_buf, layout->data_size);
 }
 
 static int do_eeprom_print(struct eeprom_dev_spec *dev, int layout_ver)
@@ -345,7 +423,7 @@ static int do_eeprom_update(struct eeprom_dev_spec *dev, int layout_ver,
 	if (ret)
 		return CMD_RET_FAILURE;
 
-	return eeprom_write(dev->i2c_addr, 0, layout.data, layout.data_size);
+	return eeprom_dev_spec_write(dev, 0, layout.data, layout.data_size);
 }
 
 #endif
@@ -353,6 +431,8 @@ static int do_eeprom_update(struct eeprom_dev_spec *dev, int layout_ver,
 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;
@@ -389,6 +469,11 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	if (action == EEPROM_ACTION_INVALID)
 		return CMD_RET_USAGE;
 
+#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")) {
@@ -425,7 +510,7 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	}
 #endif
 
-	eeprom_init(dev.i2c_bus);
+	eeprom_dev_spec_init(&dev);
 
 	switch (action) {
 	case EEPROM_READ:
@@ -450,19 +535,37 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 #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 " EEPROM_LAYOUT_SPEC "[[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 " EEPROM_LAYOUT_SPEC "[[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."
+#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"
@@ -471,5 +574,4 @@ U_BOOT_CMD(
 	"The values which can be provided with the -l option are:\n"
 	CONFIG_EEPROM_LAYOUT_HELP_STRING"\n"
 #endif
-#endif
 );
-- 
2.44.1



More information about the U-Boot mailing list