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*6c880b77SEric Nelson #include <dt-bindings/gpio/gpio.h> 1096495d90SSimon Glass #include <errno.h> 110dac4d51SSimon Glass #include <fdtdec.h> 12b892d127SSimon Glass #include <malloc.h> 1396495d90SSimon Glass #include <asm/gpio.h> 1484b8bf6dSMasahiro Yamada #include <linux/bug.h> 15fe1ef503SSimon Glass #include <linux/ctype.h> 1696495d90SSimon Glass 173669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 183669e0e7SSimon Glass 1996495d90SSimon Glass /** 2096495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2196495d90SSimon Glass * 2296495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2396495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2496495d90SSimon Glass * entry on success, NULL on error. 25ae7123f8SSimon Glass * 26ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 27ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 28ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 2996495d90SSimon Glass */ 30ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3196495d90SSimon Glass { 3296495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3354c5d08aSHeiko Schocher struct udevice *dev; 3496495d90SSimon Glass int ret; 3596495d90SSimon Glass 3696495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3796495d90SSimon Glass dev; 3896495d90SSimon Glass ret = uclass_next_device(&dev)) { 39e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 4096495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4196495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 42ae7123f8SSimon Glass desc->dev = dev; 43ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 44ae7123f8SSimon Glass desc->flags = 0; 4596495d90SSimon Glass return 0; 4696495d90SSimon Glass } 4796495d90SSimon Glass } 4896495d90SSimon Glass 4996495d90SSimon Glass /* No such GPIO */ 50ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5196495d90SSimon Glass } 5296495d90SSimon Glass 5332ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5496495d90SSimon Glass { 55fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5654c5d08aSHeiko Schocher struct udevice *dev; 57fe1ef503SSimon Glass ulong offset; 58fe1ef503SSimon Glass int numeric; 5996495d90SSimon Glass int ret; 6096495d90SSimon Glass 61fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6296495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6396495d90SSimon Glass dev; 6496495d90SSimon Glass ret = uclass_next_device(&dev)) { 6596495d90SSimon Glass int len; 6696495d90SSimon Glass 67e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 68fe1ef503SSimon Glass if (numeric != -1) { 69fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 70fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 71fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 72fe1ef503SSimon Glass break; 73fe1ef503SSimon Glass } 74fe1ef503SSimon Glass 7596495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7696495d90SSimon Glass 77939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 78fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 79fe1ef503SSimon Glass break; 80fe1ef503SSimon Glass } 81fe1ef503SSimon Glass } 82fe1ef503SSimon Glass 83fe1ef503SSimon Glass if (!dev) 84fe1ef503SSimon Glass return ret ? ret : -EINVAL; 85fe1ef503SSimon Glass 8632ec1598SSimon Glass desc->dev = dev; 8732ec1598SSimon Glass desc->offset = offset; 8832ec1598SSimon Glass 8932ec1598SSimon Glass return 0; 9032ec1598SSimon Glass } 9132ec1598SSimon Glass 9232ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9332ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9432ec1598SSimon Glass { 9532ec1598SSimon Glass struct gpio_desc desc; 9632ec1598SSimon Glass int ret; 9732ec1598SSimon Glass 9896495d90SSimon Glass if (devp) 9932ec1598SSimon Glass *devp = NULL; 10032ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10132ec1598SSimon Glass if (ret) 10232ec1598SSimon Glass return ret; 10332ec1598SSimon Glass 10432ec1598SSimon Glass if (devp) 10532ec1598SSimon Glass *devp = desc.dev; 10696495d90SSimon Glass if (offsetp) 10732ec1598SSimon Glass *offsetp = desc.offset; 10832ec1598SSimon Glass if (gpiop) { 10932ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 11032ec1598SSimon Glass 11132ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11232ec1598SSimon Glass } 11396495d90SSimon Glass 114fe1ef503SSimon Glass return 0; 11596495d90SSimon Glass } 11696495d90SSimon Glass 117*6c880b77SEric Nelson int gpio_xlate_offs_flags(struct udevice *dev, 118*6c880b77SEric Nelson struct gpio_desc *desc, 119*6c880b77SEric Nelson struct fdtdec_phandle_args *args) 120*6c880b77SEric Nelson { 121*6c880b77SEric Nelson if (args->args_count < 1) 122*6c880b77SEric Nelson return -EINVAL; 123*6c880b77SEric Nelson 124*6c880b77SEric Nelson desc->offset = args->args[0]; 125*6c880b77SEric Nelson 126*6c880b77SEric Nelson if (args->args_count < 2) 127*6c880b77SEric Nelson return 0; 128*6c880b77SEric Nelson 129*6c880b77SEric Nelson if (args->args[1] & GPIO_ACTIVE_LOW) 130*6c880b77SEric Nelson desc->flags = GPIOD_ACTIVE_LOW; 131*6c880b77SEric Nelson 132*6c880b77SEric Nelson return 0; 133*6c880b77SEric Nelson } 134*6c880b77SEric Nelson 1353669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1360dac4d51SSimon Glass struct fdtdec_phandle_args *args) 1370dac4d51SSimon Glass { 1380dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1390dac4d51SSimon Glass 140*6c880b77SEric Nelson if (ops->xlate) 141*6c880b77SEric Nelson return ops->xlate(desc->dev, desc, args); 1420dac4d51SSimon Glass else 143*6c880b77SEric Nelson return gpio_xlate_offs_flags(desc->dev, desc, args); 1440dac4d51SSimon Glass } 1450dac4d51SSimon Glass 146efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 147ae7123f8SSimon Glass { 148ae7123f8SSimon Glass struct udevice *dev = desc->dev; 149ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 150ae7123f8SSimon Glass char *str; 151ae7123f8SSimon Glass int ret; 152ae7123f8SSimon Glass 153e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 154ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 155ae7123f8SSimon Glass return -EBUSY; 156ae7123f8SSimon Glass str = strdup(label); 157ae7123f8SSimon Glass if (!str) 158ae7123f8SSimon Glass return -ENOMEM; 159ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 160ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 161ae7123f8SSimon Glass if (ret) { 162ae7123f8SSimon Glass free(str); 163ae7123f8SSimon Glass return ret; 164ae7123f8SSimon Glass } 165ae7123f8SSimon Glass } 166ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 167ae7123f8SSimon Glass 168ae7123f8SSimon Glass return 0; 169ae7123f8SSimon Glass } 170ae7123f8SSimon Glass 1713669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 1723669e0e7SSimon Glass { 1734dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 1743669e0e7SSimon Glass va_list args; 1753669e0e7SSimon Glass char buf[40]; 1763669e0e7SSimon Glass 1773669e0e7SSimon Glass va_start(args, fmt); 1783669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 1793669e0e7SSimon Glass va_end(args); 1803669e0e7SSimon Glass return dm_gpio_request(desc, buf); 1814dc5259aSSimon Glass #else 1824dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 1834dc5259aSSimon Glass #endif 1843669e0e7SSimon Glass } 1853669e0e7SSimon Glass 18696495d90SSimon Glass /** 18796495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 18896495d90SSimon Glass * gpio: GPIO number 18996495d90SSimon Glass * label: Name for the requested GPIO 19096495d90SSimon Glass * 191b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 192b892d127SSimon Glass * the pointer around. 193b892d127SSimon Glass * 19496495d90SSimon Glass * This function implements the API that's compatible with current 19596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 19696495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 19796495d90SSimon Glass */ 19896495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 19996495d90SSimon Glass { 200ae7123f8SSimon Glass struct gpio_desc desc; 20196495d90SSimon Glass int ret; 20296495d90SSimon Glass 203ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 20496495d90SSimon Glass if (ret) 20596495d90SSimon Glass return ret; 20696495d90SSimon Glass 207ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 20896495d90SSimon Glass } 20996495d90SSimon Glass 21096495d90SSimon Glass /** 211d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 212d44f597bSSimon Glass * @gpio: GPIO number 213d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 214d44f597bSSimon Glass * @...: Arguments for the printf() format string 215d44f597bSSimon Glass * 216d44f597bSSimon Glass * This function implements the API that's compatible with current 217d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 218d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 219d44f597bSSimon Glass */ 220d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 221d44f597bSSimon Glass { 2224dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 223d44f597bSSimon Glass va_list args; 224d44f597bSSimon Glass char buf[40]; 225d44f597bSSimon Glass 226d44f597bSSimon Glass va_start(args, fmt); 227d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 228d44f597bSSimon Glass va_end(args); 229d44f597bSSimon Glass return gpio_request(gpio, buf); 2304dc5259aSSimon Glass #else 2314dc5259aSSimon Glass return gpio_request(gpio, fmt); 2324dc5259aSSimon Glass #endif 233d44f597bSSimon Glass } 234d44f597bSSimon Glass 235ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 23696495d90SSimon Glass { 237b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 23896495d90SSimon Glass int ret; 23996495d90SSimon Glass 240e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 241b892d127SSimon Glass if (!uc_priv->name[offset]) 242b892d127SSimon Glass return -ENXIO; 243b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 244b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 245b892d127SSimon Glass if (ret) 246b892d127SSimon Glass return ret; 247b892d127SSimon Glass } 248b892d127SSimon Glass 249b892d127SSimon Glass free(uc_priv->name[offset]); 250b892d127SSimon Glass uc_priv->name[offset] = NULL; 251b892d127SSimon Glass 25296495d90SSimon Glass return 0; 253b892d127SSimon Glass } 254b892d127SSimon Glass 255ae7123f8SSimon Glass /** 256ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 257ae7123f8SSimon Glass * gpio: GPIO number 258ae7123f8SSimon Glass * 259ae7123f8SSimon Glass * This function implements the API that's compatible with current 260ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 261ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 262ae7123f8SSimon Glass */ 263ae7123f8SSimon Glass int gpio_free(unsigned gpio) 264b892d127SSimon Glass { 265ae7123f8SSimon Glass struct gpio_desc desc; 266ae7123f8SSimon Glass int ret; 267b892d127SSimon Glass 268ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 269ae7123f8SSimon Glass if (ret) 270ae7123f8SSimon Glass return ret; 271ae7123f8SSimon Glass 272ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 273ae7123f8SSimon Glass } 274ae7123f8SSimon Glass 27517c43f1aSSimon Glass static int check_reserved(const struct gpio_desc *desc, const char *func) 276ae7123f8SSimon Glass { 277eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 278ae7123f8SSimon Glass 279eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 280eca48665SSimon Glass return -ENOENT; 281eca48665SSimon Glass 282eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 283ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 284b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 285ae7123f8SSimon Glass desc->dev->name, func, 286ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 287ae7123f8SSimon Glass desc->offset); 288b892d127SSimon Glass return -EBUSY; 289b892d127SSimon Glass } 290b892d127SSimon Glass 291b892d127SSimon Glass return 0; 29296495d90SSimon Glass } 29396495d90SSimon Glass 29496495d90SSimon Glass /** 29596495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 29696495d90SSimon Glass * gpio: GPIO number 29796495d90SSimon Glass * 29896495d90SSimon Glass * This function implements the API that's compatible with current 29996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 30096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 30196495d90SSimon Glass */ 30296495d90SSimon Glass int gpio_direction_input(unsigned gpio) 30396495d90SSimon Glass { 304ae7123f8SSimon Glass struct gpio_desc desc; 30596495d90SSimon Glass int ret; 30696495d90SSimon Glass 307ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 30896495d90SSimon Glass if (ret) 30996495d90SSimon Glass return ret; 310ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 311ae7123f8SSimon Glass if (ret) 312ae7123f8SSimon Glass return ret; 31396495d90SSimon Glass 314ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 31596495d90SSimon Glass } 31696495d90SSimon Glass 31796495d90SSimon Glass /** 31896495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 31996495d90SSimon Glass * gpio: GPIO number 32096495d90SSimon Glass * value: Logical value to be set on the GPIO pin 32196495d90SSimon Glass * 32296495d90SSimon Glass * This function implements the API that's compatible with current 32396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 32496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 32596495d90SSimon Glass */ 32696495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 32796495d90SSimon Glass { 328ae7123f8SSimon Glass struct gpio_desc desc; 32996495d90SSimon Glass int ret; 33096495d90SSimon Glass 331ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 33296495d90SSimon Glass if (ret) 33396495d90SSimon Glass return ret; 334ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 335ae7123f8SSimon Glass if (ret) 336ae7123f8SSimon Glass return ret; 33796495d90SSimon Glass 338ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 339ae7123f8SSimon Glass desc.offset, value); 340ae7123f8SSimon Glass } 341ae7123f8SSimon Glass 34217c43f1aSSimon Glass int dm_gpio_get_value(const struct gpio_desc *desc) 343ae7123f8SSimon Glass { 344ae7123f8SSimon Glass int value; 345ae7123f8SSimon Glass int ret; 346ae7123f8SSimon Glass 347ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 348ae7123f8SSimon Glass if (ret) 349ae7123f8SSimon Glass return ret; 350ae7123f8SSimon Glass 351ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 352ae7123f8SSimon Glass 353ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 354ae7123f8SSimon Glass } 355ae7123f8SSimon Glass 35617c43f1aSSimon Glass int dm_gpio_set_value(const struct gpio_desc *desc, int value) 357ae7123f8SSimon Glass { 358ae7123f8SSimon Glass int ret; 359ae7123f8SSimon Glass 360ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 361ae7123f8SSimon Glass if (ret) 362ae7123f8SSimon Glass return ret; 363ae7123f8SSimon Glass 364ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 365ae7123f8SSimon Glass value = !value; 366ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 367ae7123f8SSimon Glass return 0; 368ae7123f8SSimon Glass } 369ae7123f8SSimon Glass 370ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 371ae7123f8SSimon Glass { 372ae7123f8SSimon Glass struct udevice *dev = desc->dev; 373ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 374ae7123f8SSimon Glass int ret; 375ae7123f8SSimon Glass 376ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 377ae7123f8SSimon Glass if (ret) 378ae7123f8SSimon Glass return ret; 379ae7123f8SSimon Glass 380ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 381ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 382ae7123f8SSimon Glass 383ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 384ae7123f8SSimon Glass value = !value; 385ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 386ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 387ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 388ae7123f8SSimon Glass } 389ae7123f8SSimon Glass if (ret) 390ae7123f8SSimon Glass return ret; 391ae7123f8SSimon Glass /* 392ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 393ae7123f8SSimon Glass * futures 394ae7123f8SSimon Glass */ 395ae7123f8SSimon Glass desc->flags = flags; 396ae7123f8SSimon Glass 397ae7123f8SSimon Glass return 0; 398ae7123f8SSimon Glass } 399ae7123f8SSimon Glass 400ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 401ae7123f8SSimon Glass { 402ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 40396495d90SSimon Glass } 40496495d90SSimon Glass 40596495d90SSimon Glass /** 40696495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 40796495d90SSimon Glass * gpio: GPIO number 40896495d90SSimon Glass * 40996495d90SSimon Glass * This function implements the API that's compatible with current 41096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 41196495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 41296495d90SSimon Glass * on error. 41396495d90SSimon Glass */ 41496495d90SSimon Glass int gpio_get_value(unsigned gpio) 41596495d90SSimon Glass { 41696495d90SSimon Glass int ret; 41796495d90SSimon Glass 418ae7123f8SSimon Glass struct gpio_desc desc; 419ae7123f8SSimon Glass 420ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 42196495d90SSimon Glass if (ret) 42296495d90SSimon Glass return ret; 423ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 42496495d90SSimon Glass } 42596495d90SSimon Glass 42696495d90SSimon Glass /** 42796495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 42896495d90SSimon Glass * gpio: GPIO number 42996495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 43096495d90SSimon Glass * 43196495d90SSimon Glass * This function implements the API that's compatible with current 43296495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 43396495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 43496495d90SSimon Glass */ 43596495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 43696495d90SSimon Glass { 437ae7123f8SSimon Glass struct gpio_desc desc; 43896495d90SSimon Glass int ret; 43996495d90SSimon Glass 440ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 44196495d90SSimon Glass if (ret) 44296495d90SSimon Glass return ret; 443ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 44496495d90SSimon Glass } 44596495d90SSimon Glass 44654c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 44796495d90SSimon Glass { 44896495d90SSimon Glass struct gpio_dev_priv *priv; 44996495d90SSimon Glass 45096495d90SSimon Glass /* Must be called on an active device */ 451e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 45296495d90SSimon Glass assert(priv); 45396495d90SSimon Glass 45496495d90SSimon Glass *bit_count = priv->gpio_count; 45596495d90SSimon Glass return priv->bank_name; 45696495d90SSimon Glass } 45796495d90SSimon Glass 4586449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4596449a506SSimon Glass "input", 4606449a506SSimon Glass "output", 4616449a506SSimon Glass "unused", 4626449a506SSimon Glass "unknown", 4636449a506SSimon Glass "func", 4646449a506SSimon Glass }; 4656449a506SSimon Glass 4666449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4676449a506SSimon Glass const char **namep) 4686449a506SSimon Glass { 469e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 4706449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4716449a506SSimon Glass 4726449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4736449a506SSimon Glass if (!device_active(dev)) 4746449a506SSimon Glass return -ENODEV; 4756449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4766449a506SSimon Glass return -EINVAL; 4776449a506SSimon Glass if (namep) 4786449a506SSimon Glass *namep = uc_priv->name[offset]; 4796449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4806449a506SSimon Glass return GPIOF_UNUSED; 4816449a506SSimon Glass if (ops->get_function) { 4826449a506SSimon Glass int ret; 4836449a506SSimon Glass 4846449a506SSimon Glass ret = ops->get_function(dev, offset); 4856449a506SSimon Glass if (ret < 0) 4866449a506SSimon Glass return ret; 4876449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4886449a506SSimon Glass return -ENODATA; 4896449a506SSimon Glass return ret; 4906449a506SSimon Glass } 4916449a506SSimon Glass 4926449a506SSimon Glass return GPIOF_UNKNOWN; 4936449a506SSimon Glass } 4946449a506SSimon Glass 4956449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4966449a506SSimon Glass { 4976449a506SSimon Glass return get_function(dev, offset, true, namep); 4986449a506SSimon Glass } 4996449a506SSimon Glass 5006449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 5016449a506SSimon Glass { 5026449a506SSimon Glass return get_function(dev, offset, false, namep); 5036449a506SSimon Glass } 5046449a506SSimon Glass 5050757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 5060757535aSSimon Glass { 5070757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 5080757535aSSimon Glass struct gpio_dev_priv *priv; 5090757535aSSimon Glass char *str = buf; 5100757535aSSimon Glass int func; 5110757535aSSimon Glass int ret; 5120757535aSSimon Glass int len; 5130757535aSSimon Glass 5140757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 5150757535aSSimon Glass 5160757535aSSimon Glass *buf = 0; 517e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 5180757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 5190757535aSSimon Glass if (ret < 0) 5200757535aSSimon Glass return ret; 5210757535aSSimon Glass func = ret; 5220757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 5230757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 5240757535aSSimon Glass offset, gpio_function[func]); 5250757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 5260757535aSSimon Glass func == GPIOF_UNUSED) { 5270757535aSSimon Glass const char *label; 5280757535aSSimon Glass bool used; 5290757535aSSimon Glass 5300757535aSSimon Glass ret = ops->get_value(dev, offset); 5310757535aSSimon Glass if (ret < 0) 5320757535aSSimon Glass return ret; 5330757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 5340757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 5350757535aSSimon Glass ret, 5360757535aSSimon Glass used ? 'x' : ' ', 5370757535aSSimon Glass used ? " " : "", 5380757535aSSimon Glass label ? label : ""); 5390757535aSSimon Glass } 5400757535aSSimon Glass 5410757535aSSimon Glass return 0; 5420757535aSSimon Glass } 5430757535aSSimon Glass 544962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 545962f5cafSSimon Glass { 546962f5cafSSimon Glass int i, ret; 547962f5cafSSimon Glass int gpio; 548962f5cafSSimon Glass 549962f5cafSSimon Glass for (i = 0; i < 32; i++) { 550962f5cafSSimon Glass gpio = gpio_num_array[i]; 551962f5cafSSimon Glass if (gpio == -1) 552962f5cafSSimon Glass break; 553962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 554962f5cafSSimon Glass if (ret) 555962f5cafSSimon Glass goto err; 556962f5cafSSimon Glass ret = gpio_direction_input(gpio); 557962f5cafSSimon Glass if (ret) { 558962f5cafSSimon Glass gpio_free(gpio); 559962f5cafSSimon Glass goto err; 560962f5cafSSimon Glass } 561962f5cafSSimon Glass } 562962f5cafSSimon Glass 563962f5cafSSimon Glass return 0; 564962f5cafSSimon Glass err: 565962f5cafSSimon Glass for (i--; i >= 0; i--) 566962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 567962f5cafSSimon Glass 568962f5cafSSimon Glass return ret; 569962f5cafSSimon Glass } 570962f5cafSSimon Glass 571e5901c94SSimon Glass /* 572e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 573e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 574e5901c94SSimon Glass */ 575962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 576e5901c94SSimon Glass { 577e5901c94SSimon Glass int gpio; 578e5901c94SSimon Glass unsigned bitmask = 1; 579e5901c94SSimon Glass unsigned vector = 0; 580962f5cafSSimon Glass int ret; 581e5901c94SSimon Glass 582e5901c94SSimon Glass while (bitmask && 583962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 584962f5cafSSimon Glass ret = gpio_get_value(gpio); 585962f5cafSSimon Glass if (ret < 0) 586962f5cafSSimon Glass return ret; 587962f5cafSSimon Glass else if (ret) 588e5901c94SSimon Glass vector |= bitmask; 589e5901c94SSimon Glass bitmask <<= 1; 590e5901c94SSimon Glass } 591962f5cafSSimon Glass 592e5901c94SSimon Glass return vector; 593e5901c94SSimon Glass } 594e5901c94SSimon Glass 59517c43f1aSSimon Glass int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) 596bbf24780SSimon Glass { 597bbf24780SSimon Glass unsigned bitmask = 1; 598bbf24780SSimon Glass unsigned vector = 0; 599bbf24780SSimon Glass int ret, i; 600bbf24780SSimon Glass 601bbf24780SSimon Glass for (i = 0; i < count; i++) { 602bbf24780SSimon Glass ret = dm_gpio_get_value(&desc_list[i]); 603bbf24780SSimon Glass if (ret < 0) 604bbf24780SSimon Glass return ret; 605bbf24780SSimon Glass else if (ret) 606bbf24780SSimon Glass vector |= bitmask; 607bbf24780SSimon Glass bitmask <<= 1; 608bbf24780SSimon Glass } 609bbf24780SSimon Glass 610bbf24780SSimon Glass return vector; 611bbf24780SSimon Glass } 612bbf24780SSimon Glass 6133669e0e7SSimon Glass static int _gpio_request_by_name_nodev(const void *blob, int node, 6143669e0e7SSimon Glass const char *list_name, int index, 6153669e0e7SSimon Glass struct gpio_desc *desc, int flags, 6163669e0e7SSimon Glass bool add_index) 6173669e0e7SSimon Glass { 6183669e0e7SSimon Glass struct fdtdec_phandle_args args; 6193669e0e7SSimon Glass int ret; 6203669e0e7SSimon Glass 6213669e0e7SSimon Glass desc->dev = NULL; 6223669e0e7SSimon Glass desc->offset = 0; 623*6c880b77SEric Nelson desc->flags = 0; 6243669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(blob, node, list_name, 6253669e0e7SSimon Glass "#gpio-cells", 0, index, &args); 6263669e0e7SSimon Glass if (ret) { 6273669e0e7SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__); 6283669e0e7SSimon Glass goto err; 6293669e0e7SSimon Glass } 6303669e0e7SSimon Glass 6313669e0e7SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node, 6323669e0e7SSimon Glass &desc->dev); 6333669e0e7SSimon Glass if (ret) { 6343669e0e7SSimon Glass debug("%s: uclass_get_device_by_of_offset failed\n", __func__); 6353669e0e7SSimon Glass goto err; 6363669e0e7SSimon Glass } 6373669e0e7SSimon Glass ret = gpio_find_and_xlate(desc, &args); 6383669e0e7SSimon Glass if (ret) { 6393669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 6403669e0e7SSimon Glass goto err; 6413669e0e7SSimon Glass } 6423669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 6433669e0e7SSimon Glass fdt_get_name(blob, node, NULL), 6443669e0e7SSimon Glass list_name, index); 6453669e0e7SSimon Glass if (ret) { 6463669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 6473669e0e7SSimon Glass goto err; 6483669e0e7SSimon Glass } 6493669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 6503669e0e7SSimon Glass if (ret) { 6513669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 6523669e0e7SSimon Glass goto err; 6533669e0e7SSimon Glass } 6543669e0e7SSimon Glass 6553669e0e7SSimon Glass return 0; 6563669e0e7SSimon Glass err: 6573669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 6583669e0e7SSimon Glass __func__, fdt_get_name(blob, node, NULL), list_name, index, ret); 6593669e0e7SSimon Glass return ret; 6603669e0e7SSimon Glass } 6613669e0e7SSimon Glass 6623669e0e7SSimon Glass int gpio_request_by_name_nodev(const void *blob, int node, 6633669e0e7SSimon Glass const char *list_name, int index, 6643669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6653669e0e7SSimon Glass { 6663669e0e7SSimon Glass return _gpio_request_by_name_nodev(blob, node, list_name, index, desc, 6673669e0e7SSimon Glass flags, index > 0); 6683669e0e7SSimon Glass } 6693669e0e7SSimon Glass 6703669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 6713669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6723669e0e7SSimon Glass { 6733669e0e7SSimon Glass /* 6743669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6753669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6763669e0e7SSimon Glass * gpio_request_by_name_nodev() can be dropped. 6773669e0e7SSimon Glass */ 6783669e0e7SSimon Glass return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset, 6793669e0e7SSimon Glass list_name, index, desc, flags); 6803669e0e7SSimon Glass } 6813669e0e7SSimon Glass 6823669e0e7SSimon Glass int gpio_request_list_by_name_nodev(const void *blob, int node, 6833669e0e7SSimon Glass const char *list_name, 6843669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6853669e0e7SSimon Glass int flags) 6863669e0e7SSimon Glass { 6873669e0e7SSimon Glass int count; 6883669e0e7SSimon Glass int ret; 6893669e0e7SSimon Glass 6902984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 6913669e0e7SSimon Glass ret = _gpio_request_by_name_nodev(blob, node, list_name, count, 6923669e0e7SSimon Glass &desc[count], flags, true); 6933669e0e7SSimon Glass if (ret == -ENOENT) 6943669e0e7SSimon Glass break; 6953669e0e7SSimon Glass else if (ret) 6963669e0e7SSimon Glass goto err; 6973669e0e7SSimon Glass } 6983669e0e7SSimon Glass 6993669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 7003669e0e7SSimon Glass return count; 7013669e0e7SSimon Glass 7023669e0e7SSimon Glass err: 7033669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 7043669e0e7SSimon Glass 7053669e0e7SSimon Glass return ret; 7063669e0e7SSimon Glass } 7073669e0e7SSimon Glass 7083669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 7093669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 7103669e0e7SSimon Glass int flags) 7113669e0e7SSimon Glass { 7123669e0e7SSimon Glass /* 7133669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 7143669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 7153669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 7163669e0e7SSimon Glass */ 7173669e0e7SSimon Glass return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset, 7183669e0e7SSimon Glass list_name, desc, max_count, 7193669e0e7SSimon Glass flags); 7203669e0e7SSimon Glass } 7213669e0e7SSimon Glass 7223669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 7233669e0e7SSimon Glass { 7243669e0e7SSimon Glass int ret; 7253669e0e7SSimon Glass 7263669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 7273669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 7283669e0e7SSimon Glass NULL); 7293669e0e7SSimon Glass if (ret) { 7303669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 7313669e0e7SSimon Glass __func__, dev->name, list_name, ret); 7323669e0e7SSimon Glass } 7333669e0e7SSimon Glass 7343669e0e7SSimon Glass return ret; 7353669e0e7SSimon Glass } 7363669e0e7SSimon Glass 7373669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 7383669e0e7SSimon Glass { 7393669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7403669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 7413669e0e7SSimon Glass } 7423669e0e7SSimon Glass 7433669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 7443669e0e7SSimon Glass { 7453669e0e7SSimon Glass int i; 7463669e0e7SSimon Glass 7473669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7483669e0e7SSimon Glass for (i = 0; i < count; i++) 7493669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 7503669e0e7SSimon Glass 7513669e0e7SSimon Glass return 0; 7523669e0e7SSimon Glass } 7533669e0e7SSimon Glass 7543669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 7553669e0e7SSimon Glass { 7563669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 7573669e0e7SSimon Glass } 7583669e0e7SSimon Glass 75996495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 760b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 76196495d90SSimon Glass { 76296495d90SSimon Glass struct gpio_dev_priv *uc_priv; 76354c5d08aSHeiko Schocher struct udevice *dev; 76496495d90SSimon Glass struct uclass *uc; 76596495d90SSimon Glass unsigned base; 76696495d90SSimon Glass int ret; 76796495d90SSimon Glass 76896495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 76996495d90SSimon Glass if (ret) 77096495d90SSimon Glass return ret; 77196495d90SSimon Glass 77296495d90SSimon Glass /* Ensure that we have a base for each bank */ 77396495d90SSimon Glass base = 0; 77496495d90SSimon Glass uclass_foreach_dev(dev, uc) { 775b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 776e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 77796495d90SSimon Glass uc_priv->gpio_base = base; 77896495d90SSimon Glass base += uc_priv->gpio_count; 77996495d90SSimon Glass } 78096495d90SSimon Glass } 78196495d90SSimon Glass 78296495d90SSimon Glass return 0; 78396495d90SSimon Glass } 78496495d90SSimon Glass 78517c43f1aSSimon Glass int gpio_get_number(const struct gpio_desc *desc) 78656a71f89SSimon Glass { 78756a71f89SSimon Glass struct udevice *dev = desc->dev; 78856a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 78956a71f89SSimon Glass 79056a71f89SSimon Glass if (!dev) 79156a71f89SSimon Glass return -1; 79256a71f89SSimon Glass uc_priv = dev->uclass_priv; 79356a71f89SSimon Glass 79456a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 79556a71f89SSimon Glass } 79656a71f89SSimon Glass 79754c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 79896495d90SSimon Glass { 799e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 800b892d127SSimon Glass 801b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 802b892d127SSimon Glass if (!uc_priv->name) 803b892d127SSimon Glass return -ENOMEM; 804b892d127SSimon Glass 805b892d127SSimon Glass return gpio_renumber(NULL); 80696495d90SSimon Glass } 80796495d90SSimon Glass 80854c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 80996495d90SSimon Glass { 810e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 811b892d127SSimon Glass int i; 812b892d127SSimon Glass 813b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 814b892d127SSimon Glass if (uc_priv->name[i]) 815b892d127SSimon Glass free(uc_priv->name[i]); 816b892d127SSimon Glass } 817b892d127SSimon Glass free(uc_priv->name); 818b892d127SSimon Glass 819b892d127SSimon Glass return gpio_renumber(dev); 82096495d90SSimon Glass } 82196495d90SSimon Glass 82296495d90SSimon Glass UCLASS_DRIVER(gpio) = { 82396495d90SSimon Glass .id = UCLASS_GPIO, 82496495d90SSimon Glass .name = "gpio", 825ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 82696495d90SSimon Glass .post_probe = gpio_post_probe, 82796495d90SSimon Glass .pre_remove = gpio_pre_remove, 82896495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 82996495d90SSimon Glass }; 830