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