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