blob: a5ffd85c42f1005fc80417886d2033c3148a20d4 [file] [log] [blame]
Simon Glasse821d182014-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>
10#include <asm/gpio.h>
Simon Glass43b2e1a2014-10-22 21:37:01 -060011#include <linux/ctype.h>
Simon Glasse821d182014-02-26 15:59:24 -070012
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 */
Heiko Schocherb74fcb42014-05-22 12:43:05 +020021static int gpio_to_device(unsigned int gpio, struct udevice **devp,
Simon Glasse821d182014-02-26 15:59:24 -070022 unsigned int *offset)
23{
24 struct gpio_dev_priv *uc_priv;
Heiko Schocherb74fcb42014-05-22 12:43:05 +020025 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -070026 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
Heiko Schocherb74fcb42014-05-22 12:43:05 +020044int gpio_lookup_name(const char *name, struct udevice **devp,
Simon Glasse821d182014-02-26 15:59:24 -070045 unsigned int *offsetp, unsigned int *gpiop)
46{
Simon Glass43b2e1a2014-10-22 21:37:01 -060047 struct gpio_dev_priv *uc_priv = NULL;
Heiko Schocherb74fcb42014-05-22 12:43:05 +020048 struct udevice *dev;
Simon Glass43b2e1a2014-10-22 21:37:01 -060049 ulong offset;
50 int numeric;
Simon Glasse821d182014-02-26 15:59:24 -070051 int ret;
52
53 if (devp)
54 *devp = NULL;
Simon Glass43b2e1a2014-10-22 21:37:01 -060055 numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
Simon Glasse821d182014-02-26 15:59:24 -070056 for (ret = uclass_first_device(UCLASS_GPIO, &dev);
57 dev;
58 ret = uclass_next_device(&dev)) {
Simon Glasse821d182014-02-26 15:59:24 -070059 int len;
60
61 uc_priv = dev->uclass_priv;
Simon Glass43b2e1a2014-10-22 21:37:01 -060062 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
Simon Glasse821d182014-02-26 15:59:24 -070069 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
70
Simon Glassd4acf632014-06-11 23:29:47 -060071 if (!strncasecmp(name, uc_priv->bank_name, len)) {
Simon Glass43b2e1a2014-10-22 21:37:01 -060072 if (!strict_strtoul(name + len, 10, &offset))
73 break;
Simon Glasse821d182014-02-26 15:59:24 -070074 }
75 }
76
Simon Glass43b2e1a2014-10-22 21:37:01 -060077 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;
Simon Glasse821d182014-02-26 15:59:24 -070088}
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 */
99int gpio_request(unsigned gpio, const char *label)
100{
101 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200102 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700103 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 */
123int gpio_free(unsigned gpio)
124{
125 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200126 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700127 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 */
146int gpio_direction_input(unsigned gpio)
147{
148 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200149 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700150 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 */
168int gpio_direction_output(unsigned gpio, int value)
169{
170 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200171 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700172 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 */
190int gpio_get_value(unsigned gpio)
191{
192 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200193 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700194 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 */
212int gpio_set_value(unsigned gpio, int value)
213{
214 unsigned int offset;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200215 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700216 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
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200225const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
Simon Glasse821d182014-02-26 15:59:24 -0700226{
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 */
238static int gpio_renumber(void)
239{
240 struct gpio_dev_priv *uc_priv;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200241 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -0700242 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
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200263static int gpio_post_probe(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -0700264{
265 return gpio_renumber();
266}
267
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200268static int gpio_pre_remove(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -0700269{
270 return gpio_renumber();
271}
272
273UCLASS_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};