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