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> 97e044b9aSHeiko Schocher #include <dm/device-internal.h> 107e044b9aSHeiko Schocher #include <dm/lists.h> 117e044b9aSHeiko Schocher #include <dm/uclass-internal.h> 126c880b77SEric Nelson #include <dt-bindings/gpio/gpio.h> 1396495d90SSimon Glass #include <errno.h> 140dac4d51SSimon Glass #include <fdtdec.h> 15b892d127SSimon Glass #include <malloc.h> 1696495d90SSimon Glass #include <asm/gpio.h> 1784b8bf6dSMasahiro Yamada #include <linux/bug.h> 18fe1ef503SSimon Glass #include <linux/ctype.h> 1996495d90SSimon Glass 203669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 213669e0e7SSimon Glass 2296495d90SSimon Glass /** 2396495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2496495d90SSimon Glass * 2596495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2696495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2796495d90SSimon Glass * entry on success, NULL on error. 28ae7123f8SSimon Glass * 29ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 30ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 31ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 3296495d90SSimon Glass */ 33ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3496495d90SSimon Glass { 3596495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3654c5d08aSHeiko Schocher struct udevice *dev; 3796495d90SSimon Glass int ret; 3896495d90SSimon Glass 3996495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 4096495d90SSimon Glass dev; 4196495d90SSimon Glass ret = uclass_next_device(&dev)) { 42e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 4396495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4496495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 45ae7123f8SSimon Glass desc->dev = dev; 46ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 47ae7123f8SSimon Glass desc->flags = 0; 4896495d90SSimon Glass return 0; 4996495d90SSimon Glass } 5096495d90SSimon Glass } 5196495d90SSimon Glass 5296495d90SSimon Glass /* No such GPIO */ 53ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5496495d90SSimon Glass } 5596495d90SSimon Glass 5632ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5796495d90SSimon Glass { 58fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5954c5d08aSHeiko Schocher struct udevice *dev; 60fe1ef503SSimon Glass ulong offset; 61fe1ef503SSimon Glass int numeric; 6296495d90SSimon Glass int ret; 6396495d90SSimon Glass 64fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6596495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6696495d90SSimon Glass dev; 6796495d90SSimon Glass ret = uclass_next_device(&dev)) { 6896495d90SSimon Glass int len; 6996495d90SSimon Glass 70e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 71fe1ef503SSimon Glass if (numeric != -1) { 72fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 73fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 7475897910STom Rini if (offset < uc_priv->gpio_count) 75fe1ef503SSimon Glass break; 76fe1ef503SSimon Glass } 77fe1ef503SSimon Glass 7896495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7996495d90SSimon Glass 80939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 81fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 82fe1ef503SSimon Glass break; 83fe1ef503SSimon Glass } 84fe1ef503SSimon Glass } 85fe1ef503SSimon Glass 86fe1ef503SSimon Glass if (!dev) 87fe1ef503SSimon Glass return ret ? ret : -EINVAL; 88fe1ef503SSimon Glass 8932ec1598SSimon Glass desc->dev = dev; 9032ec1598SSimon Glass desc->offset = offset; 9132ec1598SSimon Glass 9232ec1598SSimon Glass return 0; 9332ec1598SSimon Glass } 9432ec1598SSimon Glass 9532ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9632ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9732ec1598SSimon Glass { 9832ec1598SSimon Glass struct gpio_desc desc; 9932ec1598SSimon Glass int ret; 10032ec1598SSimon Glass 10196495d90SSimon Glass if (devp) 10232ec1598SSimon Glass *devp = NULL; 10332ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10432ec1598SSimon Glass if (ret) 10532ec1598SSimon Glass return ret; 10632ec1598SSimon Glass 10732ec1598SSimon Glass if (devp) 10832ec1598SSimon Glass *devp = desc.dev; 10996495d90SSimon Glass if (offsetp) 11032ec1598SSimon Glass *offsetp = desc.offset; 11132ec1598SSimon Glass if (gpiop) { 11232ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 11332ec1598SSimon Glass 11432ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11532ec1598SSimon Glass } 11696495d90SSimon Glass 117fe1ef503SSimon Glass return 0; 11896495d90SSimon Glass } 11996495d90SSimon Glass 1203a57123eSSimon Glass int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, 1213a57123eSSimon Glass struct ofnode_phandle_args *args) 1226c880b77SEric Nelson { 1236c880b77SEric Nelson if (args->args_count < 1) 1246c880b77SEric Nelson return -EINVAL; 1256c880b77SEric Nelson 1266c880b77SEric Nelson desc->offset = args->args[0]; 1276c880b77SEric Nelson 1286c880b77SEric Nelson if (args->args_count < 2) 1296c880b77SEric Nelson return 0; 1306c880b77SEric Nelson 1316c880b77SEric Nelson if (args->args[1] & GPIO_ACTIVE_LOW) 1326c880b77SEric Nelson desc->flags = GPIOD_ACTIVE_LOW; 1336c880b77SEric Nelson 1346c880b77SEric Nelson return 0; 1356c880b77SEric Nelson } 1366c880b77SEric Nelson 1373669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1383a57123eSSimon Glass struct ofnode_phandle_args *args) 1390dac4d51SSimon Glass { 1400dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1410dac4d51SSimon Glass 1426c880b77SEric Nelson if (ops->xlate) 1436c880b77SEric Nelson return ops->xlate(desc->dev, desc, args); 1440dac4d51SSimon Glass else 1456c880b77SEric Nelson return gpio_xlate_offs_flags(desc->dev, desc, args); 1460dac4d51SSimon Glass } 1470dac4d51SSimon Glass 14825cd3b96SHeiko Schocher #if defined(CONFIG_GPIO_HOG) 1497e044b9aSHeiko Schocher 1507e044b9aSHeiko Schocher struct gpio_hog_priv { 1517e044b9aSHeiko Schocher struct gpio_desc gpiod; 1527e044b9aSHeiko Schocher }; 1537e044b9aSHeiko Schocher 1547e044b9aSHeiko Schocher struct gpio_hog_data { 1557e044b9aSHeiko Schocher int gpiod_flags; 1567e044b9aSHeiko Schocher int value; 1577e044b9aSHeiko Schocher u32 val[2]; 1587e044b9aSHeiko Schocher }; 1597e044b9aSHeiko Schocher 1607e044b9aSHeiko Schocher static int gpio_hog_ofdata_to_platdata(struct udevice *dev) 1617e044b9aSHeiko Schocher { 1627e044b9aSHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 1637e044b9aSHeiko Schocher const char *nodename; 1647e044b9aSHeiko Schocher int ret; 1657e044b9aSHeiko Schocher 1667e044b9aSHeiko Schocher plat->value = 0; 1677e044b9aSHeiko Schocher if (dev_read_bool(dev, "input")) { 1687e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_IN; 1697e044b9aSHeiko Schocher } else if (dev_read_bool(dev, "output-high")) { 1707e044b9aSHeiko Schocher plat->value = 1; 1717e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 1727e044b9aSHeiko Schocher } else if (dev_read_bool(dev, "output-low")) { 1737e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 1747e044b9aSHeiko Schocher } else { 1757e044b9aSHeiko Schocher printf("%s: missing gpio-hog state.\n", __func__); 1767e044b9aSHeiko Schocher return -EINVAL; 1777e044b9aSHeiko Schocher } 1787e044b9aSHeiko Schocher ret = dev_read_u32_array(dev, "gpios", plat->val, 2); 1797e044b9aSHeiko Schocher if (ret) { 1807e044b9aSHeiko Schocher printf("%s: wrong gpios property, 2 values needed %d\n", 1817e044b9aSHeiko Schocher __func__, ret); 1827e044b9aSHeiko Schocher return ret; 1837e044b9aSHeiko Schocher } 1847e044b9aSHeiko Schocher nodename = dev_read_string(dev, "line-name"); 18525cd3b96SHeiko Schocher if (nodename) 1867e044b9aSHeiko Schocher device_set_name(dev, nodename); 1877e044b9aSHeiko Schocher 1887e044b9aSHeiko Schocher return 0; 1897e044b9aSHeiko Schocher } 1907e044b9aSHeiko Schocher 1917e044b9aSHeiko Schocher static int gpio_hog_probe(struct udevice *dev) 1927e044b9aSHeiko Schocher { 1937e044b9aSHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 1947e044b9aSHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 1957e044b9aSHeiko Schocher int ret; 1967e044b9aSHeiko Schocher 1977e044b9aSHeiko Schocher ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog", 1987e044b9aSHeiko Schocher plat->val[0], plat->gpiod_flags, 1997e044b9aSHeiko Schocher plat->val[1], &priv->gpiod); 2007e044b9aSHeiko Schocher if (ret < 0) { 2017e044b9aSHeiko Schocher debug("%s: node %s could not get gpio.\n", __func__, 2027e044b9aSHeiko Schocher dev->name); 2037e044b9aSHeiko Schocher return ret; 2047e044b9aSHeiko Schocher } 20525cd3b96SHeiko Schocher 20625cd3b96SHeiko Schocher if (plat->gpiod_flags == GPIOD_IS_OUT) { 20725cd3b96SHeiko Schocher ret = dm_gpio_set_value(&priv->gpiod, plat->value); 20825cd3b96SHeiko Schocher if (ret < 0) { 20925cd3b96SHeiko Schocher debug("%s: node %s could not set gpio.\n", __func__, 21025cd3b96SHeiko Schocher dev->name); 21125cd3b96SHeiko Schocher return ret; 21225cd3b96SHeiko Schocher } 21325cd3b96SHeiko Schocher } 2147e044b9aSHeiko Schocher 2157e044b9aSHeiko Schocher return 0; 2167e044b9aSHeiko Schocher } 2177e044b9aSHeiko Schocher 2187e044b9aSHeiko Schocher int gpio_hog_probe_all(void) 2197e044b9aSHeiko Schocher { 2207e044b9aSHeiko Schocher struct udevice *dev; 2217e044b9aSHeiko Schocher int ret; 22225cd3b96SHeiko Schocher int retval = 0; 2237e044b9aSHeiko Schocher 2247e044b9aSHeiko Schocher for (uclass_find_first_device(UCLASS_NOP, &dev); 2257e044b9aSHeiko Schocher dev; 2267e044b9aSHeiko Schocher uclass_find_next_device(&dev)) { 2277e044b9aSHeiko Schocher if (dev->driver == DM_GET_DRIVER(gpio_hog)) { 2287e044b9aSHeiko Schocher ret = device_probe(dev); 22925cd3b96SHeiko Schocher if (ret) { 23025cd3b96SHeiko Schocher printf("Failed to probe device %s err: %d\n", 23125cd3b96SHeiko Schocher dev->name, ret); 23225cd3b96SHeiko Schocher retval = ret; 23325cd3b96SHeiko Schocher } 2347e044b9aSHeiko Schocher } 2357e044b9aSHeiko Schocher } 2367e044b9aSHeiko Schocher 23725cd3b96SHeiko Schocher return retval; 2387e044b9aSHeiko Schocher } 2397e044b9aSHeiko Schocher 24025cd3b96SHeiko Schocher int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) 2417e044b9aSHeiko Schocher { 2427e044b9aSHeiko Schocher struct udevice *dev; 2437e044b9aSHeiko Schocher 24425cd3b96SHeiko Schocher *desc = NULL; 2457e044b9aSHeiko Schocher gpio_hog_probe_all(); 2467e044b9aSHeiko Schocher if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { 2477e044b9aSHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 2487e044b9aSHeiko Schocher 24925cd3b96SHeiko Schocher *desc = &priv->gpiod; 25025cd3b96SHeiko Schocher return 0; 2517e044b9aSHeiko Schocher } 2527e044b9aSHeiko Schocher 25325cd3b96SHeiko Schocher return -ENODEV; 2547e044b9aSHeiko Schocher } 2557e044b9aSHeiko Schocher 2567e044b9aSHeiko Schocher U_BOOT_DRIVER(gpio_hog) = { 2577e044b9aSHeiko Schocher .name = "gpio_hog", 2587e044b9aSHeiko Schocher .id = UCLASS_NOP, 2597e044b9aSHeiko Schocher .ofdata_to_platdata = gpio_hog_ofdata_to_platdata, 2607e044b9aSHeiko Schocher .probe = gpio_hog_probe, 2617e044b9aSHeiko Schocher .priv_auto_alloc_size = sizeof(struct gpio_hog_priv), 2627e044b9aSHeiko Schocher .platdata_auto_alloc_size = sizeof(struct gpio_hog_data), 2637e044b9aSHeiko Schocher }; 2647e044b9aSHeiko Schocher #else 26525cd3b96SHeiko Schocher int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) 2667e044b9aSHeiko Schocher { 26725cd3b96SHeiko Schocher return 0; 2687e044b9aSHeiko Schocher } 2697e044b9aSHeiko Schocher #endif 2707e044b9aSHeiko Schocher 271efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 272ae7123f8SSimon Glass { 273ae7123f8SSimon Glass struct udevice *dev = desc->dev; 274ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 275ae7123f8SSimon Glass char *str; 276ae7123f8SSimon Glass int ret; 277ae7123f8SSimon Glass 278e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 279ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 280ae7123f8SSimon Glass return -EBUSY; 281ae7123f8SSimon Glass str = strdup(label); 282ae7123f8SSimon Glass if (!str) 283ae7123f8SSimon Glass return -ENOMEM; 284ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 285ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 286ae7123f8SSimon Glass if (ret) { 287ae7123f8SSimon Glass free(str); 288ae7123f8SSimon Glass return ret; 289ae7123f8SSimon Glass } 290ae7123f8SSimon Glass } 291ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 292ae7123f8SSimon Glass 293ae7123f8SSimon Glass return 0; 294ae7123f8SSimon Glass } 295ae7123f8SSimon Glass 2963669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 2973669e0e7SSimon Glass { 2984dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 2993669e0e7SSimon Glass va_list args; 3003669e0e7SSimon Glass char buf[40]; 3013669e0e7SSimon Glass 3023669e0e7SSimon Glass va_start(args, fmt); 3033669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 3043669e0e7SSimon Glass va_end(args); 3053669e0e7SSimon Glass return dm_gpio_request(desc, buf); 3064dc5259aSSimon Glass #else 3074dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 3084dc5259aSSimon Glass #endif 3093669e0e7SSimon Glass } 3103669e0e7SSimon Glass 31196495d90SSimon Glass /** 31296495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 31396495d90SSimon Glass * gpio: GPIO number 31496495d90SSimon Glass * label: Name for the requested GPIO 31596495d90SSimon Glass * 316b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 317b892d127SSimon Glass * the pointer around. 318b892d127SSimon Glass * 31996495d90SSimon Glass * This function implements the API that's compatible with current 32096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 32196495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 32296495d90SSimon Glass */ 32396495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 32496495d90SSimon Glass { 325ae7123f8SSimon Glass struct gpio_desc desc; 32696495d90SSimon Glass int ret; 32796495d90SSimon Glass 328ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 32996495d90SSimon Glass if (ret) 33096495d90SSimon Glass return ret; 33196495d90SSimon Glass 332ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 33396495d90SSimon Glass } 33496495d90SSimon Glass 33596495d90SSimon Glass /** 336d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 337d44f597bSSimon Glass * @gpio: GPIO number 338d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 339d44f597bSSimon Glass * @...: Arguments for the printf() format string 340d44f597bSSimon Glass * 341d44f597bSSimon Glass * This function implements the API that's compatible with current 342d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 343d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 344d44f597bSSimon Glass */ 345d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 346d44f597bSSimon Glass { 3474dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 348d44f597bSSimon Glass va_list args; 349d44f597bSSimon Glass char buf[40]; 350d44f597bSSimon Glass 351d44f597bSSimon Glass va_start(args, fmt); 352d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 353d44f597bSSimon Glass va_end(args); 354d44f597bSSimon Glass return gpio_request(gpio, buf); 3554dc5259aSSimon Glass #else 3564dc5259aSSimon Glass return gpio_request(gpio, fmt); 3574dc5259aSSimon Glass #endif 358d44f597bSSimon Glass } 359d44f597bSSimon Glass 360ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 36196495d90SSimon Glass { 362b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 36396495d90SSimon Glass int ret; 36496495d90SSimon Glass 365e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 366b892d127SSimon Glass if (!uc_priv->name[offset]) 367b892d127SSimon Glass return -ENXIO; 368b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 369b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 370b892d127SSimon Glass if (ret) 371b892d127SSimon Glass return ret; 372b892d127SSimon Glass } 373b892d127SSimon Glass 374b892d127SSimon Glass free(uc_priv->name[offset]); 375b892d127SSimon Glass uc_priv->name[offset] = NULL; 376b892d127SSimon Glass 37796495d90SSimon Glass return 0; 378b892d127SSimon Glass } 379b892d127SSimon Glass 380ae7123f8SSimon Glass /** 381ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 382ae7123f8SSimon Glass * gpio: GPIO number 383ae7123f8SSimon Glass * 384ae7123f8SSimon Glass * This function implements the API that's compatible with current 385ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 386ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 387ae7123f8SSimon Glass */ 388ae7123f8SSimon Glass int gpio_free(unsigned gpio) 389b892d127SSimon Glass { 390ae7123f8SSimon Glass struct gpio_desc desc; 391ae7123f8SSimon Glass int ret; 392b892d127SSimon Glass 393ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 394ae7123f8SSimon Glass if (ret) 395ae7123f8SSimon Glass return ret; 396ae7123f8SSimon Glass 397ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 398ae7123f8SSimon Glass } 399ae7123f8SSimon Glass 40017c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 401ae7123f8SSimon Glass { 402eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 403ae7123f8SSimon Glass 404eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 405eca48665SSimon Glass return -ENOENT; 406eca48665SSimon Glass 407eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 408ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 409b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 410ae7123f8SSimon Glass desc->dev->name, func, 411ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 412ae7123f8SSimon Glass desc->offset); 413b892d127SSimon Glass return -EBUSY; 414b892d127SSimon Glass } 415b892d127SSimon Glass 416b892d127SSimon Glass return 0; 41796495d90SSimon Glass } 41896495d90SSimon Glass 41996495d90SSimon Glass /** 42096495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 42196495d90SSimon Glass * gpio: GPIO number 42296495d90SSimon Glass * 42396495d90SSimon Glass * This function implements the API that's compatible with current 42496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 42596495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 42696495d90SSimon Glass */ 42796495d90SSimon Glass int gpio_direction_input(unsigned gpio) 42896495d90SSimon Glass { 429ae7123f8SSimon Glass struct gpio_desc desc; 43096495d90SSimon Glass int ret; 43196495d90SSimon Glass 432ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 43396495d90SSimon Glass if (ret) 43496495d90SSimon Glass return ret; 435ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 436ae7123f8SSimon Glass if (ret) 437ae7123f8SSimon Glass return ret; 43896495d90SSimon Glass 439ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 44096495d90SSimon Glass } 44196495d90SSimon Glass 44296495d90SSimon Glass /** 44396495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 44496495d90SSimon Glass * gpio: GPIO number 44596495d90SSimon Glass * value: Logical value to be set on the GPIO pin 44696495d90SSimon Glass * 44796495d90SSimon Glass * This function implements the API that's compatible with current 44896495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 44996495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 45096495d90SSimon Glass */ 45196495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 45296495d90SSimon Glass { 453ae7123f8SSimon Glass struct gpio_desc desc; 45496495d90SSimon Glass int ret; 45596495d90SSimon Glass 456ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 45796495d90SSimon Glass if (ret) 45896495d90SSimon Glass return ret; 459ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 460ae7123f8SSimon Glass if (ret) 461ae7123f8SSimon Glass return ret; 46296495d90SSimon Glass 463ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 464ae7123f8SSimon Glass desc.offset, value); 465ae7123f8SSimon Glass } 466ae7123f8SSimon Glass 46717c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 468ae7123f8SSimon Glass { 469ae7123f8SSimon Glass int value; 470ae7123f8SSimon Glass int ret; 471ae7123f8SSimon Glass 472ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 473ae7123f8SSimon Glass if (ret) 474ae7123f8SSimon Glass return ret; 475ae7123f8SSimon Glass 476ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 477ae7123f8SSimon Glass 478ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 479ae7123f8SSimon Glass } 480ae7123f8SSimon Glass 48117c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 482ae7123f8SSimon Glass { 483ae7123f8SSimon Glass int ret; 484ae7123f8SSimon Glass 485ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 486ae7123f8SSimon Glass if (ret) 487ae7123f8SSimon Glass return ret; 488ae7123f8SSimon Glass 489ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 490ae7123f8SSimon Glass value = !value; 491ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 492ae7123f8SSimon Glass return 0; 493ae7123f8SSimon Glass } 494ae7123f8SSimon Glass 49553ecdfb9Smario.six@gdsys.cc int dm_gpio_get_open_drain(struct gpio_desc *desc) 49653ecdfb9Smario.six@gdsys.cc { 49753ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 49853ecdfb9Smario.six@gdsys.cc int ret; 49953ecdfb9Smario.six@gdsys.cc 50053ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "get_open_drain"); 50153ecdfb9Smario.six@gdsys.cc if (ret) 50253ecdfb9Smario.six@gdsys.cc return ret; 50353ecdfb9Smario.six@gdsys.cc 50453ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 50553ecdfb9Smario.six@gdsys.cc return ops->get_open_drain(desc->dev, desc->offset); 50653ecdfb9Smario.six@gdsys.cc else 50753ecdfb9Smario.six@gdsys.cc return -ENOSYS; 50853ecdfb9Smario.six@gdsys.cc } 50953ecdfb9Smario.six@gdsys.cc 51053ecdfb9Smario.six@gdsys.cc int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) 51153ecdfb9Smario.six@gdsys.cc { 51253ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 51353ecdfb9Smario.six@gdsys.cc int ret; 51453ecdfb9Smario.six@gdsys.cc 51553ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "set_open_drain"); 51653ecdfb9Smario.six@gdsys.cc if (ret) 51753ecdfb9Smario.six@gdsys.cc return ret; 51853ecdfb9Smario.six@gdsys.cc 51953ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 52053ecdfb9Smario.six@gdsys.cc ret = ops->set_open_drain(desc->dev, desc->offset, value); 52153ecdfb9Smario.six@gdsys.cc else 52253ecdfb9Smario.six@gdsys.cc return 0; /* feature not supported -> ignore setting */ 52353ecdfb9Smario.six@gdsys.cc 52453ecdfb9Smario.six@gdsys.cc return ret; 52553ecdfb9Smario.six@gdsys.cc } 52653ecdfb9Smario.six@gdsys.cc 527ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 528ae7123f8SSimon Glass { 529ae7123f8SSimon Glass struct udevice *dev = desc->dev; 530ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 531ae7123f8SSimon Glass int ret; 532ae7123f8SSimon Glass 533ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 534ae7123f8SSimon Glass if (ret) 535ae7123f8SSimon Glass return ret; 536ae7123f8SSimon Glass 537ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 538ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 539ae7123f8SSimon Glass 540ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 541ae7123f8SSimon Glass value = !value; 542ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 543ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 544ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 545ae7123f8SSimon Glass } 546ae7123f8SSimon Glass if (ret) 547ae7123f8SSimon Glass return ret; 548ae7123f8SSimon Glass /* 549ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 550ae7123f8SSimon Glass * futures 551ae7123f8SSimon Glass */ 552ae7123f8SSimon Glass desc->flags = flags; 553ae7123f8SSimon Glass 554ae7123f8SSimon Glass return 0; 555ae7123f8SSimon Glass } 556ae7123f8SSimon Glass 557ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 558ae7123f8SSimon Glass { 559ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 56096495d90SSimon Glass } 56196495d90SSimon Glass 56296495d90SSimon Glass /** 56396495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 56496495d90SSimon Glass * gpio: GPIO number 56596495d90SSimon Glass * 56696495d90SSimon Glass * This function implements the API that's compatible with current 56796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 56896495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 56996495d90SSimon Glass * on error. 57096495d90SSimon Glass */ 57196495d90SSimon Glass int gpio_get_value(unsigned gpio) 57296495d90SSimon Glass { 57396495d90SSimon Glass int ret; 57496495d90SSimon Glass 575ae7123f8SSimon Glass struct gpio_desc desc; 576ae7123f8SSimon Glass 577ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 57896495d90SSimon Glass if (ret) 57996495d90SSimon Glass return ret; 580ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 58196495d90SSimon Glass } 58296495d90SSimon Glass 58396495d90SSimon Glass /** 58496495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 58596495d90SSimon Glass * gpio: GPIO number 58696495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 58796495d90SSimon Glass * 58896495d90SSimon Glass * This function implements the API that's compatible with current 58996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 59096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 59196495d90SSimon Glass */ 59296495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 59396495d90SSimon Glass { 594ae7123f8SSimon Glass struct gpio_desc desc; 59596495d90SSimon Glass int ret; 59696495d90SSimon Glass 597ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 59896495d90SSimon Glass if (ret) 59996495d90SSimon Glass return ret; 600ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 60196495d90SSimon Glass } 60296495d90SSimon Glass 60354c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 60496495d90SSimon Glass { 60596495d90SSimon Glass struct gpio_dev_priv *priv; 60696495d90SSimon Glass 60796495d90SSimon Glass /* Must be called on an active device */ 608e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 60996495d90SSimon Glass assert(priv); 61096495d90SSimon Glass 61196495d90SSimon Glass *bit_count = priv->gpio_count; 61296495d90SSimon Glass return priv->bank_name; 61396495d90SSimon Glass } 61496495d90SSimon Glass 6156449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 6166449a506SSimon Glass "input", 6176449a506SSimon Glass "output", 6186449a506SSimon Glass "unused", 6196449a506SSimon Glass "unknown", 6206449a506SSimon Glass "func", 6216449a506SSimon Glass }; 6226449a506SSimon Glass 623fb07f97dSMasahiro Yamada static int get_function(struct udevice *dev, int offset, bool skip_unused, 6246449a506SSimon Glass const char **namep) 6256449a506SSimon Glass { 626e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 6276449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6286449a506SSimon Glass 6296449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6306449a506SSimon Glass if (!device_active(dev)) 6316449a506SSimon Glass return -ENODEV; 6326449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 6336449a506SSimon Glass return -EINVAL; 6346449a506SSimon Glass if (namep) 6356449a506SSimon Glass *namep = uc_priv->name[offset]; 6366449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 6376449a506SSimon Glass return GPIOF_UNUSED; 6386449a506SSimon Glass if (ops->get_function) { 6396449a506SSimon Glass int ret; 6406449a506SSimon Glass 6416449a506SSimon Glass ret = ops->get_function(dev, offset); 6426449a506SSimon Glass if (ret < 0) 6436449a506SSimon Glass return ret; 6446449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 6456449a506SSimon Glass return -ENODATA; 6466449a506SSimon Glass return ret; 6476449a506SSimon Glass } 6486449a506SSimon Glass 6496449a506SSimon Glass return GPIOF_UNKNOWN; 6506449a506SSimon Glass } 6516449a506SSimon Glass 6526449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 6536449a506SSimon Glass { 6546449a506SSimon Glass return get_function(dev, offset, true, namep); 6556449a506SSimon Glass } 6566449a506SSimon Glass 6576449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 6586449a506SSimon Glass { 6596449a506SSimon Glass return get_function(dev, offset, false, namep); 6606449a506SSimon Glass } 6616449a506SSimon Glass 6620757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 6630757535aSSimon Glass { 6640757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6650757535aSSimon Glass struct gpio_dev_priv *priv; 6660757535aSSimon Glass char *str = buf; 6670757535aSSimon Glass int func; 6680757535aSSimon Glass int ret; 6690757535aSSimon Glass int len; 6700757535aSSimon Glass 6710757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6720757535aSSimon Glass 6730757535aSSimon Glass *buf = 0; 674e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 6750757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 6760757535aSSimon Glass if (ret < 0) 6770757535aSSimon Glass return ret; 6780757535aSSimon Glass func = ret; 6790757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 6800757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 6810757535aSSimon Glass offset, gpio_function[func]); 6820757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 6830757535aSSimon Glass func == GPIOF_UNUSED) { 6840757535aSSimon Glass const char *label; 6850757535aSSimon Glass bool used; 6860757535aSSimon Glass 6870757535aSSimon Glass ret = ops->get_value(dev, offset); 6880757535aSSimon Glass if (ret < 0) 6890757535aSSimon Glass return ret; 6900757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 6910757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 6920757535aSSimon Glass ret, 6930757535aSSimon Glass used ? 'x' : ' ', 6940757535aSSimon Glass used ? " " : "", 6950757535aSSimon Glass label ? label : ""); 6960757535aSSimon Glass } 6970757535aSSimon Glass 6980757535aSSimon Glass return 0; 6990757535aSSimon Glass } 7000757535aSSimon Glass 701962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 702962f5cafSSimon Glass { 703962f5cafSSimon Glass int i, ret; 704962f5cafSSimon Glass int gpio; 705962f5cafSSimon Glass 706962f5cafSSimon Glass for (i = 0; i < 32; i++) { 707962f5cafSSimon Glass gpio = gpio_num_array[i]; 708962f5cafSSimon Glass if (gpio == -1) 709962f5cafSSimon Glass break; 710962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 711962f5cafSSimon Glass if (ret) 712962f5cafSSimon Glass goto err; 713962f5cafSSimon Glass ret = gpio_direction_input(gpio); 714962f5cafSSimon Glass if (ret) { 715962f5cafSSimon Glass gpio_free(gpio); 716962f5cafSSimon Glass goto err; 717962f5cafSSimon Glass } 718962f5cafSSimon Glass } 719962f5cafSSimon Glass 720962f5cafSSimon Glass return 0; 721962f5cafSSimon Glass err: 722962f5cafSSimon Glass for (i--; i >= 0; i--) 723962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 724962f5cafSSimon Glass 725962f5cafSSimon Glass return ret; 726962f5cafSSimon Glass } 727962f5cafSSimon Glass 728e5901c94SSimon Glass /* 729e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 730e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 731e5901c94SSimon Glass */ 732962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 733e5901c94SSimon Glass { 734e5901c94SSimon Glass int gpio; 735e5901c94SSimon Glass unsigned bitmask = 1; 736e5901c94SSimon Glass unsigned vector = 0; 737962f5cafSSimon Glass int ret; 738e5901c94SSimon Glass 739e5901c94SSimon Glass while (bitmask && 740962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 741962f5cafSSimon Glass ret = gpio_get_value(gpio); 742962f5cafSSimon Glass if (ret < 0) 743962f5cafSSimon Glass return ret; 744962f5cafSSimon Glass else if (ret) 745e5901c94SSimon Glass vector |= bitmask; 746e5901c94SSimon Glass bitmask <<= 1; 747e5901c94SSimon Glass } 748962f5cafSSimon Glass 749e5901c94SSimon Glass return vector; 750e5901c94SSimon Glass } 751e5901c94SSimon Glass 75217c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 753bbf24780SSimon Glass { 754bbf24780SSimon Glass unsigned bitmask = 1; 755bbf24780SSimon Glass unsigned vector = 0; 756bbf24780SSimon Glass int ret, i; 757bbf24780SSimon Glass 758bbf24780SSimon Glass for (i = 0; i < count; i++) { 759bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 760bbf24780SSimon Glass if (ret < 0) 761bbf24780SSimon Glass return ret; 762bbf24780SSimon Glass else if (ret) 763bbf24780SSimon Glass vector |= bitmask; 764bbf24780SSimon Glass bitmask <<= 1; 765bbf24780SSimon Glass } 766bbf24780SSimon Glass 767bbf24780SSimon Glass return vector; 768bbf24780SSimon Glass } 769bbf24780SSimon Glass 77025cd3b96SHeiko Schocher /** 77125cd3b96SHeiko Schocher * gpio_request_tail: common work for requesting a gpio. 77225cd3b96SHeiko Schocher * 77325cd3b96SHeiko Schocher * ret: return value from previous work in function which calls 77425cd3b96SHeiko Schocher * this function. 77525cd3b96SHeiko Schocher * This seems bogus (why calling this function instead not 77625cd3b96SHeiko Schocher * calling it and end caller function instead?). 77725cd3b96SHeiko Schocher * Because on error in caller function we want to set some 77825cd3b96SHeiko Schocher * default values in gpio desc and have a common error 77925cd3b96SHeiko Schocher * debug message, which provides this function. 78025cd3b96SHeiko Schocher * nodename: Name of node for which gpio gets requested 78125cd3b96SHeiko Schocher * used for gpio label name. 78225cd3b96SHeiko Schocher * args: pointer to output arguments structure 78325cd3b96SHeiko Schocher * list_name: Name of GPIO list 78425cd3b96SHeiko Schocher * used for gpio label name. 78525cd3b96SHeiko Schocher * index: gpio index in gpio list 78625cd3b96SHeiko Schocher * used for gpio label name. 78725cd3b96SHeiko Schocher * desc: pointer to gpio descriptor, filled from this 78825cd3b96SHeiko Schocher * function. 78925cd3b96SHeiko Schocher * flags: gpio flags to use. 79025cd3b96SHeiko Schocher * add_index: should index added to gpio label name 79125cd3b96SHeiko Schocher * gpio_dev: pointer to gpio device from which the gpio 79225cd3b96SHeiko Schocher * will be requested. If NULL try to get the 79325cd3b96SHeiko Schocher * gpio device with uclass_get_device_by_ofnode() 79425cd3b96SHeiko Schocher * 79525cd3b96SHeiko Schocher * return: In error case this function sets default values in 79625cd3b96SHeiko Schocher * gpio descriptor, also emmits a debug message. 79725cd3b96SHeiko Schocher * On success it returns 0 else the error code from 79825cd3b96SHeiko Schocher * function calls, or the error code passed through 79925cd3b96SHeiko Schocher * ret to this function. 80025cd3b96SHeiko Schocher * 80125cd3b96SHeiko Schocher */ 8027e044b9aSHeiko Schocher static int gpio_request_tail(int ret, const char *nodename, 8033a57123eSSimon Glass struct ofnode_phandle_args *args, 8043669e0e7SSimon Glass const char *list_name, int index, 8057e044b9aSHeiko Schocher struct gpio_desc *desc, int flags, 80625cd3b96SHeiko Schocher bool add_index, struct udevice *gpio_dev) 8073669e0e7SSimon Glass { 80825cd3b96SHeiko Schocher desc->dev = gpio_dev; 8093669e0e7SSimon Glass desc->offset = 0; 8106c880b77SEric Nelson desc->flags = 0; 8113a57123eSSimon Glass if (ret) 8123669e0e7SSimon Glass goto err; 8133669e0e7SSimon Glass 8147e044b9aSHeiko Schocher if (!desc->dev) { 8153a57123eSSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, 8163669e0e7SSimon Glass &desc->dev); 8173669e0e7SSimon Glass if (ret) { 81825cd3b96SHeiko Schocher debug("%s: uclass_get_device_by_ofnode failed\n", 81925cd3b96SHeiko Schocher __func__); 8203669e0e7SSimon Glass goto err; 8213669e0e7SSimon Glass } 8227e044b9aSHeiko Schocher } 8233a57123eSSimon Glass ret = gpio_find_and_xlate(desc, args); 8243669e0e7SSimon Glass if (ret) { 8253669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 8263669e0e7SSimon Glass goto err; 8273669e0e7SSimon Glass } 8283669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 8297e044b9aSHeiko Schocher nodename, list_name, index); 8303669e0e7SSimon Glass if (ret) { 8313669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 8323669e0e7SSimon Glass goto err; 8333669e0e7SSimon Glass } 8343669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 8353669e0e7SSimon Glass if (ret) { 8363669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 8373669e0e7SSimon Glass goto err; 8383669e0e7SSimon Glass } 8393669e0e7SSimon Glass 8403669e0e7SSimon Glass return 0; 8413669e0e7SSimon Glass err: 8423669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 8437e044b9aSHeiko Schocher __func__, nodename, list_name, index, ret); 8443669e0e7SSimon Glass return ret; 8453669e0e7SSimon Glass } 8463669e0e7SSimon Glass 847150c5afeSSimon Glass static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, 848150c5afeSSimon Glass int index, struct gpio_desc *desc, 849150c5afeSSimon Glass int flags, bool add_index) 8503a57123eSSimon Glass { 8513a57123eSSimon Glass struct ofnode_phandle_args args; 8523a57123eSSimon Glass int ret; 8533a57123eSSimon Glass 854150c5afeSSimon Glass ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, 855150c5afeSSimon Glass index, &args); 8563a57123eSSimon Glass 8577e044b9aSHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 8587e044b9aSHeiko Schocher index, desc, flags, add_index, NULL); 8593a57123eSSimon Glass } 8603a57123eSSimon Glass 861150c5afeSSimon Glass int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, 8623669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8633669e0e7SSimon Glass { 864150c5afeSSimon Glass return _gpio_request_by_name_nodev(node, list_name, index, desc, flags, 865150c5afeSSimon Glass index > 0); 8663669e0e7SSimon Glass } 8673669e0e7SSimon Glass 8683669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 8693669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8703669e0e7SSimon Glass { 871150c5afeSSimon Glass struct ofnode_phandle_args args; 8727e044b9aSHeiko Schocher ofnode node; 873150c5afeSSimon Glass int ret; 874150c5afeSSimon Glass 875150c5afeSSimon Glass ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, 876150c5afeSSimon Glass index, &args); 8777e044b9aSHeiko Schocher node = dev_ofnode(dev); 8787e044b9aSHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 8797e044b9aSHeiko Schocher index, desc, flags, index > 0, NULL); 8803669e0e7SSimon Glass } 8813669e0e7SSimon Glass 882150c5afeSSimon Glass int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, 8833669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8843669e0e7SSimon Glass int flags) 8853669e0e7SSimon Glass { 8863669e0e7SSimon Glass int count; 8873669e0e7SSimon Glass int ret; 8883669e0e7SSimon Glass 8892984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 890150c5afeSSimon Glass ret = _gpio_request_by_name_nodev(node, list_name, count, 8913669e0e7SSimon Glass &desc[count], flags, true); 8923669e0e7SSimon Glass if (ret == -ENOENT) 8933669e0e7SSimon Glass break; 8943669e0e7SSimon Glass else if (ret) 8953669e0e7SSimon Glass goto err; 8963669e0e7SSimon Glass } 8973669e0e7SSimon Glass 8983669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 8993669e0e7SSimon Glass return count; 9003669e0e7SSimon Glass 9013669e0e7SSimon Glass err: 9023669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 9033669e0e7SSimon Glass 9043669e0e7SSimon Glass return ret; 9053669e0e7SSimon Glass } 9063669e0e7SSimon Glass 9073669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 9083669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 9093669e0e7SSimon Glass int flags) 9103669e0e7SSimon Glass { 9113669e0e7SSimon Glass /* 9123669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 9133669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 9143669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 9153669e0e7SSimon Glass */ 916150c5afeSSimon Glass return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc, 917150c5afeSSimon Glass max_count, flags); 9183669e0e7SSimon Glass } 9193669e0e7SSimon Glass 9203669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 9213669e0e7SSimon Glass { 9223669e0e7SSimon Glass int ret; 9233669e0e7SSimon Glass 924e160f7d4SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 9253669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 9263669e0e7SSimon Glass NULL); 9273669e0e7SSimon Glass if (ret) { 9283669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 9293669e0e7SSimon Glass __func__, dev->name, list_name, ret); 9303669e0e7SSimon Glass } 9313669e0e7SSimon Glass 9323669e0e7SSimon Glass return ret; 9333669e0e7SSimon Glass } 9343669e0e7SSimon Glass 9353669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 9363669e0e7SSimon Glass { 9373669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9383669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 9393669e0e7SSimon Glass } 9403669e0e7SSimon Glass 9413669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 9423669e0e7SSimon Glass { 9433669e0e7SSimon Glass int i; 9443669e0e7SSimon Glass 9453669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9463669e0e7SSimon Glass for (i = 0; i < count; i++) 9473669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 9483669e0e7SSimon Glass 9493669e0e7SSimon Glass return 0; 9503669e0e7SSimon Glass } 9513669e0e7SSimon Glass 9523669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 9533669e0e7SSimon Glass { 9543669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 9553669e0e7SSimon Glass } 9563669e0e7SSimon Glass 95796495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 958b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 95996495d90SSimon Glass { 96096495d90SSimon Glass struct gpio_dev_priv *uc_priv; 96154c5d08aSHeiko Schocher struct udevice *dev; 96296495d90SSimon Glass struct uclass *uc; 96396495d90SSimon Glass unsigned base; 96496495d90SSimon Glass int ret; 96596495d90SSimon Glass 96696495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 96796495d90SSimon Glass if (ret) 96896495d90SSimon Glass return ret; 96996495d90SSimon Glass 97096495d90SSimon Glass /* Ensure that we have a base for each bank */ 97196495d90SSimon Glass base = 0; 97296495d90SSimon Glass uclass_foreach_dev(dev, uc) { 973b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 974e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 97596495d90SSimon Glass uc_priv->gpio_base = base; 97696495d90SSimon Glass base += uc_priv->gpio_count; 97796495d90SSimon Glass } 97896495d90SSimon Glass } 97996495d90SSimon Glass 98096495d90SSimon Glass return 0; 98196495d90SSimon Glass } 98296495d90SSimon Glass 98317c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 98456a71f89SSimon Glass { 98556a71f89SSimon Glass struct udevice *dev = desc->dev; 98656a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 98756a71f89SSimon Glass 98856a71f89SSimon Glass if (!dev) 98956a71f89SSimon Glass return -1; 99056a71f89SSimon Glass uc_priv = dev->uclass_priv; 99156a71f89SSimon Glass 99256a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 99356a71f89SSimon Glass } 99456a71f89SSimon Glass 99554c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 99696495d90SSimon Glass { 997e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 998b892d127SSimon Glass 999b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 1000b892d127SSimon Glass if (!uc_priv->name) 1001b892d127SSimon Glass return -ENOMEM; 1002b892d127SSimon Glass 1003b892d127SSimon Glass return gpio_renumber(NULL); 100496495d90SSimon Glass } 100596495d90SSimon Glass 100654c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 100796495d90SSimon Glass { 1008e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 1009b892d127SSimon Glass int i; 1010b892d127SSimon Glass 1011b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 1012b892d127SSimon Glass if (uc_priv->name[i]) 1013b892d127SSimon Glass free(uc_priv->name[i]); 1014b892d127SSimon Glass } 1015b892d127SSimon Glass free(uc_priv->name); 1016b892d127SSimon Glass 1017b892d127SSimon Glass return gpio_renumber(dev); 101896495d90SSimon Glass } 101996495d90SSimon Glass 10207e044b9aSHeiko Schocher int gpio_dev_request_index(struct udevice *dev, const char *nodename, 10217e044b9aSHeiko Schocher char *list_name, int index, int flags, 10227e044b9aSHeiko Schocher int dtflags, struct gpio_desc *desc) 10237e044b9aSHeiko Schocher { 10247e044b9aSHeiko Schocher struct ofnode_phandle_args args; 10257e044b9aSHeiko Schocher 10267e044b9aSHeiko Schocher args.node = ofnode_null(); 10277e044b9aSHeiko Schocher args.args_count = 2; 10287e044b9aSHeiko Schocher args.args[0] = index; 10297e044b9aSHeiko Schocher args.args[1] = dtflags; 10307e044b9aSHeiko Schocher 10317e044b9aSHeiko Schocher return gpio_request_tail(0, nodename, &args, list_name, index, desc, 10327e044b9aSHeiko Schocher flags, 0, dev); 10337e044b9aSHeiko Schocher } 10347e044b9aSHeiko Schocher 10357e044b9aSHeiko Schocher static int gpio_post_bind(struct udevice *dev) 10367e044b9aSHeiko Schocher { 10377e044b9aSHeiko Schocher struct udevice *child; 10387e044b9aSHeiko Schocher ofnode node; 10397e044b9aSHeiko Schocher 104025cd3b96SHeiko Schocher if (IS_ENABLED(CONFIG_GPIO_HOG)) { 10417e044b9aSHeiko Schocher dev_for_each_subnode(node, dev) { 10427e044b9aSHeiko Schocher if (ofnode_read_bool(node, "gpio-hog")) { 10437e044b9aSHeiko Schocher const char *name = ofnode_get_name(node); 104425cd3b96SHeiko Schocher int ret; 10457e044b9aSHeiko Schocher 104625cd3b96SHeiko Schocher ret = device_bind_driver_to_node(dev, 104725cd3b96SHeiko Schocher "gpio_hog", 104825cd3b96SHeiko Schocher name, node, 104925cd3b96SHeiko Schocher &child); 105025cd3b96SHeiko Schocher if (ret) 105125cd3b96SHeiko Schocher return ret; 10527e044b9aSHeiko Schocher } 10537e044b9aSHeiko Schocher } 105425cd3b96SHeiko Schocher } 10557e044b9aSHeiko Schocher return 0; 10567e044b9aSHeiko Schocher } 10577e044b9aSHeiko Schocher 105896495d90SSimon Glass UCLASS_DRIVER(gpio) = { 105996495d90SSimon Glass .id = UCLASS_GPIO, 106096495d90SSimon Glass .name = "gpio", 1061*7e0ce50bSJoseph Chen #ifndef CONFIG_GPIO_NO_UC_FLAG_SEQ_ALIAS 1062ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 1063*7e0ce50bSJoseph Chen #endif 106496495d90SSimon Glass .post_probe = gpio_post_probe, 10657e044b9aSHeiko Schocher .post_bind = gpio_post_bind, 106696495d90SSimon Glass .pre_remove = gpio_pre_remove, 106796495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 106896495d90SSimon Glass }; 1069