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> 8*04c095b2SHeiko Schocher #include <dm/device-internal.h> 9*04c095b2SHeiko Schocher #include <dm/lists.h> 10*04c095b2SHeiko 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*04c095b2SHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 148*04c095b2SHeiko Schocher 149*04c095b2SHeiko Schocher struct gpio_hog_priv { 150*04c095b2SHeiko Schocher struct gpio_desc gpiod; 151*04c095b2SHeiko Schocher }; 152*04c095b2SHeiko Schocher 153*04c095b2SHeiko Schocher struct gpio_hog_data { 154*04c095b2SHeiko Schocher int gpiod_flags; 155*04c095b2SHeiko Schocher int value; 156*04c095b2SHeiko Schocher u32 val[2]; 157*04c095b2SHeiko Schocher }; 158*04c095b2SHeiko Schocher 159*04c095b2SHeiko Schocher static int gpio_hog_ofdata_to_platdata(struct udevice *dev) 160*04c095b2SHeiko Schocher { 161*04c095b2SHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 162*04c095b2SHeiko Schocher const char *nodename; 163*04c095b2SHeiko Schocher int ret; 164*04c095b2SHeiko Schocher 165*04c095b2SHeiko Schocher plat->value = 0; 166*04c095b2SHeiko Schocher if (dev_read_bool(dev, "input")) { 167*04c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_IN; 168*04c095b2SHeiko Schocher } else if (dev_read_bool(dev, "output-high")) { 169*04c095b2SHeiko Schocher plat->value = 1; 170*04c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 171*04c095b2SHeiko Schocher } else if (dev_read_bool(dev, "output-low")) { 172*04c095b2SHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 173*04c095b2SHeiko Schocher } else { 174*04c095b2SHeiko Schocher printf("%s: missing gpio-hog state.\n", __func__); 175*04c095b2SHeiko Schocher return -EINVAL; 176*04c095b2SHeiko Schocher } 177*04c095b2SHeiko Schocher ret = dev_read_u32_array(dev, "gpios", plat->val, 2); 178*04c095b2SHeiko Schocher if (ret) { 179*04c095b2SHeiko Schocher printf("%s: wrong gpios property, 2 values needed %d\n", 180*04c095b2SHeiko Schocher __func__, ret); 181*04c095b2SHeiko Schocher return ret; 182*04c095b2SHeiko Schocher } 183*04c095b2SHeiko Schocher nodename = dev_read_string(dev, "line-name"); 184*04c095b2SHeiko Schocher if (!nodename) 185*04c095b2SHeiko Schocher nodename = dev_read_name(dev); 186*04c095b2SHeiko Schocher device_set_name(dev, nodename); 187*04c095b2SHeiko Schocher 188*04c095b2SHeiko Schocher return 0; 189*04c095b2SHeiko Schocher } 190*04c095b2SHeiko Schocher 191*04c095b2SHeiko Schocher static int gpio_hog_probe(struct udevice *dev) 192*04c095b2SHeiko Schocher { 193*04c095b2SHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 194*04c095b2SHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 195*04c095b2SHeiko Schocher int ret; 196*04c095b2SHeiko Schocher 197*04c095b2SHeiko Schocher ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog", 198*04c095b2SHeiko Schocher plat->val[0], plat->gpiod_flags, 199*04c095b2SHeiko Schocher plat->val[1], &priv->gpiod); 200*04c095b2SHeiko Schocher if (ret < 0) { 201*04c095b2SHeiko Schocher debug("%s: node %s could not get gpio.\n", __func__, 202*04c095b2SHeiko Schocher dev->name); 203*04c095b2SHeiko Schocher return ret; 204*04c095b2SHeiko Schocher } 205*04c095b2SHeiko Schocher dm_gpio_set_dir(&priv->gpiod); 206*04c095b2SHeiko Schocher if (plat->gpiod_flags == GPIOD_IS_OUT) 207*04c095b2SHeiko Schocher dm_gpio_set_value(&priv->gpiod, plat->value); 208*04c095b2SHeiko Schocher 209*04c095b2SHeiko Schocher return 0; 210*04c095b2SHeiko Schocher } 211*04c095b2SHeiko Schocher 212*04c095b2SHeiko Schocher int gpio_hog_probe_all(void) 213*04c095b2SHeiko Schocher { 214*04c095b2SHeiko Schocher struct udevice *dev; 215*04c095b2SHeiko Schocher int ret; 216*04c095b2SHeiko Schocher 217*04c095b2SHeiko Schocher for (uclass_first_device(UCLASS_NOP, &dev); 218*04c095b2SHeiko Schocher dev; 219*04c095b2SHeiko Schocher uclass_find_next_device(&dev)) { 220*04c095b2SHeiko Schocher if (dev->driver == DM_GET_DRIVER(gpio_hog)) { 221*04c095b2SHeiko Schocher ret = device_probe(dev); 222*04c095b2SHeiko Schocher if (ret) 223*04c095b2SHeiko Schocher return ret; 224*04c095b2SHeiko Schocher } 225*04c095b2SHeiko Schocher } 226*04c095b2SHeiko Schocher 227*04c095b2SHeiko Schocher return 0; 228*04c095b2SHeiko Schocher } 229*04c095b2SHeiko Schocher 230*04c095b2SHeiko Schocher struct gpio_desc *gpio_hog_lookup_name(const char *name) 231*04c095b2SHeiko Schocher { 232*04c095b2SHeiko Schocher struct udevice *dev; 233*04c095b2SHeiko Schocher 234*04c095b2SHeiko Schocher gpio_hog_probe_all(); 235*04c095b2SHeiko Schocher if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { 236*04c095b2SHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 237*04c095b2SHeiko Schocher 238*04c095b2SHeiko Schocher return &priv->gpiod; 239*04c095b2SHeiko Schocher } 240*04c095b2SHeiko Schocher 241*04c095b2SHeiko Schocher return NULL; 242*04c095b2SHeiko Schocher } 243*04c095b2SHeiko Schocher 244*04c095b2SHeiko Schocher U_BOOT_DRIVER(gpio_hog) = { 245*04c095b2SHeiko Schocher .name = "gpio_hog", 246*04c095b2SHeiko Schocher .id = UCLASS_NOP, 247*04c095b2SHeiko Schocher .ofdata_to_platdata = gpio_hog_ofdata_to_platdata, 248*04c095b2SHeiko Schocher .probe = gpio_hog_probe, 249*04c095b2SHeiko Schocher .priv_auto_alloc_size = sizeof(struct gpio_hog_priv), 250*04c095b2SHeiko Schocher .platdata_auto_alloc_size = sizeof(struct gpio_hog_data), 251*04c095b2SHeiko Schocher }; 252*04c095b2SHeiko Schocher #else 253*04c095b2SHeiko Schocher struct gpio_desc *gpio_hog_lookup_name(const char *name) 254*04c095b2SHeiko Schocher { 255*04c095b2SHeiko Schocher return NULL; 256*04c095b2SHeiko Schocher } 257*04c095b2SHeiko Schocher #endif 258*04c095b2SHeiko Schocher 259efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 260ae7123f8SSimon Glass { 261ae7123f8SSimon Glass struct udevice *dev = desc->dev; 262ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 263ae7123f8SSimon Glass char *str; 264ae7123f8SSimon Glass int ret; 265ae7123f8SSimon Glass 266e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 267ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 268ae7123f8SSimon Glass return -EBUSY; 269ae7123f8SSimon Glass str = strdup(label); 270ae7123f8SSimon Glass if (!str) 271ae7123f8SSimon Glass return -ENOMEM; 272ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 273ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 274ae7123f8SSimon Glass if (ret) { 275ae7123f8SSimon Glass free(str); 276ae7123f8SSimon Glass return ret; 277ae7123f8SSimon Glass } 278ae7123f8SSimon Glass } 279ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 280ae7123f8SSimon Glass 281ae7123f8SSimon Glass return 0; 282ae7123f8SSimon Glass } 283ae7123f8SSimon Glass 2843669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 2853669e0e7SSimon Glass { 2864dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 2873669e0e7SSimon Glass va_list args; 2883669e0e7SSimon Glass char buf[40]; 2893669e0e7SSimon Glass 2903669e0e7SSimon Glass va_start(args, fmt); 2913669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 2923669e0e7SSimon Glass va_end(args); 2933669e0e7SSimon Glass return dm_gpio_request(desc, buf); 2944dc5259aSSimon Glass #else 2954dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 2964dc5259aSSimon Glass #endif 2973669e0e7SSimon Glass } 2983669e0e7SSimon Glass 29996495d90SSimon Glass /** 30096495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 30196495d90SSimon Glass * gpio: GPIO number 30296495d90SSimon Glass * label: Name for the requested GPIO 30396495d90SSimon Glass * 304b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 305b892d127SSimon Glass * the pointer around. 306b892d127SSimon Glass * 30796495d90SSimon Glass * This function implements the API that's compatible with current 30896495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 30996495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 31096495d90SSimon Glass */ 31196495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 31296495d90SSimon Glass { 313ae7123f8SSimon Glass struct gpio_desc desc; 31496495d90SSimon Glass int ret; 31596495d90SSimon Glass 316ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 31796495d90SSimon Glass if (ret) 31896495d90SSimon Glass return ret; 31996495d90SSimon Glass 320ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 32196495d90SSimon Glass } 32296495d90SSimon Glass 32396495d90SSimon Glass /** 324d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 325d44f597bSSimon Glass * @gpio: GPIO number 326d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 327d44f597bSSimon Glass * @...: Arguments for the printf() format string 328d44f597bSSimon Glass * 329d44f597bSSimon Glass * This function implements the API that's compatible with current 330d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 331d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 332d44f597bSSimon Glass */ 333d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 334d44f597bSSimon Glass { 3354dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 336d44f597bSSimon Glass va_list args; 337d44f597bSSimon Glass char buf[40]; 338d44f597bSSimon Glass 339d44f597bSSimon Glass va_start(args, fmt); 340d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 341d44f597bSSimon Glass va_end(args); 342d44f597bSSimon Glass return gpio_request(gpio, buf); 3434dc5259aSSimon Glass #else 3444dc5259aSSimon Glass return gpio_request(gpio, fmt); 3454dc5259aSSimon Glass #endif 346d44f597bSSimon Glass } 347d44f597bSSimon Glass 348ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 34996495d90SSimon Glass { 350b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 35196495d90SSimon Glass int ret; 35296495d90SSimon Glass 353e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 354b892d127SSimon Glass if (!uc_priv->name[offset]) 355b892d127SSimon Glass return -ENXIO; 356b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 357b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 358b892d127SSimon Glass if (ret) 359b892d127SSimon Glass return ret; 360b892d127SSimon Glass } 361b892d127SSimon Glass 362b892d127SSimon Glass free(uc_priv->name[offset]); 363b892d127SSimon Glass uc_priv->name[offset] = NULL; 364b892d127SSimon Glass 36596495d90SSimon Glass return 0; 366b892d127SSimon Glass } 367b892d127SSimon Glass 368ae7123f8SSimon Glass /** 369ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 370ae7123f8SSimon Glass * gpio: GPIO number 371ae7123f8SSimon Glass * 372ae7123f8SSimon Glass * This function implements the API that's compatible with current 373ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 374ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 375ae7123f8SSimon Glass */ 376ae7123f8SSimon Glass int gpio_free(unsigned gpio) 377b892d127SSimon Glass { 378ae7123f8SSimon Glass struct gpio_desc desc; 379ae7123f8SSimon Glass int ret; 380b892d127SSimon Glass 381ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 382ae7123f8SSimon Glass if (ret) 383ae7123f8SSimon Glass return ret; 384ae7123f8SSimon Glass 385ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 386ae7123f8SSimon Glass } 387ae7123f8SSimon Glass 38817c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 389ae7123f8SSimon Glass { 390eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 391ae7123f8SSimon Glass 392eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 393eca48665SSimon Glass return -ENOENT; 394eca48665SSimon Glass 395eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 396ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 397b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 398ae7123f8SSimon Glass desc->dev->name, func, 399ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 400ae7123f8SSimon Glass desc->offset); 401b892d127SSimon Glass return -EBUSY; 402b892d127SSimon Glass } 403b892d127SSimon Glass 404b892d127SSimon Glass return 0; 40596495d90SSimon Glass } 40696495d90SSimon Glass 40796495d90SSimon Glass /** 40896495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 40996495d90SSimon Glass * gpio: GPIO number 41096495d90SSimon Glass * 41196495d90SSimon Glass * This function implements the API that's compatible with current 41296495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 41396495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 41496495d90SSimon Glass */ 41596495d90SSimon Glass int gpio_direction_input(unsigned gpio) 41696495d90SSimon Glass { 417ae7123f8SSimon Glass struct gpio_desc desc; 41896495d90SSimon Glass int ret; 41996495d90SSimon Glass 420ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 42196495d90SSimon Glass if (ret) 42296495d90SSimon Glass return ret; 423ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 424ae7123f8SSimon Glass if (ret) 425ae7123f8SSimon Glass return ret; 42696495d90SSimon Glass 427ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 42896495d90SSimon Glass } 42996495d90SSimon Glass 43096495d90SSimon Glass /** 43196495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 43296495d90SSimon Glass * gpio: GPIO number 43396495d90SSimon Glass * value: Logical value to be set on the GPIO pin 43496495d90SSimon Glass * 43596495d90SSimon Glass * This function implements the API that's compatible with current 43696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 43796495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 43896495d90SSimon Glass */ 43996495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 44096495d90SSimon Glass { 441ae7123f8SSimon Glass struct gpio_desc desc; 44296495d90SSimon Glass int ret; 44396495d90SSimon Glass 444ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 44596495d90SSimon Glass if (ret) 44696495d90SSimon Glass return ret; 447ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 448ae7123f8SSimon Glass if (ret) 449ae7123f8SSimon Glass return ret; 45096495d90SSimon Glass 451ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 452ae7123f8SSimon Glass desc.offset, value); 453ae7123f8SSimon Glass } 454ae7123f8SSimon Glass 45517c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 456ae7123f8SSimon Glass { 457ae7123f8SSimon Glass int value; 458ae7123f8SSimon Glass int ret; 459ae7123f8SSimon Glass 460ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 461ae7123f8SSimon Glass if (ret) 462ae7123f8SSimon Glass return ret; 463ae7123f8SSimon Glass 464ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 465ae7123f8SSimon Glass 466ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 467ae7123f8SSimon Glass } 468ae7123f8SSimon Glass 46917c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 470ae7123f8SSimon Glass { 471ae7123f8SSimon Glass int ret; 472ae7123f8SSimon Glass 473ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 474ae7123f8SSimon Glass if (ret) 475ae7123f8SSimon Glass return ret; 476ae7123f8SSimon Glass 477ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 478ae7123f8SSimon Glass value = !value; 479ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 480ae7123f8SSimon Glass return 0; 481ae7123f8SSimon Glass } 482ae7123f8SSimon Glass 48353ecdfb9Smario.six@gdsys.cc int dm_gpio_get_open_drain(struct gpio_desc *desc) 48453ecdfb9Smario.six@gdsys.cc { 48553ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 48653ecdfb9Smario.six@gdsys.cc int ret; 48753ecdfb9Smario.six@gdsys.cc 48853ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "get_open_drain"); 48953ecdfb9Smario.six@gdsys.cc if (ret) 49053ecdfb9Smario.six@gdsys.cc return ret; 49153ecdfb9Smario.six@gdsys.cc 49253ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 49353ecdfb9Smario.six@gdsys.cc return ops->get_open_drain(desc->dev, desc->offset); 49453ecdfb9Smario.six@gdsys.cc else 49553ecdfb9Smario.six@gdsys.cc return -ENOSYS; 49653ecdfb9Smario.six@gdsys.cc } 49753ecdfb9Smario.six@gdsys.cc 49853ecdfb9Smario.six@gdsys.cc int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) 49953ecdfb9Smario.six@gdsys.cc { 50053ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 50153ecdfb9Smario.six@gdsys.cc int ret; 50253ecdfb9Smario.six@gdsys.cc 50353ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "set_open_drain"); 50453ecdfb9Smario.six@gdsys.cc if (ret) 50553ecdfb9Smario.six@gdsys.cc return ret; 50653ecdfb9Smario.six@gdsys.cc 50753ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 50853ecdfb9Smario.six@gdsys.cc ret = ops->set_open_drain(desc->dev, desc->offset, value); 50953ecdfb9Smario.six@gdsys.cc else 51053ecdfb9Smario.six@gdsys.cc return 0; /* feature not supported -> ignore setting */ 51153ecdfb9Smario.six@gdsys.cc 51253ecdfb9Smario.six@gdsys.cc return ret; 51353ecdfb9Smario.six@gdsys.cc } 51453ecdfb9Smario.six@gdsys.cc 515ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 516ae7123f8SSimon Glass { 517ae7123f8SSimon Glass struct udevice *dev = desc->dev; 518ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 519ae7123f8SSimon Glass int ret; 520ae7123f8SSimon Glass 521ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 522ae7123f8SSimon Glass if (ret) 523ae7123f8SSimon Glass return ret; 524ae7123f8SSimon Glass 525ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 526ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 527ae7123f8SSimon Glass 528ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 529ae7123f8SSimon Glass value = !value; 530ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 531ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 532ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 533ae7123f8SSimon Glass } 534ae7123f8SSimon Glass if (ret) 535ae7123f8SSimon Glass return ret; 536ae7123f8SSimon Glass /* 537ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 538ae7123f8SSimon Glass * futures 539ae7123f8SSimon Glass */ 540ae7123f8SSimon Glass desc->flags = flags; 541ae7123f8SSimon Glass 542ae7123f8SSimon Glass return 0; 543ae7123f8SSimon Glass } 544ae7123f8SSimon Glass 545ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 546ae7123f8SSimon Glass { 547ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 54896495d90SSimon Glass } 54996495d90SSimon Glass 55096495d90SSimon Glass /** 55196495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 55296495d90SSimon Glass * gpio: GPIO number 55396495d90SSimon Glass * 55496495d90SSimon Glass * This function implements the API that's compatible with current 55596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 55696495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 55796495d90SSimon Glass * on error. 55896495d90SSimon Glass */ 55996495d90SSimon Glass int gpio_get_value(unsigned gpio) 56096495d90SSimon Glass { 56196495d90SSimon Glass int ret; 56296495d90SSimon Glass 563ae7123f8SSimon Glass struct gpio_desc desc; 564ae7123f8SSimon Glass 565ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 56696495d90SSimon Glass if (ret) 56796495d90SSimon Glass return ret; 568ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 56996495d90SSimon Glass } 57096495d90SSimon Glass 57196495d90SSimon Glass /** 57296495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 57396495d90SSimon Glass * gpio: GPIO number 57496495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 57596495d90SSimon Glass * 57696495d90SSimon Glass * This function implements the API that's compatible with current 57796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 57896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 57996495d90SSimon Glass */ 58096495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 58196495d90SSimon Glass { 582ae7123f8SSimon Glass struct gpio_desc desc; 58396495d90SSimon Glass int ret; 58496495d90SSimon Glass 585ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 58696495d90SSimon Glass if (ret) 58796495d90SSimon Glass return ret; 588ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 58996495d90SSimon Glass } 59096495d90SSimon Glass 59154c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 59296495d90SSimon Glass { 59396495d90SSimon Glass struct gpio_dev_priv *priv; 59496495d90SSimon Glass 59596495d90SSimon Glass /* Must be called on an active device */ 596e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 59796495d90SSimon Glass assert(priv); 59896495d90SSimon Glass 59996495d90SSimon Glass *bit_count = priv->gpio_count; 60096495d90SSimon Glass return priv->bank_name; 60196495d90SSimon Glass } 60296495d90SSimon Glass 6036449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 6046449a506SSimon Glass "input", 6056449a506SSimon Glass "output", 6066449a506SSimon Glass "unused", 6076449a506SSimon Glass "unknown", 6086449a506SSimon Glass "func", 6096449a506SSimon Glass }; 6106449a506SSimon Glass 611fb07f97dSMasahiro Yamada static int get_function(struct udevice *dev, int offset, bool skip_unused, 6126449a506SSimon Glass const char **namep) 6136449a506SSimon Glass { 614e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 6156449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6166449a506SSimon Glass 6176449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6186449a506SSimon Glass if (!device_active(dev)) 6196449a506SSimon Glass return -ENODEV; 6206449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 6216449a506SSimon Glass return -EINVAL; 6226449a506SSimon Glass if (namep) 6236449a506SSimon Glass *namep = uc_priv->name[offset]; 6246449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 6256449a506SSimon Glass return GPIOF_UNUSED; 6266449a506SSimon Glass if (ops->get_function) { 6276449a506SSimon Glass int ret; 6286449a506SSimon Glass 6296449a506SSimon Glass ret = ops->get_function(dev, offset); 6306449a506SSimon Glass if (ret < 0) 6316449a506SSimon Glass return ret; 6326449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 6336449a506SSimon Glass return -ENODATA; 6346449a506SSimon Glass return ret; 6356449a506SSimon Glass } 6366449a506SSimon Glass 6376449a506SSimon Glass return GPIOF_UNKNOWN; 6386449a506SSimon Glass } 6396449a506SSimon Glass 6406449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 6416449a506SSimon Glass { 6426449a506SSimon Glass return get_function(dev, offset, true, namep); 6436449a506SSimon Glass } 6446449a506SSimon Glass 6456449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 6466449a506SSimon Glass { 6476449a506SSimon Glass return get_function(dev, offset, false, namep); 6486449a506SSimon Glass } 6496449a506SSimon Glass 6500757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 6510757535aSSimon Glass { 6520757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6530757535aSSimon Glass struct gpio_dev_priv *priv; 6540757535aSSimon Glass char *str = buf; 6550757535aSSimon Glass int func; 6560757535aSSimon Glass int ret; 6570757535aSSimon Glass int len; 6580757535aSSimon Glass 6590757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6600757535aSSimon Glass 6610757535aSSimon Glass *buf = 0; 662e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 6630757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 6640757535aSSimon Glass if (ret < 0) 6650757535aSSimon Glass return ret; 6660757535aSSimon Glass func = ret; 6670757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 6680757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 6690757535aSSimon Glass offset, gpio_function[func]); 6700757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 6710757535aSSimon Glass func == GPIOF_UNUSED) { 6720757535aSSimon Glass const char *label; 6730757535aSSimon Glass bool used; 6740757535aSSimon Glass 6750757535aSSimon Glass ret = ops->get_value(dev, offset); 6760757535aSSimon Glass if (ret < 0) 6770757535aSSimon Glass return ret; 6780757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 6790757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 6800757535aSSimon Glass ret, 6810757535aSSimon Glass used ? 'x' : ' ', 6820757535aSSimon Glass used ? " " : "", 6830757535aSSimon Glass label ? label : ""); 6840757535aSSimon Glass } 6850757535aSSimon Glass 6860757535aSSimon Glass return 0; 6870757535aSSimon Glass } 6880757535aSSimon Glass 689962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 690962f5cafSSimon Glass { 691962f5cafSSimon Glass int i, ret; 692962f5cafSSimon Glass int gpio; 693962f5cafSSimon Glass 694962f5cafSSimon Glass for (i = 0; i < 32; i++) { 695962f5cafSSimon Glass gpio = gpio_num_array[i]; 696962f5cafSSimon Glass if (gpio == -1) 697962f5cafSSimon Glass break; 698962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 699962f5cafSSimon Glass if (ret) 700962f5cafSSimon Glass goto err; 701962f5cafSSimon Glass ret = gpio_direction_input(gpio); 702962f5cafSSimon Glass if (ret) { 703962f5cafSSimon Glass gpio_free(gpio); 704962f5cafSSimon Glass goto err; 705962f5cafSSimon Glass } 706962f5cafSSimon Glass } 707962f5cafSSimon Glass 708962f5cafSSimon Glass return 0; 709962f5cafSSimon Glass err: 710962f5cafSSimon Glass for (i--; i >= 0; i--) 711962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 712962f5cafSSimon Glass 713962f5cafSSimon Glass return ret; 714962f5cafSSimon Glass } 715962f5cafSSimon Glass 716e5901c94SSimon Glass /* 717e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 718e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 719e5901c94SSimon Glass */ 720962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 721e5901c94SSimon Glass { 722e5901c94SSimon Glass int gpio; 723e5901c94SSimon Glass unsigned bitmask = 1; 724e5901c94SSimon Glass unsigned vector = 0; 725962f5cafSSimon Glass int ret; 726e5901c94SSimon Glass 727e5901c94SSimon Glass while (bitmask && 728962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 729962f5cafSSimon Glass ret = gpio_get_value(gpio); 730962f5cafSSimon Glass if (ret < 0) 731962f5cafSSimon Glass return ret; 732962f5cafSSimon Glass else if (ret) 733e5901c94SSimon Glass vector |= bitmask; 734e5901c94SSimon Glass bitmask <<= 1; 735e5901c94SSimon Glass } 736962f5cafSSimon Glass 737e5901c94SSimon Glass return vector; 738e5901c94SSimon Glass } 739e5901c94SSimon Glass 74017c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 741bbf24780SSimon Glass { 742bbf24780SSimon Glass unsigned bitmask = 1; 743bbf24780SSimon Glass unsigned vector = 0; 744bbf24780SSimon Glass int ret, i; 745bbf24780SSimon Glass 746bbf24780SSimon Glass for (i = 0; i < count; i++) { 747bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 748bbf24780SSimon Glass if (ret < 0) 749bbf24780SSimon Glass return ret; 750bbf24780SSimon Glass else if (ret) 751bbf24780SSimon Glass vector |= bitmask; 752bbf24780SSimon Glass bitmask <<= 1; 753bbf24780SSimon Glass } 754bbf24780SSimon Glass 755bbf24780SSimon Glass return vector; 756bbf24780SSimon Glass } 757bbf24780SSimon Glass 758*04c095b2SHeiko Schocher static int gpio_request_tail(int ret, const char *nodename, 7593a57123eSSimon Glass struct ofnode_phandle_args *args, 7603669e0e7SSimon Glass const char *list_name, int index, 761*04c095b2SHeiko Schocher struct gpio_desc *desc, int flags, 762*04c095b2SHeiko Schocher bool add_index, struct udevice *dev) 7633669e0e7SSimon Glass { 764*04c095b2SHeiko Schocher desc->dev = dev; 7653669e0e7SSimon Glass desc->offset = 0; 7666c880b77SEric Nelson desc->flags = 0; 7673a57123eSSimon Glass if (ret) 7683669e0e7SSimon Glass goto err; 7693669e0e7SSimon Glass 770*04c095b2SHeiko Schocher if (!desc->dev) { 7713a57123eSSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, 7723669e0e7SSimon Glass &desc->dev); 7733669e0e7SSimon Glass if (ret) { 774b053dd7cSMario Six debug("%s: uclass_get_device_by_ofnode failed\n", __func__); 7753669e0e7SSimon Glass goto err; 7763669e0e7SSimon Glass } 777*04c095b2SHeiko Schocher } 7783a57123eSSimon Glass ret = gpio_find_and_xlate(desc, args); 7793669e0e7SSimon Glass if (ret) { 7803669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 7813669e0e7SSimon Glass goto err; 7823669e0e7SSimon Glass } 7833669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 784*04c095b2SHeiko Schocher nodename, list_name, index); 7853669e0e7SSimon Glass if (ret) { 7863669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 7873669e0e7SSimon Glass goto err; 7883669e0e7SSimon Glass } 7893669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 7903669e0e7SSimon Glass if (ret) { 7913669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 7923669e0e7SSimon Glass goto err; 7933669e0e7SSimon Glass } 7943669e0e7SSimon Glass 7953669e0e7SSimon Glass return 0; 7963669e0e7SSimon Glass err: 7973669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 798*04c095b2SHeiko Schocher __func__, nodename, list_name, index, ret); 7993669e0e7SSimon Glass return ret; 8003669e0e7SSimon Glass } 8013669e0e7SSimon Glass 802150c5afeSSimon Glass static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, 803150c5afeSSimon Glass int index, struct gpio_desc *desc, 804150c5afeSSimon Glass int flags, bool add_index) 8053a57123eSSimon Glass { 8063a57123eSSimon Glass struct ofnode_phandle_args args; 8073a57123eSSimon Glass int ret; 8083a57123eSSimon Glass 809150c5afeSSimon Glass ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, 810150c5afeSSimon Glass index, &args); 8113a57123eSSimon Glass 812*04c095b2SHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 813*04c095b2SHeiko Schocher index, desc, flags, add_index, NULL); 8143a57123eSSimon Glass } 8153a57123eSSimon Glass 816150c5afeSSimon Glass int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, 8173669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8183669e0e7SSimon Glass { 819150c5afeSSimon Glass return _gpio_request_by_name_nodev(node, list_name, index, desc, flags, 820150c5afeSSimon Glass index > 0); 8213669e0e7SSimon Glass } 8223669e0e7SSimon Glass 8233669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 8243669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8253669e0e7SSimon Glass { 826150c5afeSSimon Glass struct ofnode_phandle_args args; 827*04c095b2SHeiko Schocher ofnode node; 828150c5afeSSimon Glass int ret; 829150c5afeSSimon Glass 830150c5afeSSimon Glass ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, 831150c5afeSSimon Glass index, &args); 832*04c095b2SHeiko Schocher node = dev_ofnode(dev); 833*04c095b2SHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 834*04c095b2SHeiko Schocher index, desc, flags, index > 0, NULL); 8353669e0e7SSimon Glass } 8363669e0e7SSimon Glass 837150c5afeSSimon Glass int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, 8383669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8393669e0e7SSimon Glass int flags) 8403669e0e7SSimon Glass { 8413669e0e7SSimon Glass int count; 8423669e0e7SSimon Glass int ret; 8433669e0e7SSimon Glass 8442984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 845150c5afeSSimon Glass ret = _gpio_request_by_name_nodev(node, list_name, count, 8463669e0e7SSimon Glass &desc[count], flags, true); 8473669e0e7SSimon Glass if (ret == -ENOENT) 8483669e0e7SSimon Glass break; 8493669e0e7SSimon Glass else if (ret) 8503669e0e7SSimon Glass goto err; 8513669e0e7SSimon Glass } 8523669e0e7SSimon Glass 8533669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 8543669e0e7SSimon Glass return count; 8553669e0e7SSimon Glass 8563669e0e7SSimon Glass err: 8573669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 8583669e0e7SSimon Glass 8593669e0e7SSimon Glass return ret; 8603669e0e7SSimon Glass } 8613669e0e7SSimon Glass 8623669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 8633669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8643669e0e7SSimon Glass int flags) 8653669e0e7SSimon Glass { 8663669e0e7SSimon Glass /* 8673669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 8683669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 8693669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 8703669e0e7SSimon Glass */ 871150c5afeSSimon Glass return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc, 872150c5afeSSimon Glass max_count, flags); 8733669e0e7SSimon Glass } 8743669e0e7SSimon Glass 8753669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 8763669e0e7SSimon Glass { 8773669e0e7SSimon Glass int ret; 8783669e0e7SSimon Glass 879e160f7d4SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 8803669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 8813669e0e7SSimon Glass NULL); 8823669e0e7SSimon Glass if (ret) { 8833669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 8843669e0e7SSimon Glass __func__, dev->name, list_name, ret); 8853669e0e7SSimon Glass } 8863669e0e7SSimon Glass 8873669e0e7SSimon Glass return ret; 8883669e0e7SSimon Glass } 8893669e0e7SSimon Glass 8903669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 8913669e0e7SSimon Glass { 8923669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 8933669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 8943669e0e7SSimon Glass } 8953669e0e7SSimon Glass 8963669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 8973669e0e7SSimon Glass { 8983669e0e7SSimon Glass int i; 8993669e0e7SSimon Glass 9003669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9013669e0e7SSimon Glass for (i = 0; i < count; i++) 9023669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 9033669e0e7SSimon Glass 9043669e0e7SSimon Glass return 0; 9053669e0e7SSimon Glass } 9063669e0e7SSimon Glass 9073669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 9083669e0e7SSimon Glass { 9093669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 9103669e0e7SSimon Glass } 9113669e0e7SSimon Glass 91296495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 913b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 91496495d90SSimon Glass { 91596495d90SSimon Glass struct gpio_dev_priv *uc_priv; 91654c5d08aSHeiko Schocher struct udevice *dev; 91796495d90SSimon Glass struct uclass *uc; 91896495d90SSimon Glass unsigned base; 91996495d90SSimon Glass int ret; 92096495d90SSimon Glass 92196495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 92296495d90SSimon Glass if (ret) 92396495d90SSimon Glass return ret; 92496495d90SSimon Glass 92596495d90SSimon Glass /* Ensure that we have a base for each bank */ 92696495d90SSimon Glass base = 0; 92796495d90SSimon Glass uclass_foreach_dev(dev, uc) { 928b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 929e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 93096495d90SSimon Glass uc_priv->gpio_base = base; 93196495d90SSimon Glass base += uc_priv->gpio_count; 93296495d90SSimon Glass } 93396495d90SSimon Glass } 93496495d90SSimon Glass 93596495d90SSimon Glass return 0; 93696495d90SSimon Glass } 93796495d90SSimon Glass 93817c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 93956a71f89SSimon Glass { 94056a71f89SSimon Glass struct udevice *dev = desc->dev; 94156a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 94256a71f89SSimon Glass 94356a71f89SSimon Glass if (!dev) 94456a71f89SSimon Glass return -1; 94556a71f89SSimon Glass uc_priv = dev->uclass_priv; 94656a71f89SSimon Glass 94756a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 94856a71f89SSimon Glass } 94956a71f89SSimon Glass 95054c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 95196495d90SSimon Glass { 952e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 953b892d127SSimon Glass 954b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 955b892d127SSimon Glass if (!uc_priv->name) 956b892d127SSimon Glass return -ENOMEM; 957b892d127SSimon Glass 958b892d127SSimon Glass return gpio_renumber(NULL); 95996495d90SSimon Glass } 96096495d90SSimon Glass 96154c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 96296495d90SSimon Glass { 963e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 964b892d127SSimon Glass int i; 965b892d127SSimon Glass 966b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 967b892d127SSimon Glass if (uc_priv->name[i]) 968b892d127SSimon Glass free(uc_priv->name[i]); 969b892d127SSimon Glass } 970b892d127SSimon Glass free(uc_priv->name); 971b892d127SSimon Glass 972b892d127SSimon Glass return gpio_renumber(dev); 97396495d90SSimon Glass } 97496495d90SSimon Glass 975*04c095b2SHeiko Schocher int gpio_dev_request_index(struct udevice *dev, const char *nodename, 976*04c095b2SHeiko Schocher char *list_name, int index, int flags, 977*04c095b2SHeiko Schocher int dtflags, struct gpio_desc *desc) 978*04c095b2SHeiko Schocher { 979*04c095b2SHeiko Schocher struct ofnode_phandle_args args; 980*04c095b2SHeiko Schocher 981*04c095b2SHeiko Schocher args.node = ofnode_null(); 982*04c095b2SHeiko Schocher args.args_count = 2; 983*04c095b2SHeiko Schocher args.args[0] = index; 984*04c095b2SHeiko Schocher args.args[1] = dtflags; 985*04c095b2SHeiko Schocher 986*04c095b2SHeiko Schocher return gpio_request_tail(0, nodename, &args, list_name, index, desc, 987*04c095b2SHeiko Schocher flags, 0, dev); 988*04c095b2SHeiko Schocher } 989*04c095b2SHeiko Schocher 9901b4c2aa2SMichal Simek static int gpio_post_bind(struct udevice *dev) 9911b4c2aa2SMichal Simek { 992*04c095b2SHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 993*04c095b2SHeiko Schocher struct udevice *child; 994*04c095b2SHeiko Schocher ofnode node; 995*04c095b2SHeiko Schocher #endif 996*04c095b2SHeiko Schocher 9971b4c2aa2SMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC) 9981b4c2aa2SMichal Simek struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); 9991b4c2aa2SMichal Simek static int reloc_done; 10001b4c2aa2SMichal Simek 10011b4c2aa2SMichal Simek if (!reloc_done) { 10021b4c2aa2SMichal Simek if (ops->request) 10031b4c2aa2SMichal Simek ops->request += gd->reloc_off; 10041b4c2aa2SMichal Simek if (ops->free) 10051b4c2aa2SMichal Simek ops->free += gd->reloc_off; 10061b4c2aa2SMichal Simek if (ops->direction_input) 10071b4c2aa2SMichal Simek ops->direction_input += gd->reloc_off; 10081b4c2aa2SMichal Simek if (ops->direction_output) 10091b4c2aa2SMichal Simek ops->direction_output += gd->reloc_off; 10101b4c2aa2SMichal Simek if (ops->get_value) 10111b4c2aa2SMichal Simek ops->get_value += gd->reloc_off; 10121b4c2aa2SMichal Simek if (ops->set_value) 10131b4c2aa2SMichal Simek ops->set_value += gd->reloc_off; 10141b4c2aa2SMichal Simek if (ops->get_open_drain) 10151b4c2aa2SMichal Simek ops->get_open_drain += gd->reloc_off; 10161b4c2aa2SMichal Simek if (ops->set_open_drain) 10171b4c2aa2SMichal Simek ops->set_open_drain += gd->reloc_off; 10181b4c2aa2SMichal Simek if (ops->get_function) 10191b4c2aa2SMichal Simek ops->get_function += gd->reloc_off; 10201b4c2aa2SMichal Simek if (ops->xlate) 10211b4c2aa2SMichal Simek ops->xlate += gd->reloc_off; 10221b4c2aa2SMichal Simek 10231b4c2aa2SMichal Simek reloc_done++; 10241b4c2aa2SMichal Simek } 10251b4c2aa2SMichal Simek #endif 1026*04c095b2SHeiko Schocher 1027*04c095b2SHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 1028*04c095b2SHeiko Schocher dev_for_each_subnode(node, dev) { 1029*04c095b2SHeiko Schocher if (ofnode_read_bool(node, "gpio-hog")) { 1030*04c095b2SHeiko Schocher const char *name = ofnode_get_name(node); 1031*04c095b2SHeiko Schocher 1032*04c095b2SHeiko Schocher device_bind_driver_to_node(dev, "gpio_hog", name, 1033*04c095b2SHeiko Schocher node, &child); 1034*04c095b2SHeiko Schocher } 1035*04c095b2SHeiko Schocher } 1036*04c095b2SHeiko Schocher #endif 10371b4c2aa2SMichal Simek return 0; 10381b4c2aa2SMichal Simek } 10391b4c2aa2SMichal Simek 104096495d90SSimon Glass UCLASS_DRIVER(gpio) = { 104196495d90SSimon Glass .id = UCLASS_GPIO, 104296495d90SSimon Glass .name = "gpio", 1043ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 104496495d90SSimon Glass .post_probe = gpio_post_probe, 10451b4c2aa2SMichal Simek .post_bind = gpio_post_bind, 104696495d90SSimon Glass .pre_remove = gpio_pre_remove, 104796495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 104896495d90SSimon Glass }; 1049