xref: /openbmc/u-boot/drivers/gpio/gpio-uclass.c (revision ae7123f876357a81fc4c393239a378f1058cad5e)
196495d90SSimon Glass /*
296495d90SSimon Glass  * Copyright (c) 2013 Google, Inc
396495d90SSimon Glass  *
496495d90SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
596495d90SSimon Glass  */
696495d90SSimon Glass 
796495d90SSimon Glass #include <common.h>
896495d90SSimon Glass #include <dm.h>
996495d90SSimon Glass #include <errno.h>
10b892d127SSimon Glass #include <malloc.h>
1196495d90SSimon Glass #include <asm/gpio.h>
12fe1ef503SSimon Glass #include <linux/ctype.h>
1396495d90SSimon Glass 
1496495d90SSimon Glass /**
1596495d90SSimon Glass  * gpio_to_device() - Convert global GPIO number to device, number
1696495d90SSimon Glass  *
1796495d90SSimon Glass  * Convert the GPIO number to an entry in the list of GPIOs
1896495d90SSimon Glass  * or GPIO blocks registered with the GPIO controller. Returns
1996495d90SSimon Glass  * entry on success, NULL on error.
20*ae7123f8SSimon Glass  *
21*ae7123f8SSimon Glass  * @gpio:	The numeric representation of the GPIO
22*ae7123f8SSimon Glass  * @desc:	Returns description (desc->flags will always be 0)
23*ae7123f8SSimon Glass  * @return 0 if found, -ENOENT if not found
2496495d90SSimon Glass  */
25*ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
2696495d90SSimon Glass {
2796495d90SSimon Glass 	struct gpio_dev_priv *uc_priv;
2854c5d08aSHeiko Schocher 	struct udevice *dev;
2996495d90SSimon Glass 	int ret;
3096495d90SSimon Glass 
3196495d90SSimon Glass 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
3296495d90SSimon Glass 	     dev;
3396495d90SSimon Glass 	     ret = uclass_next_device(&dev)) {
3496495d90SSimon Glass 		uc_priv = dev->uclass_priv;
3596495d90SSimon Glass 		if (gpio >= uc_priv->gpio_base &&
3696495d90SSimon Glass 		    gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
37*ae7123f8SSimon Glass 			desc->dev = dev;
38*ae7123f8SSimon Glass 			desc->offset = gpio - uc_priv->gpio_base;
39*ae7123f8SSimon Glass 			desc->flags = 0;
4096495d90SSimon Glass 			return 0;
4196495d90SSimon Glass 		}
4296495d90SSimon Glass 	}
4396495d90SSimon Glass 
4496495d90SSimon Glass 	/* No such GPIO */
45*ae7123f8SSimon Glass 	return ret ? ret : -ENOENT;
4696495d90SSimon Glass }
4796495d90SSimon Glass 
4854c5d08aSHeiko Schocher int gpio_lookup_name(const char *name, struct udevice **devp,
4996495d90SSimon Glass 		     unsigned int *offsetp, unsigned int *gpiop)
5096495d90SSimon Glass {
51fe1ef503SSimon Glass 	struct gpio_dev_priv *uc_priv = NULL;
5254c5d08aSHeiko Schocher 	struct udevice *dev;
53fe1ef503SSimon Glass 	ulong offset;
54fe1ef503SSimon Glass 	int numeric;
5596495d90SSimon Glass 	int ret;
5696495d90SSimon Glass 
5796495d90SSimon Glass 	if (devp)
5896495d90SSimon Glass 		*devp = NULL;
59fe1ef503SSimon Glass 	numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
6096495d90SSimon Glass 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
6196495d90SSimon Glass 	     dev;
6296495d90SSimon Glass 	     ret = uclass_next_device(&dev)) {
6396495d90SSimon Glass 		int len;
6496495d90SSimon Glass 
6596495d90SSimon Glass 		uc_priv = dev->uclass_priv;
66fe1ef503SSimon Glass 		if (numeric != -1) {
67fe1ef503SSimon Glass 			offset = numeric - uc_priv->gpio_base;
68fe1ef503SSimon Glass 			/* Allow GPIOs to be numbered from 0 */
69fe1ef503SSimon Glass 			if (offset >= 0 && offset < uc_priv->gpio_count)
70fe1ef503SSimon Glass 				break;
71fe1ef503SSimon Glass 		}
72fe1ef503SSimon Glass 
7396495d90SSimon Glass 		len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
7496495d90SSimon Glass 
75939cda5bSSimon Glass 		if (!strncasecmp(name, uc_priv->bank_name, len)) {
76fe1ef503SSimon Glass 			if (!strict_strtoul(name + len, 10, &offset))
77fe1ef503SSimon Glass 				break;
78fe1ef503SSimon Glass 		}
79fe1ef503SSimon Glass 	}
80fe1ef503SSimon Glass 
81fe1ef503SSimon Glass 	if (!dev)
82fe1ef503SSimon Glass 		return ret ? ret : -EINVAL;
83fe1ef503SSimon Glass 
8496495d90SSimon Glass 	if (devp)
8596495d90SSimon Glass 		*devp = dev;
8696495d90SSimon Glass 	if (offsetp)
8796495d90SSimon Glass 		*offsetp = offset;
8896495d90SSimon Glass 	if (gpiop)
8996495d90SSimon Glass 		*gpiop = uc_priv->gpio_base + offset;
9096495d90SSimon Glass 
91fe1ef503SSimon Glass 	return 0;
9296495d90SSimon Glass }
9396495d90SSimon Glass 
94*ae7123f8SSimon Glass static int dm_gpio_request(struct gpio_desc *desc, const char *label)
95*ae7123f8SSimon Glass {
96*ae7123f8SSimon Glass 	struct udevice *dev = desc->dev;
97*ae7123f8SSimon Glass 	struct gpio_dev_priv *uc_priv;
98*ae7123f8SSimon Glass 	char *str;
99*ae7123f8SSimon Glass 	int ret;
100*ae7123f8SSimon Glass 
101*ae7123f8SSimon Glass 	uc_priv = dev->uclass_priv;
102*ae7123f8SSimon Glass 	if (uc_priv->name[desc->offset])
103*ae7123f8SSimon Glass 		return -EBUSY;
104*ae7123f8SSimon Glass 	str = strdup(label);
105*ae7123f8SSimon Glass 	if (!str)
106*ae7123f8SSimon Glass 		return -ENOMEM;
107*ae7123f8SSimon Glass 	if (gpio_get_ops(dev)->request) {
108*ae7123f8SSimon Glass 		ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
109*ae7123f8SSimon Glass 		if (ret) {
110*ae7123f8SSimon Glass 			free(str);
111*ae7123f8SSimon Glass 			return ret;
112*ae7123f8SSimon Glass 		}
113*ae7123f8SSimon Glass 	}
114*ae7123f8SSimon Glass 	uc_priv->name[desc->offset] = str;
115*ae7123f8SSimon Glass 
116*ae7123f8SSimon Glass 	return 0;
117*ae7123f8SSimon Glass }
118*ae7123f8SSimon Glass 
11996495d90SSimon Glass /**
12096495d90SSimon Glass  * gpio_request() - [COMPAT] Request GPIO
12196495d90SSimon Glass  * gpio:	GPIO number
12296495d90SSimon Glass  * label:	Name for the requested GPIO
12396495d90SSimon Glass  *
124b892d127SSimon Glass  * The label is copied and allocated so the caller does not need to keep
125b892d127SSimon Glass  * the pointer around.
126b892d127SSimon Glass  *
12796495d90SSimon Glass  * This function implements the API that's compatible with current
12896495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
12996495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
13096495d90SSimon Glass  */
13196495d90SSimon Glass int gpio_request(unsigned gpio, const char *label)
13296495d90SSimon Glass {
133*ae7123f8SSimon Glass 	struct gpio_desc desc;
13496495d90SSimon Glass 	int ret;
13596495d90SSimon Glass 
136*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
13796495d90SSimon Glass 	if (ret)
13896495d90SSimon Glass 		return ret;
13996495d90SSimon Glass 
140*ae7123f8SSimon Glass 	return dm_gpio_request(&desc, label);
14196495d90SSimon Glass }
14296495d90SSimon Glass 
14396495d90SSimon Glass /**
144d44f597bSSimon Glass  * gpio_requestf() - [COMPAT] Request GPIO
145d44f597bSSimon Glass  * @gpio:	GPIO number
146d44f597bSSimon Glass  * @fmt:	Format string for the requested GPIO
147d44f597bSSimon Glass  * @...:	Arguments for the printf() format string
148d44f597bSSimon Glass  *
149d44f597bSSimon Glass  * This function implements the API that's compatible with current
150d44f597bSSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
151d44f597bSSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
152d44f597bSSimon Glass  */
153d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...)
154d44f597bSSimon Glass {
155d44f597bSSimon Glass 	va_list args;
156d44f597bSSimon Glass 	char buf[40];
157d44f597bSSimon Glass 
158d44f597bSSimon Glass 	va_start(args, fmt);
159d44f597bSSimon Glass 	vscnprintf(buf, sizeof(buf), fmt, args);
160d44f597bSSimon Glass 	va_end(args);
161d44f597bSSimon Glass 	return gpio_request(gpio, buf);
162d44f597bSSimon Glass }
163d44f597bSSimon Glass 
164*ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset)
16596495d90SSimon Glass {
166b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv;
16796495d90SSimon Glass 	int ret;
16896495d90SSimon Glass 
169b892d127SSimon Glass 	uc_priv = dev->uclass_priv;
170b892d127SSimon Glass 	if (!uc_priv->name[offset])
171b892d127SSimon Glass 		return -ENXIO;
172b892d127SSimon Glass 	if (gpio_get_ops(dev)->free) {
173b892d127SSimon Glass 		ret = gpio_get_ops(dev)->free(dev, offset);
174b892d127SSimon Glass 		if (ret)
175b892d127SSimon Glass 			return ret;
176b892d127SSimon Glass 	}
177b892d127SSimon Glass 
178b892d127SSimon Glass 	free(uc_priv->name[offset]);
179b892d127SSimon Glass 	uc_priv->name[offset] = NULL;
180b892d127SSimon Glass 
18196495d90SSimon Glass 	return 0;
182b892d127SSimon Glass }
183b892d127SSimon Glass 
184*ae7123f8SSimon Glass /**
185*ae7123f8SSimon Glass  * gpio_free() - [COMPAT] Relinquish GPIO
186*ae7123f8SSimon Glass  * gpio:	GPIO number
187*ae7123f8SSimon Glass  *
188*ae7123f8SSimon Glass  * This function implements the API that's compatible with current
189*ae7123f8SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
190*ae7123f8SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
191*ae7123f8SSimon Glass  */
192*ae7123f8SSimon Glass int gpio_free(unsigned gpio)
193b892d127SSimon Glass {
194*ae7123f8SSimon Glass 	struct gpio_desc desc;
195*ae7123f8SSimon Glass 	int ret;
196b892d127SSimon Glass 
197*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
198*ae7123f8SSimon Glass 	if (ret)
199*ae7123f8SSimon Glass 		return ret;
200*ae7123f8SSimon Glass 
201*ae7123f8SSimon Glass 	return _dm_gpio_free(desc.dev, desc.offset);
202*ae7123f8SSimon Glass }
203*ae7123f8SSimon Glass 
204*ae7123f8SSimon Glass static int check_reserved(struct gpio_desc *desc, const char *func)
205*ae7123f8SSimon Glass {
206*ae7123f8SSimon Glass 	struct gpio_dev_priv *uc_priv = desc->dev->uclass_priv;
207*ae7123f8SSimon Glass 
208*ae7123f8SSimon Glass 	if (!uc_priv->name[desc->offset]) {
209b892d127SSimon Glass 		printf("%s: %s: error: gpio %s%d not reserved\n",
210*ae7123f8SSimon Glass 		       desc->dev->name, func,
211*ae7123f8SSimon Glass 		       uc_priv->bank_name ? uc_priv->bank_name : "",
212*ae7123f8SSimon Glass 		       desc->offset);
213b892d127SSimon Glass 		return -EBUSY;
214b892d127SSimon Glass 	}
215b892d127SSimon Glass 
216b892d127SSimon Glass 	return 0;
21796495d90SSimon Glass }
21896495d90SSimon Glass 
21996495d90SSimon Glass /**
22096495d90SSimon Glass  * gpio_direction_input() - [COMPAT] Set GPIO direction to input
22196495d90SSimon Glass  * gpio:	GPIO number
22296495d90SSimon Glass  *
22396495d90SSimon Glass  * This function implements the API that's compatible with current
22496495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
22596495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
22696495d90SSimon Glass  */
22796495d90SSimon Glass int gpio_direction_input(unsigned gpio)
22896495d90SSimon Glass {
229*ae7123f8SSimon Glass 	struct gpio_desc desc;
23096495d90SSimon Glass 	int ret;
23196495d90SSimon Glass 
232*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
23396495d90SSimon Glass 	if (ret)
23496495d90SSimon Glass 		return ret;
235*ae7123f8SSimon Glass 	ret = check_reserved(&desc, "dir_input");
236*ae7123f8SSimon Glass 	if (ret)
237*ae7123f8SSimon Glass 		return ret;
23896495d90SSimon Glass 
239*ae7123f8SSimon Glass 	return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
24096495d90SSimon Glass }
24196495d90SSimon Glass 
24296495d90SSimon Glass /**
24396495d90SSimon Glass  * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
24496495d90SSimon Glass  * gpio:	GPIO number
24596495d90SSimon Glass  * value:	Logical value to be set on the GPIO pin
24696495d90SSimon Glass  *
24796495d90SSimon Glass  * This function implements the API that's compatible with current
24896495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
24996495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
25096495d90SSimon Glass  */
25196495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value)
25296495d90SSimon Glass {
253*ae7123f8SSimon Glass 	struct gpio_desc desc;
25496495d90SSimon Glass 	int ret;
25596495d90SSimon Glass 
256*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
25796495d90SSimon Glass 	if (ret)
25896495d90SSimon Glass 		return ret;
259*ae7123f8SSimon Glass 	ret = check_reserved(&desc, "dir_output");
260*ae7123f8SSimon Glass 	if (ret)
261*ae7123f8SSimon Glass 		return ret;
26296495d90SSimon Glass 
263*ae7123f8SSimon Glass 	return gpio_get_ops(desc.dev)->direction_output(desc.dev,
264*ae7123f8SSimon Glass 							desc.offset, value);
265*ae7123f8SSimon Glass }
266*ae7123f8SSimon Glass 
267*ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc)
268*ae7123f8SSimon Glass {
269*ae7123f8SSimon Glass 	int value;
270*ae7123f8SSimon Glass 	int ret;
271*ae7123f8SSimon Glass 
272*ae7123f8SSimon Glass 	ret = check_reserved(desc, "get_value");
273*ae7123f8SSimon Glass 	if (ret)
274*ae7123f8SSimon Glass 		return ret;
275*ae7123f8SSimon Glass 
276*ae7123f8SSimon Glass 	value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
277*ae7123f8SSimon Glass 
278*ae7123f8SSimon Glass 	return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
279*ae7123f8SSimon Glass }
280*ae7123f8SSimon Glass 
281*ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value)
282*ae7123f8SSimon Glass {
283*ae7123f8SSimon Glass 	int ret;
284*ae7123f8SSimon Glass 
285*ae7123f8SSimon Glass 	ret = check_reserved(desc, "set_value");
286*ae7123f8SSimon Glass 	if (ret)
287*ae7123f8SSimon Glass 		return ret;
288*ae7123f8SSimon Glass 
289*ae7123f8SSimon Glass 	if (desc->flags & GPIOD_ACTIVE_LOW)
290*ae7123f8SSimon Glass 		value = !value;
291*ae7123f8SSimon Glass 	gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
292*ae7123f8SSimon Glass 	return 0;
293*ae7123f8SSimon Glass }
294*ae7123f8SSimon Glass 
295*ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
296*ae7123f8SSimon Glass {
297*ae7123f8SSimon Glass 	struct udevice *dev = desc->dev;
298*ae7123f8SSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
299*ae7123f8SSimon Glass 	int ret;
300*ae7123f8SSimon Glass 
301*ae7123f8SSimon Glass 	ret = check_reserved(desc, "set_dir");
302*ae7123f8SSimon Glass 	if (ret)
303*ae7123f8SSimon Glass 		return ret;
304*ae7123f8SSimon Glass 
305*ae7123f8SSimon Glass 	if (flags & GPIOD_IS_OUT) {
306*ae7123f8SSimon Glass 		int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
307*ae7123f8SSimon Glass 
308*ae7123f8SSimon Glass 		if (flags & GPIOD_ACTIVE_LOW)
309*ae7123f8SSimon Glass 			value = !value;
310*ae7123f8SSimon Glass 		ret = ops->direction_output(dev, desc->offset, value);
311*ae7123f8SSimon Glass 	} else  if (flags & GPIOD_IS_IN) {
312*ae7123f8SSimon Glass 		ret = ops->direction_input(dev, desc->offset);
313*ae7123f8SSimon Glass 	}
314*ae7123f8SSimon Glass 	if (ret)
315*ae7123f8SSimon Glass 		return ret;
316*ae7123f8SSimon Glass 	/*
317*ae7123f8SSimon Glass 	 * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in
318*ae7123f8SSimon Glass 	 * futures
319*ae7123f8SSimon Glass 	 */
320*ae7123f8SSimon Glass 	desc->flags = flags;
321*ae7123f8SSimon Glass 
322*ae7123f8SSimon Glass 	return 0;
323*ae7123f8SSimon Glass }
324*ae7123f8SSimon Glass 
325*ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc)
326*ae7123f8SSimon Glass {
327*ae7123f8SSimon Glass 	return dm_gpio_set_dir_flags(desc, desc->flags);
32896495d90SSimon Glass }
32996495d90SSimon Glass 
33096495d90SSimon Glass /**
33196495d90SSimon Glass  * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
33296495d90SSimon Glass  * gpio:	GPIO number
33396495d90SSimon Glass  *
33496495d90SSimon Glass  * This function implements the API that's compatible with current
33596495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
33696495d90SSimon Glass  * GPIO driver. Returns the value of the GPIO pin, or negative value
33796495d90SSimon Glass  * on error.
33896495d90SSimon Glass  */
33996495d90SSimon Glass int gpio_get_value(unsigned gpio)
34096495d90SSimon Glass {
34196495d90SSimon Glass 	int ret;
34296495d90SSimon Glass 
343*ae7123f8SSimon Glass 	struct gpio_desc desc;
344*ae7123f8SSimon Glass 
345*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
34696495d90SSimon Glass 	if (ret)
34796495d90SSimon Glass 		return ret;
348*ae7123f8SSimon Glass 	return dm_gpio_get_value(&desc);
34996495d90SSimon Glass }
35096495d90SSimon Glass 
35196495d90SSimon Glass /**
35296495d90SSimon Glass  * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
35396495d90SSimon Glass  * gpio:	GPIO number
35496495d90SSimon Glass  * value:	Logical value to be set on the GPIO pin.
35596495d90SSimon Glass  *
35696495d90SSimon Glass  * This function implements the API that's compatible with current
35796495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
35896495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
35996495d90SSimon Glass  */
36096495d90SSimon Glass int gpio_set_value(unsigned gpio, int value)
36196495d90SSimon Glass {
362*ae7123f8SSimon Glass 	struct gpio_desc desc;
36396495d90SSimon Glass 	int ret;
36496495d90SSimon Glass 
365*ae7123f8SSimon Glass 	ret = gpio_to_device(gpio, &desc);
36696495d90SSimon Glass 	if (ret)
36796495d90SSimon Glass 		return ret;
368*ae7123f8SSimon Glass 	return dm_gpio_set_value(&desc, value);
36996495d90SSimon Glass }
37096495d90SSimon Glass 
37154c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
37296495d90SSimon Glass {
37396495d90SSimon Glass 	struct gpio_dev_priv *priv;
37496495d90SSimon Glass 
37596495d90SSimon Glass 	/* Must be called on an active device */
37696495d90SSimon Glass 	priv = dev->uclass_priv;
37796495d90SSimon Glass 	assert(priv);
37896495d90SSimon Glass 
37996495d90SSimon Glass 	*bit_count = priv->gpio_count;
38096495d90SSimon Glass 	return priv->bank_name;
38196495d90SSimon Glass }
38296495d90SSimon Glass 
3836449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = {
3846449a506SSimon Glass 	"input",
3856449a506SSimon Glass 	"output",
3866449a506SSimon Glass 	"unused",
3876449a506SSimon Glass 	"unknown",
3886449a506SSimon Glass 	"func",
3896449a506SSimon Glass };
3906449a506SSimon Glass 
3916449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused,
3926449a506SSimon Glass 		 const char **namep)
3936449a506SSimon Glass {
3946449a506SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
3956449a506SSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
3966449a506SSimon Glass 
3976449a506SSimon Glass 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
3986449a506SSimon Glass 	if (!device_active(dev))
3996449a506SSimon Glass 		return -ENODEV;
4006449a506SSimon Glass 	if (offset < 0 || offset >= uc_priv->gpio_count)
4016449a506SSimon Glass 		return -EINVAL;
4026449a506SSimon Glass 	if (namep)
4036449a506SSimon Glass 		*namep = uc_priv->name[offset];
4046449a506SSimon Glass 	if (skip_unused && !uc_priv->name[offset])
4056449a506SSimon Glass 		return GPIOF_UNUSED;
4066449a506SSimon Glass 	if (ops->get_function) {
4076449a506SSimon Glass 		int ret;
4086449a506SSimon Glass 
4096449a506SSimon Glass 		ret = ops->get_function(dev, offset);
4106449a506SSimon Glass 		if (ret < 0)
4116449a506SSimon Glass 			return ret;
4126449a506SSimon Glass 		if (ret >= ARRAY_SIZE(gpio_function))
4136449a506SSimon Glass 			return -ENODATA;
4146449a506SSimon Glass 		return ret;
4156449a506SSimon Glass 	}
4166449a506SSimon Glass 
4176449a506SSimon Glass 	return GPIOF_UNKNOWN;
4186449a506SSimon Glass }
4196449a506SSimon Glass 
4206449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep)
4216449a506SSimon Glass {
4226449a506SSimon Glass 	return get_function(dev, offset, true, namep);
4236449a506SSimon Glass }
4246449a506SSimon Glass 
4256449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
4266449a506SSimon Glass {
4276449a506SSimon Glass 	return get_function(dev, offset, false, namep);
4286449a506SSimon Glass }
4296449a506SSimon Glass 
4300757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
4310757535aSSimon Glass {
4320757535aSSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
4330757535aSSimon Glass 	struct gpio_dev_priv *priv;
4340757535aSSimon Glass 	char *str = buf;
4350757535aSSimon Glass 	int func;
4360757535aSSimon Glass 	int ret;
4370757535aSSimon Glass 	int len;
4380757535aSSimon Glass 
4390757535aSSimon Glass 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
4400757535aSSimon Glass 
4410757535aSSimon Glass 	*buf = 0;
4420757535aSSimon Glass 	priv = dev->uclass_priv;
4430757535aSSimon Glass 	ret = gpio_get_raw_function(dev, offset, NULL);
4440757535aSSimon Glass 	if (ret < 0)
4450757535aSSimon Glass 		return ret;
4460757535aSSimon Glass 	func = ret;
4470757535aSSimon Glass 	len = snprintf(str, buffsize, "%s%d: %s",
4480757535aSSimon Glass 		       priv->bank_name ? priv->bank_name : "",
4490757535aSSimon Glass 		       offset, gpio_function[func]);
4500757535aSSimon Glass 	if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
4510757535aSSimon Glass 	    func == GPIOF_UNUSED) {
4520757535aSSimon Glass 		const char *label;
4530757535aSSimon Glass 		bool used;
4540757535aSSimon Glass 
4550757535aSSimon Glass 		ret = ops->get_value(dev, offset);
4560757535aSSimon Glass 		if (ret < 0)
4570757535aSSimon Glass 			return ret;
4580757535aSSimon Glass 		used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
4590757535aSSimon Glass 		snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
4600757535aSSimon Glass 			 ret,
4610757535aSSimon Glass 			 used ? 'x' : ' ',
4620757535aSSimon Glass 			 used ? " " : "",
4630757535aSSimon Glass 			 label ? label : "");
4640757535aSSimon Glass 	}
4650757535aSSimon Glass 
4660757535aSSimon Glass 	return 0;
4670757535aSSimon Glass }
4680757535aSSimon Glass 
469e5901c94SSimon Glass /*
470e5901c94SSimon Glass  * get a number comprised of multiple GPIO values. gpio_num_array points to
471e5901c94SSimon Glass  * the array of gpio pin numbers to scan, terminated by -1.
472e5901c94SSimon Glass  */
473e5901c94SSimon Glass unsigned gpio_get_values_as_int(const int *gpio_num_array)
474e5901c94SSimon Glass {
475e5901c94SSimon Glass 	int gpio;
476e5901c94SSimon Glass 	unsigned bitmask = 1;
477e5901c94SSimon Glass 	unsigned vector = 0;
478e5901c94SSimon Glass 
479e5901c94SSimon Glass 	while (bitmask &&
480e5901c94SSimon Glass 	       ((gpio = *gpio_num_array++) != -1)) {
481e5901c94SSimon Glass 		if (gpio_get_value(gpio))
482e5901c94SSimon Glass 			vector |= bitmask;
483e5901c94SSimon Glass 		bitmask <<= 1;
484e5901c94SSimon Glass 	}
485e5901c94SSimon Glass 	return vector;
486e5901c94SSimon Glass }
487e5901c94SSimon Glass 
48896495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */
489b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev)
49096495d90SSimon Glass {
49196495d90SSimon Glass 	struct gpio_dev_priv *uc_priv;
49254c5d08aSHeiko Schocher 	struct udevice *dev;
49396495d90SSimon Glass 	struct uclass *uc;
49496495d90SSimon Glass 	unsigned base;
49596495d90SSimon Glass 	int ret;
49696495d90SSimon Glass 
49796495d90SSimon Glass 	ret = uclass_get(UCLASS_GPIO, &uc);
49896495d90SSimon Glass 	if (ret)
49996495d90SSimon Glass 		return ret;
50096495d90SSimon Glass 
50196495d90SSimon Glass 	/* Ensure that we have a base for each bank */
50296495d90SSimon Glass 	base = 0;
50396495d90SSimon Glass 	uclass_foreach_dev(dev, uc) {
504b892d127SSimon Glass 		if (device_active(dev) && dev != removed_dev) {
50596495d90SSimon Glass 			uc_priv = dev->uclass_priv;
50696495d90SSimon Glass 			uc_priv->gpio_base = base;
50796495d90SSimon Glass 			base += uc_priv->gpio_count;
50896495d90SSimon Glass 		}
50996495d90SSimon Glass 	}
51096495d90SSimon Glass 
51196495d90SSimon Glass 	return 0;
51296495d90SSimon Glass }
51396495d90SSimon Glass 
51454c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev)
51596495d90SSimon Glass {
516b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
517b892d127SSimon Glass 
518b892d127SSimon Glass 	uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
519b892d127SSimon Glass 	if (!uc_priv->name)
520b892d127SSimon Glass 		return -ENOMEM;
521b892d127SSimon Glass 
522b892d127SSimon Glass 	return gpio_renumber(NULL);
52396495d90SSimon Glass }
52496495d90SSimon Glass 
52554c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev)
52696495d90SSimon Glass {
527b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
528b892d127SSimon Glass 	int i;
529b892d127SSimon Glass 
530b892d127SSimon Glass 	for (i = 0; i < uc_priv->gpio_count; i++) {
531b892d127SSimon Glass 		if (uc_priv->name[i])
532b892d127SSimon Glass 			free(uc_priv->name[i]);
533b892d127SSimon Glass 	}
534b892d127SSimon Glass 	free(uc_priv->name);
535b892d127SSimon Glass 
536b892d127SSimon Glass 	return gpio_renumber(dev);
53796495d90SSimon Glass }
53896495d90SSimon Glass 
53996495d90SSimon Glass UCLASS_DRIVER(gpio) = {
54096495d90SSimon Glass 	.id		= UCLASS_GPIO,
54196495d90SSimon Glass 	.name		= "gpio",
54296495d90SSimon Glass 	.post_probe	= gpio_post_probe,
54396495d90SSimon Glass 	.pre_remove	= gpio_pre_remove,
54496495d90SSimon Glass 	.per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
54596495d90SSimon Glass };
546