uboot/cmd/gpio.c
<<
>>
Prefs
   1/*
   2 * Control GPIO pins on the fly
   3 *
   4 * Copyright (c) 2008-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <common.h>
  10#include <command.h>
  11#include <errno.h>
  12#include <dm.h>
  13#include <log.h>
  14#include <malloc.h>
  15#include <asm/gpio.h>
  16#include <linux/err.h>
  17
  18__weak int name_to_gpio(const char *name)
  19{
  20        return dectoul(name, NULL);
  21}
  22
  23enum gpio_cmd {
  24        GPIOC_INPUT,
  25        GPIOC_SET,
  26        GPIOC_CLEAR,
  27        GPIOC_TOGGLE,
  28};
  29
  30#if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
  31
  32/* A few flags used by show_gpio() */
  33enum {
  34        FLAG_SHOW_ALL           = 1 << 0,
  35        FLAG_SHOW_BANK          = 1 << 1,
  36        FLAG_SHOW_NEWLINE       = 1 << 2,
  37};
  38
  39static void gpio_get_description(struct udevice *dev, const char *bank_name,
  40                                 int offset, int *flagsp, bool show_all)
  41{
  42        char buf[80];
  43        int ret;
  44
  45        ret = gpio_get_function(dev, offset, NULL);
  46        if (ret < 0)
  47                goto err;
  48        if (!show_all && !(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
  49                return;
  50        if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
  51                if (*flagsp & FLAG_SHOW_NEWLINE) {
  52                        putc('\n');
  53                        *flagsp &= ~FLAG_SHOW_NEWLINE;
  54                }
  55                printf("Bank %s:\n", bank_name);
  56                *flagsp &= ~FLAG_SHOW_BANK;
  57        }
  58
  59        ret = gpio_get_status(dev, offset, buf, sizeof(buf));
  60        if (ret)
  61                goto err;
  62
  63        printf("%s\n", buf);
  64        return;
  65err:
  66        printf("Error %d\n", ret);
  67}
  68
  69static int do_gpio_status(bool all, const char *gpio_name)
  70{
  71        struct udevice *dev;
  72        int banklen;
  73        int flags;
  74        int ret;
  75
  76        flags = 0;
  77        if (gpio_name && !*gpio_name)
  78                gpio_name = NULL;
  79        for (ret = uclass_first_device(UCLASS_GPIO, &dev);
  80             dev;
  81             ret = uclass_next_device(&dev)) {
  82                const char *bank_name;
  83                int num_bits;
  84
  85                flags |= FLAG_SHOW_BANK;
  86                if (all)
  87                        flags |= FLAG_SHOW_ALL;
  88                bank_name = gpio_get_bank_info(dev, &num_bits);
  89                if (!num_bits) {
  90                        debug("GPIO device %s has no bits\n", dev->name);
  91                        continue;
  92                }
  93                banklen = bank_name ? strlen(bank_name) : 0;
  94
  95                if (!gpio_name || !bank_name ||
  96                    !strncasecmp(gpio_name, bank_name, banklen)) {
  97                        const char *p;
  98                        int offset;
  99
 100                        p = gpio_name + banklen;
 101                        if (gpio_name && *p) {
 102                                offset = dectoul(p, NULL);
 103                                gpio_get_description(dev, bank_name, offset,
 104                                                     &flags, true);
 105                        } else {
 106                                for (offset = 0; offset < num_bits; offset++) {
 107                                        gpio_get_description(dev, bank_name,
 108                                                     offset, &flags, false);
 109                                }
 110                        }
 111                }
 112                /* Add a newline between bank names */
 113                if (!(flags & FLAG_SHOW_BANK))
 114                        flags |= FLAG_SHOW_NEWLINE;
 115        }
 116
 117        return ret;
 118}
 119#endif
 120
 121static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 122                   char *const argv[])
 123{
 124        unsigned int gpio;
 125        enum gpio_cmd sub_cmd;
 126        int value;
 127        const char *str_cmd, *str_gpio = NULL;
 128        int ret;
 129#ifdef CONFIG_DM_GPIO
 130        bool all = false;
 131#endif
 132
 133        if (argc < 2)
 134 show_usage:
 135                return CMD_RET_USAGE;
 136        str_cmd = argv[1];
 137        argc -= 2;
 138        argv += 2;
 139#ifdef CONFIG_DM_GPIO
 140        if (argc > 0 && !strcmp(*argv, "-a")) {
 141                all = true;
 142                argc--;
 143                argv++;
 144        }
 145#endif
 146        if (argc > 0)
 147                str_gpio = *argv;
 148        if (!strncmp(str_cmd, "status", 2)) {
 149                /* Support deprecated gpio_status() */
 150#ifdef gpio_status
 151                gpio_status();
 152                return 0;
 153#elif defined(CONFIG_DM_GPIO)
 154                return cmd_process_error(cmdtp, do_gpio_status(all, str_gpio));
 155#else
 156                goto show_usage;
 157#endif
 158        }
 159
 160        if (!str_gpio)
 161                goto show_usage;
 162
 163        /* parse the behavior */
 164        switch (*str_cmd) {
 165        case 'i':
 166                sub_cmd = GPIOC_INPUT;
 167                break;
 168        case 's':
 169                sub_cmd = GPIOC_SET;
 170                break;
 171        case 'c':
 172                sub_cmd = GPIOC_CLEAR;
 173                break;
 174        case 't':
 175                sub_cmd = GPIOC_TOGGLE;
 176                break;
 177        default:
 178                goto show_usage;
 179        }
 180
 181#if defined(CONFIG_DM_GPIO)
 182        /*
 183         * TODO(sjg@chromium.org): For now we must fit into the existing GPIO
 184         * framework, so we look up the name here and convert it to a GPIO number.
 185         * Once all GPIO drivers are converted to driver model, we can change the
 186         * code here to use the GPIO uclass interface instead of the numbered
 187         * GPIO compatibility layer.
 188         */
 189        ret = gpio_lookup_name(str_gpio, NULL, NULL, &gpio);
 190        if (ret) {
 191                printf("GPIO: '%s' not found\n", str_gpio);
 192                return cmd_process_error(cmdtp, ret);
 193        }
 194#else
 195        /* turn the gpio name into a gpio number */
 196        gpio = name_to_gpio(str_gpio);
 197        if (gpio < 0)
 198                goto show_usage;
 199#endif
 200        /* grab the pin before we tweak it */
 201        ret = gpio_request(gpio, "cmd_gpio");
 202        if (ret && ret != -EBUSY) {
 203                printf("gpio: requesting pin %u failed\n", gpio);
 204                return -1;
 205        }
 206
 207        /* finally, let's do it: set direction and exec command */
 208        if (sub_cmd == GPIOC_INPUT) {
 209                gpio_direction_input(gpio);
 210                value = gpio_get_value(gpio);
 211        } else {
 212                switch (sub_cmd) {
 213                case GPIOC_SET:
 214                        value = 1;
 215                        break;
 216                case GPIOC_CLEAR:
 217                        value = 0;
 218                        break;
 219                case GPIOC_TOGGLE:
 220                        value = gpio_get_value(gpio);
 221                        if (!IS_ERR_VALUE(value))
 222                                value = !value;
 223                        break;
 224                default:
 225                        goto show_usage;
 226                }
 227                gpio_direction_output(gpio, value);
 228        }
 229        printf("gpio: pin %s (gpio %u) value is ", str_gpio, gpio);
 230
 231        if (IS_ERR_VALUE(value)) {
 232                printf("unknown (ret=%d)\n", value);
 233                goto err;
 234        } else {
 235                printf("%d\n", value);
 236        }
 237
 238        if (sub_cmd != GPIOC_INPUT && !IS_ERR_VALUE(value)) {
 239                int nval = gpio_get_value(gpio);
 240
 241                if (IS_ERR_VALUE(nval)) {
 242                        printf("   Warning: no access to GPIO output value\n");
 243                        goto err;
 244                } else if (nval != value) {
 245                        printf("   Warning: value of pin is still %d\n", nval);
 246                        goto err;
 247                }
 248        }
 249
 250        if (ret != -EBUSY)
 251                gpio_free(gpio);
 252
 253        /*
 254         * Whilst wrong, the legacy gpio input command returns the pin
 255         * value, or CMD_RET_FAILURE (which is indistinguishable from a
 256         * valid pin value).
 257         */
 258        return (sub_cmd == GPIOC_INPUT) ? value : CMD_RET_SUCCESS;
 259
 260err:
 261        if (ret != -EBUSY)
 262                gpio_free(gpio);
 263        return CMD_RET_FAILURE;
 264}
 265
 266U_BOOT_CMD(gpio, 4, 0, do_gpio,
 267           "query and control gpio pins",
 268           "<input|set|clear|toggle> <pin>\n"
 269           "    - input/set/clear/toggle the specified pin\n"
 270           "gpio status [-a] [<bank> | <pin>]  - show [all/claimed] GPIOs");
 271