Merge branch '2021-05-24-add-lto-support'
[platform/kernel/u-boot.git] / cmd / gpio.c
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 simple_strtoul(name, NULL, 10);
21 }
22
23 enum 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() */
33 enum {
34         FLAG_SHOW_ALL           = 1 << 0,
35         FLAG_SHOW_BANK          = 1 << 1,
36         FLAG_SHOW_NEWLINE       = 1 << 2,
37 };
38
39 static 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;
65 err:
66         printf("Error %d\n", ret);
67 }
68
69 static 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 = simple_strtoul(p, NULL, 10);
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
121 static 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
260 err:
261         if (ret != -EBUSY)
262                 gpio_free(gpio);
263         return CMD_RET_FAILURE;
264 }
265
266 U_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");