kbuild: fix CROSS_COMPILE settings in config.mk
[oweals/u-boot.git] / common / 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 <dm.h>
12 #include <asm/gpio.h>
13
14 #ifndef name_to_gpio
15 #define name_to_gpio(name) simple_strtoul(name, NULL, 10)
16 #endif
17
18 enum gpio_cmd {
19         GPIO_INPUT,
20         GPIO_SET,
21         GPIO_CLEAR,
22         GPIO_TOGGLE,
23 };
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
104 static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
105 {
106         unsigned int gpio;
107         enum gpio_cmd sub_cmd;
108         ulong value;
109         const char *str_cmd, *str_gpio = NULL;
110 #ifdef CONFIG_DM_GPIO
111         int ret;
112 #endif
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() */
122 #ifdef gpio_status
123                 gpio_status();
124                 return 0;
125 #elif defined(CONFIG_DM_GPIO)
126                 return cmd_process_error(cmdtp, do_gpio_status(str_gpio));
127 #else
128                 goto show_usage;
129 #endif
130         }
131
132         if (!str_gpio)
133                 goto show_usage;
134
135         /* parse the behavior */
136         switch (*str_cmd) {
137                 case 'i': sub_cmd = GPIO_INPUT;  break;
138                 case 's': sub_cmd = GPIO_SET;    break;
139                 case 'c': sub_cmd = GPIO_CLEAR;  break;
140                 case 't': sub_cmd = GPIO_TOGGLE; break;
141                 default:  goto show_usage;
142         }
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
156         /* turn the gpio name into a gpio number */
157         gpio = name_to_gpio(str_gpio);
158         if (gpio < 0)
159                 goto show_usage;
160 #endif
161         /* grab the pin before we tweak it */
162         if (gpio_request(gpio, "cmd_gpio")) {
163                 printf("gpio: requesting pin %u failed\n", gpio);
164                 return -1;
165         }
166
167         /* finally, let's do it: set direction and exec command */
168         if (sub_cmd == GPIO_INPUT) {
169                 gpio_direction_input(gpio);
170                 value = gpio_get_value(gpio);
171         } else {
172                 switch (sub_cmd) {
173                         case GPIO_SET:    value = 1; break;
174                         case GPIO_CLEAR:  value = 0; break;
175                         case GPIO_TOGGLE: value = !gpio_get_value(gpio); break;
176                         default:          goto show_usage;
177                 }
178                 gpio_direction_output(gpio, value);
179         }
180         printf("gpio: pin %s (gpio %i) value is %lu\n",
181                 str_gpio, gpio, value);
182
183         gpio_free(gpio);
184
185         return value;
186 }
187
188 U_BOOT_CMD(gpio, 3, 0, do_gpio,
189         "query and control gpio pins",
190         "<input|set|clear|toggle> <pin>\n"
191         "    - input/set/clear/toggle the specified pin\n"
192         "gpio status [<bank> | <pin>]");