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