Coverage Report

Created: 2026-03-11 06:21

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