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> 804c095b2SHeiko Schocher #include <dm/device-internal.h> 904c095b2SHeiko Schocher #include <dm/lists.h> 1004c095b2SHeiko Schocher #include <dm/uclass-internal.h> 116c880b77SEric Nelson #include <dt-bindings/gpio/gpio.h> 1296495d90SSimon Glass #include <errno.h> 130dac4d51SSimon Glass #include <fdtdec.h> 14b892d127SSimon Glass #include <malloc.h> 1596495d90SSimon Glass #include <asm/gpio.h> 1684b8bf6dSMasahiro Yamada #include <linux/bug.h> 17fe1ef503SSimon Glass #include <linux/ctype.h> 1896495d90SSimon Glass 193669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 203669e0e7SSimon Glass 2196495d90SSimon Glass /** 2296495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2396495d90SSimon Glass * 2496495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2596495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2696495d90SSimon Glass * entry on success, NULL on error. 27ae7123f8SSimon Glass * 28ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 29ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 30ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 3196495d90SSimon Glass */ 32ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3396495d90SSimon Glass { 3496495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3554c5d08aSHeiko Schocher struct udevice *dev; 3696495d90SSimon Glass int ret; 3796495d90SSimon Glass 3896495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3996495d90SSimon Glass dev; 4096495d90SSimon Glass ret = uclass_next_device(&dev)) { 41e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 4296495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4396495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 44ae7123f8SSimon Glass desc->dev = dev; 45ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 46ae7123f8SSimon Glass desc->flags = 0; 4796495d90SSimon Glass return 0; 4896495d90SSimon Glass } 4996495d90SSimon Glass } 5096495d90SSimon Glass 5196495d90SSimon Glass /* No such GPIO */ 52ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5396495d90SSimon Glass } 5496495d90SSimon Glass 5532ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5696495d90SSimon Glass { 57fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5854c5d08aSHeiko Schocher struct udevice *dev; 59fe1ef503SSimon Glass ulong offset; 60fe1ef503SSimon Glass int numeric; 6196495d90SSimon Glass int ret; 6296495d90SSimon Glass 63fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6496495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6596495d90SSimon Glass dev; 6696495d90SSimon Glass ret = uclass_next_device(&dev)) { 6796495d90SSimon Glass int len; 6896495d90SSimon Glass 69e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 70fe1ef503SSimon Glass if (numeric != -1) { 71fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 72fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 7375897910STom Rini if (offset < uc_priv->gpio_count) 74fe1ef503SSimon Glass break; 75fe1ef503SSimon Glass } 76fe1ef503SSimon Glass 7796495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7896495d90SSimon Glass 79939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 80fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 81fe1ef503SSimon Glass break; 82fe1ef503SSimon Glass } 83fe1ef503SSimon Glass } 84fe1ef503SSimon Glass 85fe1ef503SSimon Glass if (!dev) 86fe1ef503SSimon Glass return ret ? ret : -EINVAL; 87fe1ef503SSimon Glass 8832ec1598SSimon Glass desc->dev = dev; 8932ec1598SSimon Glass desc->offset = offset; 9032ec1598SSimon Glass 9132ec1598SSimon Glass return 0; 9232ec1598SSimon Glass } 9332ec1598SSimon Glass 9432ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9532ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9632ec1598SSimon Glass { 9732ec1598SSimon Glass struct gpio_desc desc; 9832ec1598SSimon Glass int ret; 9932ec1598SSimon Glass 10096495d90SSimon Glass if (devp) 10132ec1598SSimon Glass *devp = NULL; 10232ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10332ec1598SSimon Glass if (ret) 10432ec1598SSimon Glass return ret; 10532ec1598SSimon Glass 10632ec1598SSimon Glass if (devp) 10732ec1598SSimon Glass *devp = desc.dev; 10896495d90SSimon Glass if (offsetp) 10932ec1598SSimon Glass *offsetp = desc.offset; 11032ec1598SSimon Glass if (gpiop) { 11132ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 11232ec1598SSimon Glass 11332ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11432ec1598SSimon Glass } 11596495d90SSimon Glass 116fe1ef503SSimon Glass return 0; 11796495d90SSimon Glass } 11896495d90SSimon Glass 1193a57123eSSimon Glass int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, 1203a57123eSSimon Glass struct ofnode_phandle_args *args) 1216c880b77SEric Nelson { 1226c880b77SEric Nelson if (args->args_count < 1) 1236c880b77SEric Nelson return -EINVAL; 1246c880b77SEric Nelson 1256c880b77SEric Nelson desc->offset = args->args[0]; 1266c880b77SEric Nelson 1276c880b77SEric Nelson if (args->args_count < 2) 1286c880b77SEric Nelson return 0; 1296c880b77SEric Nelson 1306c880b77SEric Nelson if (args->args[1] & GPIO_ACTIVE_LOW) 1316c880b77SEric Nelson desc->flags = GPIOD_ACTIVE_LOW; 1326c880b77SEric Nelson 1336c880b77SEric Nelson return 0; 1346c880b77SEric Nelson } 1356c880b77SEric Nelson 1363669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1373a57123eSSimon Glass struct ofnode_phandle_args *args) 1380dac4d51SSimon Glass { 1390dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1400dac4d51SSimon Glass 1416c880b77SEric Nelson if (ops->xlate) 1426c880b77SEric Nelson return ops->xlate(desc->dev, desc, args); 1430dac4d51SSimon Glass else 1446c880b77SEric Nelson return gpio_xlate_offs_flags(desc->dev, desc, args); 1450dac4d51SSimon Glass } 1460dac4d51SSimon Glass 147*dab778a2SHeiko Schocher #if defined(CONFIG_GPIO_HOG) 14804c095b2SHeiko Schocher 14904c095b2SHeiko Schocher struct gpio_hog_priv { 15004c095b2SHeiko Schocher struct gpio_desc gpiod; 15104c095b2SHeiko Schocher }; 15204c095b2SHeiko Schocher 15304c095b2SHeiko Schocher struct gpio_hog_data { 15404c095b2SHeiko Schocher int gpiod_flags; 15504c095b2SHeiko Schocher int value; 15604c095b2SHeiko Schocher u32 val[2]; 15704c095b2SHeiko Schocher }; 15804c095b2SHeiko Schocher 15904c095b2SHeiko Schocher static int gpio_hog_ofdata_to_platdata(struct udevice *dev) 16004c095b2SHeiko Schocher { 16104c095b2SHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 16204c095b2SHeiko Schocher const char *nodename; 16304c095b2SHeiko Schocher int ret; 16404c095b2SHeiko Schocher 16504c095b2SHeiko Schocher plat->value = 0; 16604c095b2SHeiko Schocher if (dev_read_bool(dev, "input")) { 16704c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_IN; 16804c095b2SHeiko Schocher } else if (dev_read_bool(dev, "output-high")) { 16904c095b2SHeiko Schocher plat->value = 1; 17004c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 17104c095b2SHeiko Schocher } else if (dev_read_bool(dev, "output-low")) { 17204c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 17304c095b2SHeiko Schocher } else { 17404c095b2SHeiko Schocher printf("%s: missing gpio-hog state.\n", __func__); 17504c095b2SHeiko Schocher return -EINVAL; 17604c095b2SHeiko Schocher } 17704c095b2SHeiko Schocher ret = dev_read_u32_array(dev, "gpios", plat->val, 2); 17804c095b2SHeiko Schocher if (ret) { 17904c095b2SHeiko Schocher printf("%s: wrong gpios property, 2 values needed %d\n", 18004c095b2SHeiko Schocher __func__, ret); 18104c095b2SHeiko Schocher return ret; 18204c095b2SHeiko Schocher } 18304c095b2SHeiko Schocher nodename = dev_read_string(dev, "line-name"); 184*dab778a2SHeiko Schocher if (nodename) 18504c095b2SHeiko Schocher device_set_name(dev, nodename); 18604c095b2SHeiko Schocher 18704c095b2SHeiko Schocher return 0; 18804c095b2SHeiko Schocher } 18904c095b2SHeiko Schocher 19004c095b2SHeiko Schocher static int gpio_hog_probe(struct udevice *dev) 19104c095b2SHeiko Schocher { 19204c095b2SHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 19304c095b2SHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 19404c095b2SHeiko Schocher int ret; 19504c095b2SHeiko Schocher 19604c095b2SHeiko Schocher ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog", 19704c095b2SHeiko Schocher plat->val[0], plat->gpiod_flags, 19804c095b2SHeiko Schocher plat->val[1], &priv->gpiod); 19904c095b2SHeiko Schocher if (ret < 0) { 20004c095b2SHeiko Schocher debug("%s: node %s could not get gpio.\n", __func__, 20104c095b2SHeiko Schocher dev->name); 20204c095b2SHeiko Schocher return ret; 20304c095b2SHeiko Schocher } 204*dab778a2SHeiko Schocher 205*dab778a2SHeiko Schocher if (plat->gpiod_flags == GPIOD_IS_OUT) { 206*dab778a2SHeiko Schocher ret = dm_gpio_set_value(&priv->gpiod, plat->value); 207*dab778a2SHeiko Schocher if (ret < 0) { 208*dab778a2SHeiko Schocher debug("%s: node %s could not set gpio.\n", __func__, 209*dab778a2SHeiko Schocher dev->name); 210*dab778a2SHeiko Schocher return ret; 211*dab778a2SHeiko Schocher } 212*dab778a2SHeiko Schocher } 21304c095b2SHeiko Schocher 21404c095b2SHeiko Schocher return 0; 21504c095b2SHeiko Schocher } 21604c095b2SHeiko Schocher 21704c095b2SHeiko Schocher int gpio_hog_probe_all(void) 21804c095b2SHeiko Schocher { 21904c095b2SHeiko Schocher struct udevice *dev; 22004c095b2SHeiko Schocher int ret; 221*dab778a2SHeiko Schocher int retval = 0; 22204c095b2SHeiko Schocher 22304c095b2SHeiko Schocher for (uclass_first_device(UCLASS_NOP, &dev); 22404c095b2SHeiko Schocher dev; 22504c095b2SHeiko Schocher uclass_find_next_device(&dev)) { 22604c095b2SHeiko Schocher if (dev->driver == DM_GET_DRIVER(gpio_hog)) { 22704c095b2SHeiko Schocher ret = device_probe(dev); 228*dab778a2SHeiko Schocher if (ret) { 229*dab778a2SHeiko Schocher printf("Failed to probe device %s err: %d\n", 230*dab778a2SHeiko Schocher dev->name, ret); 231*dab778a2SHeiko Schocher retval = ret; 232*dab778a2SHeiko Schocher } 23304c095b2SHeiko Schocher } 23404c095b2SHeiko Schocher } 23504c095b2SHeiko Schocher 236*dab778a2SHeiko Schocher return retval; 23704c095b2SHeiko Schocher } 23804c095b2SHeiko Schocher 239*dab778a2SHeiko Schocher int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) 24004c095b2SHeiko Schocher { 24104c095b2SHeiko Schocher struct udevice *dev; 24204c095b2SHeiko Schocher 243*dab778a2SHeiko Schocher *desc = NULL; 24404c095b2SHeiko Schocher gpio_hog_probe_all(); 24504c095b2SHeiko Schocher if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { 24604c095b2SHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 24704c095b2SHeiko Schocher 248*dab778a2SHeiko Schocher *desc = &priv->gpiod; 249*dab778a2SHeiko Schocher return 0; 25004c095b2SHeiko Schocher } 25104c095b2SHeiko Schocher 252*dab778a2SHeiko Schocher return -ENODEV; 25304c095b2SHeiko Schocher } 25404c095b2SHeiko Schocher 25504c095b2SHeiko Schocher U_BOOT_DRIVER(gpio_hog) = { 25604c095b2SHeiko Schocher .name = "gpio_hog", 25704c095b2SHeiko Schocher .id = UCLASS_NOP, 25804c095b2SHeiko Schocher .ofdata_to_platdata = gpio_hog_ofdata_to_platdata, 25904c095b2SHeiko Schocher .probe = gpio_hog_probe, 26004c095b2SHeiko Schocher .priv_auto_alloc_size = sizeof(struct gpio_hog_priv), 26104c095b2SHeiko Schocher .platdata_auto_alloc_size = sizeof(struct gpio_hog_data), 26204c095b2SHeiko Schocher }; 26304c095b2SHeiko Schocher #else 264*dab778a2SHeiko Schocher int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) 26504c095b2SHeiko Schocher { 266*dab778a2SHeiko Schocher return 0; 26704c095b2SHeiko Schocher } 26804c095b2SHeiko Schocher #endif 26904c095b2SHeiko Schocher 270efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 271ae7123f8SSimon Glass { 272ae7123f8SSimon Glass struct udevice *dev = desc->dev; 273ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 274ae7123f8SSimon Glass char *str; 275ae7123f8SSimon Glass int ret; 276ae7123f8SSimon Glass 277e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 278ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 279ae7123f8SSimon Glass return -EBUSY; 280ae7123f8SSimon Glass str = strdup(label); 281ae7123f8SSimon Glass if (!str) 282ae7123f8SSimon Glass return -ENOMEM; 283ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 284ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 285ae7123f8SSimon Glass if (ret) { 286ae7123f8SSimon Glass free(str); 287ae7123f8SSimon Glass return ret; 288ae7123f8SSimon Glass } 289ae7123f8SSimon Glass } 290ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 291ae7123f8SSimon Glass 292ae7123f8SSimon Glass return 0; 293ae7123f8SSimon Glass } 294ae7123f8SSimon Glass 2953669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 2963669e0e7SSimon Glass { 2974dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 2983669e0e7SSimon Glass va_list args; 2993669e0e7SSimon Glass char buf[40]; 3003669e0e7SSimon Glass 3013669e0e7SSimon Glass va_start(args, fmt); 3023669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 3033669e0e7SSimon Glass va_end(args); 3043669e0e7SSimon Glass return dm_gpio_request(desc, buf); 3054dc5259aSSimon Glass #else 3064dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 3074dc5259aSSimon Glass #endif 3083669e0e7SSimon Glass } 3093669e0e7SSimon Glass 31096495d90SSimon Glass /** 31196495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 31296495d90SSimon Glass * gpio: GPIO number 31396495d90SSimon Glass * label: Name for the requested GPIO 31496495d90SSimon Glass * 315b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 316b892d127SSimon Glass * the pointer around. 317b892d127SSimon Glass * 31896495d90SSimon Glass * This function implements the API that's compatible with current 31996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 32096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 32196495d90SSimon Glass */ 32296495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 32396495d90SSimon Glass { 324ae7123f8SSimon Glass struct gpio_desc desc; 32596495d90SSimon Glass int ret; 32696495d90SSimon Glass 327ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 32896495d90SSimon Glass if (ret) 32996495d90SSimon Glass return ret; 33096495d90SSimon Glass 331ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 33296495d90SSimon Glass } 33396495d90SSimon Glass 33496495d90SSimon Glass /** 335d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 336d44f597bSSimon Glass * @gpio: GPIO number 337d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 338d44f597bSSimon Glass * @...: Arguments for the printf() format string 339d44f597bSSimon Glass * 340d44f597bSSimon Glass * This function implements the API that's compatible with current 341d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 342d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 343d44f597bSSimon Glass */ 344d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 345d44f597bSSimon Glass { 3464dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 347d44f597bSSimon Glass va_list args; 348d44f597bSSimon Glass char buf[40]; 349d44f597bSSimon Glass 350d44f597bSSimon Glass va_start(args, fmt); 351d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 352d44f597bSSimon Glass va_end(args); 353d44f597bSSimon Glass return gpio_request(gpio, buf); 3544dc5259aSSimon Glass #else 3554dc5259aSSimon Glass return gpio_request(gpio, fmt); 3564dc5259aSSimon Glass #endif 357d44f597bSSimon Glass } 358d44f597bSSimon Glass 359ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 36096495d90SSimon Glass { 361b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 36296495d90SSimon Glass int ret; 36396495d90SSimon Glass 364e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 365b892d127SSimon Glass if (!uc_priv->name[offset]) 366b892d127SSimon Glass return -ENXIO; 367b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 368b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 369b892d127SSimon Glass if (ret) 370b892d127SSimon Glass return ret; 371b892d127SSimon Glass } 372b892d127SSimon Glass 373b892d127SSimon Glass free(uc_priv->name[offset]); 374b892d127SSimon Glass uc_priv->name[offset] = NULL; 375b892d127SSimon Glass 37696495d90SSimon Glass return 0; 377b892d127SSimon Glass } 378b892d127SSimon Glass 379ae7123f8SSimon Glass /** 380ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 381ae7123f8SSimon Glass * gpio: GPIO number 382ae7123f8SSimon Glass * 383ae7123f8SSimon Glass * This function implements the API that's compatible with current 384ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 385ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 386ae7123f8SSimon Glass */ 387ae7123f8SSimon Glass int gpio_free(unsigned gpio) 388b892d127SSimon Glass { 389ae7123f8SSimon Glass struct gpio_desc desc; 390ae7123f8SSimon Glass int ret; 391b892d127SSimon Glass 392ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 393ae7123f8SSimon Glass if (ret) 394ae7123f8SSimon Glass return ret; 395ae7123f8SSimon Glass 396ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 397ae7123f8SSimon Glass } 398ae7123f8SSimon Glass 39917c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 400ae7123f8SSimon Glass { 401eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 402ae7123f8SSimon Glass 403eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 404eca48665SSimon Glass return -ENOENT; 405eca48665SSimon Glass 406eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 407ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 408b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 409ae7123f8SSimon Glass desc->dev->name, func, 410ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 411ae7123f8SSimon Glass desc->offset); 412b892d127SSimon Glass return -EBUSY; 413b892d127SSimon Glass } 414b892d127SSimon Glass 415b892d127SSimon Glass return 0; 41696495d90SSimon Glass } 41796495d90SSimon Glass 41896495d90SSimon Glass /** 41996495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 42096495d90SSimon Glass * gpio: GPIO number 42196495d90SSimon Glass * 42296495d90SSimon Glass * This function implements the API that's compatible with current 42396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 42496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 42596495d90SSimon Glass */ 42696495d90SSimon Glass int gpio_direction_input(unsigned gpio) 42796495d90SSimon Glass { 428ae7123f8SSimon Glass struct gpio_desc desc; 42996495d90SSimon Glass int ret; 43096495d90SSimon Glass 431ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 43296495d90SSimon Glass if (ret) 43396495d90SSimon Glass return ret; 434ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 435ae7123f8SSimon Glass if (ret) 436ae7123f8SSimon Glass return ret; 43796495d90SSimon Glass 438ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 43996495d90SSimon Glass } 44096495d90SSimon Glass 44196495d90SSimon Glass /** 44296495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 44396495d90SSimon Glass * gpio: GPIO number 44496495d90SSimon Glass * value: Logical value to be set on the GPIO pin 44596495d90SSimon Glass * 44696495d90SSimon Glass * This function implements the API that's compatible with current 44796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 44896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 44996495d90SSimon Glass */ 45096495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 45196495d90SSimon Glass { 452ae7123f8SSimon Glass struct gpio_desc desc; 45396495d90SSimon Glass int ret; 45496495d90SSimon Glass 455ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 45696495d90SSimon Glass if (ret) 45796495d90SSimon Glass return ret; 458ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 459ae7123f8SSimon Glass if (ret) 460ae7123f8SSimon Glass return ret; 46196495d90SSimon Glass 462ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 463ae7123f8SSimon Glass desc.offset, value); 464ae7123f8SSimon Glass } 465ae7123f8SSimon Glass 46617c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 467ae7123f8SSimon Glass { 468ae7123f8SSimon Glass int value; 469ae7123f8SSimon Glass int ret; 470ae7123f8SSimon Glass 471ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 472ae7123f8SSimon Glass if (ret) 473ae7123f8SSimon Glass return ret; 474ae7123f8SSimon Glass 475ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 476ae7123f8SSimon Glass 477ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 478ae7123f8SSimon Glass } 479ae7123f8SSimon Glass 48017c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 481ae7123f8SSimon Glass { 482ae7123f8SSimon Glass int ret; 483ae7123f8SSimon Glass 484ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 485ae7123f8SSimon Glass if (ret) 486ae7123f8SSimon Glass return ret; 487ae7123f8SSimon Glass 488ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 489ae7123f8SSimon Glass value = !value; 490ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 491ae7123f8SSimon Glass return 0; 492ae7123f8SSimon Glass } 493ae7123f8SSimon Glass 49453ecdfb9Smario.six@gdsys.cc int dm_gpio_get_open_drain(struct gpio_desc *desc) 49553ecdfb9Smario.six@gdsys.cc { 49653ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 49753ecdfb9Smario.six@gdsys.cc int ret; 49853ecdfb9Smario.six@gdsys.cc 49953ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "get_open_drain"); 50053ecdfb9Smario.six@gdsys.cc if (ret) 50153ecdfb9Smario.six@gdsys.cc return ret; 50253ecdfb9Smario.six@gdsys.cc 50353ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 50453ecdfb9Smario.six@gdsys.cc return ops->get_open_drain(desc->dev, desc->offset); 50553ecdfb9Smario.six@gdsys.cc else 50653ecdfb9Smario.six@gdsys.cc return -ENOSYS; 50753ecdfb9Smario.six@gdsys.cc } 50853ecdfb9Smario.six@gdsys.cc 50953ecdfb9Smario.six@gdsys.cc int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) 51053ecdfb9Smario.six@gdsys.cc { 51153ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 51253ecdfb9Smario.six@gdsys.cc int ret; 51353ecdfb9Smario.six@gdsys.cc 51453ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "set_open_drain"); 51553ecdfb9Smario.six@gdsys.cc if (ret) 51653ecdfb9Smario.six@gdsys.cc return ret; 51753ecdfb9Smario.six@gdsys.cc 51853ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 51953ecdfb9Smario.six@gdsys.cc ret = ops->set_open_drain(desc->dev, desc->offset, value); 52053ecdfb9Smario.six@gdsys.cc else 52153ecdfb9Smario.six@gdsys.cc return 0; /* feature not supported -> ignore setting */ 52253ecdfb9Smario.six@gdsys.cc 52353ecdfb9Smario.six@gdsys.cc return ret; 52453ecdfb9Smario.six@gdsys.cc } 52553ecdfb9Smario.six@gdsys.cc 526ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 527ae7123f8SSimon Glass { 528ae7123f8SSimon Glass struct udevice *dev = desc->dev; 529ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 530ae7123f8SSimon Glass int ret; 531ae7123f8SSimon Glass 532ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 533ae7123f8SSimon Glass if (ret) 534ae7123f8SSimon Glass return ret; 535ae7123f8SSimon Glass 536ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 537ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 538ae7123f8SSimon Glass 539ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 540ae7123f8SSimon Glass value = !value; 541ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 542ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 543ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 544ae7123f8SSimon Glass } 545ae7123f8SSimon Glass if (ret) 546ae7123f8SSimon Glass return ret; 547ae7123f8SSimon Glass /* 548ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 549ae7123f8SSimon Glass * futures 550ae7123f8SSimon Glass */ 551ae7123f8SSimon Glass desc->flags = flags; 552ae7123f8SSimon Glass 553ae7123f8SSimon Glass return 0; 554ae7123f8SSimon Glass } 555ae7123f8SSimon Glass 556ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 557ae7123f8SSimon Glass { 558ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 55996495d90SSimon Glass } 56096495d90SSimon Glass 56196495d90SSimon Glass /** 56296495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 56396495d90SSimon Glass * gpio: GPIO number 56496495d90SSimon Glass * 56596495d90SSimon Glass * This function implements the API that's compatible with current 56696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 56796495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 56896495d90SSimon Glass * on error. 56996495d90SSimon Glass */ 57096495d90SSimon Glass int gpio_get_value(unsigned gpio) 57196495d90SSimon Glass { 57296495d90SSimon Glass int ret; 57396495d90SSimon Glass 574ae7123f8SSimon Glass struct gpio_desc desc; 575ae7123f8SSimon Glass 576ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 57796495d90SSimon Glass if (ret) 57896495d90SSimon Glass return ret; 579ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 58096495d90SSimon Glass } 58196495d90SSimon Glass 58296495d90SSimon Glass /** 58396495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 58496495d90SSimon Glass * gpio: GPIO number 58596495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 58696495d90SSimon Glass * 58796495d90SSimon Glass * This function implements the API that's compatible with current 58896495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 58996495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 59096495d90SSimon Glass */ 59196495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 59296495d90SSimon Glass { 593ae7123f8SSimon Glass struct gpio_desc desc; 59496495d90SSimon Glass int ret; 59596495d90SSimon Glass 596ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 59796495d90SSimon Glass if (ret) 59896495d90SSimon Glass return ret; 599ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 60096495d90SSimon Glass } 60196495d90SSimon Glass 60254c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 60396495d90SSimon Glass { 60496495d90SSimon Glass struct gpio_dev_priv *priv; 60596495d90SSimon Glass 60696495d90SSimon Glass /* Must be called on an active device */ 607e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 60896495d90SSimon Glass assert(priv); 60996495d90SSimon Glass 61096495d90SSimon Glass *bit_count = priv->gpio_count; 61196495d90SSimon Glass return priv->bank_name; 61296495d90SSimon Glass } 61396495d90SSimon Glass 6146449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 6156449a506SSimon Glass "input", 6166449a506SSimon Glass "output", 6176449a506SSimon Glass "unused", 6186449a506SSimon Glass "unknown", 6196449a506SSimon Glass "func", 6206449a506SSimon Glass }; 6216449a506SSimon Glass 622fb07f97dSMasahiro Yamada static int get_function(struct udevice *dev, int offset, bool skip_unused, 6236449a506SSimon Glass const char **namep) 6246449a506SSimon Glass { 625e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 6266449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6276449a506SSimon Glass 6286449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6296449a506SSimon Glass if (!device_active(dev)) 6306449a506SSimon Glass return -ENODEV; 6316449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 6326449a506SSimon Glass return -EINVAL; 6336449a506SSimon Glass if (namep) 6346449a506SSimon Glass *namep = uc_priv->name[offset]; 6356449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 6366449a506SSimon Glass return GPIOF_UNUSED; 6376449a506SSimon Glass if (ops->get_function) { 6386449a506SSimon Glass int ret; 6396449a506SSimon Glass 6406449a506SSimon Glass ret = ops->get_function(dev, offset); 6416449a506SSimon Glass if (ret < 0) 6426449a506SSimon Glass return ret; 6436449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 6446449a506SSimon Glass return -ENODATA; 6456449a506SSimon Glass return ret; 6466449a506SSimon Glass } 6476449a506SSimon Glass 6486449a506SSimon Glass return GPIOF_UNKNOWN; 6496449a506SSimon Glass } 6506449a506SSimon Glass 6516449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 6526449a506SSimon Glass { 6536449a506SSimon Glass return get_function(dev, offset, true, namep); 6546449a506SSimon Glass } 6556449a506SSimon Glass 6566449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 6576449a506SSimon Glass { 6586449a506SSimon Glass return get_function(dev, offset, false, namep); 6596449a506SSimon Glass } 6606449a506SSimon Glass 6610757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 6620757535aSSimon Glass { 6630757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6640757535aSSimon Glass struct gpio_dev_priv *priv; 6650757535aSSimon Glass char *str = buf; 6660757535aSSimon Glass int func; 6670757535aSSimon Glass int ret; 6680757535aSSimon Glass int len; 6690757535aSSimon Glass 6700757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6710757535aSSimon Glass 6720757535aSSimon Glass *buf = 0; 673e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 6740757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 6750757535aSSimon Glass if (ret < 0) 6760757535aSSimon Glass return ret; 6770757535aSSimon Glass func = ret; 6780757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 6790757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 6800757535aSSimon Glass offset, gpio_function[func]); 6810757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 6820757535aSSimon Glass func == GPIOF_UNUSED) { 6830757535aSSimon Glass const char *label; 6840757535aSSimon Glass bool used; 6850757535aSSimon Glass 6860757535aSSimon Glass ret = ops->get_value(dev, offset); 6870757535aSSimon Glass if (ret < 0) 6880757535aSSimon Glass return ret; 6890757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 6900757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 6910757535aSSimon Glass ret, 6920757535aSSimon Glass used ? 'x' : ' ', 6930757535aSSimon Glass used ? " " : "", 6940757535aSSimon Glass label ? label : ""); 6950757535aSSimon Glass } 6960757535aSSimon Glass 6970757535aSSimon Glass return 0; 6980757535aSSimon Glass } 6990757535aSSimon Glass 700962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 701962f5cafSSimon Glass { 702962f5cafSSimon Glass int i, ret; 703962f5cafSSimon Glass int gpio; 704962f5cafSSimon Glass 705962f5cafSSimon Glass for (i = 0; i < 32; i++) { 706962f5cafSSimon Glass gpio = gpio_num_array[i]; 707962f5cafSSimon Glass if (gpio == -1) 708962f5cafSSimon Glass break; 709962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 710962f5cafSSimon Glass if (ret) 711962f5cafSSimon Glass goto err; 712962f5cafSSimon Glass ret = gpio_direction_input(gpio); 713962f5cafSSimon Glass if (ret) { 714962f5cafSSimon Glass gpio_free(gpio); 715962f5cafSSimon Glass goto err; 716962f5cafSSimon Glass } 717962f5cafSSimon Glass } 718962f5cafSSimon Glass 719962f5cafSSimon Glass return 0; 720962f5cafSSimon Glass err: 721962f5cafSSimon Glass for (i--; i >= 0; i--) 722962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 723962f5cafSSimon Glass 724962f5cafSSimon Glass return ret; 725962f5cafSSimon Glass } 726962f5cafSSimon Glass 727e5901c94SSimon Glass /* 728e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 729e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 730e5901c94SSimon Glass */ 731962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 732e5901c94SSimon Glass { 733e5901c94SSimon Glass int gpio; 734e5901c94SSimon Glass unsigned bitmask = 1; 735e5901c94SSimon Glass unsigned vector = 0; 736962f5cafSSimon Glass int ret; 737e5901c94SSimon Glass 738e5901c94SSimon Glass while (bitmask && 739962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 740962f5cafSSimon Glass ret = gpio_get_value(gpio); 741962f5cafSSimon Glass if (ret < 0) 742962f5cafSSimon Glass return ret; 743962f5cafSSimon Glass else if (ret) 744e5901c94SSimon Glass vector |= bitmask; 745e5901c94SSimon Glass bitmask <<= 1; 746e5901c94SSimon Glass } 747962f5cafSSimon Glass 748e5901c94SSimon Glass return vector; 749e5901c94SSimon Glass } 750e5901c94SSimon Glass 75117c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 752bbf24780SSimon Glass { 753bbf24780SSimon Glass unsigned bitmask = 1; 754bbf24780SSimon Glass unsigned vector = 0; 755bbf24780SSimon Glass int ret, i; 756bbf24780SSimon Glass 757bbf24780SSimon Glass for (i = 0; i < count; i++) { 758bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 759bbf24780SSimon Glass if (ret < 0) 760bbf24780SSimon Glass return ret; 761bbf24780SSimon Glass else if (ret) 762bbf24780SSimon Glass vector |= bitmask; 763bbf24780SSimon Glass bitmask <<= 1; 764bbf24780SSimon Glass } 765bbf24780SSimon Glass 766bbf24780SSimon Glass return vector; 767bbf24780SSimon Glass } 768bbf24780SSimon Glass 769*dab778a2SHeiko Schocher /** 770*dab778a2SHeiko Schocher * gpio_request_tail: common work for requesting a gpio. 771*dab778a2SHeiko Schocher * 772*dab778a2SHeiko Schocher * ret: return value from previous work in function which calls 773*dab778a2SHeiko Schocher * this function. 774*dab778a2SHeiko Schocher * This seems bogus (why calling this function instead not 775*dab778a2SHeiko Schocher * calling it and end caller function instead?). 776*dab778a2SHeiko Schocher * Because on error in caller function we want to set some 777*dab778a2SHeiko Schocher * default values in gpio desc and have a common error 778*dab778a2SHeiko Schocher * debug message, which provides this function. 779*dab778a2SHeiko Schocher * nodename: Name of node for which gpio gets requested 780*dab778a2SHeiko Schocher * used for gpio label name. 781*dab778a2SHeiko Schocher * args: pointer to output arguments structure 782*dab778a2SHeiko Schocher * list_name: Name of GPIO list 783*dab778a2SHeiko Schocher * used for gpio label name. 784*dab778a2SHeiko Schocher * index: gpio index in gpio list 785*dab778a2SHeiko Schocher * used for gpio label name. 786*dab778a2SHeiko Schocher * desc: pointer to gpio descriptor, filled from this 787*dab778a2SHeiko Schocher * function. 788*dab778a2SHeiko Schocher * flags: gpio flags to use. 789*dab778a2SHeiko Schocher * add_index: should index added to gpio label name 790*dab778a2SHeiko Schocher * gpio_dev: pointer to gpio device from which the gpio 791*dab778a2SHeiko Schocher * will be requested. If NULL try to get the 792*dab778a2SHeiko Schocher * gpio device with uclass_get_device_by_ofnode() 793*dab778a2SHeiko Schocher * 794*dab778a2SHeiko Schocher * return: In error case this function sets default values in 795*dab778a2SHeiko Schocher * gpio descriptor, also emmits a debug message. 796*dab778a2SHeiko Schocher * On success it returns 0 else the error code from 797*dab778a2SHeiko Schocher * function calls, or the error code passed through 798*dab778a2SHeiko Schocher * ret to this function. 799*dab778a2SHeiko Schocher * 800*dab778a2SHeiko Schocher */ 80104c095b2SHeiko Schocher static int gpio_request_tail(int ret, const char *nodename, 8023a57123eSSimon Glass struct ofnode_phandle_args *args, 8033669e0e7SSimon Glass const char *list_name, int index, 80404c095b2SHeiko Schocher struct gpio_desc *desc, int flags, 805*dab778a2SHeiko Schocher bool add_index, struct udevice *gpio_dev) 8063669e0e7SSimon Glass { 807*dab778a2SHeiko Schocher desc->dev = gpio_dev; 8083669e0e7SSimon Glass desc->offset = 0; 8096c880b77SEric Nelson desc->flags = 0; 8103a57123eSSimon Glass if (ret) 8113669e0e7SSimon Glass goto err; 8123669e0e7SSimon Glass 81304c095b2SHeiko Schocher if (!desc->dev) { 8143a57123eSSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, 8153669e0e7SSimon Glass &desc->dev); 8163669e0e7SSimon Glass if (ret) { 817*dab778a2SHeiko Schocher debug("%s: uclass_get_device_by_ofnode failed\n", 818*dab778a2SHeiko Schocher __func__); 8193669e0e7SSimon Glass goto err; 8203669e0e7SSimon Glass } 82104c095b2SHeiko Schocher } 8223a57123eSSimon Glass ret = gpio_find_and_xlate(desc, args); 8233669e0e7SSimon Glass if (ret) { 8243669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 8253669e0e7SSimon Glass goto err; 8263669e0e7SSimon Glass } 8273669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 82804c095b2SHeiko Schocher nodename, list_name, index); 8293669e0e7SSimon Glass if (ret) { 8303669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 8313669e0e7SSimon Glass goto err; 8323669e0e7SSimon Glass } 8333669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 8343669e0e7SSimon Glass if (ret) { 8353669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 8363669e0e7SSimon Glass goto err; 8373669e0e7SSimon Glass } 8383669e0e7SSimon Glass 8393669e0e7SSimon Glass return 0; 8403669e0e7SSimon Glass err: 8413669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 84204c095b2SHeiko Schocher __func__, nodename, list_name, index, ret); 8433669e0e7SSimon Glass return ret; 8443669e0e7SSimon Glass } 8453669e0e7SSimon Glass 846150c5afeSSimon Glass static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, 847150c5afeSSimon Glass int index, struct gpio_desc *desc, 848150c5afeSSimon Glass int flags, bool add_index) 8493a57123eSSimon Glass { 8503a57123eSSimon Glass struct ofnode_phandle_args args; 8513a57123eSSimon Glass int ret; 8523a57123eSSimon Glass 853150c5afeSSimon Glass ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, 854150c5afeSSimon Glass index, &args); 8553a57123eSSimon Glass 85604c095b2SHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 85704c095b2SHeiko Schocher index, desc, flags, add_index, NULL); 8583a57123eSSimon Glass } 8593a57123eSSimon Glass 860150c5afeSSimon Glass int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, 8613669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8623669e0e7SSimon Glass { 863150c5afeSSimon Glass return _gpio_request_by_name_nodev(node, list_name, index, desc, flags, 864150c5afeSSimon Glass index > 0); 8653669e0e7SSimon Glass } 8663669e0e7SSimon Glass 8673669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 8683669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8693669e0e7SSimon Glass { 870150c5afeSSimon Glass struct ofnode_phandle_args args; 87104c095b2SHeiko Schocher ofnode node; 872150c5afeSSimon Glass int ret; 873150c5afeSSimon Glass 874150c5afeSSimon Glass ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, 875150c5afeSSimon Glass index, &args); 87604c095b2SHeiko Schocher node = dev_ofnode(dev); 87704c095b2SHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 87804c095b2SHeiko Schocher index, desc, flags, index > 0, NULL); 8793669e0e7SSimon Glass } 8803669e0e7SSimon Glass 881150c5afeSSimon Glass int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, 8823669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8833669e0e7SSimon Glass int flags) 8843669e0e7SSimon Glass { 8853669e0e7SSimon Glass int count; 8863669e0e7SSimon Glass int ret; 8873669e0e7SSimon Glass 8882984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 889150c5afeSSimon Glass ret = _gpio_request_by_name_nodev(node, list_name, count, 8903669e0e7SSimon Glass &desc[count], flags, true); 8913669e0e7SSimon Glass if (ret == -ENOENT) 8923669e0e7SSimon Glass break; 8933669e0e7SSimon Glass else if (ret) 8943669e0e7SSimon Glass goto err; 8953669e0e7SSimon Glass } 8963669e0e7SSimon Glass 8973669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 8983669e0e7SSimon Glass return count; 8993669e0e7SSimon Glass 9003669e0e7SSimon Glass err: 9013669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 9023669e0e7SSimon Glass 9033669e0e7SSimon Glass return ret; 9043669e0e7SSimon Glass } 9053669e0e7SSimon Glass 9063669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 9073669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 9083669e0e7SSimon Glass int flags) 9093669e0e7SSimon Glass { 9103669e0e7SSimon Glass /* 9113669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 9123669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 9133669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 9143669e0e7SSimon Glass */ 915150c5afeSSimon Glass return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc, 916150c5afeSSimon Glass max_count, flags); 9173669e0e7SSimon Glass } 9183669e0e7SSimon Glass 9193669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 9203669e0e7SSimon Glass { 9213669e0e7SSimon Glass int ret; 9223669e0e7SSimon Glass 923e160f7d4SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 9243669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 9253669e0e7SSimon Glass NULL); 9263669e0e7SSimon Glass if (ret) { 9273669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 9283669e0e7SSimon Glass __func__, dev->name, list_name, ret); 9293669e0e7SSimon Glass } 9303669e0e7SSimon Glass 9313669e0e7SSimon Glass return ret; 9323669e0e7SSimon Glass } 9333669e0e7SSimon Glass 9343669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 9353669e0e7SSimon Glass { 9363669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9373669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 9383669e0e7SSimon Glass } 9393669e0e7SSimon Glass 9403669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 9413669e0e7SSimon Glass { 9423669e0e7SSimon Glass int i; 9433669e0e7SSimon Glass 9443669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9453669e0e7SSimon Glass for (i = 0; i < count; i++) 9463669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 9473669e0e7SSimon Glass 9483669e0e7SSimon Glass return 0; 9493669e0e7SSimon Glass } 9503669e0e7SSimon Glass 9513669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 9523669e0e7SSimon Glass { 9533669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 9543669e0e7SSimon Glass } 9553669e0e7SSimon Glass 95696495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 957b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 95896495d90SSimon Glass { 95996495d90SSimon Glass struct gpio_dev_priv *uc_priv; 96054c5d08aSHeiko Schocher struct udevice *dev; 96196495d90SSimon Glass struct uclass *uc; 96296495d90SSimon Glass unsigned base; 96396495d90SSimon Glass int ret; 96496495d90SSimon Glass 96596495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 96696495d90SSimon Glass if (ret) 96796495d90SSimon Glass return ret; 96896495d90SSimon Glass 96996495d90SSimon Glass /* Ensure that we have a base for each bank */ 97096495d90SSimon Glass base = 0; 97196495d90SSimon Glass uclass_foreach_dev(dev, uc) { 972b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 973e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 97496495d90SSimon Glass uc_priv->gpio_base = base; 97596495d90SSimon Glass base += uc_priv->gpio_count; 97696495d90SSimon Glass } 97796495d90SSimon Glass } 97896495d90SSimon Glass 97996495d90SSimon Glass return 0; 98096495d90SSimon Glass } 98196495d90SSimon Glass 98217c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 98356a71f89SSimon Glass { 98456a71f89SSimon Glass struct udevice *dev = desc->dev; 98556a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 98656a71f89SSimon Glass 98756a71f89SSimon Glass if (!dev) 98856a71f89SSimon Glass return -1; 98956a71f89SSimon Glass uc_priv = dev->uclass_priv; 99056a71f89SSimon Glass 99156a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 99256a71f89SSimon Glass } 99356a71f89SSimon Glass 99454c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 99596495d90SSimon Glass { 996e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 997b892d127SSimon Glass 998b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 999b892d127SSimon Glass if (!uc_priv->name) 1000b892d127SSimon Glass return -ENOMEM; 1001b892d127SSimon Glass 1002b892d127SSimon Glass return gpio_renumber(NULL); 100396495d90SSimon Glass } 100496495d90SSimon Glass 100554c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 100696495d90SSimon Glass { 1007e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 1008b892d127SSimon Glass int i; 1009b892d127SSimon Glass 1010b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 1011b892d127SSimon Glass if (uc_priv->name[i]) 1012b892d127SSimon Glass free(uc_priv->name[i]); 1013b892d127SSimon Glass } 1014b892d127SSimon Glass free(uc_priv->name); 1015b892d127SSimon Glass 1016b892d127SSimon Glass return gpio_renumber(dev); 101796495d90SSimon Glass } 101896495d90SSimon Glass 101904c095b2SHeiko Schocher int gpio_dev_request_index(struct udevice *dev, const char *nodename, 102004c095b2SHeiko Schocher char *list_name, int index, int flags, 102104c095b2SHeiko Schocher int dtflags, struct gpio_desc *desc) 102204c095b2SHeiko Schocher { 102304c095b2SHeiko Schocher struct ofnode_phandle_args args; 102404c095b2SHeiko Schocher 102504c095b2SHeiko Schocher args.node = ofnode_null(); 102604c095b2SHeiko Schocher args.args_count = 2; 102704c095b2SHeiko Schocher args.args[0] = index; 102804c095b2SHeiko Schocher args.args[1] = dtflags; 102904c095b2SHeiko Schocher 103004c095b2SHeiko Schocher return gpio_request_tail(0, nodename, &args, list_name, index, desc, 103104c095b2SHeiko Schocher flags, 0, dev); 103204c095b2SHeiko Schocher } 103304c095b2SHeiko Schocher 10341b4c2aa2SMichal Simek static int gpio_post_bind(struct udevice *dev) 10351b4c2aa2SMichal Simek { 103604c095b2SHeiko Schocher struct udevice *child; 103704c095b2SHeiko Schocher ofnode node; 103804c095b2SHeiko Schocher 10391b4c2aa2SMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC) 10401b4c2aa2SMichal Simek struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); 10411b4c2aa2SMichal Simek static int reloc_done; 10421b4c2aa2SMichal Simek 10431b4c2aa2SMichal Simek if (!reloc_done) { 10441b4c2aa2SMichal Simek if (ops->request) 10451b4c2aa2SMichal Simek ops->request += gd->reloc_off; 10461b4c2aa2SMichal Simek if (ops->free) 10471b4c2aa2SMichal Simek ops->free += gd->reloc_off; 10481b4c2aa2SMichal Simek if (ops->direction_input) 10491b4c2aa2SMichal Simek ops->direction_input += gd->reloc_off; 10501b4c2aa2SMichal Simek if (ops->direction_output) 10511b4c2aa2SMichal Simek ops->direction_output += gd->reloc_off; 10521b4c2aa2SMichal Simek if (ops->get_value) 10531b4c2aa2SMichal Simek ops->get_value += gd->reloc_off; 10541b4c2aa2SMichal Simek if (ops->set_value) 10551b4c2aa2SMichal Simek ops->set_value += gd->reloc_off; 10561b4c2aa2SMichal Simek if (ops->get_open_drain) 10571b4c2aa2SMichal Simek ops->get_open_drain += gd->reloc_off; 10581b4c2aa2SMichal Simek if (ops->set_open_drain) 10591b4c2aa2SMichal Simek ops->set_open_drain += gd->reloc_off; 10601b4c2aa2SMichal Simek if (ops->get_function) 10611b4c2aa2SMichal Simek ops->get_function += gd->reloc_off; 10621b4c2aa2SMichal Simek if (ops->xlate) 10631b4c2aa2SMichal Simek ops->xlate += gd->reloc_off; 10641b4c2aa2SMichal Simek 10651b4c2aa2SMichal Simek reloc_done++; 10661b4c2aa2SMichal Simek } 10671b4c2aa2SMichal Simek #endif 106804c095b2SHeiko Schocher 1069*dab778a2SHeiko Schocher if (IS_ENABLED(CONFIG_GPIO_HOG)) { 107004c095b2SHeiko Schocher dev_for_each_subnode(node, dev) { 107104c095b2SHeiko Schocher if (ofnode_read_bool(node, "gpio-hog")) { 107204c095b2SHeiko Schocher const char *name = ofnode_get_name(node); 1073*dab778a2SHeiko Schocher int ret; 107404c095b2SHeiko Schocher 1075*dab778a2SHeiko Schocher ret = device_bind_driver_to_node(dev, 1076*dab778a2SHeiko Schocher "gpio_hog", 1077*dab778a2SHeiko Schocher name, node, 1078*dab778a2SHeiko Schocher &child); 1079*dab778a2SHeiko Schocher if (ret) 1080*dab778a2SHeiko Schocher return ret; 108104c095b2SHeiko Schocher } 108204c095b2SHeiko Schocher } 1083*dab778a2SHeiko Schocher } 10841b4c2aa2SMichal Simek return 0; 10851b4c2aa2SMichal Simek } 10861b4c2aa2SMichal Simek 108796495d90SSimon Glass UCLASS_DRIVER(gpio) = { 108896495d90SSimon Glass .id = UCLASS_GPIO, 108996495d90SSimon Glass .name = "gpio", 1090ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 109196495d90SSimon Glass .post_probe = gpio_post_probe, 10921b4c2aa2SMichal Simek .post_bind = gpio_post_bind, 109396495d90SSimon Glass .pre_remove = gpio_pre_remove, 109496495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 109596495d90SSimon Glass }; 1096