blob: e11c5a69c583fa3c2ab96269d28228bc942cc518 [file] [log] [blame]
Simon Glass96495d92014-02-26 15:59:24 -07001/*
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>
Simon Glassb892d122014-10-04 11:29:42 -060010#include <malloc.h>
Simon Glass96495d92014-02-26 15:59:24 -070011#include <asm/gpio.h>
Simon Glassfe1ef502014-10-22 21:37:01 -060012#include <linux/ctype.h>
Simon Glass96495d92014-02-26 15:59:24 -070013
14/**
15 * gpio_to_device() - Convert global GPIO number to device, number
16 * gpio: The numeric representation of the GPIO
17 *
18 * Convert the GPIO number to an entry in the list of GPIOs
19 * or GPIO blocks registered with the GPIO controller. Returns
20 * entry on success, NULL on error.
21 */
Heiko Schocher54c5d082014-05-22 12:43:05 +020022static int gpio_to_device(unsigned int gpio, struct udevice **devp,
Simon Glass96495d92014-02-26 15:59:24 -070023 unsigned int *offset)
24{
25 struct gpio_dev_priv *uc_priv;
Heiko Schocher54c5d082014-05-22 12:43:05 +020026 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -070027 int ret;
28
29 for (ret = uclass_first_device(UCLASS_GPIO, &dev);
30 dev;
31 ret = uclass_next_device(&dev)) {
32 uc_priv = dev->uclass_priv;
33 if (gpio >= uc_priv->gpio_base &&
34 gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
35 *devp = dev;
36 *offset = gpio - uc_priv->gpio_base;
37 return 0;
38 }
39 }
40
41 /* No such GPIO */
42 return ret ? ret : -EINVAL;
43}
44
Heiko Schocher54c5d082014-05-22 12:43:05 +020045int gpio_lookup_name(const char *name, struct udevice **devp,
Simon Glass96495d92014-02-26 15:59:24 -070046 unsigned int *offsetp, unsigned int *gpiop)
47{
Simon Glassfe1ef502014-10-22 21:37:01 -060048 struct gpio_dev_priv *uc_priv = NULL;
Heiko Schocher54c5d082014-05-22 12:43:05 +020049 struct udevice *dev;
Simon Glassfe1ef502014-10-22 21:37:01 -060050 ulong offset;
51 int numeric;
Simon Glass96495d92014-02-26 15:59:24 -070052 int ret;
53
54 if (devp)
55 *devp = NULL;
Simon Glassfe1ef502014-10-22 21:37:01 -060056 numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
Simon Glass96495d92014-02-26 15:59:24 -070057 for (ret = uclass_first_device(UCLASS_GPIO, &dev);
58 dev;
59 ret = uclass_next_device(&dev)) {
Simon Glass96495d92014-02-26 15:59:24 -070060 int len;
61
62 uc_priv = dev->uclass_priv;
Simon Glassfe1ef502014-10-22 21:37:01 -060063 if (numeric != -1) {
64 offset = numeric - uc_priv->gpio_base;
65 /* Allow GPIOs to be numbered from 0 */
66 if (offset >= 0 && offset < uc_priv->gpio_count)
67 break;
68 }
69
Simon Glass96495d92014-02-26 15:59:24 -070070 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
71
Simon Glass939cda52014-06-11 23:29:47 -060072 if (!strncasecmp(name, uc_priv->bank_name, len)) {
Simon Glassfe1ef502014-10-22 21:37:01 -060073 if (!strict_strtoul(name + len, 10, &offset))
74 break;
Simon Glass96495d92014-02-26 15:59:24 -070075 }
76 }
77
Simon Glassfe1ef502014-10-22 21:37:01 -060078 if (!dev)
79 return ret ? ret : -EINVAL;
80
81 if (devp)
82 *devp = dev;
83 if (offsetp)
84 *offsetp = offset;
85 if (gpiop)
86 *gpiop = uc_priv->gpio_base + offset;
87
88 return 0;
Simon Glass96495d92014-02-26 15:59:24 -070089}
90
91/**
92 * gpio_request() - [COMPAT] Request GPIO
93 * gpio: GPIO number
94 * label: Name for the requested GPIO
95 *
Simon Glassb892d122014-10-04 11:29:42 -060096 * The label is copied and allocated so the caller does not need to keep
97 * the pointer around.
98 *
Simon Glass96495d92014-02-26 15:59:24 -070099 * This function implements the API that's compatible with current
100 * GPIO API used in U-Boot. The request is forwarded to particular
101 * GPIO driver. Returns 0 on success, negative value on error.
102 */
103int gpio_request(unsigned gpio, const char *label)
104{
Simon Glassb892d122014-10-04 11:29:42 -0600105 struct gpio_dev_priv *uc_priv;
Simon Glass96495d92014-02-26 15:59:24 -0700106 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200107 struct udevice *dev;
Simon Glassb892d122014-10-04 11:29:42 -0600108 char *str;
Simon Glass96495d92014-02-26 15:59:24 -0700109 int ret;
110
111 ret = gpio_to_device(gpio, &dev, &offset);
112 if (ret)
113 return ret;
114
Simon Glassb892d122014-10-04 11:29:42 -0600115 uc_priv = dev->uclass_priv;
116 if (uc_priv->name[offset])
117 return -EBUSY;
118 str = strdup(label);
119 if (!str)
120 return -ENOMEM;
121 if (gpio_get_ops(dev)->request) {
122 ret = gpio_get_ops(dev)->request(dev, offset, label);
123 if (ret) {
124 free(str);
125 return ret;
126 }
127 }
128 uc_priv->name[offset] = str;
Simon Glass96495d92014-02-26 15:59:24 -0700129
Simon Glassb892d122014-10-04 11:29:42 -0600130 return 0;
Simon Glass96495d92014-02-26 15:59:24 -0700131}
132
133/**
134 * gpio_free() - [COMPAT] Relinquish GPIO
135 * gpio: GPIO number
136 *
137 * This function implements the API that's compatible with current
138 * GPIO API used in U-Boot. The request is forwarded to particular
139 * GPIO driver. Returns 0 on success, negative value on error.
140 */
141int gpio_free(unsigned gpio)
142{
Simon Glassb892d122014-10-04 11:29:42 -0600143 struct gpio_dev_priv *uc_priv;
Simon Glass96495d92014-02-26 15:59:24 -0700144 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200145 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700146 int ret;
147
148 ret = gpio_to_device(gpio, &dev, &offset);
149 if (ret)
150 return ret;
151
Simon Glassb892d122014-10-04 11:29:42 -0600152 uc_priv = dev->uclass_priv;
153 if (!uc_priv->name[offset])
154 return -ENXIO;
155 if (gpio_get_ops(dev)->free) {
156 ret = gpio_get_ops(dev)->free(dev, offset);
157 if (ret)
158 return ret;
159 }
160
161 free(uc_priv->name[offset]);
162 uc_priv->name[offset] = NULL;
163
164 return 0;
165}
166
167static int check_reserved(struct udevice *dev, unsigned offset,
168 const char *func)
169{
170 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
171
172 if (!uc_priv->name[offset]) {
173 printf("%s: %s: error: gpio %s%d not reserved\n",
174 dev->name, func,
175 uc_priv->bank_name ? uc_priv->bank_name : "", offset);
176 return -EBUSY;
177 }
178
179 return 0;
Simon Glass96495d92014-02-26 15:59:24 -0700180}
181
182/**
183 * gpio_direction_input() - [COMPAT] Set GPIO direction to input
184 * gpio: GPIO number
185 *
186 * This function implements the API that's compatible with current
187 * GPIO API used in U-Boot. The request is forwarded to particular
188 * GPIO driver. Returns 0 on success, negative value on error.
189 */
190int gpio_direction_input(unsigned gpio)
191{
192 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200193 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700194 int ret;
195
196 ret = gpio_to_device(gpio, &dev, &offset);
197 if (ret)
198 return ret;
Simon Glassb892d122014-10-04 11:29:42 -0600199 ret = check_reserved(dev, offset, "dir_input");
Simon Glass96495d92014-02-26 15:59:24 -0700200
Simon Glassb892d122014-10-04 11:29:42 -0600201 return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
Simon Glass96495d92014-02-26 15:59:24 -0700202}
203
204/**
205 * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
206 * gpio: GPIO number
207 * value: Logical value to be set on the GPIO pin
208 *
209 * This function implements the API that's compatible with current
210 * GPIO API used in U-Boot. The request is forwarded to particular
211 * GPIO driver. Returns 0 on success, negative value on error.
212 */
213int gpio_direction_output(unsigned gpio, int value)
214{
215 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200216 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700217 int ret;
218
219 ret = gpio_to_device(gpio, &dev, &offset);
220 if (ret)
221 return ret;
Simon Glassb892d122014-10-04 11:29:42 -0600222 ret = check_reserved(dev, offset, "dir_output");
Simon Glass96495d92014-02-26 15:59:24 -0700223
Simon Glassb892d122014-10-04 11:29:42 -0600224 return ret ? ret :
225 gpio_get_ops(dev)->direction_output(dev, offset, value);
Simon Glass96495d92014-02-26 15:59:24 -0700226}
227
228/**
229 * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
230 * gpio: GPIO number
231 *
232 * This function implements the API that's compatible with current
233 * GPIO API used in U-Boot. The request is forwarded to particular
234 * GPIO driver. Returns the value of the GPIO pin, or negative value
235 * on error.
236 */
237int gpio_get_value(unsigned gpio)
238{
239 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200240 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700241 int ret;
242
243 ret = gpio_to_device(gpio, &dev, &offset);
244 if (ret)
245 return ret;
Simon Glassb892d122014-10-04 11:29:42 -0600246 ret = check_reserved(dev, offset, "get_value");
Simon Glass96495d92014-02-26 15:59:24 -0700247
Simon Glassb892d122014-10-04 11:29:42 -0600248 return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
Simon Glass96495d92014-02-26 15:59:24 -0700249}
250
251/**
252 * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
253 * gpio: GPIO number
254 * value: Logical value to be set on the GPIO pin.
255 *
256 * This function implements the API that's compatible with current
257 * GPIO API used in U-Boot. The request is forwarded to particular
258 * GPIO driver. Returns 0 on success, negative value on error.
259 */
260int gpio_set_value(unsigned gpio, int value)
261{
262 unsigned int offset;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200263 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700264 int ret;
265
266 ret = gpio_to_device(gpio, &dev, &offset);
267 if (ret)
268 return ret;
Simon Glassb892d122014-10-04 11:29:42 -0600269 ret = check_reserved(dev, offset, "set_value");
Simon Glass96495d92014-02-26 15:59:24 -0700270
Simon Glassb892d122014-10-04 11:29:42 -0600271 return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
Simon Glass96495d92014-02-26 15:59:24 -0700272}
273
Heiko Schocher54c5d082014-05-22 12:43:05 +0200274const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
Simon Glass96495d92014-02-26 15:59:24 -0700275{
276 struct gpio_dev_priv *priv;
277
278 /* Must be called on an active device */
279 priv = dev->uclass_priv;
280 assert(priv);
281
282 *bit_count = priv->gpio_count;
283 return priv->bank_name;
284}
285
286/* We need to renumber the GPIOs when any driver is probed/removed */
Simon Glassb892d122014-10-04 11:29:42 -0600287static int gpio_renumber(struct udevice *removed_dev)
Simon Glass96495d92014-02-26 15:59:24 -0700288{
289 struct gpio_dev_priv *uc_priv;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200290 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -0700291 struct uclass *uc;
292 unsigned base;
293 int ret;
294
295 ret = uclass_get(UCLASS_GPIO, &uc);
296 if (ret)
297 return ret;
298
299 /* Ensure that we have a base for each bank */
300 base = 0;
301 uclass_foreach_dev(dev, uc) {
Simon Glassb892d122014-10-04 11:29:42 -0600302 if (device_active(dev) && dev != removed_dev) {
Simon Glass96495d92014-02-26 15:59:24 -0700303 uc_priv = dev->uclass_priv;
304 uc_priv->gpio_base = base;
305 base += uc_priv->gpio_count;
306 }
307 }
308
309 return 0;
310}
311
Heiko Schocher54c5d082014-05-22 12:43:05 +0200312static int gpio_post_probe(struct udevice *dev)
Simon Glass96495d92014-02-26 15:59:24 -0700313{
Simon Glassb892d122014-10-04 11:29:42 -0600314 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
315
316 uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
317 if (!uc_priv->name)
318 return -ENOMEM;
319
320 return gpio_renumber(NULL);
Simon Glass96495d92014-02-26 15:59:24 -0700321}
322
Heiko Schocher54c5d082014-05-22 12:43:05 +0200323static int gpio_pre_remove(struct udevice *dev)
Simon Glass96495d92014-02-26 15:59:24 -0700324{
Simon Glassb892d122014-10-04 11:29:42 -0600325 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
326 int i;
327
328 for (i = 0; i < uc_priv->gpio_count; i++) {
329 if (uc_priv->name[i])
330 free(uc_priv->name[i]);
331 }
332 free(uc_priv->name);
333
334 return gpio_renumber(dev);
Simon Glass96495d92014-02-26 15:59:24 -0700335}
336
337UCLASS_DRIVER(gpio) = {
338 .id = UCLASS_GPIO,
339 .name = "gpio",
340 .post_probe = gpio_post_probe,
341 .pre_remove = gpio_pre_remove,
342 .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
343};