196495d90SSimon Glass /* 296495d90SSimon Glass * Copyright (c) 2013 Google, Inc 396495d90SSimon Glass * 496495d90SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 596495d90SSimon Glass */ 696495d90SSimon Glass 796495d90SSimon Glass #include <common.h> 896495d90SSimon Glass #include <dm.h> 9*7e044b9aSHeiko Schocher #include <dm/device-internal.h> 10*7e044b9aSHeiko Schocher #include <dm/lists.h> 11*7e044b9aSHeiko Schocher #include <dm/uclass-internal.h> 126c880b77SEric Nelson #include <dt-bindings/gpio/gpio.h> 1396495d90SSimon Glass #include <errno.h> 140dac4d51SSimon Glass #include <fdtdec.h> 15b892d127SSimon Glass #include <malloc.h> 1696495d90SSimon Glass #include <asm/gpio.h> 1784b8bf6dSMasahiro Yamada #include <linux/bug.h> 18fe1ef503SSimon Glass #include <linux/ctype.h> 1996495d90SSimon Glass 203669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 213669e0e7SSimon Glass 2296495d90SSimon Glass /** 2396495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2496495d90SSimon Glass * 2596495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2696495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2796495d90SSimon Glass * entry on success, NULL on error. 28ae7123f8SSimon Glass * 29ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 30ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 31ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 3296495d90SSimon Glass */ 33ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3496495d90SSimon Glass { 3596495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3654c5d08aSHeiko Schocher struct udevice *dev; 3796495d90SSimon Glass int ret; 3896495d90SSimon Glass 3996495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 4096495d90SSimon Glass dev; 4196495d90SSimon Glass ret = uclass_next_device(&dev)) { 42e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 4396495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4496495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 45ae7123f8SSimon Glass desc->dev = dev; 46ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 47ae7123f8SSimon Glass desc->flags = 0; 4896495d90SSimon Glass return 0; 4996495d90SSimon Glass } 5096495d90SSimon Glass } 5196495d90SSimon Glass 5296495d90SSimon Glass /* No such GPIO */ 53ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5496495d90SSimon Glass } 5596495d90SSimon Glass 5632ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5796495d90SSimon Glass { 58fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5954c5d08aSHeiko Schocher struct udevice *dev; 60fe1ef503SSimon Glass ulong offset; 61fe1ef503SSimon Glass int numeric; 6296495d90SSimon Glass int ret; 6396495d90SSimon Glass 64fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6596495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6696495d90SSimon Glass dev; 6796495d90SSimon Glass ret = uclass_next_device(&dev)) { 6896495d90SSimon Glass int len; 6996495d90SSimon Glass 70e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 71fe1ef503SSimon Glass if (numeric != -1) { 72fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 73fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 7475897910STom Rini if (offset < uc_priv->gpio_count) 75fe1ef503SSimon Glass break; 76fe1ef503SSimon Glass } 77fe1ef503SSimon Glass 7896495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7996495d90SSimon Glass 80939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 81fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 82fe1ef503SSimon Glass break; 83fe1ef503SSimon Glass } 84fe1ef503SSimon Glass } 85fe1ef503SSimon Glass 86fe1ef503SSimon Glass if (!dev) 87fe1ef503SSimon Glass return ret ? ret : -EINVAL; 88fe1ef503SSimon Glass 8932ec1598SSimon Glass desc->dev = dev; 9032ec1598SSimon Glass desc->offset = offset; 9132ec1598SSimon Glass 9232ec1598SSimon Glass return 0; 9332ec1598SSimon Glass } 9432ec1598SSimon Glass 9532ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9632ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9732ec1598SSimon Glass { 9832ec1598SSimon Glass struct gpio_desc desc; 9932ec1598SSimon Glass int ret; 10032ec1598SSimon Glass 10196495d90SSimon Glass if (devp) 10232ec1598SSimon Glass *devp = NULL; 10332ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10432ec1598SSimon Glass if (ret) 10532ec1598SSimon Glass return ret; 10632ec1598SSimon Glass 10732ec1598SSimon Glass if (devp) 10832ec1598SSimon Glass *devp = desc.dev; 10996495d90SSimon Glass if (offsetp) 11032ec1598SSimon Glass *offsetp = desc.offset; 11132ec1598SSimon Glass if (gpiop) { 11232ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 11332ec1598SSimon Glass 11432ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11532ec1598SSimon Glass } 11696495d90SSimon Glass 117fe1ef503SSimon Glass return 0; 11896495d90SSimon Glass } 11996495d90SSimon Glass 1203a57123eSSimon Glass int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, 1213a57123eSSimon Glass struct ofnode_phandle_args *args) 1226c880b77SEric Nelson { 1236c880b77SEric Nelson if (args->args_count < 1) 1246c880b77SEric Nelson return -EINVAL; 1256c880b77SEric Nelson 1266c880b77SEric Nelson desc->offset = args->args[0]; 1276c880b77SEric Nelson 1286c880b77SEric Nelson if (args->args_count < 2) 1296c880b77SEric Nelson return 0; 1306c880b77SEric Nelson 1316c880b77SEric Nelson if (args->args[1] & GPIO_ACTIVE_LOW) 1326c880b77SEric Nelson desc->flags = GPIOD_ACTIVE_LOW; 1336c880b77SEric Nelson 1346c880b77SEric Nelson return 0; 1356c880b77SEric Nelson } 1366c880b77SEric Nelson 1373669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1383a57123eSSimon Glass struct ofnode_phandle_args *args) 1390dac4d51SSimon Glass { 1400dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1410dac4d51SSimon Glass 1426c880b77SEric Nelson if (ops->xlate) 1436c880b77SEric Nelson return ops->xlate(desc->dev, desc, args); 1440dac4d51SSimon Glass else 1456c880b77SEric Nelson return gpio_xlate_offs_flags(desc->dev, desc, args); 1460dac4d51SSimon Glass } 1470dac4d51SSimon Glass 148*7e044b9aSHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 149*7e044b9aSHeiko Schocher 150*7e044b9aSHeiko Schocher struct gpio_hog_priv { 151*7e044b9aSHeiko Schocher struct gpio_desc gpiod; 152*7e044b9aSHeiko Schocher }; 153*7e044b9aSHeiko Schocher 154*7e044b9aSHeiko Schocher struct gpio_hog_data { 155*7e044b9aSHeiko Schocher int gpiod_flags; 156*7e044b9aSHeiko Schocher int value; 157*7e044b9aSHeiko Schocher u32 val[2]; 158*7e044b9aSHeiko Schocher }; 159*7e044b9aSHeiko Schocher 160*7e044b9aSHeiko Schocher static int gpio_hog_ofdata_to_platdata(struct udevice *dev) 161*7e044b9aSHeiko Schocher { 162*7e044b9aSHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 163*7e044b9aSHeiko Schocher const char *nodename; 164*7e044b9aSHeiko Schocher int ret; 165*7e044b9aSHeiko Schocher 166*7e044b9aSHeiko Schocher plat->value = 0; 167*7e044b9aSHeiko Schocher if (dev_read_bool(dev, "input")) { 168*7e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_IN; 169*7e044b9aSHeiko Schocher } else if (dev_read_bool(dev, "output-high")) { 170*7e044b9aSHeiko Schocher plat->value = 1; 171*7e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 172*7e044b9aSHeiko Schocher } else if (dev_read_bool(dev, "output-low")) { 173*7e044b9aSHeiko Schocher plat->gpiod_flags = GPIOD_IS_OUT; 174*7e044b9aSHeiko Schocher } else { 175*7e044b9aSHeiko Schocher printf("%s: missing gpio-hog state.\n", __func__); 176*7e044b9aSHeiko Schocher return -EINVAL; 177*7e044b9aSHeiko Schocher } 178*7e044b9aSHeiko Schocher ret = dev_read_u32_array(dev, "gpios", plat->val, 2); 179*7e044b9aSHeiko Schocher if (ret) { 180*7e044b9aSHeiko Schocher printf("%s: wrong gpios property, 2 values needed %d\n", 181*7e044b9aSHeiko Schocher __func__, ret); 182*7e044b9aSHeiko Schocher return ret; 183*7e044b9aSHeiko Schocher } 184*7e044b9aSHeiko Schocher nodename = dev_read_string(dev, "line-name"); 185*7e044b9aSHeiko Schocher if (!nodename) 186*7e044b9aSHeiko Schocher nodename = dev_read_name(dev); 187*7e044b9aSHeiko Schocher device_set_name(dev, nodename); 188*7e044b9aSHeiko Schocher 189*7e044b9aSHeiko Schocher return 0; 190*7e044b9aSHeiko Schocher } 191*7e044b9aSHeiko Schocher 192*7e044b9aSHeiko Schocher static int gpio_hog_probe(struct udevice *dev) 193*7e044b9aSHeiko Schocher { 194*7e044b9aSHeiko Schocher struct gpio_hog_data *plat = dev_get_platdata(dev); 195*7e044b9aSHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 196*7e044b9aSHeiko Schocher int ret; 197*7e044b9aSHeiko Schocher 198*7e044b9aSHeiko Schocher ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog", 199*7e044b9aSHeiko Schocher plat->val[0], plat->gpiod_flags, 200*7e044b9aSHeiko Schocher plat->val[1], &priv->gpiod); 201*7e044b9aSHeiko Schocher if (ret < 0) { 202*7e044b9aSHeiko Schocher debug("%s: node %s could not get gpio.\n", __func__, 203*7e044b9aSHeiko Schocher dev->name); 204*7e044b9aSHeiko Schocher return ret; 205*7e044b9aSHeiko Schocher } 206*7e044b9aSHeiko Schocher dm_gpio_set_dir(&priv->gpiod); 207*7e044b9aSHeiko Schocher if (plat->gpiod_flags == GPIOD_IS_OUT) 208*7e044b9aSHeiko Schocher dm_gpio_set_value(&priv->gpiod, plat->value); 209*7e044b9aSHeiko Schocher 210*7e044b9aSHeiko Schocher return 0; 211*7e044b9aSHeiko Schocher } 212*7e044b9aSHeiko Schocher 213*7e044b9aSHeiko Schocher int gpio_hog_probe_all(void) 214*7e044b9aSHeiko Schocher { 215*7e044b9aSHeiko Schocher struct udevice *dev; 216*7e044b9aSHeiko Schocher int ret; 217*7e044b9aSHeiko Schocher 218*7e044b9aSHeiko Schocher for (uclass_find_first_device(UCLASS_NOP, &dev); 219*7e044b9aSHeiko Schocher dev; 220*7e044b9aSHeiko Schocher uclass_find_next_device(&dev)) { 221*7e044b9aSHeiko Schocher if (dev->driver == DM_GET_DRIVER(gpio_hog)) { 222*7e044b9aSHeiko Schocher ret = device_probe(dev); 223*7e044b9aSHeiko Schocher if (ret) 224*7e044b9aSHeiko Schocher return ret; 225*7e044b9aSHeiko Schocher } 226*7e044b9aSHeiko Schocher } 227*7e044b9aSHeiko Schocher 228*7e044b9aSHeiko Schocher return 0; 229*7e044b9aSHeiko Schocher } 230*7e044b9aSHeiko Schocher 231*7e044b9aSHeiko Schocher struct gpio_desc *gpio_hog_lookup_name(const char *name) 232*7e044b9aSHeiko Schocher { 233*7e044b9aSHeiko Schocher struct udevice *dev; 234*7e044b9aSHeiko Schocher 235*7e044b9aSHeiko Schocher gpio_hog_probe_all(); 236*7e044b9aSHeiko Schocher if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { 237*7e044b9aSHeiko Schocher struct gpio_hog_priv *priv = dev_get_priv(dev); 238*7e044b9aSHeiko Schocher 239*7e044b9aSHeiko Schocher return &priv->gpiod; 240*7e044b9aSHeiko Schocher } 241*7e044b9aSHeiko Schocher 242*7e044b9aSHeiko Schocher return NULL; 243*7e044b9aSHeiko Schocher } 244*7e044b9aSHeiko Schocher 245*7e044b9aSHeiko Schocher U_BOOT_DRIVER(gpio_hog) = { 246*7e044b9aSHeiko Schocher .name = "gpio_hog", 247*7e044b9aSHeiko Schocher .id = UCLASS_NOP, 248*7e044b9aSHeiko Schocher .ofdata_to_platdata = gpio_hog_ofdata_to_platdata, 249*7e044b9aSHeiko Schocher .probe = gpio_hog_probe, 250*7e044b9aSHeiko Schocher .priv_auto_alloc_size = sizeof(struct gpio_hog_priv), 251*7e044b9aSHeiko Schocher .platdata_auto_alloc_size = sizeof(struct gpio_hog_data), 252*7e044b9aSHeiko Schocher }; 253*7e044b9aSHeiko Schocher #else 254*7e044b9aSHeiko Schocher struct gpio_desc *gpio_hog_lookup_name(const char *name) 255*7e044b9aSHeiko Schocher { 256*7e044b9aSHeiko Schocher return NULL; 257*7e044b9aSHeiko Schocher } 258*7e044b9aSHeiko Schocher #endif 259*7e044b9aSHeiko Schocher 260efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 261ae7123f8SSimon Glass { 262ae7123f8SSimon Glass struct udevice *dev = desc->dev; 263ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 264ae7123f8SSimon Glass char *str; 265ae7123f8SSimon Glass int ret; 266ae7123f8SSimon Glass 267e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 268ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 269ae7123f8SSimon Glass return -EBUSY; 270ae7123f8SSimon Glass str = strdup(label); 271ae7123f8SSimon Glass if (!str) 272ae7123f8SSimon Glass return -ENOMEM; 273ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 274ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 275ae7123f8SSimon Glass if (ret) { 276ae7123f8SSimon Glass free(str); 277ae7123f8SSimon Glass return ret; 278ae7123f8SSimon Glass } 279ae7123f8SSimon Glass } 280ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 281ae7123f8SSimon Glass 282ae7123f8SSimon Glass return 0; 283ae7123f8SSimon Glass } 284ae7123f8SSimon Glass 2853669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 2863669e0e7SSimon Glass { 2874dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 2883669e0e7SSimon Glass va_list args; 2893669e0e7SSimon Glass char buf[40]; 2903669e0e7SSimon Glass 2913669e0e7SSimon Glass va_start(args, fmt); 2923669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 2933669e0e7SSimon Glass va_end(args); 2943669e0e7SSimon Glass return dm_gpio_request(desc, buf); 2954dc5259aSSimon Glass #else 2964dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 2974dc5259aSSimon Glass #endif 2983669e0e7SSimon Glass } 2993669e0e7SSimon Glass 30096495d90SSimon Glass /** 30196495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 30296495d90SSimon Glass * gpio: GPIO number 30396495d90SSimon Glass * label: Name for the requested GPIO 30496495d90SSimon Glass * 305b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 306b892d127SSimon Glass * the pointer around. 307b892d127SSimon Glass * 30896495d90SSimon Glass * This function implements the API that's compatible with current 30996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 31096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 31196495d90SSimon Glass */ 31296495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 31396495d90SSimon Glass { 314ae7123f8SSimon Glass struct gpio_desc desc; 31596495d90SSimon Glass int ret; 31696495d90SSimon Glass 317ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 31896495d90SSimon Glass if (ret) 31996495d90SSimon Glass return ret; 32096495d90SSimon Glass 321ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 32296495d90SSimon Glass } 32396495d90SSimon Glass 32496495d90SSimon Glass /** 325d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 326d44f597bSSimon Glass * @gpio: GPIO number 327d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 328d44f597bSSimon Glass * @...: Arguments for the printf() format string 329d44f597bSSimon Glass * 330d44f597bSSimon Glass * This function implements the API that's compatible with current 331d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 332d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 333d44f597bSSimon Glass */ 334d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 335d44f597bSSimon Glass { 3364dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 337d44f597bSSimon Glass va_list args; 338d44f597bSSimon Glass char buf[40]; 339d44f597bSSimon Glass 340d44f597bSSimon Glass va_start(args, fmt); 341d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 342d44f597bSSimon Glass va_end(args); 343d44f597bSSimon Glass return gpio_request(gpio, buf); 3444dc5259aSSimon Glass #else 3454dc5259aSSimon Glass return gpio_request(gpio, fmt); 3464dc5259aSSimon Glass #endif 347d44f597bSSimon Glass } 348d44f597bSSimon Glass 349ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 35096495d90SSimon Glass { 351b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 35296495d90SSimon Glass int ret; 35396495d90SSimon Glass 354e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 355b892d127SSimon Glass if (!uc_priv->name[offset]) 356b892d127SSimon Glass return -ENXIO; 357b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 358b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 359b892d127SSimon Glass if (ret) 360b892d127SSimon Glass return ret; 361b892d127SSimon Glass } 362b892d127SSimon Glass 363b892d127SSimon Glass free(uc_priv->name[offset]); 364b892d127SSimon Glass uc_priv->name[offset] = NULL; 365b892d127SSimon Glass 36696495d90SSimon Glass return 0; 367b892d127SSimon Glass } 368b892d127SSimon Glass 369ae7123f8SSimon Glass /** 370ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 371ae7123f8SSimon Glass * gpio: GPIO number 372ae7123f8SSimon Glass * 373ae7123f8SSimon Glass * This function implements the API that's compatible with current 374ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 375ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 376ae7123f8SSimon Glass */ 377ae7123f8SSimon Glass int gpio_free(unsigned gpio) 378b892d127SSimon Glass { 379ae7123f8SSimon Glass struct gpio_desc desc; 380ae7123f8SSimon Glass int ret; 381b892d127SSimon Glass 382ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 383ae7123f8SSimon Glass if (ret) 384ae7123f8SSimon Glass return ret; 385ae7123f8SSimon Glass 386ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 387ae7123f8SSimon Glass } 388ae7123f8SSimon Glass 38917c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 390ae7123f8SSimon Glass { 391eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 392ae7123f8SSimon Glass 393eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 394eca48665SSimon Glass return -ENOENT; 395eca48665SSimon Glass 396eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 397ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 398b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 399ae7123f8SSimon Glass desc->dev->name, func, 400ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 401ae7123f8SSimon Glass desc->offset); 402b892d127SSimon Glass return -EBUSY; 403b892d127SSimon Glass } 404b892d127SSimon Glass 405b892d127SSimon Glass return 0; 40696495d90SSimon Glass } 40796495d90SSimon Glass 40896495d90SSimon Glass /** 40996495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 41096495d90SSimon Glass * gpio: GPIO number 41196495d90SSimon Glass * 41296495d90SSimon Glass * This function implements the API that's compatible with current 41396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 41496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 41596495d90SSimon Glass */ 41696495d90SSimon Glass int gpio_direction_input(unsigned gpio) 41796495d90SSimon Glass { 418ae7123f8SSimon Glass struct gpio_desc desc; 41996495d90SSimon Glass int ret; 42096495d90SSimon Glass 421ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 42296495d90SSimon Glass if (ret) 42396495d90SSimon Glass return ret; 424ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 425ae7123f8SSimon Glass if (ret) 426ae7123f8SSimon Glass return ret; 42796495d90SSimon Glass 428ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 42996495d90SSimon Glass } 43096495d90SSimon Glass 43196495d90SSimon Glass /** 43296495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 43396495d90SSimon Glass * gpio: GPIO number 43496495d90SSimon Glass * value: Logical value to be set on the GPIO pin 43596495d90SSimon Glass * 43696495d90SSimon Glass * This function implements the API that's compatible with current 43796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 43896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 43996495d90SSimon Glass */ 44096495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 44196495d90SSimon Glass { 442ae7123f8SSimon Glass struct gpio_desc desc; 44396495d90SSimon Glass int ret; 44496495d90SSimon Glass 445ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 44696495d90SSimon Glass if (ret) 44796495d90SSimon Glass return ret; 448ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 449ae7123f8SSimon Glass if (ret) 450ae7123f8SSimon Glass return ret; 45196495d90SSimon Glass 452ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 453ae7123f8SSimon Glass desc.offset, value); 454ae7123f8SSimon Glass } 455ae7123f8SSimon Glass 45617c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 457ae7123f8SSimon Glass { 458ae7123f8SSimon Glass int value; 459ae7123f8SSimon Glass int ret; 460ae7123f8SSimon Glass 461ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 462ae7123f8SSimon Glass if (ret) 463ae7123f8SSimon Glass return ret; 464ae7123f8SSimon Glass 465ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 466ae7123f8SSimon Glass 467ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 468ae7123f8SSimon Glass } 469ae7123f8SSimon Glass 47017c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 471ae7123f8SSimon Glass { 472ae7123f8SSimon Glass int ret; 473ae7123f8SSimon Glass 474ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 475ae7123f8SSimon Glass if (ret) 476ae7123f8SSimon Glass return ret; 477ae7123f8SSimon Glass 478ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 479ae7123f8SSimon Glass value = !value; 480ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 481ae7123f8SSimon Glass return 0; 482ae7123f8SSimon Glass } 483ae7123f8SSimon Glass 48453ecdfb9Smario.six@gdsys.cc int dm_gpio_get_open_drain(struct gpio_desc *desc) 48553ecdfb9Smario.six@gdsys.cc { 48653ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 48753ecdfb9Smario.six@gdsys.cc int ret; 48853ecdfb9Smario.six@gdsys.cc 48953ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "get_open_drain"); 49053ecdfb9Smario.six@gdsys.cc if (ret) 49153ecdfb9Smario.six@gdsys.cc return ret; 49253ecdfb9Smario.six@gdsys.cc 49353ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 49453ecdfb9Smario.six@gdsys.cc return ops->get_open_drain(desc->dev, desc->offset); 49553ecdfb9Smario.six@gdsys.cc else 49653ecdfb9Smario.six@gdsys.cc return -ENOSYS; 49753ecdfb9Smario.six@gdsys.cc } 49853ecdfb9Smario.six@gdsys.cc 49953ecdfb9Smario.six@gdsys.cc int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) 50053ecdfb9Smario.six@gdsys.cc { 50153ecdfb9Smario.six@gdsys.cc struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 50253ecdfb9Smario.six@gdsys.cc int ret; 50353ecdfb9Smario.six@gdsys.cc 50453ecdfb9Smario.six@gdsys.cc ret = check_reserved(desc, "set_open_drain"); 50553ecdfb9Smario.six@gdsys.cc if (ret) 50653ecdfb9Smario.six@gdsys.cc return ret; 50753ecdfb9Smario.six@gdsys.cc 50853ecdfb9Smario.six@gdsys.cc if (ops->set_open_drain) 50953ecdfb9Smario.six@gdsys.cc ret = ops->set_open_drain(desc->dev, desc->offset, value); 51053ecdfb9Smario.six@gdsys.cc else 51153ecdfb9Smario.six@gdsys.cc return 0; /* feature not supported -> ignore setting */ 51253ecdfb9Smario.six@gdsys.cc 51353ecdfb9Smario.six@gdsys.cc return ret; 51453ecdfb9Smario.six@gdsys.cc } 51553ecdfb9Smario.six@gdsys.cc 516ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 517ae7123f8SSimon Glass { 518ae7123f8SSimon Glass struct udevice *dev = desc->dev; 519ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 520ae7123f8SSimon Glass int ret; 521ae7123f8SSimon Glass 522ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 523ae7123f8SSimon Glass if (ret) 524ae7123f8SSimon Glass return ret; 525ae7123f8SSimon Glass 526ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 527ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 528ae7123f8SSimon Glass 529ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 530ae7123f8SSimon Glass value = !value; 531ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 532ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 533ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 534ae7123f8SSimon Glass } 535ae7123f8SSimon Glass if (ret) 536ae7123f8SSimon Glass return ret; 537ae7123f8SSimon Glass /* 538ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 539ae7123f8SSimon Glass * futures 540ae7123f8SSimon Glass */ 541ae7123f8SSimon Glass desc->flags = flags; 542ae7123f8SSimon Glass 543ae7123f8SSimon Glass return 0; 544ae7123f8SSimon Glass } 545ae7123f8SSimon Glass 546ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 547ae7123f8SSimon Glass { 548ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 54996495d90SSimon Glass } 55096495d90SSimon Glass 55196495d90SSimon Glass /** 55296495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 55396495d90SSimon Glass * gpio: GPIO number 55496495d90SSimon Glass * 55596495d90SSimon Glass * This function implements the API that's compatible with current 55696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 55796495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 55896495d90SSimon Glass * on error. 55996495d90SSimon Glass */ 56096495d90SSimon Glass int gpio_get_value(unsigned gpio) 56196495d90SSimon Glass { 56296495d90SSimon Glass int ret; 56396495d90SSimon Glass 564ae7123f8SSimon Glass struct gpio_desc desc; 565ae7123f8SSimon Glass 566ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 56796495d90SSimon Glass if (ret) 56896495d90SSimon Glass return ret; 569ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 57096495d90SSimon Glass } 57196495d90SSimon Glass 57296495d90SSimon Glass /** 57396495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 57496495d90SSimon Glass * gpio: GPIO number 57596495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 57696495d90SSimon Glass * 57796495d90SSimon Glass * This function implements the API that's compatible with current 57896495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 57996495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 58096495d90SSimon Glass */ 58196495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 58296495d90SSimon Glass { 583ae7123f8SSimon Glass struct gpio_desc desc; 58496495d90SSimon Glass int ret; 58596495d90SSimon Glass 586ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 58796495d90SSimon Glass if (ret) 58896495d90SSimon Glass return ret; 589ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 59096495d90SSimon Glass } 59196495d90SSimon Glass 59254c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 59396495d90SSimon Glass { 59496495d90SSimon Glass struct gpio_dev_priv *priv; 59596495d90SSimon Glass 59696495d90SSimon Glass /* Must be called on an active device */ 597e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 59896495d90SSimon Glass assert(priv); 59996495d90SSimon Glass 60096495d90SSimon Glass *bit_count = priv->gpio_count; 60196495d90SSimon Glass return priv->bank_name; 60296495d90SSimon Glass } 60396495d90SSimon Glass 6046449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 6056449a506SSimon Glass "input", 6066449a506SSimon Glass "output", 6076449a506SSimon Glass "unused", 6086449a506SSimon Glass "unknown", 6096449a506SSimon Glass "func", 6106449a506SSimon Glass }; 6116449a506SSimon Glass 612fb07f97dSMasahiro Yamada static int get_function(struct udevice *dev, int offset, bool skip_unused, 6136449a506SSimon Glass const char **namep) 6146449a506SSimon Glass { 615e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 6166449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6176449a506SSimon Glass 6186449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6196449a506SSimon Glass if (!device_active(dev)) 6206449a506SSimon Glass return -ENODEV; 6216449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 6226449a506SSimon Glass return -EINVAL; 6236449a506SSimon Glass if (namep) 6246449a506SSimon Glass *namep = uc_priv->name[offset]; 6256449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 6266449a506SSimon Glass return GPIOF_UNUSED; 6276449a506SSimon Glass if (ops->get_function) { 6286449a506SSimon Glass int ret; 6296449a506SSimon Glass 6306449a506SSimon Glass ret = ops->get_function(dev, offset); 6316449a506SSimon Glass if (ret < 0) 6326449a506SSimon Glass return ret; 6336449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 6346449a506SSimon Glass return -ENODATA; 6356449a506SSimon Glass return ret; 6366449a506SSimon Glass } 6376449a506SSimon Glass 6386449a506SSimon Glass return GPIOF_UNKNOWN; 6396449a506SSimon Glass } 6406449a506SSimon Glass 6416449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 6426449a506SSimon Glass { 6436449a506SSimon Glass return get_function(dev, offset, true, namep); 6446449a506SSimon Glass } 6456449a506SSimon Glass 6466449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 6476449a506SSimon Glass { 6486449a506SSimon Glass return get_function(dev, offset, false, namep); 6496449a506SSimon Glass } 6506449a506SSimon Glass 6510757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 6520757535aSSimon Glass { 6530757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 6540757535aSSimon Glass struct gpio_dev_priv *priv; 6550757535aSSimon Glass char *str = buf; 6560757535aSSimon Glass int func; 6570757535aSSimon Glass int ret; 6580757535aSSimon Glass int len; 6590757535aSSimon Glass 6600757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 6610757535aSSimon Glass 6620757535aSSimon Glass *buf = 0; 663e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 6640757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 6650757535aSSimon Glass if (ret < 0) 6660757535aSSimon Glass return ret; 6670757535aSSimon Glass func = ret; 6680757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 6690757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 6700757535aSSimon Glass offset, gpio_function[func]); 6710757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 6720757535aSSimon Glass func == GPIOF_UNUSED) { 6730757535aSSimon Glass const char *label; 6740757535aSSimon Glass bool used; 6750757535aSSimon Glass 6760757535aSSimon Glass ret = ops->get_value(dev, offset); 6770757535aSSimon Glass if (ret < 0) 6780757535aSSimon Glass return ret; 6790757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 6800757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 6810757535aSSimon Glass ret, 6820757535aSSimon Glass used ? 'x' : ' ', 6830757535aSSimon Glass used ? " " : "", 6840757535aSSimon Glass label ? label : ""); 6850757535aSSimon Glass } 6860757535aSSimon Glass 6870757535aSSimon Glass return 0; 6880757535aSSimon Glass } 6890757535aSSimon Glass 690962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 691962f5cafSSimon Glass { 692962f5cafSSimon Glass int i, ret; 693962f5cafSSimon Glass int gpio; 694962f5cafSSimon Glass 695962f5cafSSimon Glass for (i = 0; i < 32; i++) { 696962f5cafSSimon Glass gpio = gpio_num_array[i]; 697962f5cafSSimon Glass if (gpio == -1) 698962f5cafSSimon Glass break; 699962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 700962f5cafSSimon Glass if (ret) 701962f5cafSSimon Glass goto err; 702962f5cafSSimon Glass ret = gpio_direction_input(gpio); 703962f5cafSSimon Glass if (ret) { 704962f5cafSSimon Glass gpio_free(gpio); 705962f5cafSSimon Glass goto err; 706962f5cafSSimon Glass } 707962f5cafSSimon Glass } 708962f5cafSSimon Glass 709962f5cafSSimon Glass return 0; 710962f5cafSSimon Glass err: 711962f5cafSSimon Glass for (i--; i >= 0; i--) 712962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 713962f5cafSSimon Glass 714962f5cafSSimon Glass return ret; 715962f5cafSSimon Glass } 716962f5cafSSimon Glass 717e5901c94SSimon Glass /* 718e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 719e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 720e5901c94SSimon Glass */ 721962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 722e5901c94SSimon Glass { 723e5901c94SSimon Glass int gpio; 724e5901c94SSimon Glass unsigned bitmask = 1; 725e5901c94SSimon Glass unsigned vector = 0; 726962f5cafSSimon Glass int ret; 727e5901c94SSimon Glass 728e5901c94SSimon Glass while (bitmask && 729962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 730962f5cafSSimon Glass ret = gpio_get_value(gpio); 731962f5cafSSimon Glass if (ret < 0) 732962f5cafSSimon Glass return ret; 733962f5cafSSimon Glass else if (ret) 734e5901c94SSimon Glass vector |= bitmask; 735e5901c94SSimon Glass bitmask <<= 1; 736e5901c94SSimon Glass } 737962f5cafSSimon Glass 738e5901c94SSimon Glass return vector; 739e5901c94SSimon Glass } 740e5901c94SSimon Glass 74117c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 742bbf24780SSimon Glass { 743bbf24780SSimon Glass unsigned bitmask = 1; 744bbf24780SSimon Glass unsigned vector = 0; 745bbf24780SSimon Glass int ret, i; 746bbf24780SSimon Glass 747bbf24780SSimon Glass for (i = 0; i < count; i++) { 748bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 749bbf24780SSimon Glass if (ret < 0) 750bbf24780SSimon Glass return ret; 751bbf24780SSimon Glass else if (ret) 752bbf24780SSimon Glass vector |= bitmask; 753bbf24780SSimon Glass bitmask <<= 1; 754bbf24780SSimon Glass } 755bbf24780SSimon Glass 756bbf24780SSimon Glass return vector; 757bbf24780SSimon Glass } 758bbf24780SSimon Glass 759*7e044b9aSHeiko Schocher static int gpio_request_tail(int ret, const char *nodename, 7603a57123eSSimon Glass struct ofnode_phandle_args *args, 7613669e0e7SSimon Glass const char *list_name, int index, 762*7e044b9aSHeiko Schocher struct gpio_desc *desc, int flags, 763*7e044b9aSHeiko Schocher bool add_index, struct udevice *dev) 7643669e0e7SSimon Glass { 765*7e044b9aSHeiko Schocher desc->dev = dev; 7663669e0e7SSimon Glass desc->offset = 0; 7676c880b77SEric Nelson desc->flags = 0; 7683a57123eSSimon Glass if (ret) 7693669e0e7SSimon Glass goto err; 7703669e0e7SSimon Glass 771*7e044b9aSHeiko Schocher if (!desc->dev) { 7723a57123eSSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, 7733669e0e7SSimon Glass &desc->dev); 7743669e0e7SSimon Glass if (ret) { 775*7e044b9aSHeiko Schocher debug("%s: uclass_get_device_by_ofnode failed\n", __func__); 7763669e0e7SSimon Glass goto err; 7773669e0e7SSimon Glass } 778*7e044b9aSHeiko Schocher } 7793a57123eSSimon Glass ret = gpio_find_and_xlate(desc, args); 7803669e0e7SSimon Glass if (ret) { 7813669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 7823669e0e7SSimon Glass goto err; 7833669e0e7SSimon Glass } 7843669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 785*7e044b9aSHeiko Schocher nodename, list_name, index); 7863669e0e7SSimon Glass if (ret) { 7873669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 7883669e0e7SSimon Glass goto err; 7893669e0e7SSimon Glass } 7903669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 7913669e0e7SSimon Glass if (ret) { 7923669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 7933669e0e7SSimon Glass goto err; 7943669e0e7SSimon Glass } 7953669e0e7SSimon Glass 7963669e0e7SSimon Glass return 0; 7973669e0e7SSimon Glass err: 7983669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 799*7e044b9aSHeiko Schocher __func__, nodename, list_name, index, ret); 8003669e0e7SSimon Glass return ret; 8013669e0e7SSimon Glass } 8023669e0e7SSimon Glass 803150c5afeSSimon Glass static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, 804150c5afeSSimon Glass int index, struct gpio_desc *desc, 805150c5afeSSimon Glass int flags, bool add_index) 8063a57123eSSimon Glass { 8073a57123eSSimon Glass struct ofnode_phandle_args args; 8083a57123eSSimon Glass int ret; 8093a57123eSSimon Glass 810150c5afeSSimon Glass ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0, 811150c5afeSSimon Glass index, &args); 8123a57123eSSimon Glass 813*7e044b9aSHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 814*7e044b9aSHeiko Schocher index, desc, flags, add_index, NULL); 8153a57123eSSimon Glass } 8163a57123eSSimon Glass 817150c5afeSSimon Glass int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, 8183669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8193669e0e7SSimon Glass { 820150c5afeSSimon Glass return _gpio_request_by_name_nodev(node, list_name, index, desc, flags, 821150c5afeSSimon Glass index > 0); 8223669e0e7SSimon Glass } 8233669e0e7SSimon Glass 8243669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 8253669e0e7SSimon Glass struct gpio_desc *desc, int flags) 8263669e0e7SSimon Glass { 827150c5afeSSimon Glass struct ofnode_phandle_args args; 828*7e044b9aSHeiko Schocher ofnode node; 829150c5afeSSimon Glass int ret; 830150c5afeSSimon Glass 831150c5afeSSimon Glass ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, 832150c5afeSSimon Glass index, &args); 833*7e044b9aSHeiko Schocher node = dev_ofnode(dev); 834*7e044b9aSHeiko Schocher return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name, 835*7e044b9aSHeiko Schocher index, desc, flags, index > 0, NULL); 8363669e0e7SSimon Glass } 8373669e0e7SSimon Glass 838150c5afeSSimon Glass int gpio_request_list_by_name_nodev(ofnode node, const char *list_name, 8393669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8403669e0e7SSimon Glass int flags) 8413669e0e7SSimon Glass { 8423669e0e7SSimon Glass int count; 8433669e0e7SSimon Glass int ret; 8443669e0e7SSimon Glass 8452984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 846150c5afeSSimon Glass ret = _gpio_request_by_name_nodev(node, list_name, count, 8473669e0e7SSimon Glass &desc[count], flags, true); 8483669e0e7SSimon Glass if (ret == -ENOENT) 8493669e0e7SSimon Glass break; 8503669e0e7SSimon Glass else if (ret) 8513669e0e7SSimon Glass goto err; 8523669e0e7SSimon Glass } 8533669e0e7SSimon Glass 8543669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 8553669e0e7SSimon Glass return count; 8563669e0e7SSimon Glass 8573669e0e7SSimon Glass err: 8583669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 8593669e0e7SSimon Glass 8603669e0e7SSimon Glass return ret; 8613669e0e7SSimon Glass } 8623669e0e7SSimon Glass 8633669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 8643669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 8653669e0e7SSimon Glass int flags) 8663669e0e7SSimon Glass { 8673669e0e7SSimon Glass /* 8683669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 8693669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 8703669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 8713669e0e7SSimon Glass */ 872150c5afeSSimon Glass return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc, 873150c5afeSSimon Glass max_count, flags); 8743669e0e7SSimon Glass } 8753669e0e7SSimon Glass 8763669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 8773669e0e7SSimon Glass { 8783669e0e7SSimon Glass int ret; 8793669e0e7SSimon Glass 880e160f7d4SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 8813669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 8823669e0e7SSimon Glass NULL); 8833669e0e7SSimon Glass if (ret) { 8843669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 8853669e0e7SSimon Glass __func__, dev->name, list_name, ret); 8863669e0e7SSimon Glass } 8873669e0e7SSimon Glass 8883669e0e7SSimon Glass return ret; 8893669e0e7SSimon Glass } 8903669e0e7SSimon Glass 8913669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 8923669e0e7SSimon Glass { 8933669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 8943669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 8953669e0e7SSimon Glass } 8963669e0e7SSimon Glass 8973669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 8983669e0e7SSimon Glass { 8993669e0e7SSimon Glass int i; 9003669e0e7SSimon Glass 9013669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 9023669e0e7SSimon Glass for (i = 0; i < count; i++) 9033669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 9043669e0e7SSimon Glass 9053669e0e7SSimon Glass return 0; 9063669e0e7SSimon Glass } 9073669e0e7SSimon Glass 9083669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 9093669e0e7SSimon Glass { 9103669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 9113669e0e7SSimon Glass } 9123669e0e7SSimon Glass 91396495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 914b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 91596495d90SSimon Glass { 91696495d90SSimon Glass struct gpio_dev_priv *uc_priv; 91754c5d08aSHeiko Schocher struct udevice *dev; 91896495d90SSimon Glass struct uclass *uc; 91996495d90SSimon Glass unsigned base; 92096495d90SSimon Glass int ret; 92196495d90SSimon Glass 92296495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 92396495d90SSimon Glass if (ret) 92496495d90SSimon Glass return ret; 92596495d90SSimon Glass 92696495d90SSimon Glass /* Ensure that we have a base for each bank */ 92796495d90SSimon Glass base = 0; 92896495d90SSimon Glass uclass_foreach_dev(dev, uc) { 929b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 930e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 93196495d90SSimon Glass uc_priv->gpio_base = base; 93296495d90SSimon Glass base += uc_priv->gpio_count; 93396495d90SSimon Glass } 93496495d90SSimon Glass } 93596495d90SSimon Glass 93696495d90SSimon Glass return 0; 93796495d90SSimon Glass } 93896495d90SSimon Glass 93917c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 94056a71f89SSimon Glass { 94156a71f89SSimon Glass struct udevice *dev = desc->dev; 94256a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 94356a71f89SSimon Glass 94456a71f89SSimon Glass if (!dev) 94556a71f89SSimon Glass return -1; 94656a71f89SSimon Glass uc_priv = dev->uclass_priv; 94756a71f89SSimon Glass 94856a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 94956a71f89SSimon Glass } 95056a71f89SSimon Glass 95154c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 95296495d90SSimon Glass { 953e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 954b892d127SSimon Glass 955b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 956b892d127SSimon Glass if (!uc_priv->name) 957b892d127SSimon Glass return -ENOMEM; 958b892d127SSimon Glass 959b892d127SSimon Glass return gpio_renumber(NULL); 96096495d90SSimon Glass } 96196495d90SSimon Glass 96254c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 96396495d90SSimon Glass { 964e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 965b892d127SSimon Glass int i; 966b892d127SSimon Glass 967b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 968b892d127SSimon Glass if (uc_priv->name[i]) 969b892d127SSimon Glass free(uc_priv->name[i]); 970b892d127SSimon Glass } 971b892d127SSimon Glass free(uc_priv->name); 972b892d127SSimon Glass 973b892d127SSimon Glass return gpio_renumber(dev); 97496495d90SSimon Glass } 97596495d90SSimon Glass 976*7e044b9aSHeiko Schocher int gpio_dev_request_index(struct udevice *dev, const char *nodename, 977*7e044b9aSHeiko Schocher char *list_name, int index, int flags, 978*7e044b9aSHeiko Schocher int dtflags, struct gpio_desc *desc) 979*7e044b9aSHeiko Schocher { 980*7e044b9aSHeiko Schocher struct ofnode_phandle_args args; 981*7e044b9aSHeiko Schocher 982*7e044b9aSHeiko Schocher args.node = ofnode_null(); 983*7e044b9aSHeiko Schocher args.args_count = 2; 984*7e044b9aSHeiko Schocher args.args[0] = index; 985*7e044b9aSHeiko Schocher args.args[1] = dtflags; 986*7e044b9aSHeiko Schocher 987*7e044b9aSHeiko Schocher return gpio_request_tail(0, nodename, &args, list_name, index, desc, 988*7e044b9aSHeiko Schocher flags, 0, dev); 989*7e044b9aSHeiko Schocher } 990*7e044b9aSHeiko Schocher 991*7e044b9aSHeiko Schocher static int gpio_post_bind(struct udevice *dev) 992*7e044b9aSHeiko Schocher { 993*7e044b9aSHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 994*7e044b9aSHeiko Schocher struct udevice *child; 995*7e044b9aSHeiko Schocher ofnode node; 996*7e044b9aSHeiko Schocher #endif 997*7e044b9aSHeiko Schocher 998*7e044b9aSHeiko Schocher #if defined(CONFIG_DM_GPIO_HOG) 999*7e044b9aSHeiko Schocher dev_for_each_subnode(node, dev) { 1000*7e044b9aSHeiko Schocher if (ofnode_read_bool(node, "gpio-hog")) { 1001*7e044b9aSHeiko Schocher const char *name = ofnode_get_name(node); 1002*7e044b9aSHeiko Schocher 1003*7e044b9aSHeiko Schocher device_bind_driver_to_node(dev, "gpio_hog", name, 1004*7e044b9aSHeiko Schocher node, &child); 1005*7e044b9aSHeiko Schocher } 1006*7e044b9aSHeiko Schocher } 1007*7e044b9aSHeiko Schocher #endif 1008*7e044b9aSHeiko Schocher return 0; 1009*7e044b9aSHeiko Schocher } 1010*7e044b9aSHeiko Schocher 101196495d90SSimon Glass UCLASS_DRIVER(gpio) = { 101296495d90SSimon Glass .id = UCLASS_GPIO, 101396495d90SSimon Glass .name = "gpio", 1014ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 101596495d90SSimon Glass .post_probe = gpio_post_probe, 1016*7e044b9aSHeiko Schocher .post_bind = gpio_post_bind, 101796495d90SSimon Glass .pre_remove = gpio_pre_remove, 101896495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 101996495d90SSimon Glass }; 1020