xref: /openbmc/u-boot/drivers/gpio/gpio-uclass.c (revision 0757535a7eee3ae5603520fe4a0588a01a590ea7)
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  * gpio:	The numeric representation of the GPIO
1796495d90SSimon Glass  *
1896495d90SSimon Glass  * Convert the GPIO number to an entry in the list of GPIOs
1996495d90SSimon Glass  * or GPIO blocks registered with the GPIO controller. Returns
2096495d90SSimon Glass  * entry on success, NULL on error.
2196495d90SSimon Glass  */
2254c5d08aSHeiko Schocher static int gpio_to_device(unsigned int gpio, struct udevice **devp,
2396495d90SSimon Glass 			  unsigned int *offset)
2496495d90SSimon Glass {
2596495d90SSimon Glass 	struct gpio_dev_priv *uc_priv;
2654c5d08aSHeiko Schocher 	struct udevice *dev;
2796495d90SSimon Glass 	int ret;
2896495d90SSimon Glass 
2996495d90SSimon Glass 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
3096495d90SSimon Glass 	     dev;
3196495d90SSimon Glass 	     ret = uclass_next_device(&dev)) {
3296495d90SSimon Glass 		uc_priv = dev->uclass_priv;
3396495d90SSimon Glass 		if (gpio >= uc_priv->gpio_base &&
3496495d90SSimon Glass 		    gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
3596495d90SSimon Glass 			*devp = dev;
3696495d90SSimon Glass 			*offset = gpio - uc_priv->gpio_base;
3796495d90SSimon Glass 			return 0;
3896495d90SSimon Glass 		}
3996495d90SSimon Glass 	}
4096495d90SSimon Glass 
4196495d90SSimon Glass 	/* No such GPIO */
4296495d90SSimon Glass 	return ret ? ret : -EINVAL;
4396495d90SSimon Glass }
4496495d90SSimon Glass 
4554c5d08aSHeiko Schocher int gpio_lookup_name(const char *name, struct udevice **devp,
4696495d90SSimon Glass 		     unsigned int *offsetp, unsigned int *gpiop)
4796495d90SSimon Glass {
48fe1ef503SSimon Glass 	struct gpio_dev_priv *uc_priv = NULL;
4954c5d08aSHeiko Schocher 	struct udevice *dev;
50fe1ef503SSimon Glass 	ulong offset;
51fe1ef503SSimon Glass 	int numeric;
5296495d90SSimon Glass 	int ret;
5396495d90SSimon Glass 
5496495d90SSimon Glass 	if (devp)
5596495d90SSimon Glass 		*devp = NULL;
56fe1ef503SSimon Glass 	numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
5796495d90SSimon Glass 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
5896495d90SSimon Glass 	     dev;
5996495d90SSimon Glass 	     ret = uclass_next_device(&dev)) {
6096495d90SSimon Glass 		int len;
6196495d90SSimon Glass 
6296495d90SSimon Glass 		uc_priv = dev->uclass_priv;
63fe1ef503SSimon Glass 		if (numeric != -1) {
64fe1ef503SSimon Glass 			offset = numeric - uc_priv->gpio_base;
65fe1ef503SSimon Glass 			/* Allow GPIOs to be numbered from 0 */
66fe1ef503SSimon Glass 			if (offset >= 0 && offset < uc_priv->gpio_count)
67fe1ef503SSimon Glass 				break;
68fe1ef503SSimon Glass 		}
69fe1ef503SSimon Glass 
7096495d90SSimon Glass 		len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
7196495d90SSimon Glass 
72939cda5bSSimon Glass 		if (!strncasecmp(name, uc_priv->bank_name, len)) {
73fe1ef503SSimon Glass 			if (!strict_strtoul(name + len, 10, &offset))
74fe1ef503SSimon Glass 				break;
75fe1ef503SSimon Glass 		}
76fe1ef503SSimon Glass 	}
77fe1ef503SSimon Glass 
78fe1ef503SSimon Glass 	if (!dev)
79fe1ef503SSimon Glass 		return ret ? ret : -EINVAL;
80fe1ef503SSimon Glass 
8196495d90SSimon Glass 	if (devp)
8296495d90SSimon Glass 		*devp = dev;
8396495d90SSimon Glass 	if (offsetp)
8496495d90SSimon Glass 		*offsetp = offset;
8596495d90SSimon Glass 	if (gpiop)
8696495d90SSimon Glass 		*gpiop = uc_priv->gpio_base + offset;
8796495d90SSimon Glass 
88fe1ef503SSimon Glass 	return 0;
8996495d90SSimon Glass }
9096495d90SSimon Glass 
9196495d90SSimon Glass /**
9296495d90SSimon Glass  * gpio_request() - [COMPAT] Request GPIO
9396495d90SSimon Glass  * gpio:	GPIO number
9496495d90SSimon Glass  * label:	Name for the requested GPIO
9596495d90SSimon Glass  *
96b892d127SSimon Glass  * The label is copied and allocated so the caller does not need to keep
97b892d127SSimon Glass  * the pointer around.
98b892d127SSimon Glass  *
9996495d90SSimon Glass  * This function implements the API that's compatible with current
10096495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
10196495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
10296495d90SSimon Glass  */
10396495d90SSimon Glass int gpio_request(unsigned gpio, const char *label)
10496495d90SSimon Glass {
105b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv;
10696495d90SSimon Glass 	unsigned int offset;
10754c5d08aSHeiko Schocher 	struct udevice *dev;
108b892d127SSimon Glass 	char *str;
10996495d90SSimon Glass 	int ret;
11096495d90SSimon Glass 
11196495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
11296495d90SSimon Glass 	if (ret)
11396495d90SSimon Glass 		return ret;
11496495d90SSimon Glass 
115b892d127SSimon Glass 	uc_priv = dev->uclass_priv;
116b892d127SSimon Glass 	if (uc_priv->name[offset])
117b892d127SSimon Glass 		return -EBUSY;
118b892d127SSimon Glass 	str = strdup(label);
119b892d127SSimon Glass 	if (!str)
120b892d127SSimon Glass 		return -ENOMEM;
121b892d127SSimon Glass 	if (gpio_get_ops(dev)->request) {
122b892d127SSimon Glass 		ret = gpio_get_ops(dev)->request(dev, offset, label);
123b892d127SSimon Glass 		if (ret) {
124b892d127SSimon Glass 			free(str);
125b892d127SSimon Glass 			return ret;
126b892d127SSimon Glass 		}
127b892d127SSimon Glass 	}
128b892d127SSimon Glass 	uc_priv->name[offset] = str;
12996495d90SSimon Glass 
130b892d127SSimon Glass 	return 0;
13196495d90SSimon Glass }
13296495d90SSimon Glass 
13396495d90SSimon Glass /**
13496495d90SSimon Glass  * gpio_free() - [COMPAT] Relinquish GPIO
13596495d90SSimon Glass  * gpio:	GPIO number
13696495d90SSimon Glass  *
13796495d90SSimon Glass  * This function implements the API that's compatible with current
13896495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
13996495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
14096495d90SSimon Glass  */
14196495d90SSimon Glass int gpio_free(unsigned gpio)
14296495d90SSimon Glass {
143b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv;
14496495d90SSimon Glass 	unsigned int offset;
14554c5d08aSHeiko Schocher 	struct udevice *dev;
14696495d90SSimon Glass 	int ret;
14796495d90SSimon Glass 
14896495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
14996495d90SSimon Glass 	if (ret)
15096495d90SSimon Glass 		return ret;
15196495d90SSimon Glass 
152b892d127SSimon Glass 	uc_priv = dev->uclass_priv;
153b892d127SSimon Glass 	if (!uc_priv->name[offset])
154b892d127SSimon Glass 		return -ENXIO;
155b892d127SSimon Glass 	if (gpio_get_ops(dev)->free) {
156b892d127SSimon Glass 		ret = gpio_get_ops(dev)->free(dev, offset);
157b892d127SSimon Glass 		if (ret)
158b892d127SSimon Glass 			return ret;
159b892d127SSimon Glass 	}
160b892d127SSimon Glass 
161b892d127SSimon Glass 	free(uc_priv->name[offset]);
162b892d127SSimon Glass 	uc_priv->name[offset] = NULL;
163b892d127SSimon Glass 
16496495d90SSimon Glass 	return 0;
165b892d127SSimon Glass }
166b892d127SSimon Glass 
167b892d127SSimon Glass static int check_reserved(struct udevice *dev, unsigned offset,
168b892d127SSimon Glass 			  const char *func)
169b892d127SSimon Glass {
170b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
171b892d127SSimon Glass 
172b892d127SSimon Glass 	if (!uc_priv->name[offset]) {
173b892d127SSimon Glass 		printf("%s: %s: error: gpio %s%d not reserved\n",
174b892d127SSimon Glass 		       dev->name, func,
175b892d127SSimon Glass 		       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
176b892d127SSimon Glass 		return -EBUSY;
177b892d127SSimon Glass 	}
178b892d127SSimon Glass 
179b892d127SSimon Glass 	return 0;
18096495d90SSimon Glass }
18196495d90SSimon Glass 
18296495d90SSimon Glass /**
18396495d90SSimon Glass  * gpio_direction_input() - [COMPAT] Set GPIO direction to input
18496495d90SSimon Glass  * gpio:	GPIO number
18596495d90SSimon Glass  *
18696495d90SSimon Glass  * This function implements the API that's compatible with current
18796495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
18896495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
18996495d90SSimon Glass  */
19096495d90SSimon Glass int gpio_direction_input(unsigned gpio)
19196495d90SSimon Glass {
19296495d90SSimon Glass 	unsigned int offset;
19354c5d08aSHeiko Schocher 	struct udevice *dev;
19496495d90SSimon Glass 	int ret;
19596495d90SSimon Glass 
19696495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
19796495d90SSimon Glass 	if (ret)
19896495d90SSimon Glass 		return ret;
199b892d127SSimon Glass 	ret = check_reserved(dev, offset, "dir_input");
20096495d90SSimon Glass 
201b892d127SSimon Glass 	return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
20296495d90SSimon Glass }
20396495d90SSimon Glass 
20496495d90SSimon Glass /**
20596495d90SSimon Glass  * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
20696495d90SSimon Glass  * gpio:	GPIO number
20796495d90SSimon Glass  * value:	Logical value to be set on the GPIO pin
20896495d90SSimon Glass  *
20996495d90SSimon Glass  * This function implements the API that's compatible with current
21096495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
21196495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
21296495d90SSimon Glass  */
21396495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value)
21496495d90SSimon Glass {
21596495d90SSimon Glass 	unsigned int offset;
21654c5d08aSHeiko Schocher 	struct udevice *dev;
21796495d90SSimon Glass 	int ret;
21896495d90SSimon Glass 
21996495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
22096495d90SSimon Glass 	if (ret)
22196495d90SSimon Glass 		return ret;
222b892d127SSimon Glass 	ret = check_reserved(dev, offset, "dir_output");
22396495d90SSimon Glass 
224b892d127SSimon Glass 	return ret ? ret :
225b892d127SSimon Glass 		gpio_get_ops(dev)->direction_output(dev, offset, value);
22696495d90SSimon Glass }
22796495d90SSimon Glass 
22896495d90SSimon Glass /**
22996495d90SSimon Glass  * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
23096495d90SSimon Glass  * gpio:	GPIO number
23196495d90SSimon Glass  *
23296495d90SSimon Glass  * This function implements the API that's compatible with current
23396495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
23496495d90SSimon Glass  * GPIO driver. Returns the value of the GPIO pin, or negative value
23596495d90SSimon Glass  * on error.
23696495d90SSimon Glass  */
23796495d90SSimon Glass int gpio_get_value(unsigned gpio)
23896495d90SSimon Glass {
23996495d90SSimon Glass 	unsigned int offset;
24054c5d08aSHeiko Schocher 	struct udevice *dev;
24196495d90SSimon Glass 	int ret;
24296495d90SSimon Glass 
24396495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
24496495d90SSimon Glass 	if (ret)
24596495d90SSimon Glass 		return ret;
246b892d127SSimon Glass 	ret = check_reserved(dev, offset, "get_value");
24796495d90SSimon Glass 
248b892d127SSimon Glass 	return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
24996495d90SSimon Glass }
25096495d90SSimon Glass 
25196495d90SSimon Glass /**
25296495d90SSimon Glass  * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
25396495d90SSimon Glass  * gpio:	GPIO number
25496495d90SSimon Glass  * value:	Logical value to be set on the GPIO pin.
25596495d90SSimon Glass  *
25696495d90SSimon Glass  * This function implements the API that's compatible with current
25796495d90SSimon Glass  * GPIO API used in U-Boot. The request is forwarded to particular
25896495d90SSimon Glass  * GPIO driver. Returns 0 on success, negative value on error.
25996495d90SSimon Glass  */
26096495d90SSimon Glass int gpio_set_value(unsigned gpio, int value)
26196495d90SSimon Glass {
26296495d90SSimon Glass 	unsigned int offset;
26354c5d08aSHeiko Schocher 	struct udevice *dev;
26496495d90SSimon Glass 	int ret;
26596495d90SSimon Glass 
26696495d90SSimon Glass 	ret = gpio_to_device(gpio, &dev, &offset);
26796495d90SSimon Glass 	if (ret)
26896495d90SSimon Glass 		return ret;
269b892d127SSimon Glass 	ret = check_reserved(dev, offset, "set_value");
27096495d90SSimon Glass 
271b892d127SSimon Glass 	return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
27296495d90SSimon Glass }
27396495d90SSimon Glass 
27454c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
27596495d90SSimon Glass {
27696495d90SSimon Glass 	struct gpio_dev_priv *priv;
27796495d90SSimon Glass 
27896495d90SSimon Glass 	/* Must be called on an active device */
27996495d90SSimon Glass 	priv = dev->uclass_priv;
28096495d90SSimon Glass 	assert(priv);
28196495d90SSimon Glass 
28296495d90SSimon Glass 	*bit_count = priv->gpio_count;
28396495d90SSimon Glass 	return priv->bank_name;
28496495d90SSimon Glass }
28596495d90SSimon Glass 
2866449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = {
2876449a506SSimon Glass 	"input",
2886449a506SSimon Glass 	"output",
2896449a506SSimon Glass 	"unused",
2906449a506SSimon Glass 	"unknown",
2916449a506SSimon Glass 	"func",
2926449a506SSimon Glass };
2936449a506SSimon Glass 
2946449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused,
2956449a506SSimon Glass 		 const char **namep)
2966449a506SSimon Glass {
2976449a506SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
2986449a506SSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
2996449a506SSimon Glass 
3006449a506SSimon Glass 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
3016449a506SSimon Glass 	if (!device_active(dev))
3026449a506SSimon Glass 		return -ENODEV;
3036449a506SSimon Glass 	if (offset < 0 || offset >= uc_priv->gpio_count)
3046449a506SSimon Glass 		return -EINVAL;
3056449a506SSimon Glass 	if (namep)
3066449a506SSimon Glass 		*namep = uc_priv->name[offset];
3076449a506SSimon Glass 	if (skip_unused && !uc_priv->name[offset])
3086449a506SSimon Glass 		return GPIOF_UNUSED;
3096449a506SSimon Glass 	if (ops->get_function) {
3106449a506SSimon Glass 		int ret;
3116449a506SSimon Glass 
3126449a506SSimon Glass 		ret = ops->get_function(dev, offset);
3136449a506SSimon Glass 		if (ret < 0)
3146449a506SSimon Glass 			return ret;
3156449a506SSimon Glass 		if (ret >= ARRAY_SIZE(gpio_function))
3166449a506SSimon Glass 			return -ENODATA;
3176449a506SSimon Glass 		return ret;
3186449a506SSimon Glass 	}
3196449a506SSimon Glass 
3206449a506SSimon Glass 	return GPIOF_UNKNOWN;
3216449a506SSimon Glass }
3226449a506SSimon Glass 
3236449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep)
3246449a506SSimon Glass {
3256449a506SSimon Glass 	return get_function(dev, offset, true, namep);
3266449a506SSimon Glass }
3276449a506SSimon Glass 
3286449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
3296449a506SSimon Glass {
3306449a506SSimon Glass 	return get_function(dev, offset, false, namep);
3316449a506SSimon Glass }
3326449a506SSimon Glass 
333*0757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
334*0757535aSSimon Glass {
335*0757535aSSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
336*0757535aSSimon Glass 	struct gpio_dev_priv *priv;
337*0757535aSSimon Glass 	char *str = buf;
338*0757535aSSimon Glass 	int func;
339*0757535aSSimon Glass 	int ret;
340*0757535aSSimon Glass 	int len;
341*0757535aSSimon Glass 
342*0757535aSSimon Glass 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
343*0757535aSSimon Glass 
344*0757535aSSimon Glass 	*buf = 0;
345*0757535aSSimon Glass 	priv = dev->uclass_priv;
346*0757535aSSimon Glass 	ret = gpio_get_raw_function(dev, offset, NULL);
347*0757535aSSimon Glass 	if (ret < 0)
348*0757535aSSimon Glass 		return ret;
349*0757535aSSimon Glass 	func = ret;
350*0757535aSSimon Glass 	len = snprintf(str, buffsize, "%s%d: %s",
351*0757535aSSimon Glass 		       priv->bank_name ? priv->bank_name : "",
352*0757535aSSimon Glass 		       offset, gpio_function[func]);
353*0757535aSSimon Glass 	if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
354*0757535aSSimon Glass 	    func == GPIOF_UNUSED) {
355*0757535aSSimon Glass 		const char *label;
356*0757535aSSimon Glass 		bool used;
357*0757535aSSimon Glass 
358*0757535aSSimon Glass 		ret = ops->get_value(dev, offset);
359*0757535aSSimon Glass 		if (ret < 0)
360*0757535aSSimon Glass 			return ret;
361*0757535aSSimon Glass 		used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
362*0757535aSSimon Glass 		snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
363*0757535aSSimon Glass 			 ret,
364*0757535aSSimon Glass 			 used ? 'x' : ' ',
365*0757535aSSimon Glass 			 used ? " " : "",
366*0757535aSSimon Glass 			 label ? label : "");
367*0757535aSSimon Glass 	}
368*0757535aSSimon Glass 
369*0757535aSSimon Glass 	return 0;
370*0757535aSSimon Glass }
371*0757535aSSimon Glass 
37296495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */
373b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev)
37496495d90SSimon Glass {
37596495d90SSimon Glass 	struct gpio_dev_priv *uc_priv;
37654c5d08aSHeiko Schocher 	struct udevice *dev;
37796495d90SSimon Glass 	struct uclass *uc;
37896495d90SSimon Glass 	unsigned base;
37996495d90SSimon Glass 	int ret;
38096495d90SSimon Glass 
38196495d90SSimon Glass 	ret = uclass_get(UCLASS_GPIO, &uc);
38296495d90SSimon Glass 	if (ret)
38396495d90SSimon Glass 		return ret;
38496495d90SSimon Glass 
38596495d90SSimon Glass 	/* Ensure that we have a base for each bank */
38696495d90SSimon Glass 	base = 0;
38796495d90SSimon Glass 	uclass_foreach_dev(dev, uc) {
388b892d127SSimon Glass 		if (device_active(dev) && dev != removed_dev) {
38996495d90SSimon Glass 			uc_priv = dev->uclass_priv;
39096495d90SSimon Glass 			uc_priv->gpio_base = base;
39196495d90SSimon Glass 			base += uc_priv->gpio_count;
39296495d90SSimon Glass 		}
39396495d90SSimon Glass 	}
39496495d90SSimon Glass 
39596495d90SSimon Glass 	return 0;
39696495d90SSimon Glass }
39796495d90SSimon Glass 
39854c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev)
39996495d90SSimon Glass {
400b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
401b892d127SSimon Glass 
402b892d127SSimon Glass 	uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
403b892d127SSimon Glass 	if (!uc_priv->name)
404b892d127SSimon Glass 		return -ENOMEM;
405b892d127SSimon Glass 
406b892d127SSimon Glass 	return gpio_renumber(NULL);
40796495d90SSimon Glass }
40896495d90SSimon Glass 
40954c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev)
41096495d90SSimon Glass {
411b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
412b892d127SSimon Glass 	int i;
413b892d127SSimon Glass 
414b892d127SSimon Glass 	for (i = 0; i < uc_priv->gpio_count; i++) {
415b892d127SSimon Glass 		if (uc_priv->name[i])
416b892d127SSimon Glass 			free(uc_priv->name[i]);
417b892d127SSimon Glass 	}
418b892d127SSimon Glass 	free(uc_priv->name);
419b892d127SSimon Glass 
420b892d127SSimon Glass 	return gpio_renumber(dev);
42196495d90SSimon Glass }
42296495d90SSimon Glass 
42396495d90SSimon Glass UCLASS_DRIVER(gpio) = {
42496495d90SSimon Glass 	.id		= UCLASS_GPIO,
42596495d90SSimon Glass 	.name		= "gpio",
42696495d90SSimon Glass 	.post_probe	= gpio_post_probe,
42796495d90SSimon Glass 	.pre_remove	= gpio_pre_remove,
42896495d90SSimon Glass 	.per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
42996495d90SSimon Glass };
430