xref: /openbmc/u-boot/drivers/gpio/gpio-uclass.c (revision 6449a506d67b0374bf23a3833f15afa0c92a7a0e)
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 
286*6449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = {
287*6449a506SSimon Glass 	"input",
288*6449a506SSimon Glass 	"output",
289*6449a506SSimon Glass 	"unused",
290*6449a506SSimon Glass 	"unknown",
291*6449a506SSimon Glass 	"func",
292*6449a506SSimon Glass };
293*6449a506SSimon Glass 
294*6449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused,
295*6449a506SSimon Glass 		 const char **namep)
296*6449a506SSimon Glass {
297*6449a506SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
298*6449a506SSimon Glass 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
299*6449a506SSimon Glass 
300*6449a506SSimon Glass 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
301*6449a506SSimon Glass 	if (!device_active(dev))
302*6449a506SSimon Glass 		return -ENODEV;
303*6449a506SSimon Glass 	if (offset < 0 || offset >= uc_priv->gpio_count)
304*6449a506SSimon Glass 		return -EINVAL;
305*6449a506SSimon Glass 	if (namep)
306*6449a506SSimon Glass 		*namep = uc_priv->name[offset];
307*6449a506SSimon Glass 	if (skip_unused && !uc_priv->name[offset])
308*6449a506SSimon Glass 		return GPIOF_UNUSED;
309*6449a506SSimon Glass 	if (ops->get_function) {
310*6449a506SSimon Glass 		int ret;
311*6449a506SSimon Glass 
312*6449a506SSimon Glass 		ret = ops->get_function(dev, offset);
313*6449a506SSimon Glass 		if (ret < 0)
314*6449a506SSimon Glass 			return ret;
315*6449a506SSimon Glass 		if (ret >= ARRAY_SIZE(gpio_function))
316*6449a506SSimon Glass 			return -ENODATA;
317*6449a506SSimon Glass 		return ret;
318*6449a506SSimon Glass 	}
319*6449a506SSimon Glass 
320*6449a506SSimon Glass 	return GPIOF_UNKNOWN;
321*6449a506SSimon Glass }
322*6449a506SSimon Glass 
323*6449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep)
324*6449a506SSimon Glass {
325*6449a506SSimon Glass 	return get_function(dev, offset, true, namep);
326*6449a506SSimon Glass }
327*6449a506SSimon Glass 
328*6449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
329*6449a506SSimon Glass {
330*6449a506SSimon Glass 	return get_function(dev, offset, false, namep);
331*6449a506SSimon Glass }
332*6449a506SSimon Glass 
33396495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */
334b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev)
33596495d90SSimon Glass {
33696495d90SSimon Glass 	struct gpio_dev_priv *uc_priv;
33754c5d08aSHeiko Schocher 	struct udevice *dev;
33896495d90SSimon Glass 	struct uclass *uc;
33996495d90SSimon Glass 	unsigned base;
34096495d90SSimon Glass 	int ret;
34196495d90SSimon Glass 
34296495d90SSimon Glass 	ret = uclass_get(UCLASS_GPIO, &uc);
34396495d90SSimon Glass 	if (ret)
34496495d90SSimon Glass 		return ret;
34596495d90SSimon Glass 
34696495d90SSimon Glass 	/* Ensure that we have a base for each bank */
34796495d90SSimon Glass 	base = 0;
34896495d90SSimon Glass 	uclass_foreach_dev(dev, uc) {
349b892d127SSimon Glass 		if (device_active(dev) && dev != removed_dev) {
35096495d90SSimon Glass 			uc_priv = dev->uclass_priv;
35196495d90SSimon Glass 			uc_priv->gpio_base = base;
35296495d90SSimon Glass 			base += uc_priv->gpio_count;
35396495d90SSimon Glass 		}
35496495d90SSimon Glass 	}
35596495d90SSimon Glass 
35696495d90SSimon Glass 	return 0;
35796495d90SSimon Glass }
35896495d90SSimon Glass 
35954c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev)
36096495d90SSimon Glass {
361b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
362b892d127SSimon Glass 
363b892d127SSimon Glass 	uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
364b892d127SSimon Glass 	if (!uc_priv->name)
365b892d127SSimon Glass 		return -ENOMEM;
366b892d127SSimon Glass 
367b892d127SSimon Glass 	return gpio_renumber(NULL);
36896495d90SSimon Glass }
36996495d90SSimon Glass 
37054c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev)
37196495d90SSimon Glass {
372b892d127SSimon Glass 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
373b892d127SSimon Glass 	int i;
374b892d127SSimon Glass 
375b892d127SSimon Glass 	for (i = 0; i < uc_priv->gpio_count; i++) {
376b892d127SSimon Glass 		if (uc_priv->name[i])
377b892d127SSimon Glass 			free(uc_priv->name[i]);
378b892d127SSimon Glass 	}
379b892d127SSimon Glass 	free(uc_priv->name);
380b892d127SSimon Glass 
381b892d127SSimon Glass 	return gpio_renumber(dev);
38296495d90SSimon Glass }
38396495d90SSimon Glass 
38496495d90SSimon Glass UCLASS_DRIVER(gpio) = {
38596495d90SSimon Glass 	.id		= UCLASS_GPIO,
38696495d90SSimon Glass 	.name		= "gpio",
38796495d90SSimon Glass 	.post_probe	= gpio_post_probe,
38896495d90SSimon Glass 	.pre_remove	= gpio_pre_remove,
38996495d90SSimon Glass 	.per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
39096495d90SSimon Glass };
391