[U-Boot] [PATCH v6 01/12] dm: gpio: Enhance gpio command to show only active GPIOs

Simon Glass sjg at chromium.org
Mon Aug 11 17:23:52 CEST 2014


The GPIO list is very long in many cases and most of them are not used.
By default, show only the GPIOs that are in use, and provide a flag to show
all of them. This makes the 'gpio status' command much more pleasant.

In order to do this, driver model now exposes a method for obtaining the
'function' of a GPIO, which describes whether it is an input or output, for
example. Implementation of this method is optional.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v6: None
Changes in v5: None
Changes in v4:
- Add new patch to enhance 'gpio' command

Changes in v3: None
Changes in v2: None

 common/cmd_gpio.c          | 101 +++++++++++++++++++++++++++++++--------------
 include/asm-generic/gpio.h |  15 ++++++-
 2 files changed, 82 insertions(+), 34 deletions(-)

diff --git a/common/cmd_gpio.c b/common/cmd_gpio.c
index 4634f91..b97533f 100644
--- a/common/cmd_gpio.c
+++ b/common/cmd_gpio.c
@@ -24,18 +24,46 @@ enum gpio_cmd {
 };
 
 #if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
-static const char * const gpio_function[] = {
+static const char * const gpio_function[GPIOF_COUNT] = {
 	"input",
 	"output",
+	"unused",
 	"unknown",
+	"func",
 };
 
-static void show_gpio(struct udevice *dev, const char *bank_name, int offset)
+/* A few flags used by show_gpio() */
+enum {
+	FLAG_SHOW_ALL		= 1 << 0,
+	FLAG_SHOW_BANK		= 1 << 1,
+	FLAG_SHOW_NEWLINE	= 1 << 2,
+};
+
+static void show_gpio(struct udevice *dev, const char *bank_name, int offset,
+		      int *flagsp)
 {
 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	int func = GPIOF_UNKNOWN;
 	char buf[80];
 	int ret;
 
+	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+
+	if (ops->get_function) {
+		ret = ops->get_function(dev, offset);
+		if (ret >= 0 && ret < ARRAY_SIZE(gpio_function))
+			func = ret;
+	}
+	if (!(*flagsp & FLAG_SHOW_ALL) && func == GPIOF_UNUSED)
+		return;
+	if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
+		if (*flagsp & FLAG_SHOW_NEWLINE) {
+			putc('\n');
+			*flagsp &= ~FLAG_SHOW_NEWLINE;
+		}
+		printf("Bank %s:\n", bank_name);
+		*flagsp &= ~FLAG_SHOW_BANK;
+	}
 	*buf = '\0';
 	if (ops->get_state) {
 		ret = ops->get_state(dev, offset, buf, sizeof(buf));
@@ -44,14 +72,6 @@ static void show_gpio(struct udevice *dev, const char *bank_name, int offset)
 			return;
 		}
 	} else {
-		int func =  GPIOF_UNKNOWN;
-		int ret;
-
-		if (ops->get_function) {
-			ret = ops->get_function(dev, offset);
-			if (ret >= 0 && ret < ARRAY_SIZE(gpio_function))
-				func = ret;
-		}
 		sprintf(buf, "%s%u: %8s %d", bank_name, offset,
 			gpio_function[func], ops->get_value(dev, offset));
 	}
@@ -60,12 +80,14 @@ static void show_gpio(struct udevice *dev, const char *bank_name, int offset)
 	puts("\n");
 }
 
-static int do_gpio_status(const char *gpio_name)
+static int do_gpio_status(bool all, const char *gpio_name)
 {
 	struct udevice *dev;
-	int newline = 0;
+	int banklen;
+	int flags;
 	int ret;
 
+	flags = 0;
 	if (gpio_name && !*gpio_name)
 		gpio_name = NULL;
 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
@@ -74,28 +96,33 @@ static int do_gpio_status(const char *gpio_name)
 		const char *bank_name;
 		int num_bits;
 
+		flags |= FLAG_SHOW_BANK;
+		if (all)
+			flags |= FLAG_SHOW_ALL;
 		bank_name = gpio_get_bank_info(dev, &num_bits);
+		if (!num_bits)
+			continue;
+		banklen = bank_name ? strlen(bank_name) : 0;
 
 		if (!gpio_name || !bank_name ||
-		    !strncmp(gpio_name, bank_name, strlen(bank_name))) {
+		    !strncmp(gpio_name, bank_name, banklen)) {
 			const char *p = NULL;
 			int offset;
 
-			if (bank_name) {
-				if (newline)
-					putc('\n');
-				printf("Bank %s:\n", bank_name);
-			}
-			newline = 1;
-			if (gpio_name && bank_name) {
-				p = gpio_name + strlen(bank_name);
+			p = gpio_name + banklen;
+			if (gpio_name && *p) {
 				offset = simple_strtoul(p, NULL, 10);
-				show_gpio(dev, bank_name, offset);
+				show_gpio(dev, bank_name, offset, &flags);
 			} else {
-				for (offset = 0; offset < num_bits; offset++)
-					show_gpio(dev, bank_name, offset);
+				for (offset = 0; offset < num_bits; offset++) {
+					show_gpio(dev, bank_name, offset,
+						  &flags);
+				}
 			}
 		}
+		/* Add a newline between bank names */
+		if (!(flags & FLAG_SHOW_BANK))
+			flags |= FLAG_SHOW_NEWLINE;
 	}
 
 	return ret;
@@ -109,6 +136,7 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	ulong value;
 	const char *str_cmd, *str_gpio = NULL;
 #ifdef CONFIG_DM_GPIO
+	bool all = false;
 	int ret;
 #endif
 
@@ -116,15 +144,24 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  show_usage:
 		return CMD_RET_USAGE;
 	str_cmd = argv[1];
-	if (argc > 2)
-		str_gpio = argv[2];
+	argc -= 2;
+	argv += 2;
+#ifdef CONFIG_DM_GPIO
+	if (argc > 0 && !strcmp(*argv, "-a")) {
+		all = true;
+		argc--;
+		argv++;
+	}
+#endif
+	if (argc > 0)
+		str_gpio = *argv;
 	if (!strcmp(str_cmd, "status")) {
 		/* Support deprecated gpio_status() */
 #ifdef gpio_status
 		gpio_status();
 		return 0;
 #elif defined(CONFIG_DM_GPIO)
-		return cmd_process_error(cmdtp, do_gpio_status(str_gpio));
+		return cmd_process_error(cmdtp, do_gpio_status(all, str_gpio));
 #else
 		goto show_usage;
 #endif
@@ -186,8 +223,8 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return value;
 }
 
-U_BOOT_CMD(gpio, 3, 0, do_gpio,
-	"query and control gpio pins",
-	"<input|set|clear|toggle> <pin>\n"
-	"    - input/set/clear/toggle the specified pin\n"
-	"gpio status [<bank> | <pin>]");
+U_BOOT_CMD(gpio, 4, 0, do_gpio,
+	   "query and control gpio pins",
+	   "<input|set|clear|toggle> <pin>\n"
+	   "    - input/set/clear/toggle the specified pin\n"
+	   "gpio status [-a] [<bank> | <pin>]  - show [all/claimed] GPIOs");
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a6e52a0..60539d8 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -79,11 +79,15 @@ int gpio_get_value(unsigned gpio);
  */
 int gpio_set_value(unsigned gpio, int value);
 
-/* State of a GPIO, as reported by get_state() */
+/* State of a GPIO, as reported by get_function() */
 enum {
 	GPIOF_INPUT = 0,
 	GPIOF_OUTPUT,
-	GPIOF_UNKNOWN,
+	GPIOF_UNUSED,		/* Not claimed */
+	GPIOF_UNKNOWN,		/* Not known */
+	GPIOF_FUNC,		/* Not used as a GPIO */
+
+	GPIOF_COUNT,
 };
 
 struct udevice;
@@ -123,6 +127,13 @@ struct dm_gpio_ops {
 				int value);
 	int (*get_value)(struct udevice *dev, unsigned offset);
 	int (*set_value)(struct udevice *dev, unsigned offset, int value);
+	/**
+	 * get_function() Get the GPIO function
+	 *
+	 * @dev:     Device to check
+	 * @offset:  GPIO offset within that device
+	 * @return current function - GPIOF_...
+	 */
 	int (*get_function)(struct udevice *dev, unsigned offset);
 	int (*get_state)(struct udevice *dev, unsigned offset, char *state,
 			 int maxlen);
-- 
2.0.0.526.g5318336



More information about the U-Boot mailing list