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> 10*0dac4d51SSimon Glass #include <fdtdec.h> 11b892d127SSimon Glass #include <malloc.h> 1296495d90SSimon Glass #include <asm/gpio.h> 13fe1ef503SSimon Glass #include <linux/ctype.h> 1496495d90SSimon Glass 1596495d90SSimon Glass /** 1696495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 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. 21ae7123f8SSimon Glass * 22ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 23ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 24ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 2596495d90SSimon Glass */ 26ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 2796495d90SSimon Glass { 2896495d90SSimon Glass struct gpio_dev_priv *uc_priv; 2954c5d08aSHeiko Schocher struct udevice *dev; 3096495d90SSimon Glass int ret; 3196495d90SSimon Glass 3296495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3396495d90SSimon Glass dev; 3496495d90SSimon Glass ret = uclass_next_device(&dev)) { 3596495d90SSimon Glass uc_priv = dev->uclass_priv; 3696495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 3796495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 38ae7123f8SSimon Glass desc->dev = dev; 39ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 40ae7123f8SSimon Glass desc->flags = 0; 4196495d90SSimon Glass return 0; 4296495d90SSimon Glass } 4396495d90SSimon Glass } 4496495d90SSimon Glass 4596495d90SSimon Glass /* No such GPIO */ 46ae7123f8SSimon Glass return ret ? ret : -ENOENT; 4796495d90SSimon Glass } 4896495d90SSimon Glass 4954c5d08aSHeiko Schocher int gpio_lookup_name(const char *name, struct udevice **devp, 5096495d90SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 5196495d90SSimon Glass { 52fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5354c5d08aSHeiko Schocher struct udevice *dev; 54fe1ef503SSimon Glass ulong offset; 55fe1ef503SSimon Glass int numeric; 5696495d90SSimon Glass int ret; 5796495d90SSimon Glass 5896495d90SSimon Glass if (devp) 5996495d90SSimon Glass *devp = NULL; 60fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6196495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6296495d90SSimon Glass dev; 6396495d90SSimon Glass ret = uclass_next_device(&dev)) { 6496495d90SSimon Glass int len; 6596495d90SSimon Glass 6696495d90SSimon Glass uc_priv = dev->uclass_priv; 67fe1ef503SSimon Glass if (numeric != -1) { 68fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 69fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 70fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 71fe1ef503SSimon Glass break; 72fe1ef503SSimon Glass } 73fe1ef503SSimon Glass 7496495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7596495d90SSimon Glass 76939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 77fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 78fe1ef503SSimon Glass break; 79fe1ef503SSimon Glass } 80fe1ef503SSimon Glass } 81fe1ef503SSimon Glass 82fe1ef503SSimon Glass if (!dev) 83fe1ef503SSimon Glass return ret ? ret : -EINVAL; 84fe1ef503SSimon Glass 8596495d90SSimon Glass if (devp) 8696495d90SSimon Glass *devp = dev; 8796495d90SSimon Glass if (offsetp) 8896495d90SSimon Glass *offsetp = offset; 8996495d90SSimon Glass if (gpiop) 9096495d90SSimon Glass *gpiop = uc_priv->gpio_base + offset; 9196495d90SSimon Glass 92fe1ef503SSimon Glass return 0; 9396495d90SSimon Glass } 9496495d90SSimon Glass 95*0dac4d51SSimon Glass int gpio_find_and_xlate(struct gpio_desc *desc, 96*0dac4d51SSimon Glass struct fdtdec_phandle_args *args) 97*0dac4d51SSimon Glass { 98*0dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 99*0dac4d51SSimon Glass 100*0dac4d51SSimon Glass /* Use the first argument as the offset by default */ 101*0dac4d51SSimon Glass if (args->args_count > 0) 102*0dac4d51SSimon Glass desc->offset = args->args[0]; 103*0dac4d51SSimon Glass else 104*0dac4d51SSimon Glass desc->offset = -1; 105*0dac4d51SSimon Glass desc->flags = 0; 106*0dac4d51SSimon Glass 107*0dac4d51SSimon Glass return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; 108*0dac4d51SSimon Glass } 109*0dac4d51SSimon Glass 110ae7123f8SSimon Glass static int dm_gpio_request(struct gpio_desc *desc, const char *label) 111ae7123f8SSimon Glass { 112ae7123f8SSimon Glass struct udevice *dev = desc->dev; 113ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 114ae7123f8SSimon Glass char *str; 115ae7123f8SSimon Glass int ret; 116ae7123f8SSimon Glass 117ae7123f8SSimon Glass uc_priv = dev->uclass_priv; 118ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 119ae7123f8SSimon Glass return -EBUSY; 120ae7123f8SSimon Glass str = strdup(label); 121ae7123f8SSimon Glass if (!str) 122ae7123f8SSimon Glass return -ENOMEM; 123ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 124ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 125ae7123f8SSimon Glass if (ret) { 126ae7123f8SSimon Glass free(str); 127ae7123f8SSimon Glass return ret; 128ae7123f8SSimon Glass } 129ae7123f8SSimon Glass } 130ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 131ae7123f8SSimon Glass 132ae7123f8SSimon Glass return 0; 133ae7123f8SSimon Glass } 134ae7123f8SSimon Glass 13596495d90SSimon Glass /** 13696495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 13796495d90SSimon Glass * gpio: GPIO number 13896495d90SSimon Glass * label: Name for the requested GPIO 13996495d90SSimon Glass * 140b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 141b892d127SSimon Glass * the pointer around. 142b892d127SSimon Glass * 14396495d90SSimon Glass * This function implements the API that's compatible with current 14496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 14596495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 14696495d90SSimon Glass */ 14796495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 14896495d90SSimon Glass { 149ae7123f8SSimon Glass struct gpio_desc desc; 15096495d90SSimon Glass int ret; 15196495d90SSimon Glass 152ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 15396495d90SSimon Glass if (ret) 15496495d90SSimon Glass return ret; 15596495d90SSimon Glass 156ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 15796495d90SSimon Glass } 15896495d90SSimon Glass 15996495d90SSimon Glass /** 160d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 161d44f597bSSimon Glass * @gpio: GPIO number 162d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 163d44f597bSSimon Glass * @...: Arguments for the printf() format string 164d44f597bSSimon Glass * 165d44f597bSSimon Glass * This function implements the API that's compatible with current 166d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 167d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 168d44f597bSSimon Glass */ 169d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 170d44f597bSSimon Glass { 171d44f597bSSimon Glass va_list args; 172d44f597bSSimon Glass char buf[40]; 173d44f597bSSimon Glass 174d44f597bSSimon Glass va_start(args, fmt); 175d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 176d44f597bSSimon Glass va_end(args); 177d44f597bSSimon Glass return gpio_request(gpio, buf); 178d44f597bSSimon Glass } 179d44f597bSSimon Glass 180ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 18196495d90SSimon Glass { 182b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 18396495d90SSimon Glass int ret; 18496495d90SSimon Glass 185b892d127SSimon Glass uc_priv = dev->uclass_priv; 186b892d127SSimon Glass if (!uc_priv->name[offset]) 187b892d127SSimon Glass return -ENXIO; 188b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 189b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 190b892d127SSimon Glass if (ret) 191b892d127SSimon Glass return ret; 192b892d127SSimon Glass } 193b892d127SSimon Glass 194b892d127SSimon Glass free(uc_priv->name[offset]); 195b892d127SSimon Glass uc_priv->name[offset] = NULL; 196b892d127SSimon Glass 19796495d90SSimon Glass return 0; 198b892d127SSimon Glass } 199b892d127SSimon Glass 200ae7123f8SSimon Glass /** 201ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 202ae7123f8SSimon Glass * gpio: GPIO number 203ae7123f8SSimon Glass * 204ae7123f8SSimon Glass * This function implements the API that's compatible with current 205ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 206ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 207ae7123f8SSimon Glass */ 208ae7123f8SSimon Glass int gpio_free(unsigned gpio) 209b892d127SSimon Glass { 210ae7123f8SSimon Glass struct gpio_desc desc; 211ae7123f8SSimon Glass int ret; 212b892d127SSimon Glass 213ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 214ae7123f8SSimon Glass if (ret) 215ae7123f8SSimon Glass return ret; 216ae7123f8SSimon Glass 217ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 218ae7123f8SSimon Glass } 219ae7123f8SSimon Glass 220ae7123f8SSimon Glass static int check_reserved(struct gpio_desc *desc, const char *func) 221ae7123f8SSimon Glass { 222ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv = desc->dev->uclass_priv; 223ae7123f8SSimon Glass 224ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 225b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 226ae7123f8SSimon Glass desc->dev->name, func, 227ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 228ae7123f8SSimon Glass desc->offset); 229b892d127SSimon Glass return -EBUSY; 230b892d127SSimon Glass } 231b892d127SSimon Glass 232b892d127SSimon Glass return 0; 23396495d90SSimon Glass } 23496495d90SSimon Glass 23596495d90SSimon Glass /** 23696495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 23796495d90SSimon Glass * gpio: GPIO number 23896495d90SSimon Glass * 23996495d90SSimon Glass * This function implements the API that's compatible with current 24096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 24196495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 24296495d90SSimon Glass */ 24396495d90SSimon Glass int gpio_direction_input(unsigned gpio) 24496495d90SSimon Glass { 245ae7123f8SSimon Glass struct gpio_desc desc; 24696495d90SSimon Glass int ret; 24796495d90SSimon Glass 248ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 24996495d90SSimon Glass if (ret) 25096495d90SSimon Glass return ret; 251ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 252ae7123f8SSimon Glass if (ret) 253ae7123f8SSimon Glass return ret; 25496495d90SSimon Glass 255ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 25696495d90SSimon Glass } 25796495d90SSimon Glass 25896495d90SSimon Glass /** 25996495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 26096495d90SSimon Glass * gpio: GPIO number 26196495d90SSimon Glass * value: Logical value to be set on the GPIO pin 26296495d90SSimon Glass * 26396495d90SSimon Glass * This function implements the API that's compatible with current 26496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 26596495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 26696495d90SSimon Glass */ 26796495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 26896495d90SSimon Glass { 269ae7123f8SSimon Glass struct gpio_desc desc; 27096495d90SSimon Glass int ret; 27196495d90SSimon Glass 272ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 27396495d90SSimon Glass if (ret) 27496495d90SSimon Glass return ret; 275ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 276ae7123f8SSimon Glass if (ret) 277ae7123f8SSimon Glass return ret; 27896495d90SSimon Glass 279ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 280ae7123f8SSimon Glass desc.offset, value); 281ae7123f8SSimon Glass } 282ae7123f8SSimon Glass 283ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc) 284ae7123f8SSimon Glass { 285ae7123f8SSimon Glass int value; 286ae7123f8SSimon Glass int ret; 287ae7123f8SSimon Glass 288ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 289ae7123f8SSimon Glass if (ret) 290ae7123f8SSimon Glass return ret; 291ae7123f8SSimon Glass 292ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 293ae7123f8SSimon Glass 294ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 295ae7123f8SSimon Glass } 296ae7123f8SSimon Glass 297ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value) 298ae7123f8SSimon Glass { 299ae7123f8SSimon Glass int ret; 300ae7123f8SSimon Glass 301ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 302ae7123f8SSimon Glass if (ret) 303ae7123f8SSimon Glass return ret; 304ae7123f8SSimon Glass 305ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 306ae7123f8SSimon Glass value = !value; 307ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 308ae7123f8SSimon Glass return 0; 309ae7123f8SSimon Glass } 310ae7123f8SSimon Glass 311ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 312ae7123f8SSimon Glass { 313ae7123f8SSimon Glass struct udevice *dev = desc->dev; 314ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 315ae7123f8SSimon Glass int ret; 316ae7123f8SSimon Glass 317ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 318ae7123f8SSimon Glass if (ret) 319ae7123f8SSimon Glass return ret; 320ae7123f8SSimon Glass 321ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 322ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 323ae7123f8SSimon Glass 324ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 325ae7123f8SSimon Glass value = !value; 326ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 327ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 328ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 329ae7123f8SSimon Glass } 330ae7123f8SSimon Glass if (ret) 331ae7123f8SSimon Glass return ret; 332ae7123f8SSimon Glass /* 333ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 334ae7123f8SSimon Glass * futures 335ae7123f8SSimon Glass */ 336ae7123f8SSimon Glass desc->flags = flags; 337ae7123f8SSimon Glass 338ae7123f8SSimon Glass return 0; 339ae7123f8SSimon Glass } 340ae7123f8SSimon Glass 341ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 342ae7123f8SSimon Glass { 343ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 34496495d90SSimon Glass } 34596495d90SSimon Glass 34696495d90SSimon Glass /** 34796495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 34896495d90SSimon Glass * gpio: GPIO number 34996495d90SSimon Glass * 35096495d90SSimon Glass * This function implements the API that's compatible with current 35196495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 35296495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 35396495d90SSimon Glass * on error. 35496495d90SSimon Glass */ 35596495d90SSimon Glass int gpio_get_value(unsigned gpio) 35696495d90SSimon Glass { 35796495d90SSimon Glass int ret; 35896495d90SSimon Glass 359ae7123f8SSimon Glass struct gpio_desc desc; 360ae7123f8SSimon Glass 361ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 36296495d90SSimon Glass if (ret) 36396495d90SSimon Glass return ret; 364ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 36596495d90SSimon Glass } 36696495d90SSimon Glass 36796495d90SSimon Glass /** 36896495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 36996495d90SSimon Glass * gpio: GPIO number 37096495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 37196495d90SSimon Glass * 37296495d90SSimon Glass * This function implements the API that's compatible with current 37396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 37496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 37596495d90SSimon Glass */ 37696495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 37796495d90SSimon Glass { 378ae7123f8SSimon Glass struct gpio_desc desc; 37996495d90SSimon Glass int ret; 38096495d90SSimon Glass 381ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 38296495d90SSimon Glass if (ret) 38396495d90SSimon Glass return ret; 384ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 38596495d90SSimon Glass } 38696495d90SSimon Glass 38754c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 38896495d90SSimon Glass { 38996495d90SSimon Glass struct gpio_dev_priv *priv; 39096495d90SSimon Glass 39196495d90SSimon Glass /* Must be called on an active device */ 39296495d90SSimon Glass priv = dev->uclass_priv; 39396495d90SSimon Glass assert(priv); 39496495d90SSimon Glass 39596495d90SSimon Glass *bit_count = priv->gpio_count; 39696495d90SSimon Glass return priv->bank_name; 39796495d90SSimon Glass } 39896495d90SSimon Glass 3996449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4006449a506SSimon Glass "input", 4016449a506SSimon Glass "output", 4026449a506SSimon Glass "unused", 4036449a506SSimon Glass "unknown", 4046449a506SSimon Glass "func", 4056449a506SSimon Glass }; 4066449a506SSimon Glass 4076449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4086449a506SSimon Glass const char **namep) 4096449a506SSimon Glass { 4106449a506SSimon Glass struct gpio_dev_priv *uc_priv = dev->uclass_priv; 4116449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4126449a506SSimon Glass 4136449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4146449a506SSimon Glass if (!device_active(dev)) 4156449a506SSimon Glass return -ENODEV; 4166449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4176449a506SSimon Glass return -EINVAL; 4186449a506SSimon Glass if (namep) 4196449a506SSimon Glass *namep = uc_priv->name[offset]; 4206449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4216449a506SSimon Glass return GPIOF_UNUSED; 4226449a506SSimon Glass if (ops->get_function) { 4236449a506SSimon Glass int ret; 4246449a506SSimon Glass 4256449a506SSimon Glass ret = ops->get_function(dev, offset); 4266449a506SSimon Glass if (ret < 0) 4276449a506SSimon Glass return ret; 4286449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4296449a506SSimon Glass return -ENODATA; 4306449a506SSimon Glass return ret; 4316449a506SSimon Glass } 4326449a506SSimon Glass 4336449a506SSimon Glass return GPIOF_UNKNOWN; 4346449a506SSimon Glass } 4356449a506SSimon Glass 4366449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4376449a506SSimon Glass { 4386449a506SSimon Glass return get_function(dev, offset, true, namep); 4396449a506SSimon Glass } 4406449a506SSimon Glass 4416449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 4426449a506SSimon Glass { 4436449a506SSimon Glass return get_function(dev, offset, false, namep); 4446449a506SSimon Glass } 4456449a506SSimon Glass 4460757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 4470757535aSSimon Glass { 4480757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4490757535aSSimon Glass struct gpio_dev_priv *priv; 4500757535aSSimon Glass char *str = buf; 4510757535aSSimon Glass int func; 4520757535aSSimon Glass int ret; 4530757535aSSimon Glass int len; 4540757535aSSimon Glass 4550757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4560757535aSSimon Glass 4570757535aSSimon Glass *buf = 0; 4580757535aSSimon Glass priv = dev->uclass_priv; 4590757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 4600757535aSSimon Glass if (ret < 0) 4610757535aSSimon Glass return ret; 4620757535aSSimon Glass func = ret; 4630757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 4640757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 4650757535aSSimon Glass offset, gpio_function[func]); 4660757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 4670757535aSSimon Glass func == GPIOF_UNUSED) { 4680757535aSSimon Glass const char *label; 4690757535aSSimon Glass bool used; 4700757535aSSimon Glass 4710757535aSSimon Glass ret = ops->get_value(dev, offset); 4720757535aSSimon Glass if (ret < 0) 4730757535aSSimon Glass return ret; 4740757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 4750757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 4760757535aSSimon Glass ret, 4770757535aSSimon Glass used ? 'x' : ' ', 4780757535aSSimon Glass used ? " " : "", 4790757535aSSimon Glass label ? label : ""); 4800757535aSSimon Glass } 4810757535aSSimon Glass 4820757535aSSimon Glass return 0; 4830757535aSSimon Glass } 4840757535aSSimon Glass 485e5901c94SSimon Glass /* 486e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 487e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 488e5901c94SSimon Glass */ 489e5901c94SSimon Glass unsigned gpio_get_values_as_int(const int *gpio_num_array) 490e5901c94SSimon Glass { 491e5901c94SSimon Glass int gpio; 492e5901c94SSimon Glass unsigned bitmask = 1; 493e5901c94SSimon Glass unsigned vector = 0; 494e5901c94SSimon Glass 495e5901c94SSimon Glass while (bitmask && 496e5901c94SSimon Glass ((gpio = *gpio_num_array++) != -1)) { 497e5901c94SSimon Glass if (gpio_get_value(gpio)) 498e5901c94SSimon Glass vector |= bitmask; 499e5901c94SSimon Glass bitmask <<= 1; 500e5901c94SSimon Glass } 501e5901c94SSimon Glass return vector; 502e5901c94SSimon Glass } 503e5901c94SSimon Glass 50496495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 505b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 50696495d90SSimon Glass { 50796495d90SSimon Glass struct gpio_dev_priv *uc_priv; 50854c5d08aSHeiko Schocher struct udevice *dev; 50996495d90SSimon Glass struct uclass *uc; 51096495d90SSimon Glass unsigned base; 51196495d90SSimon Glass int ret; 51296495d90SSimon Glass 51396495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 51496495d90SSimon Glass if (ret) 51596495d90SSimon Glass return ret; 51696495d90SSimon Glass 51796495d90SSimon Glass /* Ensure that we have a base for each bank */ 51896495d90SSimon Glass base = 0; 51996495d90SSimon Glass uclass_foreach_dev(dev, uc) { 520b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 52196495d90SSimon Glass uc_priv = dev->uclass_priv; 52296495d90SSimon Glass uc_priv->gpio_base = base; 52396495d90SSimon Glass base += uc_priv->gpio_count; 52496495d90SSimon Glass } 52596495d90SSimon Glass } 52696495d90SSimon Glass 52796495d90SSimon Glass return 0; 52896495d90SSimon Glass } 52996495d90SSimon Glass 53054c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 53196495d90SSimon Glass { 532b892d127SSimon Glass struct gpio_dev_priv *uc_priv = dev->uclass_priv; 533b892d127SSimon Glass 534b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 535b892d127SSimon Glass if (!uc_priv->name) 536b892d127SSimon Glass return -ENOMEM; 537b892d127SSimon Glass 538b892d127SSimon Glass return gpio_renumber(NULL); 53996495d90SSimon Glass } 54096495d90SSimon Glass 54154c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 54296495d90SSimon Glass { 543b892d127SSimon Glass struct gpio_dev_priv *uc_priv = dev->uclass_priv; 544b892d127SSimon Glass int i; 545b892d127SSimon Glass 546b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 547b892d127SSimon Glass if (uc_priv->name[i]) 548b892d127SSimon Glass free(uc_priv->name[i]); 549b892d127SSimon Glass } 550b892d127SSimon Glass free(uc_priv->name); 551b892d127SSimon Glass 552b892d127SSimon Glass return gpio_renumber(dev); 55396495d90SSimon Glass } 55496495d90SSimon Glass 55596495d90SSimon Glass UCLASS_DRIVER(gpio) = { 55696495d90SSimon Glass .id = UCLASS_GPIO, 55796495d90SSimon Glass .name = "gpio", 55896495d90SSimon Glass .post_probe = gpio_post_probe, 55996495d90SSimon Glass .pre_remove = gpio_pre_remove, 56096495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 56196495d90SSimon Glass }; 562