Commit 95a260a98c010321cdc5f2acd1f4272b9c0a19dc
Committed by
Tom Rini
1 parent
e2d8a714a7
Exists in
v2017.01-smarct4x
and in
48 other branches
dm: Enable gpio command to support driver model
Now that named GPIO banks are supported, along with a way of obtaining the status of a GPIO (input or output), we can provide an enhanced GPIO command for driver model. Where the driver provides its own operation for obtaining the GPIO state, this is used, otherwise a generic version is sufficient. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 1 changed file with 116 additions and 13 deletions Side-by-side Diff
common/cmd_gpio.c
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | |
9 | 9 | #include <common.h> |
10 | 10 | #include <command.h> |
11 | - | |
11 | +#include <dm.h> | |
12 | 12 | #include <asm/gpio.h> |
13 | 13 | |
14 | 14 | #ifndef name_to_gpio |
15 | 15 | |
16 | 16 | |
17 | 17 | |
18 | 18 | |
19 | 19 | |
20 | 20 | |
21 | 21 | |
... | ... | @@ -22,25 +22,115 @@ |
22 | 22 | GPIO_TOGGLE, |
23 | 23 | }; |
24 | 24 | |
25 | +#if defined(CONFIG_DM_GPIO) && !defined(gpio_status) | |
26 | +static const char * const gpio_function[] = { | |
27 | + "input", | |
28 | + "output", | |
29 | + "unknown", | |
30 | +}; | |
31 | + | |
32 | +static void show_gpio(struct device *dev, const char *bank_name, int offset) | |
33 | +{ | |
34 | + struct dm_gpio_ops *ops = gpio_get_ops(dev); | |
35 | + char buf[80]; | |
36 | + int ret; | |
37 | + | |
38 | + *buf = '\0'; | |
39 | + if (ops->get_state) { | |
40 | + ret = ops->get_state(dev, offset, buf, sizeof(buf)); | |
41 | + if (ret) { | |
42 | + puts("<unknown>"); | |
43 | + return; | |
44 | + } | |
45 | + } else { | |
46 | + int func = GPIOF_UNKNOWN; | |
47 | + int ret; | |
48 | + | |
49 | + if (ops->get_function) { | |
50 | + ret = ops->get_function(dev, offset); | |
51 | + if (ret >= 0 && ret < ARRAY_SIZE(gpio_function)) | |
52 | + func = ret; | |
53 | + } | |
54 | + sprintf(buf, "%s%u: %8s %d", bank_name, offset, | |
55 | + gpio_function[func], ops->get_value(dev, offset)); | |
56 | + } | |
57 | + | |
58 | + puts(buf); | |
59 | + puts("\n"); | |
60 | +} | |
61 | + | |
62 | +static int do_gpio_status(const char *gpio_name) | |
63 | +{ | |
64 | + struct device *dev; | |
65 | + int newline = 0; | |
66 | + int ret; | |
67 | + | |
68 | + if (gpio_name && !*gpio_name) | |
69 | + gpio_name = NULL; | |
70 | + for (ret = uclass_first_device(UCLASS_GPIO, &dev); | |
71 | + dev; | |
72 | + ret = uclass_next_device(&dev)) { | |
73 | + const char *bank_name; | |
74 | + int num_bits; | |
75 | + | |
76 | + bank_name = gpio_get_bank_info(dev, &num_bits); | |
77 | + | |
78 | + if (!gpio_name || !bank_name || | |
79 | + !strncmp(gpio_name, bank_name, strlen(bank_name))) { | |
80 | + const char *p = NULL; | |
81 | + int offset; | |
82 | + | |
83 | + if (bank_name) { | |
84 | + if (newline) | |
85 | + putc('\n'); | |
86 | + printf("Bank %s:\n", bank_name); | |
87 | + } | |
88 | + newline = 1; | |
89 | + if (gpio_name && bank_name) { | |
90 | + p = gpio_name + strlen(bank_name); | |
91 | + offset = simple_strtoul(p, NULL, 10); | |
92 | + show_gpio(dev, bank_name, offset); | |
93 | + } else { | |
94 | + for (offset = 0; offset < num_bits; offset++) | |
95 | + show_gpio(dev, bank_name, offset); | |
96 | + } | |
97 | + } | |
98 | + } | |
99 | + | |
100 | + return ret; | |
101 | +} | |
102 | +#endif | |
103 | + | |
25 | 104 | static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
26 | 105 | { |
27 | - int gpio; | |
106 | + unsigned int gpio; | |
28 | 107 | enum gpio_cmd sub_cmd; |
29 | 108 | ulong value; |
30 | - const char *str_cmd, *str_gpio; | |
109 | + const char *str_cmd, *str_gpio = NULL; | |
110 | +#ifdef CONFIG_DM_GPIO | |
111 | + int ret; | |
112 | +#endif | |
31 | 113 | |
114 | + if (argc < 2) | |
115 | + show_usage: | |
116 | + return CMD_RET_USAGE; | |
117 | + str_cmd = argv[1]; | |
118 | + if (argc > 2) | |
119 | + str_gpio = argv[2]; | |
120 | + if (!strcmp(str_cmd, "status")) { | |
121 | + /* Support deprecated gpio_status() */ | |
32 | 122 | #ifdef gpio_status |
33 | - if (argc == 2 && !strcmp(argv[1], "status")) { | |
34 | 123 | gpio_status(); |
35 | 124 | return 0; |
36 | - } | |
125 | +#elif defined(CONFIG_DM_GPIO) | |
126 | + return cmd_process_error(cmdtp, do_gpio_status(str_gpio)); | |
127 | +#else | |
128 | + goto show_usage; | |
37 | 129 | #endif |
130 | + } | |
38 | 131 | |
39 | - if (argc != 3) | |
40 | - show_usage: | |
41 | - return CMD_RET_USAGE; | |
42 | - str_cmd = argv[1]; | |
43 | - str_gpio = argv[2]; | |
132 | + if (!str_gpio) | |
133 | + goto show_usage; | |
44 | 134 | |
45 | 135 | /* parse the behavior */ |
46 | 136 | switch (*str_cmd) { |
47 | 137 | |
... | ... | @@ -51,11 +141,23 @@ |
51 | 141 | default: goto show_usage; |
52 | 142 | } |
53 | 143 | |
144 | +#if defined(CONFIG_DM_GPIO) | |
145 | + /* | |
146 | + * TODO(sjg@chromium.org): For now we must fit into the existing GPIO | |
147 | + * framework, so we look up the name here and convert it to a GPIO number. | |
148 | + * Once all GPIO drivers are converted to driver model, we can change the | |
149 | + * code here to use the GPIO uclass interface instead of the numbered | |
150 | + * GPIO compatibility layer. | |
151 | + */ | |
152 | + ret = gpio_lookup_name(str_gpio, NULL, NULL, &gpio); | |
153 | + if (ret) | |
154 | + return cmd_process_error(cmdtp, ret); | |
155 | +#else | |
54 | 156 | /* turn the gpio name into a gpio number */ |
55 | 157 | gpio = name_to_gpio(str_gpio); |
56 | 158 | if (gpio < 0) |
57 | 159 | goto show_usage; |
58 | - | |
160 | +#endif | |
59 | 161 | /* grab the pin before we tweak it */ |
60 | 162 | if (gpio_request(gpio, "cmd_gpio")) { |
61 | 163 | printf("gpio: requesting pin %u failed\n", gpio); |
62 | 164 | |
... | ... | @@ -84,7 +186,8 @@ |
84 | 186 | } |
85 | 187 | |
86 | 188 | U_BOOT_CMD(gpio, 3, 0, do_gpio, |
87 | - "input/set/clear/toggle gpio pins", | |
189 | + "query and control gpio pins", | |
88 | 190 | "<input|set|clear|toggle> <pin>\n" |
89 | - " - input/set/clear/toggle the specified pin"); | |
191 | + " - input/set/clear/toggle the specified pin\n" | |
192 | + "gpio status [<bank> | <pin>]"); |