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 5132ec1598SSimon Glass int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) 5296495d90SSimon Glass { 53fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 5454c5d08aSHeiko Schocher struct udevice *dev; 55fe1ef503SSimon Glass ulong offset; 56fe1ef503SSimon Glass int numeric; 5796495d90SSimon Glass int ret; 5896495d90SSimon Glass 59fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 6096495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 6196495d90SSimon Glass dev; 6296495d90SSimon Glass ret = uclass_next_device(&dev)) { 6396495d90SSimon Glass int len; 6496495d90SSimon Glass 65e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 66fe1ef503SSimon Glass if (numeric != -1) { 67fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 68fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 69fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 70fe1ef503SSimon Glass break; 71fe1ef503SSimon Glass } 72fe1ef503SSimon Glass 7396495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7496495d90SSimon Glass 75939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 76fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 77fe1ef503SSimon Glass break; 78fe1ef503SSimon Glass } 79fe1ef503SSimon Glass } 80fe1ef503SSimon Glass 81fe1ef503SSimon Glass if (!dev) 82fe1ef503SSimon Glass return ret ? ret : -EINVAL; 83fe1ef503SSimon Glass 8432ec1598SSimon Glass desc->dev = dev; 8532ec1598SSimon Glass desc->offset = offset; 8632ec1598SSimon Glass 8732ec1598SSimon Glass return 0; 8832ec1598SSimon Glass } 8932ec1598SSimon Glass 9032ec1598SSimon Glass int gpio_lookup_name(const char *name, struct udevice **devp, 9132ec1598SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 9232ec1598SSimon Glass { 9332ec1598SSimon Glass struct gpio_desc desc; 9432ec1598SSimon Glass int ret; 9532ec1598SSimon Glass 9696495d90SSimon Glass if (devp) 9732ec1598SSimon Glass *devp = NULL; 9832ec1598SSimon Glass ret = dm_gpio_lookup_name(name, &desc); 9932ec1598SSimon Glass if (ret) 10032ec1598SSimon Glass return ret; 10132ec1598SSimon Glass 10232ec1598SSimon Glass if (devp) 10332ec1598SSimon Glass *devp = desc.dev; 10496495d90SSimon Glass if (offsetp) 10532ec1598SSimon Glass *offsetp = desc.offset; 10632ec1598SSimon Glass if (gpiop) { 10732ec1598SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev); 10832ec1598SSimon Glass 10932ec1598SSimon Glass *gpiop = uc_priv->gpio_base + desc.offset; 11032ec1598SSimon Glass } 11196495d90SSimon Glass 112fe1ef503SSimon Glass return 0; 11396495d90SSimon Glass } 11496495d90SSimon Glass 1153669e0e7SSimon Glass static int gpio_find_and_xlate(struct gpio_desc *desc, 1160dac4d51SSimon Glass struct fdtdec_phandle_args *args) 1170dac4d51SSimon Glass { 1180dac4d51SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); 1190dac4d51SSimon Glass 1200dac4d51SSimon Glass /* Use the first argument as the offset by default */ 1210dac4d51SSimon Glass if (args->args_count > 0) 1220dac4d51SSimon Glass desc->offset = args->args[0]; 1230dac4d51SSimon Glass else 1240dac4d51SSimon Glass desc->offset = -1; 1250dac4d51SSimon Glass desc->flags = 0; 1260dac4d51SSimon Glass 1270dac4d51SSimon Glass return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; 1280dac4d51SSimon Glass } 1290dac4d51SSimon Glass 130*efa677fbSSimon Glass int dm_gpio_request(struct gpio_desc *desc, const char *label) 131ae7123f8SSimon Glass { 132ae7123f8SSimon Glass struct udevice *dev = desc->dev; 133ae7123f8SSimon Glass struct gpio_dev_priv *uc_priv; 134ae7123f8SSimon Glass char *str; 135ae7123f8SSimon Glass int ret; 136ae7123f8SSimon Glass 137e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 138ae7123f8SSimon Glass if (uc_priv->name[desc->offset]) 139ae7123f8SSimon Glass return -EBUSY; 140ae7123f8SSimon Glass str = strdup(label); 141ae7123f8SSimon Glass if (!str) 142ae7123f8SSimon Glass return -ENOMEM; 143ae7123f8SSimon Glass if (gpio_get_ops(dev)->request) { 144ae7123f8SSimon Glass ret = gpio_get_ops(dev)->request(dev, desc->offset, label); 145ae7123f8SSimon Glass if (ret) { 146ae7123f8SSimon Glass free(str); 147ae7123f8SSimon Glass return ret; 148ae7123f8SSimon Glass } 149ae7123f8SSimon Glass } 150ae7123f8SSimon Glass uc_priv->name[desc->offset] = str; 151ae7123f8SSimon Glass 152ae7123f8SSimon Glass return 0; 153ae7123f8SSimon Glass } 154ae7123f8SSimon Glass 1553669e0e7SSimon Glass static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) 1563669e0e7SSimon Glass { 1573669e0e7SSimon Glass va_list args; 1583669e0e7SSimon Glass char buf[40]; 1593669e0e7SSimon Glass 1603669e0e7SSimon Glass va_start(args, fmt); 1613669e0e7SSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 1623669e0e7SSimon Glass va_end(args); 1633669e0e7SSimon Glass return dm_gpio_request(desc, buf); 1643669e0e7SSimon Glass } 1653669e0e7SSimon Glass 16696495d90SSimon Glass /** 16796495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 16896495d90SSimon Glass * gpio: GPIO number 16996495d90SSimon Glass * label: Name for the requested GPIO 17096495d90SSimon Glass * 171b892d127SSimon Glass * The label is copied and allocated so the caller does not need to keep 172b892d127SSimon Glass * the pointer around. 173b892d127SSimon Glass * 17496495d90SSimon Glass * This function implements the API that's compatible with current 17596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 17696495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 17796495d90SSimon Glass */ 17896495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 17996495d90SSimon Glass { 180ae7123f8SSimon Glass struct gpio_desc desc; 18196495d90SSimon Glass int ret; 18296495d90SSimon Glass 183ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 18496495d90SSimon Glass if (ret) 18596495d90SSimon Glass return ret; 18696495d90SSimon Glass 187ae7123f8SSimon Glass return dm_gpio_request(&desc, label); 18896495d90SSimon Glass } 18996495d90SSimon Glass 19096495d90SSimon Glass /** 191d44f597bSSimon Glass * gpio_requestf() - [COMPAT] Request GPIO 192d44f597bSSimon Glass * @gpio: GPIO number 193d44f597bSSimon Glass * @fmt: Format string for the requested GPIO 194d44f597bSSimon Glass * @...: Arguments for the printf() format string 195d44f597bSSimon Glass * 196d44f597bSSimon Glass * This function implements the API that's compatible with current 197d44f597bSSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 198d44f597bSSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 199d44f597bSSimon Glass */ 200d44f597bSSimon Glass int gpio_requestf(unsigned gpio, const char *fmt, ...) 201d44f597bSSimon Glass { 202d44f597bSSimon Glass va_list args; 203d44f597bSSimon Glass char buf[40]; 204d44f597bSSimon Glass 205d44f597bSSimon Glass va_start(args, fmt); 206d44f597bSSimon Glass vscnprintf(buf, sizeof(buf), fmt, args); 207d44f597bSSimon Glass va_end(args); 208d44f597bSSimon Glass return gpio_request(gpio, buf); 209d44f597bSSimon Glass } 210d44f597bSSimon Glass 211ae7123f8SSimon Glass int _dm_gpio_free(struct udevice *dev, uint offset) 21296495d90SSimon Glass { 213b892d127SSimon Glass struct gpio_dev_priv *uc_priv; 21496495d90SSimon Glass int ret; 21596495d90SSimon Glass 216e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 217b892d127SSimon Glass if (!uc_priv->name[offset]) 218b892d127SSimon Glass return -ENXIO; 219b892d127SSimon Glass if (gpio_get_ops(dev)->free) { 220b892d127SSimon Glass ret = gpio_get_ops(dev)->free(dev, offset); 221b892d127SSimon Glass if (ret) 222b892d127SSimon Glass return ret; 223b892d127SSimon Glass } 224b892d127SSimon Glass 225b892d127SSimon Glass free(uc_priv->name[offset]); 226b892d127SSimon Glass uc_priv->name[offset] = NULL; 227b892d127SSimon Glass 22896495d90SSimon Glass return 0; 229b892d127SSimon Glass } 230b892d127SSimon Glass 231ae7123f8SSimon Glass /** 232ae7123f8SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 233ae7123f8SSimon Glass * gpio: GPIO number 234ae7123f8SSimon Glass * 235ae7123f8SSimon Glass * This function implements the API that's compatible with current 236ae7123f8SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 237ae7123f8SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 238ae7123f8SSimon Glass */ 239ae7123f8SSimon Glass int gpio_free(unsigned gpio) 240b892d127SSimon Glass { 241ae7123f8SSimon Glass struct gpio_desc desc; 242ae7123f8SSimon Glass int ret; 243b892d127SSimon Glass 244ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 245ae7123f8SSimon Glass if (ret) 246ae7123f8SSimon Glass return ret; 247ae7123f8SSimon Glass 248ae7123f8SSimon Glass return _dm_gpio_free(desc.dev, desc.offset); 249ae7123f8SSimon Glass } 250ae7123f8SSimon Glass 251ae7123f8SSimon Glass static int check_reserved(struct gpio_desc *desc, const char *func) 252ae7123f8SSimon Glass { 253e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc->dev); 254ae7123f8SSimon Glass 255ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 256b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 257ae7123f8SSimon Glass desc->dev->name, func, 258ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 259ae7123f8SSimon Glass desc->offset); 260b892d127SSimon Glass return -EBUSY; 261b892d127SSimon Glass } 262b892d127SSimon Glass 263b892d127SSimon Glass return 0; 26496495d90SSimon Glass } 26596495d90SSimon Glass 26696495d90SSimon Glass /** 26796495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 26896495d90SSimon Glass * gpio: GPIO number 26996495d90SSimon Glass * 27096495d90SSimon Glass * This function implements the API that's compatible with current 27196495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 27296495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 27396495d90SSimon Glass */ 27496495d90SSimon Glass int gpio_direction_input(unsigned gpio) 27596495d90SSimon Glass { 276ae7123f8SSimon Glass struct gpio_desc desc; 27796495d90SSimon Glass int ret; 27896495d90SSimon Glass 279ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 28096495d90SSimon Glass if (ret) 28196495d90SSimon Glass return ret; 282ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 283ae7123f8SSimon Glass if (ret) 284ae7123f8SSimon Glass return ret; 28596495d90SSimon Glass 286ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 28796495d90SSimon Glass } 28896495d90SSimon Glass 28996495d90SSimon Glass /** 29096495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 29196495d90SSimon Glass * gpio: GPIO number 29296495d90SSimon Glass * value: Logical value to be set on the GPIO pin 29396495d90SSimon Glass * 29496495d90SSimon Glass * This function implements the API that's compatible with current 29596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 29696495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 29796495d90SSimon Glass */ 29896495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 29996495d90SSimon Glass { 300ae7123f8SSimon Glass struct gpio_desc desc; 30196495d90SSimon Glass int ret; 30296495d90SSimon Glass 303ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 30496495d90SSimon Glass if (ret) 30596495d90SSimon Glass return ret; 306ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 307ae7123f8SSimon Glass if (ret) 308ae7123f8SSimon Glass return ret; 30996495d90SSimon Glass 310ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 311ae7123f8SSimon Glass desc.offset, value); 312ae7123f8SSimon Glass } 313ae7123f8SSimon Glass 314ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc) 315ae7123f8SSimon Glass { 316ae7123f8SSimon Glass int value; 317ae7123f8SSimon Glass int ret; 318ae7123f8SSimon Glass 319ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 320ae7123f8SSimon Glass if (ret) 321ae7123f8SSimon Glass return ret; 322ae7123f8SSimon Glass 323ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 324ae7123f8SSimon Glass 325ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 326ae7123f8SSimon Glass } 327ae7123f8SSimon Glass 328ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value) 329ae7123f8SSimon Glass { 330ae7123f8SSimon Glass int ret; 331ae7123f8SSimon Glass 332ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 333ae7123f8SSimon Glass if (ret) 334ae7123f8SSimon Glass return ret; 335ae7123f8SSimon Glass 336ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 337ae7123f8SSimon Glass value = !value; 338ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 339ae7123f8SSimon Glass return 0; 340ae7123f8SSimon Glass } 341ae7123f8SSimon Glass 342ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 343ae7123f8SSimon Glass { 344ae7123f8SSimon Glass struct udevice *dev = desc->dev; 345ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 346ae7123f8SSimon Glass int ret; 347ae7123f8SSimon Glass 348ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 349ae7123f8SSimon Glass if (ret) 350ae7123f8SSimon Glass return ret; 351ae7123f8SSimon Glass 352ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 353ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 354ae7123f8SSimon Glass 355ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 356ae7123f8SSimon Glass value = !value; 357ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 358ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 359ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 360ae7123f8SSimon Glass } 361ae7123f8SSimon Glass if (ret) 362ae7123f8SSimon Glass return ret; 363ae7123f8SSimon Glass /* 364ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 365ae7123f8SSimon Glass * futures 366ae7123f8SSimon Glass */ 367ae7123f8SSimon Glass desc->flags = flags; 368ae7123f8SSimon Glass 369ae7123f8SSimon Glass return 0; 370ae7123f8SSimon Glass } 371ae7123f8SSimon Glass 372ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 373ae7123f8SSimon Glass { 374ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 37596495d90SSimon Glass } 37696495d90SSimon Glass 37796495d90SSimon Glass /** 37896495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 37996495d90SSimon Glass * gpio: GPIO number 38096495d90SSimon Glass * 38196495d90SSimon Glass * This function implements the API that's compatible with current 38296495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 38396495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 38496495d90SSimon Glass * on error. 38596495d90SSimon Glass */ 38696495d90SSimon Glass int gpio_get_value(unsigned gpio) 38796495d90SSimon Glass { 38896495d90SSimon Glass int ret; 38996495d90SSimon Glass 390ae7123f8SSimon Glass struct gpio_desc desc; 391ae7123f8SSimon Glass 392ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 39396495d90SSimon Glass if (ret) 39496495d90SSimon Glass return ret; 395ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 39696495d90SSimon Glass } 39796495d90SSimon Glass 39896495d90SSimon Glass /** 39996495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 40096495d90SSimon Glass * gpio: GPIO number 40196495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 40296495d90SSimon Glass * 40396495d90SSimon Glass * This function implements the API that's compatible with current 40496495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 40596495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 40696495d90SSimon Glass */ 40796495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 40896495d90SSimon Glass { 409ae7123f8SSimon Glass struct gpio_desc desc; 41096495d90SSimon Glass int ret; 41196495d90SSimon Glass 412ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 41396495d90SSimon Glass if (ret) 41496495d90SSimon Glass return ret; 415ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 41696495d90SSimon Glass } 41796495d90SSimon Glass 41854c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 41996495d90SSimon Glass { 42096495d90SSimon Glass struct gpio_dev_priv *priv; 42196495d90SSimon Glass 42296495d90SSimon Glass /* Must be called on an active device */ 423e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 42496495d90SSimon Glass assert(priv); 42596495d90SSimon Glass 42696495d90SSimon Glass *bit_count = priv->gpio_count; 42796495d90SSimon Glass return priv->bank_name; 42896495d90SSimon Glass } 42996495d90SSimon Glass 4306449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4316449a506SSimon Glass "input", 4326449a506SSimon Glass "output", 4336449a506SSimon Glass "unused", 4346449a506SSimon Glass "unknown", 4356449a506SSimon Glass "func", 4366449a506SSimon Glass }; 4376449a506SSimon Glass 4386449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4396449a506SSimon Glass const char **namep) 4406449a506SSimon Glass { 441e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 4426449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4436449a506SSimon Glass 4446449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4456449a506SSimon Glass if (!device_active(dev)) 4466449a506SSimon Glass return -ENODEV; 4476449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4486449a506SSimon Glass return -EINVAL; 4496449a506SSimon Glass if (namep) 4506449a506SSimon Glass *namep = uc_priv->name[offset]; 4516449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4526449a506SSimon Glass return GPIOF_UNUSED; 4536449a506SSimon Glass if (ops->get_function) { 4546449a506SSimon Glass int ret; 4556449a506SSimon Glass 4566449a506SSimon Glass ret = ops->get_function(dev, offset); 4576449a506SSimon Glass if (ret < 0) 4586449a506SSimon Glass return ret; 4596449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4606449a506SSimon Glass return -ENODATA; 4616449a506SSimon Glass return ret; 4626449a506SSimon Glass } 4636449a506SSimon Glass 4646449a506SSimon Glass return GPIOF_UNKNOWN; 4656449a506SSimon Glass } 4666449a506SSimon Glass 4676449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4686449a506SSimon Glass { 4696449a506SSimon Glass return get_function(dev, offset, true, namep); 4706449a506SSimon Glass } 4716449a506SSimon Glass 4726449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 4736449a506SSimon Glass { 4746449a506SSimon Glass return get_function(dev, offset, false, namep); 4756449a506SSimon Glass } 4766449a506SSimon Glass 4770757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 4780757535aSSimon Glass { 4790757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4800757535aSSimon Glass struct gpio_dev_priv *priv; 4810757535aSSimon Glass char *str = buf; 4820757535aSSimon Glass int func; 4830757535aSSimon Glass int ret; 4840757535aSSimon Glass int len; 4850757535aSSimon Glass 4860757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4870757535aSSimon Glass 4880757535aSSimon Glass *buf = 0; 489e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 4900757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 4910757535aSSimon Glass if (ret < 0) 4920757535aSSimon Glass return ret; 4930757535aSSimon Glass func = ret; 4940757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 4950757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 4960757535aSSimon Glass offset, gpio_function[func]); 4970757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 4980757535aSSimon Glass func == GPIOF_UNUSED) { 4990757535aSSimon Glass const char *label; 5000757535aSSimon Glass bool used; 5010757535aSSimon Glass 5020757535aSSimon Glass ret = ops->get_value(dev, offset); 5030757535aSSimon Glass if (ret < 0) 5040757535aSSimon Glass return ret; 5050757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 5060757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 5070757535aSSimon Glass ret, 5080757535aSSimon Glass used ? 'x' : ' ', 5090757535aSSimon Glass used ? " " : "", 5100757535aSSimon Glass label ? label : ""); 5110757535aSSimon Glass } 5120757535aSSimon Glass 5130757535aSSimon Glass return 0; 5140757535aSSimon Glass } 5150757535aSSimon Glass 516962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 517962f5cafSSimon Glass { 518962f5cafSSimon Glass int i, ret; 519962f5cafSSimon Glass int gpio; 520962f5cafSSimon Glass 521962f5cafSSimon Glass for (i = 0; i < 32; i++) { 522962f5cafSSimon Glass gpio = gpio_num_array[i]; 523962f5cafSSimon Glass if (gpio == -1) 524962f5cafSSimon Glass break; 525962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 526962f5cafSSimon Glass if (ret) 527962f5cafSSimon Glass goto err; 528962f5cafSSimon Glass ret = gpio_direction_input(gpio); 529962f5cafSSimon Glass if (ret) { 530962f5cafSSimon Glass gpio_free(gpio); 531962f5cafSSimon Glass goto err; 532962f5cafSSimon Glass } 533962f5cafSSimon Glass } 534962f5cafSSimon Glass 535962f5cafSSimon Glass return 0; 536962f5cafSSimon Glass err: 537962f5cafSSimon Glass for (i--; i >= 0; i--) 538962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 539962f5cafSSimon Glass 540962f5cafSSimon Glass return ret; 541962f5cafSSimon Glass } 542962f5cafSSimon Glass 543e5901c94SSimon Glass /* 544e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 545e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 546e5901c94SSimon Glass */ 547962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 548e5901c94SSimon Glass { 549e5901c94SSimon Glass int gpio; 550e5901c94SSimon Glass unsigned bitmask = 1; 551e5901c94SSimon Glass unsigned vector = 0; 552962f5cafSSimon Glass int ret; 553e5901c94SSimon Glass 554e5901c94SSimon Glass while (bitmask && 555962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 556962f5cafSSimon Glass ret = gpio_get_value(gpio); 557962f5cafSSimon Glass if (ret < 0) 558962f5cafSSimon Glass return ret; 559962f5cafSSimon Glass else if (ret) 560e5901c94SSimon Glass vector |= bitmask; 561e5901c94SSimon Glass bitmask <<= 1; 562e5901c94SSimon Glass } 563962f5cafSSimon Glass 564e5901c94SSimon Glass return vector; 565e5901c94SSimon Glass } 566e5901c94SSimon Glass 5673669e0e7SSimon Glass static int _gpio_request_by_name_nodev(const void *blob, int node, 5683669e0e7SSimon Glass const char *list_name, int index, 5693669e0e7SSimon Glass struct gpio_desc *desc, int flags, 5703669e0e7SSimon Glass bool add_index) 5713669e0e7SSimon Glass { 5723669e0e7SSimon Glass struct fdtdec_phandle_args args; 5733669e0e7SSimon Glass int ret; 5743669e0e7SSimon Glass 5753669e0e7SSimon Glass desc->dev = NULL; 5763669e0e7SSimon Glass desc->offset = 0; 5773669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(blob, node, list_name, 5783669e0e7SSimon Glass "#gpio-cells", 0, index, &args); 5793669e0e7SSimon Glass if (ret) { 5803669e0e7SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__); 5813669e0e7SSimon Glass goto err; 5823669e0e7SSimon Glass } 5833669e0e7SSimon Glass 5843669e0e7SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node, 5853669e0e7SSimon Glass &desc->dev); 5863669e0e7SSimon Glass if (ret) { 5873669e0e7SSimon Glass debug("%s: uclass_get_device_by_of_offset failed\n", __func__); 5883669e0e7SSimon Glass goto err; 5893669e0e7SSimon Glass } 5903669e0e7SSimon Glass ret = gpio_find_and_xlate(desc, &args); 5913669e0e7SSimon Glass if (ret) { 5923669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 5933669e0e7SSimon Glass goto err; 5943669e0e7SSimon Glass } 5953669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 5963669e0e7SSimon Glass fdt_get_name(blob, node, NULL), 5973669e0e7SSimon Glass list_name, index); 5983669e0e7SSimon Glass if (ret) { 5993669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 6003669e0e7SSimon Glass goto err; 6013669e0e7SSimon Glass } 6023669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 6033669e0e7SSimon Glass if (ret) { 6043669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 6053669e0e7SSimon Glass goto err; 6063669e0e7SSimon Glass } 6073669e0e7SSimon Glass 6083669e0e7SSimon Glass return 0; 6093669e0e7SSimon Glass err: 6103669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 6113669e0e7SSimon Glass __func__, fdt_get_name(blob, node, NULL), list_name, index, ret); 6123669e0e7SSimon Glass return ret; 6133669e0e7SSimon Glass } 6143669e0e7SSimon Glass 6153669e0e7SSimon Glass int gpio_request_by_name_nodev(const void *blob, int node, 6163669e0e7SSimon Glass const char *list_name, int index, 6173669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6183669e0e7SSimon Glass { 6193669e0e7SSimon Glass return _gpio_request_by_name_nodev(blob, node, list_name, index, desc, 6203669e0e7SSimon Glass flags, index > 0); 6213669e0e7SSimon Glass } 6223669e0e7SSimon Glass 6233669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 6243669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6253669e0e7SSimon Glass { 6263669e0e7SSimon Glass /* 6273669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6283669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6293669e0e7SSimon Glass * gpio_request_by_name_nodev() can be dropped. 6303669e0e7SSimon Glass */ 6313669e0e7SSimon Glass return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset, 6323669e0e7SSimon Glass list_name, index, desc, flags); 6333669e0e7SSimon Glass } 6343669e0e7SSimon Glass 6353669e0e7SSimon Glass int gpio_request_list_by_name_nodev(const void *blob, int node, 6363669e0e7SSimon Glass const char *list_name, 6373669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6383669e0e7SSimon Glass int flags) 6393669e0e7SSimon Glass { 6403669e0e7SSimon Glass int count; 6413669e0e7SSimon Glass int ret; 6423669e0e7SSimon Glass 6432984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 6443669e0e7SSimon Glass ret = _gpio_request_by_name_nodev(blob, node, list_name, count, 6453669e0e7SSimon Glass &desc[count], flags, true); 6463669e0e7SSimon Glass if (ret == -ENOENT) 6473669e0e7SSimon Glass break; 6483669e0e7SSimon Glass else if (ret) 6493669e0e7SSimon Glass goto err; 6503669e0e7SSimon Glass } 6513669e0e7SSimon Glass 6523669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 6533669e0e7SSimon Glass return count; 6543669e0e7SSimon Glass 6553669e0e7SSimon Glass err: 6563669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 6573669e0e7SSimon Glass 6583669e0e7SSimon Glass return ret; 6593669e0e7SSimon Glass } 6603669e0e7SSimon Glass 6613669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 6623669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6633669e0e7SSimon Glass int flags) 6643669e0e7SSimon Glass { 6653669e0e7SSimon Glass /* 6663669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6673669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6683669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 6693669e0e7SSimon Glass */ 6703669e0e7SSimon Glass return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset, 6713669e0e7SSimon Glass list_name, desc, max_count, 6723669e0e7SSimon Glass flags); 6733669e0e7SSimon Glass } 6743669e0e7SSimon Glass 6753669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 6763669e0e7SSimon Glass { 6773669e0e7SSimon Glass int ret; 6783669e0e7SSimon Glass 6793669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 6803669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 6813669e0e7SSimon Glass NULL); 6823669e0e7SSimon Glass if (ret) { 6833669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 6843669e0e7SSimon Glass __func__, dev->name, list_name, ret); 6853669e0e7SSimon Glass } 6863669e0e7SSimon Glass 6873669e0e7SSimon Glass return ret; 6883669e0e7SSimon Glass } 6893669e0e7SSimon Glass 6903669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 6913669e0e7SSimon Glass { 6923669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 6933669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 6943669e0e7SSimon Glass } 6953669e0e7SSimon Glass 6963669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 6973669e0e7SSimon Glass { 6983669e0e7SSimon Glass int i; 6993669e0e7SSimon Glass 7003669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7013669e0e7SSimon Glass for (i = 0; i < count; i++) 7023669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 7033669e0e7SSimon Glass 7043669e0e7SSimon Glass return 0; 7053669e0e7SSimon Glass } 7063669e0e7SSimon Glass 7073669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 7083669e0e7SSimon Glass { 7093669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 7103669e0e7SSimon Glass } 7113669e0e7SSimon Glass 71296495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 713b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 71496495d90SSimon Glass { 71596495d90SSimon Glass struct gpio_dev_priv *uc_priv; 71654c5d08aSHeiko Schocher struct udevice *dev; 71796495d90SSimon Glass struct uclass *uc; 71896495d90SSimon Glass unsigned base; 71996495d90SSimon Glass int ret; 72096495d90SSimon Glass 72196495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 72296495d90SSimon Glass if (ret) 72396495d90SSimon Glass return ret; 72496495d90SSimon Glass 72596495d90SSimon Glass /* Ensure that we have a base for each bank */ 72696495d90SSimon Glass base = 0; 72796495d90SSimon Glass uclass_foreach_dev(dev, uc) { 728b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 729e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 73096495d90SSimon Glass uc_priv->gpio_base = base; 73196495d90SSimon Glass base += uc_priv->gpio_count; 73296495d90SSimon Glass } 73396495d90SSimon Glass } 73496495d90SSimon Glass 73596495d90SSimon Glass return 0; 73696495d90SSimon Glass } 73796495d90SSimon Glass 73856a71f89SSimon Glass int gpio_get_number(struct gpio_desc *desc) 73956a71f89SSimon Glass { 74056a71f89SSimon Glass struct udevice *dev = desc->dev; 74156a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 74256a71f89SSimon Glass 74356a71f89SSimon Glass if (!dev) 74456a71f89SSimon Glass return -1; 74556a71f89SSimon Glass uc_priv = dev->uclass_priv; 74656a71f89SSimon Glass 74756a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 74856a71f89SSimon Glass } 74956a71f89SSimon Glass 75054c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 75196495d90SSimon Glass { 752e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 753b892d127SSimon Glass 754b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 755b892d127SSimon Glass if (!uc_priv->name) 756b892d127SSimon Glass return -ENOMEM; 757b892d127SSimon Glass 758b892d127SSimon Glass return gpio_renumber(NULL); 75996495d90SSimon Glass } 76096495d90SSimon Glass 76154c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 76296495d90SSimon Glass { 763e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 764b892d127SSimon Glass int i; 765b892d127SSimon Glass 766b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 767b892d127SSimon Glass if (uc_priv->name[i]) 768b892d127SSimon Glass free(uc_priv->name[i]); 769b892d127SSimon Glass } 770b892d127SSimon Glass free(uc_priv->name); 771b892d127SSimon Glass 772b892d127SSimon Glass return gpio_renumber(dev); 77396495d90SSimon Glass } 77496495d90SSimon Glass 77596495d90SSimon Glass UCLASS_DRIVER(gpio) = { 77696495d90SSimon Glass .id = UCLASS_GPIO, 77796495d90SSimon Glass .name = "gpio", 778ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 77996495d90SSimon Glass .post_probe = gpio_post_probe, 78096495d90SSimon Glass .pre_remove = gpio_pre_remove, 78196495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 78296495d90SSimon Glass }; 783