dm: gpio: Enhance gpio command to show only active GPIOs
authorSimon Glass <sjg@chromium.org>
Mon, 11 Aug 2014 15:23:52 +0000 (09:23 -0600)
committerSimon Glass <sjg@chromium.org>
Mon, 1 Sep 2014 05:21:06 +0000 (23:21 -0600)
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@chromium.org>
common/cmd_gpio.c
include/asm-generic/gpio.h

index 4634f914e66d97a0bc9fe0f244fb957cf4b544d1..b97533f313d3960c0b22f03108b779946a533724 100644 (file)
@@ -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");
index a6e52a0de63cd3d535674a140d6d4b4cac966264..60539d8a9d24fc113e9d8f839a9f84244fbe1a23 100644 (file)
@@ -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);