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> 996495d90SSimon Glass #include <errno.h> 100dac4d51SSimon Glass #include <fdtdec.h> 11b892d127SSimon Glass #include <malloc.h> 1296495d90SSimon Glass #include <asm/gpio.h> 13*84b8bf6dSMasahiro Yamada #include <linux/bug.h> 14fe1ef503SSimon Glass #include <linux/ctype.h> 1596495d90SSimon Glass 163669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 173669e0e7SSimon Glass 1896495d90SSimon Glass /** 1996495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 2096495d90SSimon Glass * 2196495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2296495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2396495d90SSimon Glass * entry on success, NULL on error. 24ae7123f8SSimon Glass * 25ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 26ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 27ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 2896495d90SSimon Glass */ 29ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 3096495d90SSimon Glass { 3196495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3254c5d08aSHeiko Schocher struct udevice *dev; 3396495d90SSimon Glass int ret; 3496495d90SSimon Glass 3596495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3696495d90SSimon Glass dev; 3796495d90SSimon Glass ret = uclass_next_device(&dev)) { 38e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 3996495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 4096495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 41ae7123f8SSimon Glass desc->dev = dev; 42ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 43ae7123f8SSimon Glass desc->flags = 0; 4496495d90SSimon Glass return 0; 4596495d90SSimon Glass } 4696495d90SSimon Glass } 4796495d90SSimon Glass 4896495d90SSimon Glass /* No such GPIO */ 49ae7123f8SSimon Glass return ret ? ret : -ENOENT; 5096495d90SSimon Glass } 5196495d90SSimon Glass 5232ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5396495d90SSimon Glass { 54fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5554c5d08aSHeiko Schocher struct udevice *dev; 56fe1ef503SSimon Glass ulong offset; 57fe1ef503SSimon Glass int numeric; 5896495d90SSimon Glass int ret; 5996495d90SSimon Glass 60fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6196495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6296495d90SSimon Glass dev; 6396495d90SSimon Glass ret = uclass_next_device(&dev)) { 6496495d90SSimon Glass int len; 6596495d90SSimon Glass 66e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 67fe1ef503SSimon Glass if (numeric != -1) { 68fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 69fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 70fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 71fe1ef503SSimon Glass break; 72fe1ef503SSimon Glass } 73fe1ef503SSimon Glass 7496495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7596495d90SSimon Glass 76939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 77fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 78fe1ef503SSimon Glass break; 79fe1ef503SSimon Glass } 80fe1ef503SSimon Glass } 81fe1ef503SSimon Glass 82fe1ef503SSimon Glass if (!dev) 83fe1ef503SSimon Glass return ret ? ret : -EINVAL; 84fe1ef503SSimon Glass 8532ec1598SSimon Glass desc->dev = dev; 8632ec1598SSimon Glass desc->offset = offset; 8732ec1598SSimon Glass 8832ec1598SSimon Glass return 0; 8932ec1598SSimon Glass } 9032ec1598SSimon Glass 9132ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9232ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9332ec1598SSimon Glass { 9432ec1598SSimon Glass struct gpio_desc desc; 9532ec1598SSimon Glass int ret; 9632ec1598SSimon Glass 9796495d90SSimon Glass if (devp) 9832ec1598SSimon Glass *devp = NULL; 9932ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 10032ec1598SSimon Glass if (ret) 10132ec1598SSimon Glass return ret; 10232ec1598SSimon Glass 10332ec1598SSimon Glass if (devp) 10432ec1598SSimon Glass *devp = desc.dev; 10596495d90SSimon Glass if (offsetp) 10632ec1598SSimon Glass *offsetp = desc.offset; 10732ec1598SSimon Glass if (gpiop) { 10832ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 10932ec1598SSimon Glass 11032ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11132ec1598SSimon Glass } 11296495d90SSimon Glass 113fe1ef503SSimon Glass return 0; 11496495d90SSimon Glass } 11596495d90SSimon Glass 1163669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1170dac4d51SSimon Glass struct fdtdec_phandle_args *args) 1180dac4d51SSimon Glass { 1190dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1200dac4d51SSimon Glass 1210dac4d51SSimon Glass /* Use the first argument as the offset by default */ 1220dac4d51SSimon Glass if (args->args_count > 0) 1230dac4d51SSimon Glass desc->offset = args->args[0]; 1240dac4d51SSimon Glass else 1250dac4d51SSimon Glass desc->offset = -1; 1260dac4d51SSimon Glass desc->flags = 0; 1270dac4d51SSimon Glass 1280dac4d51SSimon Glass return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; 1290dac4d51SSimon Glass } 1300dac4d51SSimon Glass 131efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 132ae7123f8SSimon Glass { 133ae7123f8SSimon Glass struct udevice *dev = desc->dev; 134ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 135ae7123f8SSimon Glass char *str; 136ae7123f8SSimon Glass int ret; 137ae7123f8SSimon Glass 138e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 139ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 140ae7123f8SSimon Glass return -EBUSY; 141ae7123f8SSimon Glass str = strdup(label); 142ae7123f8SSimon Glass if (!str) 143ae7123f8SSimon Glass return -ENOMEM; 144ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 145ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 146ae7123f8SSimon Glass if (ret) { 147ae7123f8SSimon Glass free(str); 148ae7123f8SSimon Glass return ret; 149ae7123f8SSimon Glass } 150ae7123f8SSimon Glass } 151ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 152ae7123f8SSimon Glass 153ae7123f8SSimon Glass return 0; 154ae7123f8SSimon Glass } 155ae7123f8SSimon Glass 1563669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 1573669e0e7SSimon Glass { 1584dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 1593669e0e7SSimon Glass va_list args; 1603669e0e7SSimon Glass char buf[40]; 1613669e0e7SSimon Glass 1623669e0e7SSimon Glass va_start(args, fmt); 1633669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 1643669e0e7SSimon Glass va_end(args); 1653669e0e7SSimon Glass return dm_gpio_request(desc, buf); 1664dc5259aSSimon Glass #else 1674dc5259aSSimon Glass return dm_gpio_request(desc, fmt); 1684dc5259aSSimon Glass #endif 1693669e0e7SSimon Glass } 1703669e0e7SSimon Glass 17196495d90SSimon Glass /** 17296495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 17396495d90SSimon Glass * gpio: GPIO number 17496495d90SSimon Glass * label: Name for the requested GPIO 17596495d90SSimon Glass * 176b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 177b892d127SSimon Glass * the pointer around. 178b892d127SSimon Glass * 17996495d90SSimon Glass * This function implements the API that's compatible with current 18096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 18196495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 18296495d90SSimon Glass */ 18396495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 18496495d90SSimon Glass { 185ae7123f8SSimon Glass struct gpio_desc desc; 18696495d90SSimon Glass int ret; 18796495d90SSimon Glass 188ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 18996495d90SSimon Glass if (ret) 19096495d90SSimon Glass return ret; 19196495d90SSimon Glass 192ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 19396495d90SSimon Glass } 19496495d90SSimon Glass 19596495d90SSimon Glass /** 196d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 197d44f597bSSimon Glass * @gpio: GPIO number 198d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 199d44f597bSSimon Glass * @...: Arguments for the printf() format string 200d44f597bSSimon Glass * 201d44f597bSSimon Glass * This function implements the API that's compatible with current 202d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 203d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 204d44f597bSSimon Glass */ 205d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 206d44f597bSSimon Glass { 2074dc5259aSSimon Glass #if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) 208d44f597bSSimon Glass va_list args; 209d44f597bSSimon Glass char buf[40]; 210d44f597bSSimon Glass 211d44f597bSSimon Glass va_start(args, fmt); 212d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 213d44f597bSSimon Glass va_end(args); 214d44f597bSSimon Glass return gpio_request(gpio, buf); 2154dc5259aSSimon Glass #else 2164dc5259aSSimon Glass return gpio_request(gpio, fmt); 2174dc5259aSSimon Glass #endif 218d44f597bSSimon Glass } 219d44f597bSSimon Glass 220ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 22196495d90SSimon Glass { 222b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 22396495d90SSimon Glass int ret; 22496495d90SSimon Glass 225e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 226b892d127SSimon Glass if (!uc_priv->name[offset]) 227b892d127SSimon Glass return -ENXIO; 228b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 229b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 230b892d127SSimon Glass if (ret) 231b892d127SSimon Glass return ret; 232b892d127SSimon Glass } 233b892d127SSimon Glass 234b892d127SSimon Glass free(uc_priv->name[offset]); 235b892d127SSimon Glass uc_priv->name[offset] = NULL; 236b892d127SSimon Glass 23796495d90SSimon Glass return 0; 238b892d127SSimon Glass } 239b892d127SSimon Glass 240ae7123f8SSimon Glass /** 241ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 242ae7123f8SSimon Glass * gpio: GPIO number 243ae7123f8SSimon Glass * 244ae7123f8SSimon Glass * This function implements the API that's compatible with current 245ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 246ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 247ae7123f8SSimon Glass */ 248ae7123f8SSimon Glass int gpio_free(unsigned gpio) 249b892d127SSimon Glass { 250ae7123f8SSimon Glass struct gpio_desc desc; 251ae7123f8SSimon Glass int ret; 252b892d127SSimon Glass 253ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 254ae7123f8SSimon Glass if (ret) 255ae7123f8SSimon Glass return ret; 256ae7123f8SSimon Glass 257ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 258ae7123f8SSimon Glass } 259ae7123f8SSimon Glass 260ae7123f8SSimon Glass static int check_reserved(struct gpio_desc *desc, const char *func) 261ae7123f8SSimon Glass { 262eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 263ae7123f8SSimon Glass 264eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 265eca48665SSimon Glass return -ENOENT; 266eca48665SSimon Glass 267eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 268ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 269b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 270ae7123f8SSimon Glass desc->dev->name, func, 271ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 272ae7123f8SSimon Glass desc->offset); 273b892d127SSimon Glass return -EBUSY; 274b892d127SSimon Glass } 275b892d127SSimon Glass 276b892d127SSimon Glass return 0; 27796495d90SSimon Glass } 27896495d90SSimon Glass 27996495d90SSimon Glass /** 28096495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 28196495d90SSimon Glass * gpio: GPIO number 28296495d90SSimon Glass * 28396495d90SSimon Glass * This function implements the API that's compatible with current 28496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 28596495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 28696495d90SSimon Glass */ 28796495d90SSimon Glass int gpio_direction_input(unsigned gpio) 28896495d90SSimon Glass { 289ae7123f8SSimon Glass struct gpio_desc desc; 29096495d90SSimon Glass int ret; 29196495d90SSimon Glass 292ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 29396495d90SSimon Glass if (ret) 29496495d90SSimon Glass return ret; 295ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 296ae7123f8SSimon Glass if (ret) 297ae7123f8SSimon Glass return ret; 29896495d90SSimon Glass 299ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 30096495d90SSimon Glass } 30196495d90SSimon Glass 30296495d90SSimon Glass /** 30396495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 30496495d90SSimon Glass * gpio: GPIO number 30596495d90SSimon Glass * value: Logical value to be set on the GPIO pin 30696495d90SSimon 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_direction_output(unsigned gpio, int value) 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; 319ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 320ae7123f8SSimon Glass if (ret) 321ae7123f8SSimon Glass return ret; 32296495d90SSimon Glass 323ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 324ae7123f8SSimon Glass desc.offset, value); 325ae7123f8SSimon Glass } 326ae7123f8SSimon Glass 327ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc) 328ae7123f8SSimon Glass { 329ae7123f8SSimon Glass int value; 330ae7123f8SSimon Glass int ret; 331ae7123f8SSimon Glass 332ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 333ae7123f8SSimon Glass if (ret) 334ae7123f8SSimon Glass return ret; 335ae7123f8SSimon Glass 336ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 337ae7123f8SSimon Glass 338ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 339ae7123f8SSimon Glass } 340ae7123f8SSimon Glass 341ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value) 342ae7123f8SSimon Glass { 343ae7123f8SSimon Glass int ret; 344ae7123f8SSimon Glass 345ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 346ae7123f8SSimon Glass if (ret) 347ae7123f8SSimon Glass return ret; 348ae7123f8SSimon Glass 349ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 350ae7123f8SSimon Glass value = !value; 351ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 352ae7123f8SSimon Glass return 0; 353ae7123f8SSimon Glass } 354ae7123f8SSimon Glass 355ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 356ae7123f8SSimon Glass { 357ae7123f8SSimon Glass struct udevice *dev = desc->dev; 358ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 359ae7123f8SSimon Glass int ret; 360ae7123f8SSimon Glass 361ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 362ae7123f8SSimon Glass if (ret) 363ae7123f8SSimon Glass return ret; 364ae7123f8SSimon Glass 365ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 366ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 367ae7123f8SSimon Glass 368ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 369ae7123f8SSimon Glass value = !value; 370ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 371ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 372ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 373ae7123f8SSimon Glass } 374ae7123f8SSimon Glass if (ret) 375ae7123f8SSimon Glass return ret; 376ae7123f8SSimon Glass /* 377ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 378ae7123f8SSimon Glass * futures 379ae7123f8SSimon Glass */ 380ae7123f8SSimon Glass desc->flags = flags; 381ae7123f8SSimon Glass 382ae7123f8SSimon Glass return 0; 383ae7123f8SSimon Glass } 384ae7123f8SSimon Glass 385ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 386ae7123f8SSimon Glass { 387ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 38896495d90SSimon Glass } 38996495d90SSimon Glass 39096495d90SSimon Glass /** 39196495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 39296495d90SSimon Glass * gpio: GPIO number 39396495d90SSimon Glass * 39496495d90SSimon Glass * This function implements the API that's compatible with current 39596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 39696495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 39796495d90SSimon Glass * on error. 39896495d90SSimon Glass */ 39996495d90SSimon Glass int gpio_get_value(unsigned gpio) 40096495d90SSimon Glass { 40196495d90SSimon Glass int ret; 40296495d90SSimon Glass 403ae7123f8SSimon Glass struct gpio_desc desc; 404ae7123f8SSimon Glass 405ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 40696495d90SSimon Glass if (ret) 40796495d90SSimon Glass return ret; 408ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 40996495d90SSimon Glass } 41096495d90SSimon Glass 41196495d90SSimon Glass /** 41296495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 41396495d90SSimon Glass * gpio: GPIO number 41496495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 41596495d90SSimon Glass * 41696495d90SSimon Glass * This function implements the API that's compatible with current 41796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 41896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 41996495d90SSimon Glass */ 42096495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 42196495d90SSimon Glass { 422ae7123f8SSimon Glass struct gpio_desc desc; 42396495d90SSimon Glass int ret; 42496495d90SSimon Glass 425ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 42696495d90SSimon Glass if (ret) 42796495d90SSimon Glass return ret; 428ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 42996495d90SSimon Glass } 43096495d90SSimon Glass 43154c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 43296495d90SSimon Glass { 43396495d90SSimon Glass struct gpio_dev_priv *priv; 43496495d90SSimon Glass 43596495d90SSimon Glass /* Must be called on an active device */ 436e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 43796495d90SSimon Glass assert(priv); 43896495d90SSimon Glass 43996495d90SSimon Glass *bit_count = priv->gpio_count; 44096495d90SSimon Glass return priv->bank_name; 44196495d90SSimon Glass } 44296495d90SSimon Glass 4436449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4446449a506SSimon Glass "input", 4456449a506SSimon Glass "output", 4466449a506SSimon Glass "unused", 4476449a506SSimon Glass "unknown", 4486449a506SSimon Glass "func", 4496449a506SSimon Glass }; 4506449a506SSimon Glass 4516449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4526449a506SSimon Glass const char **namep) 4536449a506SSimon Glass { 454e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 4556449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4566449a506SSimon Glass 4576449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4586449a506SSimon Glass if (!device_active(dev)) 4596449a506SSimon Glass return -ENODEV; 4606449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4616449a506SSimon Glass return -EINVAL; 4626449a506SSimon Glass if (namep) 4636449a506SSimon Glass *namep = uc_priv->name[offset]; 4646449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4656449a506SSimon Glass return GPIOF_UNUSED; 4666449a506SSimon Glass if (ops->get_function) { 4676449a506SSimon Glass int ret; 4686449a506SSimon Glass 4696449a506SSimon Glass ret = ops->get_function(dev, offset); 4706449a506SSimon Glass if (ret < 0) 4716449a506SSimon Glass return ret; 4726449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4736449a506SSimon Glass return -ENODATA; 4746449a506SSimon Glass return ret; 4756449a506SSimon Glass } 4766449a506SSimon Glass 4776449a506SSimon Glass return GPIOF_UNKNOWN; 4786449a506SSimon Glass } 4796449a506SSimon Glass 4806449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4816449a506SSimon Glass { 4826449a506SSimon Glass return get_function(dev, offset, true, namep); 4836449a506SSimon Glass } 4846449a506SSimon Glass 4856449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 4866449a506SSimon Glass { 4876449a506SSimon Glass return get_function(dev, offset, false, namep); 4886449a506SSimon Glass } 4896449a506SSimon Glass 4900757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 4910757535aSSimon Glass { 4920757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4930757535aSSimon Glass struct gpio_dev_priv *priv; 4940757535aSSimon Glass char *str = buf; 4950757535aSSimon Glass int func; 4960757535aSSimon Glass int ret; 4970757535aSSimon Glass int len; 4980757535aSSimon Glass 4990757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 5000757535aSSimon Glass 5010757535aSSimon Glass *buf = 0; 502e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 5030757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 5040757535aSSimon Glass if (ret < 0) 5050757535aSSimon Glass return ret; 5060757535aSSimon Glass func = ret; 5070757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 5080757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 5090757535aSSimon Glass offset, gpio_function[func]); 5100757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 5110757535aSSimon Glass func == GPIOF_UNUSED) { 5120757535aSSimon Glass const char *label; 5130757535aSSimon Glass bool used; 5140757535aSSimon Glass 5150757535aSSimon Glass ret = ops->get_value(dev, offset); 5160757535aSSimon Glass if (ret < 0) 5170757535aSSimon Glass return ret; 5180757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 5190757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 5200757535aSSimon Glass ret, 5210757535aSSimon Glass used ? 'x' : ' ', 5220757535aSSimon Glass used ? " " : "", 5230757535aSSimon Glass label ? label : ""); 5240757535aSSimon Glass } 5250757535aSSimon Glass 5260757535aSSimon Glass return 0; 5270757535aSSimon Glass } 5280757535aSSimon Glass 529962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 530962f5cafSSimon Glass { 531962f5cafSSimon Glass int i, ret; 532962f5cafSSimon Glass int gpio; 533962f5cafSSimon Glass 534962f5cafSSimon Glass for (i = 0; i < 32; i++) { 535962f5cafSSimon Glass gpio = gpio_num_array[i]; 536962f5cafSSimon Glass if (gpio == -1) 537962f5cafSSimon Glass break; 538962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 539962f5cafSSimon Glass if (ret) 540962f5cafSSimon Glass goto err; 541962f5cafSSimon Glass ret = gpio_direction_input(gpio); 542962f5cafSSimon Glass if (ret) { 543962f5cafSSimon Glass gpio_free(gpio); 544962f5cafSSimon Glass goto err; 545962f5cafSSimon Glass } 546962f5cafSSimon Glass } 547962f5cafSSimon Glass 548962f5cafSSimon Glass return 0; 549962f5cafSSimon Glass err: 550962f5cafSSimon Glass for (i--; i >= 0; i--) 551962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 552962f5cafSSimon Glass 553962f5cafSSimon Glass return ret; 554962f5cafSSimon Glass } 555962f5cafSSimon Glass 556e5901c94SSimon Glass /* 557e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 558e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 559e5901c94SSimon Glass */ 560962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 561e5901c94SSimon Glass { 562e5901c94SSimon Glass int gpio; 563e5901c94SSimon Glass unsigned bitmask = 1; 564e5901c94SSimon Glass unsigned vector = 0; 565962f5cafSSimon Glass int ret; 566e5901c94SSimon Glass 567e5901c94SSimon Glass while (bitmask && 568962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 569962f5cafSSimon Glass ret = gpio_get_value(gpio); 570962f5cafSSimon Glass if (ret < 0) 571962f5cafSSimon Glass return ret; 572962f5cafSSimon Glass else if (ret) 573e5901c94SSimon Glass vector |= bitmask; 574e5901c94SSimon Glass bitmask <<= 1; 575e5901c94SSimon Glass } 576962f5cafSSimon Glass 577e5901c94SSimon Glass return vector; 578e5901c94SSimon Glass } 579e5901c94SSimon Glass 5803669e0e7SSimon Glass static int _gpio_request_by_name_nodev(const void *blob, int node, 5813669e0e7SSimon Glass const char *list_name, int index, 5823669e0e7SSimon Glass struct gpio_desc *desc, int flags, 5833669e0e7SSimon Glass bool add_index) 5843669e0e7SSimon Glass { 5853669e0e7SSimon Glass struct fdtdec_phandle_args args; 5863669e0e7SSimon Glass int ret; 5873669e0e7SSimon Glass 5883669e0e7SSimon Glass desc->dev = NULL; 5893669e0e7SSimon Glass desc->offset = 0; 5903669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(blob, node, list_name, 5913669e0e7SSimon Glass "#gpio-cells", 0, index, &args); 5923669e0e7SSimon Glass if (ret) { 5933669e0e7SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__); 5943669e0e7SSimon Glass goto err; 5953669e0e7SSimon Glass } 5963669e0e7SSimon Glass 5973669e0e7SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node, 5983669e0e7SSimon Glass &desc->dev); 5993669e0e7SSimon Glass if (ret) { 6003669e0e7SSimon Glass debug("%s: uclass_get_device_by_of_offset failed\n", __func__); 6013669e0e7SSimon Glass goto err; 6023669e0e7SSimon Glass } 6033669e0e7SSimon Glass ret = gpio_find_and_xlate(desc, &args); 6043669e0e7SSimon Glass if (ret) { 6053669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 6063669e0e7SSimon Glass goto err; 6073669e0e7SSimon Glass } 6083669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 6093669e0e7SSimon Glass fdt_get_name(blob, node, NULL), 6103669e0e7SSimon Glass list_name, index); 6113669e0e7SSimon Glass if (ret) { 6123669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 6133669e0e7SSimon Glass goto err; 6143669e0e7SSimon Glass } 6153669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 6163669e0e7SSimon Glass if (ret) { 6173669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 6183669e0e7SSimon Glass goto err; 6193669e0e7SSimon Glass } 6203669e0e7SSimon Glass 6213669e0e7SSimon Glass return 0; 6223669e0e7SSimon Glass err: 6233669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 6243669e0e7SSimon Glass __func__, fdt_get_name(blob, node, NULL), list_name, index, ret); 6253669e0e7SSimon Glass return ret; 6263669e0e7SSimon Glass } 6273669e0e7SSimon Glass 6283669e0e7SSimon Glass int gpio_request_by_name_nodev(const void *blob, int node, 6293669e0e7SSimon Glass const char *list_name, int index, 6303669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6313669e0e7SSimon Glass { 6323669e0e7SSimon Glass return _gpio_request_by_name_nodev(blob, node, list_name, index, desc, 6333669e0e7SSimon Glass flags, index > 0); 6343669e0e7SSimon Glass } 6353669e0e7SSimon Glass 6363669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 6373669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6383669e0e7SSimon Glass { 6393669e0e7SSimon Glass /* 6403669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6413669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6423669e0e7SSimon Glass * gpio_request_by_name_nodev() can be dropped. 6433669e0e7SSimon Glass */ 6443669e0e7SSimon Glass return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset, 6453669e0e7SSimon Glass list_name, index, desc, flags); 6463669e0e7SSimon Glass } 6473669e0e7SSimon Glass 6483669e0e7SSimon Glass int gpio_request_list_by_name_nodev(const void *blob, int node, 6493669e0e7SSimon Glass const char *list_name, 6503669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6513669e0e7SSimon Glass int flags) 6523669e0e7SSimon Glass { 6533669e0e7SSimon Glass int count; 6543669e0e7SSimon Glass int ret; 6553669e0e7SSimon Glass 6562984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 6573669e0e7SSimon Glass ret = _gpio_request_by_name_nodev(blob, node, list_name, count, 6583669e0e7SSimon Glass &desc[count], flags, true); 6593669e0e7SSimon Glass if (ret == -ENOENT) 6603669e0e7SSimon Glass break; 6613669e0e7SSimon Glass else if (ret) 6623669e0e7SSimon Glass goto err; 6633669e0e7SSimon Glass } 6643669e0e7SSimon Glass 6653669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 6663669e0e7SSimon Glass return count; 6673669e0e7SSimon Glass 6683669e0e7SSimon Glass err: 6693669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 6703669e0e7SSimon Glass 6713669e0e7SSimon Glass return ret; 6723669e0e7SSimon Glass } 6733669e0e7SSimon Glass 6743669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 6753669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6763669e0e7SSimon Glass int flags) 6773669e0e7SSimon Glass { 6783669e0e7SSimon Glass /* 6793669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6803669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6813669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 6823669e0e7SSimon Glass */ 6833669e0e7SSimon Glass return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset, 6843669e0e7SSimon Glass list_name, desc, max_count, 6853669e0e7SSimon Glass flags); 6863669e0e7SSimon Glass } 6873669e0e7SSimon Glass 6883669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 6893669e0e7SSimon Glass { 6903669e0e7SSimon Glass int ret; 6913669e0e7SSimon Glass 6923669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 6933669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 6943669e0e7SSimon Glass NULL); 6953669e0e7SSimon Glass if (ret) { 6963669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 6973669e0e7SSimon Glass __func__, dev->name, list_name, ret); 6983669e0e7SSimon Glass } 6993669e0e7SSimon Glass 7003669e0e7SSimon Glass return ret; 7013669e0e7SSimon Glass } 7023669e0e7SSimon Glass 7033669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 7043669e0e7SSimon Glass { 7053669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7063669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 7073669e0e7SSimon Glass } 7083669e0e7SSimon Glass 7093669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 7103669e0e7SSimon Glass { 7113669e0e7SSimon Glass int i; 7123669e0e7SSimon Glass 7133669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7143669e0e7SSimon Glass for (i = 0; i < count; i++) 7153669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 7163669e0e7SSimon Glass 7173669e0e7SSimon Glass return 0; 7183669e0e7SSimon Glass } 7193669e0e7SSimon Glass 7203669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 7213669e0e7SSimon Glass { 7223669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 7233669e0e7SSimon Glass } 7243669e0e7SSimon Glass 72596495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 726b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 72796495d90SSimon Glass { 72896495d90SSimon Glass struct gpio_dev_priv *uc_priv; 72954c5d08aSHeiko Schocher struct udevice *dev; 73096495d90SSimon Glass struct uclass *uc; 73196495d90SSimon Glass unsigned base; 73296495d90SSimon Glass int ret; 73396495d90SSimon Glass 73496495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 73596495d90SSimon Glass if (ret) 73696495d90SSimon Glass return ret; 73796495d90SSimon Glass 73896495d90SSimon Glass /* Ensure that we have a base for each bank */ 73996495d90SSimon Glass base = 0; 74096495d90SSimon Glass uclass_foreach_dev(dev, uc) { 741b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 742e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 74396495d90SSimon Glass uc_priv->gpio_base = base; 74496495d90SSimon Glass base += uc_priv->gpio_count; 74596495d90SSimon Glass } 74696495d90SSimon Glass } 74796495d90SSimon Glass 74896495d90SSimon Glass return 0; 74996495d90SSimon Glass } 75096495d90SSimon Glass 75156a71f89SSimon Glass int gpio_get_number(struct gpio_desc *desc) 75256a71f89SSimon Glass { 75356a71f89SSimon Glass struct udevice *dev = desc->dev; 75456a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 75556a71f89SSimon Glass 75656a71f89SSimon Glass if (!dev) 75756a71f89SSimon Glass return -1; 75856a71f89SSimon Glass uc_priv = dev->uclass_priv; 75956a71f89SSimon Glass 76056a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 76156a71f89SSimon Glass } 76256a71f89SSimon Glass 76354c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 76496495d90SSimon Glass { 765e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 766b892d127SSimon Glass 767b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 768b892d127SSimon Glass if (!uc_priv->name) 769b892d127SSimon Glass return -ENOMEM; 770b892d127SSimon Glass 771b892d127SSimon Glass return gpio_renumber(NULL); 77296495d90SSimon Glass } 77396495d90SSimon Glass 77454c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 77596495d90SSimon Glass { 776e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 777b892d127SSimon Glass int i; 778b892d127SSimon Glass 779b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 780b892d127SSimon Glass if (uc_priv->name[i]) 781b892d127SSimon Glass free(uc_priv->name[i]); 782b892d127SSimon Glass } 783b892d127SSimon Glass free(uc_priv->name); 784b892d127SSimon Glass 785b892d127SSimon Glass return gpio_renumber(dev); 78696495d90SSimon Glass } 78796495d90SSimon Glass 78896495d90SSimon Glass UCLASS_DRIVER(gpio) = { 78996495d90SSimon Glass .id = UCLASS_GPIO, 79096495d90SSimon Glass .name = "gpio", 791ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 79296495d90SSimon Glass .post_probe = gpio_post_probe, 79396495d90SSimon Glass .pre_remove = gpio_pre_remove, 79496495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 79596495d90SSimon Glass }; 796