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> 13fe1ef503SSimon Glass #include <linux/ctype.h> 1496495d90SSimon Glass 153669e0e7SSimon Glass DECLARE_GLOBAL_DATA_PTR; 163669e0e7SSimon Glass 1796495d90SSimon Glass /** 1896495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 1996495d90SSimon Glass * 2096495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 2196495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 2296495d90SSimon Glass * entry on success, NULL on error. 23ae7123f8SSimon Glass * 24ae7123f8SSimon Glass * @gpio: The numeric representation of the GPIO 25ae7123f8SSimon Glass * @desc: Returns description (desc->flags will always be 0) 26ae7123f8SSimon Glass * @return 0 if found, -ENOENT if not found 2796495d90SSimon Glass */ 28ae7123f8SSimon Glass static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) 2996495d90SSimon Glass { 3096495d90SSimon Glass struct gpio_dev_priv *uc_priv; 3154c5d08aSHeiko Schocher struct udevice *dev; 3296495d90SSimon Glass int ret; 3396495d90SSimon Glass 3496495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 3596495d90SSimon Glass dev; 3696495d90SSimon Glass ret = uclass_next_device(&dev)) { 37e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 3896495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 3996495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 40ae7123f8SSimon Glass desc->dev = dev; 41ae7123f8SSimon Glass desc->offset = gpio - uc_priv->gpio_base; 42ae7123f8SSimon Glass desc->flags = 0; 4396495d90SSimon Glass return 0; 4496495d90SSimon Glass } 4596495d90SSimon Glass } 4696495d90SSimon Glass 4796495d90SSimon Glass /* No such GPIO */ 48ae7123f8SSimon Glass return ret ? ret : -ENOENT; 4996495d90SSimon Glass } 5096495d90SSimon Glass 5154c5d08aSHeiko Schocher int gpio_lookup_name(const char *name, struct udevice **devp, 5296495d90SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 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 6096495d90SSimon Glass if (devp) 6196495d90SSimon Glass *devp = NULL; 62fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6396495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6496495d90SSimon Glass dev; 6596495d90SSimon Glass ret = uclass_next_device(&dev)) { 6696495d90SSimon Glass int len; 6796495d90SSimon Glass 68e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 69fe1ef503SSimon Glass if (numeric != -1) { 70fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 71fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 72fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 73fe1ef503SSimon Glass break; 74fe1ef503SSimon Glass } 75fe1ef503SSimon Glass 7696495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7796495d90SSimon Glass 78939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 79fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 80fe1ef503SSimon Glass break; 81fe1ef503SSimon Glass } 82fe1ef503SSimon Glass } 83fe1ef503SSimon Glass 84fe1ef503SSimon Glass if (!dev) 85fe1ef503SSimon Glass return ret ? ret : -EINVAL; 86fe1ef503SSimon Glass 8796495d90SSimon Glass if (devp) 8896495d90SSimon Glass *devp = dev; 8996495d90SSimon Glass if (offsetp) 9096495d90SSimon Glass *offsetp = offset; 9196495d90SSimon Glass if (gpiop) 9296495d90SSimon Glass *gpiop = uc_priv->gpio_base + offset; 9396495d90SSimon Glass 94fe1ef503SSimon Glass return 0; 9596495d90SSimon Glass } 9696495d90SSimon Glass 973669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 980dac4d51SSimon Glass struct fdtdec_phandle_args *args) 990dac4d51SSimon Glass { 1000dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1010dac4d51SSimon Glass 1020dac4d51SSimon Glass /* Use the first argument as the offset by default */ 1030dac4d51SSimon Glass if (args->args_count > 0) 1040dac4d51SSimon Glass desc->offset = args->args[0]; 1050dac4d51SSimon Glass else 1060dac4d51SSimon Glass desc->offset = -1; 1070dac4d51SSimon Glass desc->flags = 0; 1080dac4d51SSimon Glass 1090dac4d51SSimon Glass return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; 1100dac4d51SSimon Glass } 1110dac4d51SSimon Glass 112ae7123f8SSimon Glass static int dm_gpio_request(struct gpio_desc *desc, const char *label) 113ae7123f8SSimon Glass { 114ae7123f8SSimon Glass struct udevice *dev = desc->dev; 115ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 116ae7123f8SSimon Glass char *str; 117ae7123f8SSimon Glass int ret; 118ae7123f8SSimon Glass 119e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 120ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 121ae7123f8SSimon Glass return -EBUSY; 122ae7123f8SSimon Glass str = strdup(label); 123ae7123f8SSimon Glass if (!str) 124ae7123f8SSimon Glass return -ENOMEM; 125ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 126ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 127ae7123f8SSimon Glass if (ret) { 128ae7123f8SSimon Glass free(str); 129ae7123f8SSimon Glass return ret; 130ae7123f8SSimon Glass } 131ae7123f8SSimon Glass } 132ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 133ae7123f8SSimon Glass 134ae7123f8SSimon Glass return 0; 135ae7123f8SSimon Glass } 136ae7123f8SSimon Glass 1373669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 1383669e0e7SSimon Glass { 1393669e0e7SSimon Glass va_list args; 1403669e0e7SSimon Glass char buf[40]; 1413669e0e7SSimon Glass 1423669e0e7SSimon Glass va_start(args, fmt); 1433669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 1443669e0e7SSimon Glass va_end(args); 1453669e0e7SSimon Glass return dm_gpio_request(desc, buf); 1463669e0e7SSimon Glass } 1473669e0e7SSimon Glass 14896495d90SSimon Glass /** 14996495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 15096495d90SSimon Glass * gpio: GPIO number 15196495d90SSimon Glass * label: Name for the requested GPIO 15296495d90SSimon Glass * 153b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 154b892d127SSimon Glass * the pointer around. 155b892d127SSimon Glass * 15696495d90SSimon Glass * This function implements the API that's compatible with current 15796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 15896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 15996495d90SSimon Glass */ 16096495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 16196495d90SSimon Glass { 162ae7123f8SSimon Glass struct gpio_desc desc; 16396495d90SSimon Glass int ret; 16496495d90SSimon Glass 165ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 16696495d90SSimon Glass if (ret) 16796495d90SSimon Glass return ret; 16896495d90SSimon Glass 169ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 17096495d90SSimon Glass } 17196495d90SSimon Glass 17296495d90SSimon Glass /** 173d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 174d44f597bSSimon Glass * @gpio: GPIO number 175d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 176d44f597bSSimon Glass * @...: Arguments for the printf() format string 177d44f597bSSimon Glass * 178d44f597bSSimon Glass * This function implements the API that's compatible with current 179d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 180d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 181d44f597bSSimon Glass */ 182d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 183d44f597bSSimon Glass { 184d44f597bSSimon Glass va_list args; 185d44f597bSSimon Glass char buf[40]; 186d44f597bSSimon Glass 187d44f597bSSimon Glass va_start(args, fmt); 188d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 189d44f597bSSimon Glass va_end(args); 190d44f597bSSimon Glass return gpio_request(gpio, buf); 191d44f597bSSimon Glass } 192d44f597bSSimon Glass 193ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 19496495d90SSimon Glass { 195b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 19696495d90SSimon Glass int ret; 19796495d90SSimon Glass 198e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 199b892d127SSimon Glass if (!uc_priv->name[offset]) 200b892d127SSimon Glass return -ENXIO; 201b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 202b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 203b892d127SSimon Glass if (ret) 204b892d127SSimon Glass return ret; 205b892d127SSimon Glass } 206b892d127SSimon Glass 207b892d127SSimon Glass free(uc_priv->name[offset]); 208b892d127SSimon Glass uc_priv->name[offset] = NULL; 209b892d127SSimon Glass 21096495d90SSimon Glass return 0; 211b892d127SSimon Glass } 212b892d127SSimon Glass 213ae7123f8SSimon Glass /** 214ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 215ae7123f8SSimon Glass * gpio: GPIO number 216ae7123f8SSimon Glass * 217ae7123f8SSimon Glass * This function implements the API that's compatible with current 218ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 219ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 220ae7123f8SSimon Glass */ 221ae7123f8SSimon Glass int gpio_free(unsigned gpio) 222b892d127SSimon Glass { 223ae7123f8SSimon Glass struct gpio_desc desc; 224ae7123f8SSimon Glass int ret; 225b892d127SSimon Glass 226ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 227ae7123f8SSimon Glass if (ret) 228ae7123f8SSimon Glass return ret; 229ae7123f8SSimon Glass 230ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 231ae7123f8SSimon Glass } 232ae7123f8SSimon Glass 233ae7123f8SSimon Glass static int check_reserved(struct gpio_desc *desc, const char *func) 234ae7123f8SSimon Glass { 235e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc->dev); 236ae7123f8SSimon Glass 237ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 238b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 239ae7123f8SSimon Glass desc->dev->name, func, 240ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 241ae7123f8SSimon Glass desc->offset); 242b892d127SSimon Glass return -EBUSY; 243b892d127SSimon Glass } 244b892d127SSimon Glass 245b892d127SSimon Glass return 0; 24696495d90SSimon Glass } 24796495d90SSimon Glass 24896495d90SSimon Glass /** 24996495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 25096495d90SSimon Glass * gpio: GPIO number 25196495d90SSimon Glass * 25296495d90SSimon Glass * This function implements the API that's compatible with current 25396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 25496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 25596495d90SSimon Glass */ 25696495d90SSimon Glass int gpio_direction_input(unsigned gpio) 25796495d90SSimon Glass { 258ae7123f8SSimon Glass struct gpio_desc desc; 25996495d90SSimon Glass int ret; 26096495d90SSimon Glass 261ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 26296495d90SSimon Glass if (ret) 26396495d90SSimon Glass return ret; 264ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 265ae7123f8SSimon Glass if (ret) 266ae7123f8SSimon Glass return ret; 26796495d90SSimon Glass 268ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 26996495d90SSimon Glass } 27096495d90SSimon Glass 27196495d90SSimon Glass /** 27296495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 27396495d90SSimon Glass * gpio: GPIO number 27496495d90SSimon Glass * value: Logical value to be set on the GPIO pin 27596495d90SSimon Glass * 27696495d90SSimon Glass * This function implements the API that's compatible with current 27796495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 27896495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 27996495d90SSimon Glass */ 28096495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 28196495d90SSimon Glass { 282ae7123f8SSimon Glass struct gpio_desc desc; 28396495d90SSimon Glass int ret; 28496495d90SSimon Glass 285ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 28696495d90SSimon Glass if (ret) 28796495d90SSimon Glass return ret; 288ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 289ae7123f8SSimon Glass if (ret) 290ae7123f8SSimon Glass return ret; 29196495d90SSimon Glass 292ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 293ae7123f8SSimon Glass desc.offset, value); 294ae7123f8SSimon Glass } 295ae7123f8SSimon Glass 296ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc) 297ae7123f8SSimon Glass { 298ae7123f8SSimon Glass int value; 299ae7123f8SSimon Glass int ret; 300ae7123f8SSimon Glass 301ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 302ae7123f8SSimon Glass if (ret) 303ae7123f8SSimon Glass return ret; 304ae7123f8SSimon Glass 305ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 306ae7123f8SSimon Glass 307ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 308ae7123f8SSimon Glass } 309ae7123f8SSimon Glass 310ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value) 311ae7123f8SSimon Glass { 312ae7123f8SSimon Glass int ret; 313ae7123f8SSimon Glass 314ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 315ae7123f8SSimon Glass if (ret) 316ae7123f8SSimon Glass return ret; 317ae7123f8SSimon Glass 318ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 319ae7123f8SSimon Glass value = !value; 320ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 321ae7123f8SSimon Glass return 0; 322ae7123f8SSimon Glass } 323ae7123f8SSimon Glass 324ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 325ae7123f8SSimon Glass { 326ae7123f8SSimon Glass struct udevice *dev = desc->dev; 327ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 328ae7123f8SSimon Glass int ret; 329ae7123f8SSimon Glass 330ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 331ae7123f8SSimon Glass if (ret) 332ae7123f8SSimon Glass return ret; 333ae7123f8SSimon Glass 334ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 335ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 336ae7123f8SSimon Glass 337ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 338ae7123f8SSimon Glass value = !value; 339ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 340ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 341ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 342ae7123f8SSimon Glass } 343ae7123f8SSimon Glass if (ret) 344ae7123f8SSimon Glass return ret; 345ae7123f8SSimon Glass /* 346ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 347ae7123f8SSimon Glass * futures 348ae7123f8SSimon Glass */ 349ae7123f8SSimon Glass desc->flags = flags; 350ae7123f8SSimon Glass 351ae7123f8SSimon Glass return 0; 352ae7123f8SSimon Glass } 353ae7123f8SSimon Glass 354ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 355ae7123f8SSimon Glass { 356ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 35796495d90SSimon Glass } 35896495d90SSimon Glass 35996495d90SSimon Glass /** 36096495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 36196495d90SSimon Glass * gpio: GPIO number 36296495d90SSimon Glass * 36396495d90SSimon Glass * This function implements the API that's compatible with current 36496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 36596495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 36696495d90SSimon Glass * on error. 36796495d90SSimon Glass */ 36896495d90SSimon Glass int gpio_get_value(unsigned gpio) 36996495d90SSimon Glass { 37096495d90SSimon Glass int ret; 37196495d90SSimon Glass 372ae7123f8SSimon Glass struct gpio_desc desc; 373ae7123f8SSimon Glass 374ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 37596495d90SSimon Glass if (ret) 37696495d90SSimon Glass return ret; 377ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 37896495d90SSimon Glass } 37996495d90SSimon Glass 38096495d90SSimon Glass /** 38196495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 38296495d90SSimon Glass * gpio: GPIO number 38396495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 38496495d90SSimon Glass * 38596495d90SSimon Glass * This function implements the API that's compatible with current 38696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 38796495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 38896495d90SSimon Glass */ 38996495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 39096495d90SSimon Glass { 391ae7123f8SSimon Glass struct gpio_desc desc; 39296495d90SSimon Glass int ret; 39396495d90SSimon Glass 394ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 39596495d90SSimon Glass if (ret) 39696495d90SSimon Glass return ret; 397ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 39896495d90SSimon Glass } 39996495d90SSimon Glass 40054c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 40196495d90SSimon Glass { 40296495d90SSimon Glass struct gpio_dev_priv *priv; 40396495d90SSimon Glass 40496495d90SSimon Glass /* Must be called on an active device */ 405e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 40696495d90SSimon Glass assert(priv); 40796495d90SSimon Glass 40896495d90SSimon Glass *bit_count = priv->gpio_count; 40996495d90SSimon Glass return priv->bank_name; 41096495d90SSimon Glass } 41196495d90SSimon Glass 4126449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4136449a506SSimon Glass "input", 4146449a506SSimon Glass "output", 4156449a506SSimon Glass "unused", 4166449a506SSimon Glass "unknown", 4176449a506SSimon Glass "func", 4186449a506SSimon Glass }; 4196449a506SSimon Glass 4206449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4216449a506SSimon Glass const char **namep) 4226449a506SSimon Glass { 423e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 4246449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4256449a506SSimon Glass 4266449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4276449a506SSimon Glass if (!device_active(dev)) 4286449a506SSimon Glass return -ENODEV; 4296449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4306449a506SSimon Glass return -EINVAL; 4316449a506SSimon Glass if (namep) 4326449a506SSimon Glass *namep = uc_priv->name[offset]; 4336449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4346449a506SSimon Glass return GPIOF_UNUSED; 4356449a506SSimon Glass if (ops->get_function) { 4366449a506SSimon Glass int ret; 4376449a506SSimon Glass 4386449a506SSimon Glass ret = ops->get_function(dev, offset); 4396449a506SSimon Glass if (ret < 0) 4406449a506SSimon Glass return ret; 4416449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4426449a506SSimon Glass return -ENODATA; 4436449a506SSimon Glass return ret; 4446449a506SSimon Glass } 4456449a506SSimon Glass 4466449a506SSimon Glass return GPIOF_UNKNOWN; 4476449a506SSimon Glass } 4486449a506SSimon Glass 4496449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4506449a506SSimon Glass { 4516449a506SSimon Glass return get_function(dev, offset, true, namep); 4526449a506SSimon Glass } 4536449a506SSimon Glass 4546449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 4556449a506SSimon Glass { 4566449a506SSimon Glass return get_function(dev, offset, false, namep); 4576449a506SSimon Glass } 4586449a506SSimon Glass 4590757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 4600757535aSSimon Glass { 4610757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4620757535aSSimon Glass struct gpio_dev_priv *priv; 4630757535aSSimon Glass char *str = buf; 4640757535aSSimon Glass int func; 4650757535aSSimon Glass int ret; 4660757535aSSimon Glass int len; 4670757535aSSimon Glass 4680757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4690757535aSSimon Glass 4700757535aSSimon Glass *buf = 0; 471e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 4720757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 4730757535aSSimon Glass if (ret < 0) 4740757535aSSimon Glass return ret; 4750757535aSSimon Glass func = ret; 4760757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 4770757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 4780757535aSSimon Glass offset, gpio_function[func]); 4790757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 4800757535aSSimon Glass func == GPIOF_UNUSED) { 4810757535aSSimon Glass const char *label; 4820757535aSSimon Glass bool used; 4830757535aSSimon Glass 4840757535aSSimon Glass ret = ops->get_value(dev, offset); 4850757535aSSimon Glass if (ret < 0) 4860757535aSSimon Glass return ret; 4870757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 4880757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 4890757535aSSimon Glass ret, 4900757535aSSimon Glass used ? 'x' : ' ', 4910757535aSSimon Glass used ? " " : "", 4920757535aSSimon Glass label ? label : ""); 4930757535aSSimon Glass } 4940757535aSSimon Glass 4950757535aSSimon Glass return 0; 4960757535aSSimon Glass } 4970757535aSSimon Glass 498e5901c94SSimon Glass /* 499e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 500e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 501e5901c94SSimon Glass */ 502e5901c94SSimon Glass unsigned gpio_get_values_as_int(const int *gpio_num_array) 503e5901c94SSimon Glass { 504e5901c94SSimon Glass int gpio; 505e5901c94SSimon Glass unsigned bitmask = 1; 506e5901c94SSimon Glass unsigned vector = 0; 507e5901c94SSimon Glass 508e5901c94SSimon Glass while (bitmask && 509e5901c94SSimon Glass ((gpio = *gpio_num_array++) != -1)) { 510e5901c94SSimon Glass if (gpio_get_value(gpio)) 511e5901c94SSimon Glass vector |= bitmask; 512e5901c94SSimon Glass bitmask <<= 1; 513e5901c94SSimon Glass } 514e5901c94SSimon Glass return vector; 515e5901c94SSimon Glass } 516e5901c94SSimon Glass 5173669e0e7SSimon Glass static int _gpio_request_by_name_nodev(const void *blob, int node, 5183669e0e7SSimon Glass const char *list_name, int index, 5193669e0e7SSimon Glass struct gpio_desc *desc, int flags, 5203669e0e7SSimon Glass bool add_index) 5213669e0e7SSimon Glass { 5223669e0e7SSimon Glass struct fdtdec_phandle_args args; 5233669e0e7SSimon Glass int ret; 5243669e0e7SSimon Glass 5253669e0e7SSimon Glass desc->dev = NULL; 5263669e0e7SSimon Glass desc->offset = 0; 5273669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(blob, node, list_name, 5283669e0e7SSimon Glass "#gpio-cells", 0, index, &args); 5293669e0e7SSimon Glass if (ret) { 5303669e0e7SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__); 5313669e0e7SSimon Glass goto err; 5323669e0e7SSimon Glass } 5333669e0e7SSimon Glass 5343669e0e7SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node, 5353669e0e7SSimon Glass &desc->dev); 5363669e0e7SSimon Glass if (ret) { 5373669e0e7SSimon Glass debug("%s: uclass_get_device_by_of_offset failed\n", __func__); 5383669e0e7SSimon Glass goto err; 5393669e0e7SSimon Glass } 5403669e0e7SSimon Glass ret = gpio_find_and_xlate(desc, &args); 5413669e0e7SSimon Glass if (ret) { 5423669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 5433669e0e7SSimon Glass goto err; 5443669e0e7SSimon Glass } 5453669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 5463669e0e7SSimon Glass fdt_get_name(blob, node, NULL), 5473669e0e7SSimon Glass list_name, index); 5483669e0e7SSimon Glass if (ret) { 5493669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 5503669e0e7SSimon Glass goto err; 5513669e0e7SSimon Glass } 5523669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 5533669e0e7SSimon Glass if (ret) { 5543669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 5553669e0e7SSimon Glass goto err; 5563669e0e7SSimon Glass } 5573669e0e7SSimon Glass 5583669e0e7SSimon Glass return 0; 5593669e0e7SSimon Glass err: 5603669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 5613669e0e7SSimon Glass __func__, fdt_get_name(blob, node, NULL), list_name, index, ret); 5623669e0e7SSimon Glass return ret; 5633669e0e7SSimon Glass } 5643669e0e7SSimon Glass 5653669e0e7SSimon Glass int gpio_request_by_name_nodev(const void *blob, int node, 5663669e0e7SSimon Glass const char *list_name, int index, 5673669e0e7SSimon Glass struct gpio_desc *desc, int flags) 5683669e0e7SSimon Glass { 5693669e0e7SSimon Glass return _gpio_request_by_name_nodev(blob, node, list_name, index, desc, 5703669e0e7SSimon Glass flags, index > 0); 5713669e0e7SSimon Glass } 5723669e0e7SSimon Glass 5733669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 5743669e0e7SSimon Glass struct gpio_desc *desc, int flags) 5753669e0e7SSimon Glass { 5763669e0e7SSimon Glass /* 5773669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 5783669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 5793669e0e7SSimon Glass * gpio_request_by_name_nodev() can be dropped. 5803669e0e7SSimon Glass */ 5813669e0e7SSimon Glass return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset, 5823669e0e7SSimon Glass list_name, index, desc, flags); 5833669e0e7SSimon Glass } 5843669e0e7SSimon Glass 5853669e0e7SSimon Glass int gpio_request_list_by_name_nodev(const void *blob, int node, 5863669e0e7SSimon Glass const char *list_name, 5873669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 5883669e0e7SSimon Glass int flags) 5893669e0e7SSimon Glass { 5903669e0e7SSimon Glass int count; 5913669e0e7SSimon Glass int ret; 5923669e0e7SSimon Glass 593*2984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 5943669e0e7SSimon Glass ret = _gpio_request_by_name_nodev(blob, node, list_name, count, 5953669e0e7SSimon Glass &desc[count], flags, true); 5963669e0e7SSimon Glass if (ret == -ENOENT) 5973669e0e7SSimon Glass break; 5983669e0e7SSimon Glass else if (ret) 5993669e0e7SSimon Glass goto err; 6003669e0e7SSimon Glass } 6013669e0e7SSimon Glass 6023669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 6033669e0e7SSimon Glass return count; 6043669e0e7SSimon Glass 6053669e0e7SSimon Glass err: 6063669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 6073669e0e7SSimon Glass 6083669e0e7SSimon Glass return ret; 6093669e0e7SSimon Glass } 6103669e0e7SSimon Glass 6113669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 6123669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6133669e0e7SSimon Glass int flags) 6143669e0e7SSimon Glass { 6153669e0e7SSimon Glass /* 6163669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6173669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6183669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 6193669e0e7SSimon Glass */ 6203669e0e7SSimon Glass return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset, 6213669e0e7SSimon Glass list_name, desc, max_count, 6223669e0e7SSimon Glass flags); 6233669e0e7SSimon Glass } 6243669e0e7SSimon Glass 6253669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 6263669e0e7SSimon Glass { 6273669e0e7SSimon Glass int ret; 6283669e0e7SSimon Glass 6293669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 6303669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 6313669e0e7SSimon Glass NULL); 6323669e0e7SSimon Glass if (ret) { 6333669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 6343669e0e7SSimon Glass __func__, dev->name, list_name, ret); 6353669e0e7SSimon Glass } 6363669e0e7SSimon Glass 6373669e0e7SSimon Glass return ret; 6383669e0e7SSimon Glass } 6393669e0e7SSimon Glass 6403669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 6413669e0e7SSimon Glass { 6423669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 6433669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 6443669e0e7SSimon Glass } 6453669e0e7SSimon Glass 6463669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 6473669e0e7SSimon Glass { 6483669e0e7SSimon Glass int i; 6493669e0e7SSimon Glass 6503669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 6513669e0e7SSimon Glass for (i = 0; i < count; i++) 6523669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 6533669e0e7SSimon Glass 6543669e0e7SSimon Glass return 0; 6553669e0e7SSimon Glass } 6563669e0e7SSimon Glass 6573669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 6583669e0e7SSimon Glass { 6593669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 6603669e0e7SSimon Glass } 6613669e0e7SSimon Glass 66296495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 663b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 66496495d90SSimon Glass { 66596495d90SSimon Glass struct gpio_dev_priv *uc_priv; 66654c5d08aSHeiko Schocher struct udevice *dev; 66796495d90SSimon Glass struct uclass *uc; 66896495d90SSimon Glass unsigned base; 66996495d90SSimon Glass int ret; 67096495d90SSimon Glass 67196495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 67296495d90SSimon Glass if (ret) 67396495d90SSimon Glass return ret; 67496495d90SSimon Glass 67596495d90SSimon Glass /* Ensure that we have a base for each bank */ 67696495d90SSimon Glass base = 0; 67796495d90SSimon Glass uclass_foreach_dev(dev, uc) { 678b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 679e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 68096495d90SSimon Glass uc_priv->gpio_base = base; 68196495d90SSimon Glass base += uc_priv->gpio_count; 68296495d90SSimon Glass } 68396495d90SSimon Glass } 68496495d90SSimon Glass 68596495d90SSimon Glass return 0; 68696495d90SSimon Glass } 68796495d90SSimon Glass 68854c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 68996495d90SSimon Glass { 690e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 691b892d127SSimon Glass 692b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 693b892d127SSimon Glass if (!uc_priv->name) 694b892d127SSimon Glass return -ENOMEM; 695b892d127SSimon Glass 696b892d127SSimon Glass return gpio_renumber(NULL); 69796495d90SSimon Glass } 69896495d90SSimon Glass 69954c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 70096495d90SSimon Glass { 701e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 702b892d127SSimon Glass int i; 703b892d127SSimon Glass 704b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 705b892d127SSimon Glass if (uc_priv->name[i]) 706b892d127SSimon Glass free(uc_priv->name[i]); 707b892d127SSimon Glass } 708b892d127SSimon Glass free(uc_priv->name); 709b892d127SSimon Glass 710b892d127SSimon Glass return gpio_renumber(dev); 71196495d90SSimon Glass } 71296495d90SSimon Glass 71396495d90SSimon Glass UCLASS_DRIVER(gpio) = { 71496495d90SSimon Glass .id = UCLASS_GPIO, 71596495d90SSimon Glass .name = "gpio", 71696495d90SSimon Glass .post_probe = gpio_post_probe, 71796495d90SSimon Glass .pre_remove = gpio_pre_remove, 71896495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 71996495d90SSimon Glass }; 720