dm: gpio: Support numbered GPIOs
[platform/kernel/u-boot.git] / drivers / gpio / gpio-uclass.c
1 /*
2  * Copyright (c) 2013 Google, Inc
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <asm/gpio.h>
11 #include <linux/ctype.h>
12
13 /**
14  * gpio_to_device() - Convert global GPIO number to device, number
15  * gpio:        The numeric representation of the GPIO
16  *
17  * Convert the GPIO number to an entry in the list of GPIOs
18  * or GPIO blocks registered with the GPIO controller. Returns
19  * entry on success, NULL on error.
20  */
21 static int gpio_to_device(unsigned int gpio, struct udevice **devp,
22                           unsigned int *offset)
23 {
24         struct gpio_dev_priv *uc_priv;
25         struct udevice *dev;
26         int ret;
27
28         for (ret = uclass_first_device(UCLASS_GPIO, &dev);
29              dev;
30              ret = uclass_next_device(&dev)) {
31                 uc_priv = dev->uclass_priv;
32                 if (gpio >= uc_priv->gpio_base &&
33                     gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
34                         *devp = dev;
35                         *offset = gpio - uc_priv->gpio_base;
36                         return 0;
37                 }
38         }
39
40         /* No such GPIO */
41         return ret ? ret : -EINVAL;
42 }
43
44 int gpio_lookup_name(const char *name, struct udevice **devp,
45                      unsigned int *offsetp, unsigned int *gpiop)
46 {
47         struct gpio_dev_priv *uc_priv = NULL;
48         struct udevice *dev;
49         ulong offset;
50         int numeric;
51         int ret;
52
53         if (devp)
54                 *devp = NULL;
55         numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
56         for (ret = uclass_first_device(UCLASS_GPIO, &dev);
57              dev;
58              ret = uclass_next_device(&dev)) {
59                 int len;
60
61                 uc_priv = dev->uclass_priv;
62                 if (numeric != -1) {
63                         offset = numeric - uc_priv->gpio_base;
64                         /* Allow GPIOs to be numbered from 0 */
65                         if (offset >= 0 && offset < uc_priv->gpio_count)
66                                 break;
67                 }
68
69                 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
70
71                 if (!strncasecmp(name, uc_priv->bank_name, len)) {
72                         if (!strict_strtoul(name + len, 10, &offset))
73                                 break;
74                 }
75         }
76
77         if (!dev)
78                 return ret ? ret : -EINVAL;
79
80         if (devp)
81                 *devp = dev;
82         if (offsetp)
83                 *offsetp = offset;
84         if (gpiop)
85                 *gpiop = uc_priv->gpio_base + offset;
86
87         return 0;
88 }
89
90 /**
91  * gpio_request() - [COMPAT] Request GPIO
92  * gpio:        GPIO number
93  * label:       Name for the requested GPIO
94  *
95  * This function implements the API that's compatible with current
96  * GPIO API used in U-Boot. The request is forwarded to particular
97  * GPIO driver. Returns 0 on success, negative value on error.
98  */
99 int gpio_request(unsigned gpio, const char *label)
100 {
101         unsigned int offset;
102         struct udevice *dev;
103         int ret;
104
105         ret = gpio_to_device(gpio, &dev, &offset);
106         if (ret)
107                 return ret;
108
109         if (!gpio_get_ops(dev)->request)
110                 return 0;
111
112         return gpio_get_ops(dev)->request(dev, offset, label);
113 }
114
115 /**
116  * gpio_free() - [COMPAT] Relinquish GPIO
117  * gpio:        GPIO number
118  *
119  * This function implements the API that's compatible with current
120  * GPIO API used in U-Boot. The request is forwarded to particular
121  * GPIO driver. Returns 0 on success, negative value on error.
122  */
123 int gpio_free(unsigned gpio)
124 {
125         unsigned int offset;
126         struct udevice *dev;
127         int ret;
128
129         ret = gpio_to_device(gpio, &dev, &offset);
130         if (ret)
131                 return ret;
132
133         if (!gpio_get_ops(dev)->free)
134                 return 0;
135         return gpio_get_ops(dev)->free(dev, offset);
136 }
137
138 /**
139  * gpio_direction_input() - [COMPAT] Set GPIO direction to input
140  * gpio:        GPIO number
141  *
142  * This function implements the API that's compatible with current
143  * GPIO API used in U-Boot. The request is forwarded to particular
144  * GPIO driver. Returns 0 on success, negative value on error.
145  */
146 int gpio_direction_input(unsigned gpio)
147 {
148         unsigned int offset;
149         struct udevice *dev;
150         int ret;
151
152         ret = gpio_to_device(gpio, &dev, &offset);
153         if (ret)
154                 return ret;
155
156         return gpio_get_ops(dev)->direction_input(dev, offset);
157 }
158
159 /**
160  * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
161  * gpio:        GPIO number
162  * value:       Logical value to be set on the GPIO pin
163  *
164  * This function implements the API that's compatible with current
165  * GPIO API used in U-Boot. The request is forwarded to particular
166  * GPIO driver. Returns 0 on success, negative value on error.
167  */
168 int gpio_direction_output(unsigned gpio, int value)
169 {
170         unsigned int offset;
171         struct udevice *dev;
172         int ret;
173
174         ret = gpio_to_device(gpio, &dev, &offset);
175         if (ret)
176                 return ret;
177
178         return gpio_get_ops(dev)->direction_output(dev, offset, value);
179 }
180
181 /**
182  * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
183  * gpio:        GPIO number
184  *
185  * This function implements the API that's compatible with current
186  * GPIO API used in U-Boot. The request is forwarded to particular
187  * GPIO driver. Returns the value of the GPIO pin, or negative value
188  * on error.
189  */
190 int gpio_get_value(unsigned gpio)
191 {
192         unsigned int offset;
193         struct udevice *dev;
194         int ret;
195
196         ret = gpio_to_device(gpio, &dev, &offset);
197         if (ret)
198                 return ret;
199
200         return gpio_get_ops(dev)->get_value(dev, offset);
201 }
202
203 /**
204  * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
205  * gpio:        GPIO number
206  * value:       Logical value to be set on the GPIO pin.
207  *
208  * This function implements the API that's compatible with current
209  * GPIO API used in U-Boot. The request is forwarded to particular
210  * GPIO driver. Returns 0 on success, negative value on error.
211  */
212 int gpio_set_value(unsigned gpio, int value)
213 {
214         unsigned int offset;
215         struct udevice *dev;
216         int ret;
217
218         ret = gpio_to_device(gpio, &dev, &offset);
219         if (ret)
220                 return ret;
221
222         return gpio_get_ops(dev)->set_value(dev, offset, value);
223 }
224
225 const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
226 {
227         struct gpio_dev_priv *priv;
228
229         /* Must be called on an active device */
230         priv = dev->uclass_priv;
231         assert(priv);
232
233         *bit_count = priv->gpio_count;
234         return priv->bank_name;
235 }
236
237 /* We need to renumber the GPIOs when any driver is probed/removed */
238 static int gpio_renumber(void)
239 {
240         struct gpio_dev_priv *uc_priv;
241         struct udevice *dev;
242         struct uclass *uc;
243         unsigned base;
244         int ret;
245
246         ret = uclass_get(UCLASS_GPIO, &uc);
247         if (ret)
248                 return ret;
249
250         /* Ensure that we have a base for each bank */
251         base = 0;
252         uclass_foreach_dev(dev, uc) {
253                 if (device_active(dev)) {
254                         uc_priv = dev->uclass_priv;
255                         uc_priv->gpio_base = base;
256                         base += uc_priv->gpio_count;
257                 }
258         }
259
260         return 0;
261 }
262
263 static int gpio_post_probe(struct udevice *dev)
264 {
265         return gpio_renumber();
266 }
267
268 static int gpio_pre_remove(struct udevice *dev)
269 {
270         return gpio_renumber();
271 }
272
273 UCLASS_DRIVER(gpio) = {
274         .id             = UCLASS_GPIO,
275         .name           = "gpio",
276         .post_probe     = gpio_post_probe,
277         .pre_remove     = gpio_pre_remove,
278         .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
279 };