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