183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 296495d90SSimon Glass /* 396495d90SSimon Glass * Copyright (c) 2013 Google, Inc 496495d90SSimon Glass */ 596495d90SSimon Glass 696495d90SSimon Glass #include <common.h> 796495d90SSimon Glass #include <dm.h> 86c880b77SEric Nelson #include <dt-bindings/gpio/gpio.h> 996495d90SSimon Glass #include <errno.h> 100dac4d51SSimon Glass #include <fdtdec.h> 11b892d127SSimon Glass #include <malloc.h> 1296495d90SSimon Glass #include <asm/gpio.h> 1384b8bf6dSMasahiro Yamada #include <linux/bug.h> 14fe1ef503SSimon Glass #include <linux/ctype.h> 1596495d90SSimon Glass 163669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 173669e0e7SSimon Glass 1896495d90SSimon Glass /** 1996495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2096495d90SSimon Glass * 2196495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2296495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2396495d90SSimon Glass * entry on success, NULL on error. 24ae7123f8SSimon Glass * 25ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 26ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 27ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 2896495d90SSimon Glass */ 29ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3096495d90SSimon Glass { 3196495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3254c5d08aSHeiko Schocher struct udevice *dev; 3396495d90SSimon Glass int ret; 3496495d90SSimon Glass 3596495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3696495d90SSimon Glass dev; 3796495d90SSimon Glass ret = uclass_next_device(&dev)) { 38e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 3996495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4096495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 41ae7123f8SSimon Glass desc->dev = dev; 42ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 43ae7123f8SSimon Glass desc->flags = 0; 4496495d90SSimon Glass return 0; 4596495d90SSimon Glass } 4696495d90SSimon Glass } 4796495d90SSimon Glass 4896495d90SSimon Glass /* No such GPIO */ 49ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5096495d90SSimon Glass } 5196495d90SSimon Glass 5232ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5396495d90SSimon Glass { 54fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5554c5d08aSHeiko Schocher struct udevice *dev; 56fe1ef503SSimon Glass ulong offset; 57fe1ef503SSimon Glass int numeric; 5896495d90SSimon Glass int ret; 5996495d90SSimon Glass 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 66e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 67fe1ef503SSimon Glass if (numeric != -1) { 68fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 69fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 7075897910STom Rini if (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 8532ec1598SSimon Glass desc->dev = dev; 8632ec1598SSimon Glass desc->offset = offset; 8732ec1598SSimon Glass 8832ec1598SSimon Glass return 0; 8932ec1598SSimon Glass } 9032ec1598SSimon Glass 9132ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9232ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9332ec1598SSimon Glass { 9432ec1598SSimon Glass struct gpio_desc desc; 9532ec1598SSimon Glass int ret; 9632ec1598SSimon Glass 9796495d90SSimon Glass if (devp) 9832ec1598SSimon Glass *devp = NULL; 9932ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10032ec1598SSimon Glass if (ret) 10132ec1598SSimon Glass return ret; 10232ec1598SSimon Glass 10332ec1598SSimon Glass if (devp) 10432ec1598SSimon Glass *devp = desc.dev; 10596495d90SSimon Glass if (offsetp) 10632ec1598SSimon Glass *offsetp = desc.offset; 10732ec1598SSimon Glass if (gpiop) { 10832ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 10932ec1598SSimon Glass 11032ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11132ec1598SSimon Glass } 11296495d90SSimon Glass 113fe1ef503SSimon Glass return 0; 11496495d90SSimon Glass } 11596495d90SSimon Glass 1163a57123eSSimon Glass int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, 1173a57123eSSimon Glass struct ofnode_phandle_args *args) 1186c880b77SEric Nelson { 1196c880b77SEric Nelson if (args->args_count < 1) 1206c880b77SEric Nelson return -EINVAL; 1216c880b77SEric Nelson 1226c880b77SEric Nelson desc->offset = args->args[0]; 1236c880b77SEric Nelson 1246c880b77SEric Nelson if (args->args_count < 2) 1256c880b77SEric Nelson return 0; 1266c880b77SEric Nelson 1276c880b77SEric Nelson if (args->args[1] & GPIO_ACTIVE_LOW) 1286c880b77SEric Nelson desc->flags = GPIOD_ACTIVE_LOW; 1296c880b77SEric Nelson 1306c880b77SEric Nelson return 0; 1316c880b77SEric Nelson } 1326c880b77SEric Nelson 1333669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1343a57123eSSimon Glass struct ofnode_phandle_args *args) 1350dac4d51SSimon Glass { 1360dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1370dac4d51SSimon Glass 1386c880b77SEric Nelson if (ops->xlate) 1396c880b77SEric Nelson return ops->xlate(desc->dev, desc, args); 1400dac4d51SSimon Glass else 1416c880b77SEric Nelson return gpio_xlate_offs_flags(desc->dev, desc, args); 1420dac4d51SSimon Glass } 1430dac4d51SSimon Glass 144efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 145ae7123f8SSimon Glass { 146ae7123f8SSimon Glass struct udevice *dev = desc->dev; 147ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 148ae7123f8SSimon Glass char *str; 149ae7123f8SSimon Glass int ret; 150ae7123f8SSimon Glass 151e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 152ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 153ae7123f8SSimon Glass return -EBUSY; 154ae7123f8SSimon Glass str = strdup(label); 155ae7123f8SSimon Glass if (!str) 156ae7123f8SSimon Glass return -ENOMEM; 157ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 158ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 159ae7123f8SSimon Glass if (ret) { 160ae7123f8SSimon Glass free(str); 161ae7123f8SSimon Glass return ret; 162ae7123f8SSimon Glass } 163ae7123f8SSimon Glass } 164ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 165ae7123f8SSimon Glass 166ae7123f8SSimon Glass return 0; 167ae7123f8SSimon Glass } 168ae7123f8SSimon Glass 1693669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 1703669e0e7SSimon Glass { 1714dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 1723669e0e7SSimon Glass va_list args; 1733669e0e7SSimon Glass char buf[40]; 1743669e0e7SSimon Glass 1753669e0e7SSimon Glass va_start(args, fmt); 1763669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 1773669e0e7SSimon Glass va_end(args); 1783669e0e7SSimon Glass return dm_gpio_request(desc, buf); 1794dc5259aSSimon Glass #else 1804dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 1814dc5259aSSimon Glass #endif 1823669e0e7SSimon Glass } 1833669e0e7SSimon Glass 18496495d90SSimon Glass /** 18596495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 18696495d90SSimon Glass * gpio: GPIO number 18796495d90SSimon Glass * label: Name for the requested GPIO 18896495d90SSimon Glass * 189b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 190b892d127SSimon Glass * the pointer around. 191b892d127SSimon Glass * 19296495d90SSimon Glass * This function implements the API that's compatible with current 19396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 19496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 19596495d90SSimon Glass */ 19696495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 19796495d90SSimon Glass { 198ae7123f8SSimon Glass struct gpio_desc desc; 19996495d90SSimon Glass int ret; 20096495d90SSimon Glass 201ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 20296495d90SSimon Glass if (ret) 20396495d90SSimon Glass return ret; 20496495d90SSimon Glass 205ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 20696495d90SSimon Glass } 20796495d90SSimon Glass 20896495d90SSimon Glass /** 209d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 210d44f597bSSimon Glass * @gpio: GPIO number 211d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 212d44f597bSSimon Glass * @...: Arguments for the printf() format string 213d44f597bSSimon Glass * 214d44f597bSSimon Glass * This function implements the API that's compatible with current 215d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 216d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 217d44f597bSSimon Glass */ 218d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 219d44f597bSSimon Glass { 2204dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 221d44f597bSSimon Glass va_list args; 222d44f597bSSimon Glass char buf[40]; 223d44f597bSSimon Glass 224d44f597bSSimon Glass va_start(args, fmt); 225d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 226d44f597bSSimon Glass va_end(args); 227d44f597bSSimon Glass return gpio_request(gpio, buf); 2284dc5259aSSimon Glass #else 2294dc5259aSSimon Glass return gpio_request(gpio, fmt); 2304dc5259aSSimon Glass #endif 231d44f597bSSimon Glass } 232d44f597bSSimon Glass 233ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 23496495d90SSimon Glass { 235b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 23696495d90SSimon Glass int ret; 23796495d90SSimon Glass 238e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 239b892d127SSimon Glass if (!uc_priv->name[offset]) 240b892d127SSimon Glass return -ENXIO; 241b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 242b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 243b892d127SSimon Glass if (ret) 244b892d127SSimon Glass return ret; 245b892d127SSimon Glass } 246b892d127SSimon Glass 247b892d127SSimon Glass free(uc_priv->name[offset]); 248b892d127SSimon Glass uc_priv->name[offset] = NULL; 249b892d127SSimon Glass 25096495d90SSimon Glass return 0; 251b892d127SSimon Glass } 252b892d127SSimon Glass 253ae7123f8SSimon Glass /** 254ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 255ae7123f8SSimon Glass * gpio: GPIO number 256ae7123f8SSimon Glass * 257ae7123f8SSimon Glass * This function implements the API that's compatible with current 258ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 259ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 260ae7123f8SSimon Glass */ 261ae7123f8SSimon Glass int gpio_free(unsigned gpio) 262b892d127SSimon Glass { 263ae7123f8SSimon Glass struct gpio_desc desc; 264ae7123f8SSimon Glass int ret; 265b892d127SSimon Glass 266ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 267ae7123f8SSimon Glass if (ret) 268ae7123f8SSimon Glass return ret; 269ae7123f8SSimon Glass 270ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 271ae7123f8SSimon Glass } 272ae7123f8SSimon Glass 27317c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 274ae7123f8SSimon Glass { 275eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 276ae7123f8SSimon Glass 277eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 278eca48665SSimon Glass return -ENOENT; 279eca48665SSimon Glass 280eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 281ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 282b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 283ae7123f8SSimon Glass desc->dev->name, func, 284ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 285ae7123f8SSimon Glass desc->offset); 286b892d127SSimon Glass return -EBUSY; 287b892d127SSimon Glass } 288b892d127SSimon Glass 289b892d127SSimon Glass return 0; 29096495d90SSimon Glass } 29196495d90SSimon Glass 29296495d90SSimon Glass /** 29396495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 29496495d90SSimon Glass * gpio: GPIO number 29596495d90SSimon Glass * 29696495d90SSimon Glass * This function implements the API that's compatible with current 29796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 29896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 29996495d90SSimon Glass */ 30096495d90SSimon Glass int gpio_direction_input(unsigned gpio) 30196495d90SSimon Glass { 302ae7123f8SSimon Glass struct gpio_desc desc; 30396495d90SSimon Glass int ret; 30496495d90SSimon Glass 305ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 30696495d90SSimon Glass if (ret) 30796495d90SSimon Glass return ret; 308ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 309ae7123f8SSimon Glass if (ret) 310ae7123f8SSimon Glass return ret; 31196495d90SSimon Glass 312ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 31396495d90SSimon Glass } 31496495d90SSimon Glass 31596495d90SSimon Glass /** 31696495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 31796495d90SSimon Glass * gpio: GPIO number 31896495d90SSimon Glass * value: Logical value to be set on the GPIO pin 31996495d90SSimon Glass * 32096495d90SSimon Glass * This function implements the API that's compatible with current 32196495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 32296495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 32396495d90SSimon Glass */ 32496495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 32596495d90SSimon Glass { 326ae7123f8SSimon Glass struct gpio_desc desc; 32796495d90SSimon Glass int ret; 32896495d90SSimon Glass 329ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 33096495d90SSimon Glass if (ret) 33196495d90SSimon Glass return ret; 332ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 333ae7123f8SSimon Glass if (ret) 334ae7123f8SSimon Glass return ret; 33596495d90SSimon Glass 336ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 337ae7123f8SSimon Glass desc.offset, value); 338ae7123f8SSimon Glass } 339ae7123f8SSimon Glass 34017c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 341ae7123f8SSimon Glass { 342ae7123f8SSimon Glass int value; 343ae7123f8SSimon Glass int ret; 344ae7123f8SSimon Glass 345ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 346ae7123f8SSimon Glass if (ret) 347ae7123f8SSimon Glass return ret; 348ae7123f8SSimon Glass 349ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 350ae7123f8SSimon Glass 351ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 352ae7123f8SSimon Glass } 353ae7123f8SSimon Glass 35417c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 355ae7123f8SSimon Glass { 356ae7123f8SSimon Glass int ret; 357ae7123f8SSimon Glass 358ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 359ae7123f8SSimon Glass if (ret) 360ae7123f8SSimon Glass return ret; 361ae7123f8SSimon Glass 362ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 363ae7123f8SSimon Glass value = !value; 364ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 365ae7123f8SSimon Glass return 0; 366ae7123f8SSimon Glass } 367ae7123f8SSimon Glass 36853ecdfb9Smario.six@gdsys.cc int dm_gpio_get_open_drain(struct gpio_desc *desc) 36953ecdfb9Smario.six@gdsys.cc { 37053ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 37153ecdfb9Smario.six@gdsys.cc int ret; 37253ecdfb9Smario.six@gdsys.cc 37353ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "get_open_drain"); 37453ecdfb9Smario.six@gdsys.cc if (ret) 37553ecdfb9Smario.six@gdsys.cc return ret; 37653ecdfb9Smario.six@gdsys.cc 37753ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 37853ecdfb9Smario.six@gdsys.cc return ops->get_open_drain(desc->dev, desc->offset); 37953ecdfb9Smario.six@gdsys.cc else 38053ecdfb9Smario.six@gdsys.cc return -ENOSYS; 38153ecdfb9Smario.six@gdsys.cc } 38253ecdfb9Smario.six@gdsys.cc 38353ecdfb9Smario.six@gdsys.cc int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) 38453ecdfb9Smario.six@gdsys.cc { 38553ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 38653ecdfb9Smario.six@gdsys.cc int ret; 38753ecdfb9Smario.six@gdsys.cc 38853ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "set_open_drain"); 38953ecdfb9Smario.six@gdsys.cc if (ret) 39053ecdfb9Smario.six@gdsys.cc return ret; 39153ecdfb9Smario.six@gdsys.cc 39253ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 39353ecdfb9Smario.six@gdsys.cc ret = ops->set_open_drain(desc->dev, desc->offset, value); 39453ecdfb9Smario.six@gdsys.cc else 39553ecdfb9Smario.six@gdsys.cc return 0; /* feature not supported -> ignore setting */ 39653ecdfb9Smario.six@gdsys.cc 39753ecdfb9Smario.six@gdsys.cc return ret; 39853ecdfb9Smario.six@gdsys.cc } 39953ecdfb9Smario.six@gdsys.cc 400ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 401ae7123f8SSimon Glass { 402ae7123f8SSimon Glass struct udevice *dev = desc->dev; 403ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 404ae7123f8SSimon Glass int ret; 405ae7123f8SSimon Glass 406ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 407ae7123f8SSimon Glass if (ret) 408ae7123f8SSimon Glass return ret; 409ae7123f8SSimon Glass 410ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 411ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 412ae7123f8SSimon Glass 413ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 414ae7123f8SSimon Glass value = !value; 415ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 416ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 417ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 418ae7123f8SSimon Glass } 419ae7123f8SSimon Glass if (ret) 420ae7123f8SSimon Glass return ret; 421ae7123f8SSimon Glass /* 422ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 423ae7123f8SSimon Glass * futures 424ae7123f8SSimon Glass */ 425ae7123f8SSimon Glass desc->flags = flags; 426ae7123f8SSimon Glass 427ae7123f8SSimon Glass return 0; 428ae7123f8SSimon Glass } 429ae7123f8SSimon Glass 430ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 431ae7123f8SSimon Glass { 432ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 43396495d90SSimon Glass } 43496495d90SSimon Glass 43596495d90SSimon Glass /** 43696495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 43796495d90SSimon Glass * gpio: GPIO number 43896495d90SSimon Glass * 43996495d90SSimon Glass * This function implements the API that's compatible with current 44096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 44196495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 44296495d90SSimon Glass * on error. 44396495d90SSimon Glass */ 44496495d90SSimon Glass int gpio_get_value(unsigned gpio) 44596495d90SSimon Glass { 44696495d90SSimon Glass int ret; 44796495d90SSimon Glass 448ae7123f8SSimon Glass struct gpio_desc desc; 449ae7123f8SSimon Glass 450ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 45196495d90SSimon Glass if (ret) 45296495d90SSimon Glass return ret; 453ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 45496495d90SSimon Glass } 45596495d90SSimon Glass 45696495d90SSimon Glass /** 45796495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 45896495d90SSimon Glass * gpio: GPIO number 45996495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 46096495d90SSimon Glass * 46196495d90SSimon Glass * This function implements the API that's compatible with current 46296495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 46396495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 46496495d90SSimon Glass */ 46596495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 46696495d90SSimon Glass { 467ae7123f8SSimon Glass struct gpio_desc desc; 46896495d90SSimon Glass int ret; 46996495d90SSimon Glass 470ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 47196495d90SSimon Glass if (ret) 47296495d90SSimon Glass return ret; 473ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 47496495d90SSimon Glass } 47596495d90SSimon Glass 47654c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 47796495d90SSimon Glass { 47896495d90SSimon Glass struct gpio_dev_priv *priv; 47996495d90SSimon Glass 48096495d90SSimon Glass /* Must be called on an active device */ 481e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 48296495d90SSimon Glass assert(priv); 48396495d90SSimon Glass 48496495d90SSimon Glass *bit_count = priv->gpio_count; 48596495d90SSimon Glass return priv->bank_name; 48696495d90SSimon Glass } 48796495d90SSimon Glass 4886449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4896449a506SSimon Glass "input", 4906449a506SSimon Glass "output", 4916449a506SSimon Glass "unused", 4926449a506SSimon Glass "unknown", 4936449a506SSimon Glass "func", 4946449a506SSimon Glass }; 4956449a506SSimon Glass 496fb07f97dSMasahiro Yamada static int get_function(struct udevice *dev, int offset, bool skip_unused, 4976449a506SSimon Glass const char **namep) 4986449a506SSimon Glass { 499e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 5006449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 5016449a506SSimon Glass 5026449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 5036449a506SSimon Glass if (!device_active(dev)) 5046449a506SSimon Glass return -ENODEV; 5056449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 5066449a506SSimon Glass return -EINVAL; 5076449a506SSimon Glass if (namep) 5086449a506SSimon Glass *namep = uc_priv->name[offset]; 5096449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 5106449a506SSimon Glass return GPIOF_UNUSED; 5116449a506SSimon Glass if (ops->get_function) { 5126449a506SSimon Glass int ret; 5136449a506SSimon Glass 5146449a506SSimon Glass ret = ops->get_function(dev, offset); 5156449a506SSimon Glass if (ret < 0) 5166449a506SSimon Glass return ret; 5176449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 5186449a506SSimon Glass return -ENODATA; 5196449a506SSimon Glass return ret; 5206449a506SSimon Glass } 5216449a506SSimon Glass 5226449a506SSimon Glass return GPIOF_UNKNOWN; 5236449a506SSimon Glass } 5246449a506SSimon Glass 5256449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 5266449a506SSimon Glass { 5276449a506SSimon Glass return get_function(dev, offset, true, namep); 5286449a506SSimon Glass } 5296449a506SSimon Glass 5306449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 5316449a506SSimon Glass { 5326449a506SSimon Glass return get_function(dev, offset, false, namep); 5336449a506SSimon Glass } 5346449a506SSimon Glass 5350757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 5360757535aSSimon Glass { 5370757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 5380757535aSSimon Glass struct gpio_dev_priv *priv; 5390757535aSSimon Glass char *str = buf; 5400757535aSSimon Glass int func; 5410757535aSSimon Glass int ret; 5420757535aSSimon Glass int len; 5430757535aSSimon Glass 5440757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 5450757535aSSimon Glass 5460757535aSSimon Glass *buf = 0; 547e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 5480757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 5490757535aSSimon Glass if (ret < 0) 5500757535aSSimon Glass return ret; 5510757535aSSimon Glass func = ret; 5520757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 5530757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 5540757535aSSimon Glass offset, gpio_function[func]); 5550757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 5560757535aSSimon Glass func == GPIOF_UNUSED) { 5570757535aSSimon Glass const char *label; 5580757535aSSimon Glass bool used; 5590757535aSSimon Glass 5600757535aSSimon Glass ret = ops->get_value(dev, offset); 5610757535aSSimon Glass if (ret < 0) 5620757535aSSimon Glass return ret; 5630757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 5640757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 5650757535aSSimon Glass ret, 5660757535aSSimon Glass used ? 'x' : ' ', 5670757535aSSimon Glass used ? " " : "", 5680757535aSSimon Glass label ? label : ""); 5690757535aSSimon Glass } 5700757535aSSimon Glass 5710757535aSSimon Glass return 0; 5720757535aSSimon Glass } 5730757535aSSimon Glass 574962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 575962f5cafSSimon Glass { 576962f5cafSSimon Glass int i, ret; 577962f5cafSSimon Glass int gpio; 578962f5cafSSimon Glass 579962f5cafSSimon Glass for (i = 0; i < 32; i++) { 580962f5cafSSimon Glass gpio = gpio_num_array[i]; 581962f5cafSSimon Glass if (gpio == -1) 582962f5cafSSimon Glass break; 583962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 584962f5cafSSimon Glass if (ret) 585962f5cafSSimon Glass goto err; 586962f5cafSSimon Glass ret = gpio_direction_input(gpio); 587962f5cafSSimon Glass if (ret) { 588962f5cafSSimon Glass gpio_free(gpio); 589962f5cafSSimon Glass goto err; 590962f5cafSSimon Glass } 591962f5cafSSimon Glass } 592962f5cafSSimon Glass 593962f5cafSSimon Glass return 0; 594962f5cafSSimon Glass err: 595962f5cafSSimon Glass for (i--; i >= 0; i--) 596962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 597962f5cafSSimon Glass 598962f5cafSSimon Glass return ret; 599962f5cafSSimon Glass } 600962f5cafSSimon Glass 601e5901c94SSimon Glass /* 602e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 603e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 604e5901c94SSimon Glass */ 605962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 606e5901c94SSimon Glass { 607e5901c94SSimon Glass int gpio; 608e5901c94SSimon Glass unsigned bitmask = 1; 609e5901c94SSimon Glass unsigned vector = 0; 610962f5cafSSimon Glass int ret; 611e5901c94SSimon Glass 612e5901c94SSimon Glass while (bitmask && 613962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 614962f5cafSSimon Glass ret = gpio_get_value(gpio); 615962f5cafSSimon Glass if (ret < 0) 616962f5cafSSimon Glass return ret; 617962f5cafSSimon Glass else if (ret) 618e5901c94SSimon Glass vector |= bitmask; 619e5901c94SSimon Glass bitmask <<= 1; 620e5901c94SSimon Glass } 621962f5cafSSimon Glass 622e5901c94SSimon Glass return vector; 623e5901c94SSimon Glass } 624e5901c94SSimon Glass 62517c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 626bbf24780SSimon Glass { 627bbf24780SSimon Glass unsigned bitmask = 1; 628bbf24780SSimon Glass unsigned vector = 0; 629bbf24780SSimon Glass int ret, i; 630bbf24780SSimon Glass 631bbf24780SSimon Glass for (i = 0; i < count; i++) { 632bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 633bbf24780SSimon Glass if (ret < 0) 634bbf24780SSimon Glass return ret; 635bbf24780SSimon Glass else if (ret) 636bbf24780SSimon Glass vector |= bitmask; 637bbf24780SSimon Glass bitmask <<= 1; 638bbf24780SSimon Glass } 639bbf24780SSimon Glass 640bbf24780SSimon Glass return vector; 641bbf24780SSimon Glass } 642bbf24780SSimon Glass 6433a57123eSSimon Glass static int gpio_request_tail(int ret, ofnode node, 6443a57123eSSimon Glass struct ofnode_phandle_args *args, 6453669e0e7SSimon Glass const char *list_name, int index, 6463a57123eSSimon Glass struct gpio_desc *desc, int flags, bool add_index) 6473669e0e7SSimon Glass { 6483669e0e7SSimon Glass desc->dev = NULL; 6493669e0e7SSimon Glass desc->offset = 0; 6506c880b77SEric Nelson desc->flags = 0; 6513a57123eSSimon Glass if (ret) 6523669e0e7SSimon Glass goto err; 6533669e0e7SSimon Glass 6543a57123eSSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, 6553669e0e7SSimon Glass &desc->dev); 6563669e0e7SSimon Glass if (ret) { 657b053dd7cSMario Six debug("%s: uclass_get_device_by_ofnode failed\n", __func__); 6583669e0e7SSimon Glass goto err; 6593669e0e7SSimon Glass } 6603a57123eSSimon Glass ret = gpio_find_and_xlate(desc, args); 6613669e0e7SSimon Glass if (ret) { 6623669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 6633669e0e7SSimon Glass goto err; 6643669e0e7SSimon Glass } 6653669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 6663a57123eSSimon Glass ofnode_get_name(node), 6673669e0e7SSimon Glass list_name, index); 6683669e0e7SSimon Glass if (ret) { 6693669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 6703669e0e7SSimon Glass goto err; 6713669e0e7SSimon Glass } 6723669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 6733669e0e7SSimon Glass if (ret) { 6743669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 6753669e0e7SSimon Glass goto err; 6763669e0e7SSimon Glass } 6773669e0e7SSimon Glass 6783669e0e7SSimon Glass return 0; 6793669e0e7SSimon Glass err: 6803669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 6813a57123eSSimon Glass __func__, ofnode_get_name(node), list_name, index, ret); 6823669e0e7SSimon Glass return ret; 6833669e0e7SSimon Glass } 6843669e0e7SSimon Glass 685150c5afeSSimon Glass static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, 686150c5afeSSimon Glass int index, struct gpio_desc *desc, 687150c5afeSSimon Glass int flags, bool add_index) 6883a57123eSSimon Glass { 6893a57123eSSimon Glass struct ofnode_phandle_args args; 6903a57123eSSimon Glass int ret; 6913a57123eSSimon Glass 692150c5afeSSimon Glass ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, 693150c5afeSSimon Glass index, &args); 6943a57123eSSimon Glass 695150c5afeSSimon Glass return gpio_request_tail(ret, node, &args, list_name, index, desc, 696150c5afeSSimon Glass flags, add_index); 6973a57123eSSimon Glass } 6983a57123eSSimon Glass 699150c5afeSSimon Glass int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, 7003669e0e7SSimon Glass struct gpio_desc *desc, int flags) 7013669e0e7SSimon Glass { 702150c5afeSSimon Glass return _gpio_request_by_name_nodev(node, list_name, index, desc, flags, 703150c5afeSSimon Glass index > 0); 7043669e0e7SSimon Glass } 7053669e0e7SSimon Glass 7063669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 7073669e0e7SSimon Glass struct gpio_desc *desc, int flags) 7083669e0e7SSimon Glass { 709150c5afeSSimon Glass struct ofnode_phandle_args args; 710150c5afeSSimon Glass int ret; 711150c5afeSSimon Glass 712150c5afeSSimon Glass ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, 713150c5afeSSimon Glass index, &args); 714150c5afeSSimon Glass 715150c5afeSSimon Glass return gpio_request_tail(ret, dev_ofnode(dev), &args, list_name, 716150c5afeSSimon Glass index, desc, flags, index > 0); 7173669e0e7SSimon Glass } 7183669e0e7SSimon Glass 719150c5afeSSimon Glass int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, 7203669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 7213669e0e7SSimon Glass int flags) 7223669e0e7SSimon Glass { 7233669e0e7SSimon Glass int count; 7243669e0e7SSimon Glass int ret; 7253669e0e7SSimon Glass 7262984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 727150c5afeSSimon Glass ret = _gpio_request_by_name_nodev(node, list_name, count, 7283669e0e7SSimon Glass &desc[count], flags, true); 7293669e0e7SSimon Glass if (ret == -ENOENT) 7303669e0e7SSimon Glass break; 7313669e0e7SSimon Glass else if (ret) 7323669e0e7SSimon Glass goto err; 7333669e0e7SSimon Glass } 7343669e0e7SSimon Glass 7353669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 7363669e0e7SSimon Glass return count; 7373669e0e7SSimon Glass 7383669e0e7SSimon Glass err: 7393669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 7403669e0e7SSimon Glass 7413669e0e7SSimon Glass return ret; 7423669e0e7SSimon Glass } 7433669e0e7SSimon Glass 7443669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 7453669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 7463669e0e7SSimon Glass int flags) 7473669e0e7SSimon Glass { 7483669e0e7SSimon Glass /* 7493669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 7503669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 7513669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 7523669e0e7SSimon Glass */ 753150c5afeSSimon Glass return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc, 754150c5afeSSimon Glass max_count, flags); 7553669e0e7SSimon Glass } 7563669e0e7SSimon Glass 7573669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 7583669e0e7SSimon Glass { 7593669e0e7SSimon Glass int ret; 7603669e0e7SSimon Glass 761e160f7d4SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 7623669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 7633669e0e7SSimon Glass NULL); 7643669e0e7SSimon Glass if (ret) { 7653669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 7663669e0e7SSimon Glass __func__, dev->name, list_name, ret); 7673669e0e7SSimon Glass } 7683669e0e7SSimon Glass 7693669e0e7SSimon Glass return ret; 7703669e0e7SSimon Glass } 7713669e0e7SSimon Glass 7723669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 7733669e0e7SSimon Glass { 7743669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7753669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 7763669e0e7SSimon Glass } 7773669e0e7SSimon Glass 7783669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 7793669e0e7SSimon Glass { 7803669e0e7SSimon Glass int i; 7813669e0e7SSimon Glass 7823669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7833669e0e7SSimon Glass for (i = 0; i < count; i++) 7843669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 7853669e0e7SSimon Glass 7863669e0e7SSimon Glass return 0; 7873669e0e7SSimon Glass } 7883669e0e7SSimon Glass 7893669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 7903669e0e7SSimon Glass { 7913669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 7923669e0e7SSimon Glass } 7933669e0e7SSimon Glass 79496495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 795b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 79696495d90SSimon Glass { 79796495d90SSimon Glass struct gpio_dev_priv *uc_priv; 79854c5d08aSHeiko Schocher struct udevice *dev; 79996495d90SSimon Glass struct uclass *uc; 80096495d90SSimon Glass unsigned base; 80196495d90SSimon Glass int ret; 80296495d90SSimon Glass 80396495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 80496495d90SSimon Glass if (ret) 80596495d90SSimon Glass return ret; 80696495d90SSimon Glass 80796495d90SSimon Glass /* Ensure that we have a base for each bank */ 80896495d90SSimon Glass base = 0; 80996495d90SSimon Glass uclass_foreach_dev(dev, uc) { 810b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 811e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 81296495d90SSimon Glass uc_priv->gpio_base = base; 81396495d90SSimon Glass base += uc_priv->gpio_count; 81496495d90SSimon Glass } 81596495d90SSimon Glass } 81696495d90SSimon Glass 81796495d90SSimon Glass return 0; 81896495d90SSimon Glass } 81996495d90SSimon Glass 82017c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 82156a71f89SSimon Glass { 82256a71f89SSimon Glass struct udevice *dev = desc->dev; 82356a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 82456a71f89SSimon Glass 82556a71f89SSimon Glass if (!dev) 82656a71f89SSimon Glass return -1; 82756a71f89SSimon Glass uc_priv = dev->uclass_priv; 82856a71f89SSimon Glass 82956a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 83056a71f89SSimon Glass } 83156a71f89SSimon Glass 83254c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 83396495d90SSimon Glass { 834e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 835b892d127SSimon Glass 836b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 837b892d127SSimon Glass if (!uc_priv->name) 838b892d127SSimon Glass return -ENOMEM; 839b892d127SSimon Glass 840b892d127SSimon Glass return gpio_renumber(NULL); 84196495d90SSimon Glass } 84296495d90SSimon Glass 84354c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 84496495d90SSimon Glass { 845e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 846b892d127SSimon Glass int i; 847b892d127SSimon Glass 848b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 849b892d127SSimon Glass if (uc_priv->name[i]) 850b892d127SSimon Glass free(uc_priv->name[i]); 851b892d127SSimon Glass } 852b892d127SSimon Glass free(uc_priv->name); 853b892d127SSimon Glass 854b892d127SSimon Glass return gpio_renumber(dev); 85596495d90SSimon Glass } 85696495d90SSimon Glass 857*1b4c2aa2SMichal Simek static int gpio_post_bind(struct udevice *dev) 858*1b4c2aa2SMichal Simek { 859*1b4c2aa2SMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC) 860*1b4c2aa2SMichal Simek struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); 861*1b4c2aa2SMichal Simek static int reloc_done; 862*1b4c2aa2SMichal Simek 863*1b4c2aa2SMichal Simek if (!reloc_done) { 864*1b4c2aa2SMichal Simek if (ops->request) 865*1b4c2aa2SMichal Simek ops->request += gd->reloc_off; 866*1b4c2aa2SMichal Simek if (ops->free) 867*1b4c2aa2SMichal Simek ops->free += gd->reloc_off; 868*1b4c2aa2SMichal Simek if (ops->direction_input) 869*1b4c2aa2SMichal Simek ops->direction_input += gd->reloc_off; 870*1b4c2aa2SMichal Simek if (ops->direction_output) 871*1b4c2aa2SMichal Simek ops->direction_output += gd->reloc_off; 872*1b4c2aa2SMichal Simek if (ops->get_value) 873*1b4c2aa2SMichal Simek ops->get_value += gd->reloc_off; 874*1b4c2aa2SMichal Simek if (ops->set_value) 875*1b4c2aa2SMichal Simek ops->set_value += gd->reloc_off; 876*1b4c2aa2SMichal Simek if (ops->get_open_drain) 877*1b4c2aa2SMichal Simek ops->get_open_drain += gd->reloc_off; 878*1b4c2aa2SMichal Simek if (ops->set_open_drain) 879*1b4c2aa2SMichal Simek ops->set_open_drain += gd->reloc_off; 880*1b4c2aa2SMichal Simek if (ops->get_function) 881*1b4c2aa2SMichal Simek ops->get_function += gd->reloc_off; 882*1b4c2aa2SMichal Simek if (ops->xlate) 883*1b4c2aa2SMichal Simek ops->xlate += gd->reloc_off; 884*1b4c2aa2SMichal Simek 885*1b4c2aa2SMichal Simek reloc_done++; 886*1b4c2aa2SMichal Simek } 887*1b4c2aa2SMichal Simek #endif 888*1b4c2aa2SMichal Simek return 0; 889*1b4c2aa2SMichal Simek } 890*1b4c2aa2SMichal Simek 89196495d90SSimon Glass UCLASS_DRIVER(gpio) = { 89296495d90SSimon Glass .id = UCLASS_GPIO, 89396495d90SSimon Glass .name = "gpio", 894ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 89596495d90SSimon Glass .post_probe = gpio_post_probe, 896*1b4c2aa2SMichal Simek .post_bind = gpio_post_bind, 89796495d90SSimon Glass .pre_remove = gpio_pre_remove, 89896495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 89996495d90SSimon Glass }; 900