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 130efa677fbSSimon 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 { 253*eca48665SSimon Glass struct gpio_dev_priv *uc_priv; 254ae7123f8SSimon Glass 255*eca48665SSimon Glass if (!dm_gpio_is_valid(desc)) 256*eca48665SSimon Glass return -ENOENT; 257*eca48665SSimon Glass 258*eca48665SSimon Glass uc_priv = dev_get_uclass_priv(desc->dev); 259ae7123f8SSimon Glass if (!uc_priv->name[desc->offset]) { 260b892d127SSimon Glass printf("%s: %s: error: gpio %s%d not reserved\n", 261ae7123f8SSimon Glass desc->dev->name, func, 262ae7123f8SSimon Glass uc_priv->bank_name ? uc_priv->bank_name : "", 263ae7123f8SSimon Glass desc->offset); 264b892d127SSimon Glass return -EBUSY; 265b892d127SSimon Glass } 266b892d127SSimon Glass 267b892d127SSimon Glass return 0; 26896495d90SSimon Glass } 26996495d90SSimon Glass 27096495d90SSimon Glass /** 27196495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 27296495d90SSimon Glass * gpio: GPIO number 27396495d90SSimon Glass * 27496495d90SSimon Glass * This function implements the API that's compatible with current 27596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 27696495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 27796495d90SSimon Glass */ 27896495d90SSimon Glass int gpio_direction_input(unsigned gpio) 27996495d90SSimon Glass { 280ae7123f8SSimon Glass struct gpio_desc desc; 28196495d90SSimon Glass int ret; 28296495d90SSimon Glass 283ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 28496495d90SSimon Glass if (ret) 28596495d90SSimon Glass return ret; 286ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_input"); 287ae7123f8SSimon Glass if (ret) 288ae7123f8SSimon Glass return ret; 28996495d90SSimon Glass 290ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); 29196495d90SSimon Glass } 29296495d90SSimon Glass 29396495d90SSimon Glass /** 29496495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 29596495d90SSimon Glass * gpio: GPIO number 29696495d90SSimon Glass * value: Logical value to be set on the GPIO pin 29796495d90SSimon Glass * 29896495d90SSimon Glass * This function implements the API that's compatible with current 29996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 30096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 30196495d90SSimon Glass */ 30296495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 30396495d90SSimon Glass { 304ae7123f8SSimon Glass struct gpio_desc desc; 30596495d90SSimon Glass int ret; 30696495d90SSimon Glass 307ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 30896495d90SSimon Glass if (ret) 30996495d90SSimon Glass return ret; 310ae7123f8SSimon Glass ret = check_reserved(&desc, "dir_output"); 311ae7123f8SSimon Glass if (ret) 312ae7123f8SSimon Glass return ret; 31396495d90SSimon Glass 314ae7123f8SSimon Glass return gpio_get_ops(desc.dev)->direction_output(desc.dev, 315ae7123f8SSimon Glass desc.offset, value); 316ae7123f8SSimon Glass } 317ae7123f8SSimon Glass 318ae7123f8SSimon Glass int dm_gpio_get_value(struct gpio_desc *desc) 319ae7123f8SSimon Glass { 320ae7123f8SSimon Glass int value; 321ae7123f8SSimon Glass int ret; 322ae7123f8SSimon Glass 323ae7123f8SSimon Glass ret = check_reserved(desc, "get_value"); 324ae7123f8SSimon Glass if (ret) 325ae7123f8SSimon Glass return ret; 326ae7123f8SSimon Glass 327ae7123f8SSimon Glass value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); 328ae7123f8SSimon Glass 329ae7123f8SSimon Glass return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; 330ae7123f8SSimon Glass } 331ae7123f8SSimon Glass 332ae7123f8SSimon Glass int dm_gpio_set_value(struct gpio_desc *desc, int value) 333ae7123f8SSimon Glass { 334ae7123f8SSimon Glass int ret; 335ae7123f8SSimon Glass 336ae7123f8SSimon Glass ret = check_reserved(desc, "set_value"); 337ae7123f8SSimon Glass if (ret) 338ae7123f8SSimon Glass return ret; 339ae7123f8SSimon Glass 340ae7123f8SSimon Glass if (desc->flags & GPIOD_ACTIVE_LOW) 341ae7123f8SSimon Glass value = !value; 342ae7123f8SSimon Glass gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); 343ae7123f8SSimon Glass return 0; 344ae7123f8SSimon Glass } 345ae7123f8SSimon Glass 346ae7123f8SSimon Glass int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) 347ae7123f8SSimon Glass { 348ae7123f8SSimon Glass struct udevice *dev = desc->dev; 349ae7123f8SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 350ae7123f8SSimon Glass int ret; 351ae7123f8SSimon Glass 352ae7123f8SSimon Glass ret = check_reserved(desc, "set_dir"); 353ae7123f8SSimon Glass if (ret) 354ae7123f8SSimon Glass return ret; 355ae7123f8SSimon Glass 356ae7123f8SSimon Glass if (flags & GPIOD_IS_OUT) { 357ae7123f8SSimon Glass int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; 358ae7123f8SSimon Glass 359ae7123f8SSimon Glass if (flags & GPIOD_ACTIVE_LOW) 360ae7123f8SSimon Glass value = !value; 361ae7123f8SSimon Glass ret = ops->direction_output(dev, desc->offset, value); 362ae7123f8SSimon Glass } else if (flags & GPIOD_IS_IN) { 363ae7123f8SSimon Glass ret = ops->direction_input(dev, desc->offset); 364ae7123f8SSimon Glass } 365ae7123f8SSimon Glass if (ret) 366ae7123f8SSimon Glass return ret; 367ae7123f8SSimon Glass /* 368ae7123f8SSimon Glass * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in 369ae7123f8SSimon Glass * futures 370ae7123f8SSimon Glass */ 371ae7123f8SSimon Glass desc->flags = flags; 372ae7123f8SSimon Glass 373ae7123f8SSimon Glass return 0; 374ae7123f8SSimon Glass } 375ae7123f8SSimon Glass 376ae7123f8SSimon Glass int dm_gpio_set_dir(struct gpio_desc *desc) 377ae7123f8SSimon Glass { 378ae7123f8SSimon Glass return dm_gpio_set_dir_flags(desc, desc->flags); 37996495d90SSimon Glass } 38096495d90SSimon Glass 38196495d90SSimon Glass /** 38296495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 38396495d90SSimon Glass * gpio: GPIO number 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 the value of the GPIO pin, or negative value 38896495d90SSimon Glass * on error. 38996495d90SSimon Glass */ 39096495d90SSimon Glass int gpio_get_value(unsigned gpio) 39196495d90SSimon Glass { 39296495d90SSimon Glass int ret; 39396495d90SSimon Glass 394ae7123f8SSimon Glass struct gpio_desc desc; 395ae7123f8SSimon Glass 396ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 39796495d90SSimon Glass if (ret) 39896495d90SSimon Glass return ret; 399ae7123f8SSimon Glass return dm_gpio_get_value(&desc); 40096495d90SSimon Glass } 40196495d90SSimon Glass 40296495d90SSimon Glass /** 40396495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 40496495d90SSimon Glass * gpio: GPIO number 40596495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 40696495d90SSimon Glass * 40796495d90SSimon Glass * This function implements the API that's compatible with current 40896495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 40996495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 41096495d90SSimon Glass */ 41196495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 41296495d90SSimon Glass { 413ae7123f8SSimon Glass struct gpio_desc desc; 41496495d90SSimon Glass int ret; 41596495d90SSimon Glass 416ae7123f8SSimon Glass ret = gpio_to_device(gpio, &desc); 41796495d90SSimon Glass if (ret) 41896495d90SSimon Glass return ret; 419ae7123f8SSimon Glass return dm_gpio_set_value(&desc, value); 42096495d90SSimon Glass } 42196495d90SSimon Glass 42254c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 42396495d90SSimon Glass { 42496495d90SSimon Glass struct gpio_dev_priv *priv; 42596495d90SSimon Glass 42696495d90SSimon Glass /* Must be called on an active device */ 427e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 42896495d90SSimon Glass assert(priv); 42996495d90SSimon Glass 43096495d90SSimon Glass *bit_count = priv->gpio_count; 43196495d90SSimon Glass return priv->bank_name; 43296495d90SSimon Glass } 43396495d90SSimon Glass 4346449a506SSimon Glass static const char * const gpio_function[GPIOF_COUNT] = { 4356449a506SSimon Glass "input", 4366449a506SSimon Glass "output", 4376449a506SSimon Glass "unused", 4386449a506SSimon Glass "unknown", 4396449a506SSimon Glass "func", 4406449a506SSimon Glass }; 4416449a506SSimon Glass 4426449a506SSimon Glass int get_function(struct udevice *dev, int offset, bool skip_unused, 4436449a506SSimon Glass const char **namep) 4446449a506SSimon Glass { 445e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 4466449a506SSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4476449a506SSimon Glass 4486449a506SSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4496449a506SSimon Glass if (!device_active(dev)) 4506449a506SSimon Glass return -ENODEV; 4516449a506SSimon Glass if (offset < 0 || offset >= uc_priv->gpio_count) 4526449a506SSimon Glass return -EINVAL; 4536449a506SSimon Glass if (namep) 4546449a506SSimon Glass *namep = uc_priv->name[offset]; 4556449a506SSimon Glass if (skip_unused && !uc_priv->name[offset]) 4566449a506SSimon Glass return GPIOF_UNUSED; 4576449a506SSimon Glass if (ops->get_function) { 4586449a506SSimon Glass int ret; 4596449a506SSimon Glass 4606449a506SSimon Glass ret = ops->get_function(dev, offset); 4616449a506SSimon Glass if (ret < 0) 4626449a506SSimon Glass return ret; 4636449a506SSimon Glass if (ret >= ARRAY_SIZE(gpio_function)) 4646449a506SSimon Glass return -ENODATA; 4656449a506SSimon Glass return ret; 4666449a506SSimon Glass } 4676449a506SSimon Glass 4686449a506SSimon Glass return GPIOF_UNKNOWN; 4696449a506SSimon Glass } 4706449a506SSimon Glass 4716449a506SSimon Glass int gpio_get_function(struct udevice *dev, int offset, const char **namep) 4726449a506SSimon Glass { 4736449a506SSimon Glass return get_function(dev, offset, true, namep); 4746449a506SSimon Glass } 4756449a506SSimon Glass 4766449a506SSimon Glass int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) 4776449a506SSimon Glass { 4786449a506SSimon Glass return get_function(dev, offset, false, namep); 4796449a506SSimon Glass } 4806449a506SSimon Glass 4810757535aSSimon Glass int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) 4820757535aSSimon Glass { 4830757535aSSimon Glass struct dm_gpio_ops *ops = gpio_get_ops(dev); 4840757535aSSimon Glass struct gpio_dev_priv *priv; 4850757535aSSimon Glass char *str = buf; 4860757535aSSimon Glass int func; 4870757535aSSimon Glass int ret; 4880757535aSSimon Glass int len; 4890757535aSSimon Glass 4900757535aSSimon Glass BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); 4910757535aSSimon Glass 4920757535aSSimon Glass *buf = 0; 493e564f054SSimon Glass priv = dev_get_uclass_priv(dev); 4940757535aSSimon Glass ret = gpio_get_raw_function(dev, offset, NULL); 4950757535aSSimon Glass if (ret < 0) 4960757535aSSimon Glass return ret; 4970757535aSSimon Glass func = ret; 4980757535aSSimon Glass len = snprintf(str, buffsize, "%s%d: %s", 4990757535aSSimon Glass priv->bank_name ? priv->bank_name : "", 5000757535aSSimon Glass offset, gpio_function[func]); 5010757535aSSimon Glass if (func == GPIOF_INPUT || func == GPIOF_OUTPUT || 5020757535aSSimon Glass func == GPIOF_UNUSED) { 5030757535aSSimon Glass const char *label; 5040757535aSSimon Glass bool used; 5050757535aSSimon Glass 5060757535aSSimon Glass ret = ops->get_value(dev, offset); 5070757535aSSimon Glass if (ret < 0) 5080757535aSSimon Glass return ret; 5090757535aSSimon Glass used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED; 5100757535aSSimon Glass snprintf(str + len, buffsize - len, ": %d [%c]%s%s", 5110757535aSSimon Glass ret, 5120757535aSSimon Glass used ? 'x' : ' ', 5130757535aSSimon Glass used ? " " : "", 5140757535aSSimon Glass label ? label : ""); 5150757535aSSimon Glass } 5160757535aSSimon Glass 5170757535aSSimon Glass return 0; 5180757535aSSimon Glass } 5190757535aSSimon Glass 520962f5cafSSimon Glass int gpio_claim_vector(const int *gpio_num_array, const char *fmt) 521962f5cafSSimon Glass { 522962f5cafSSimon Glass int i, ret; 523962f5cafSSimon Glass int gpio; 524962f5cafSSimon Glass 525962f5cafSSimon Glass for (i = 0; i < 32; i++) { 526962f5cafSSimon Glass gpio = gpio_num_array[i]; 527962f5cafSSimon Glass if (gpio == -1) 528962f5cafSSimon Glass break; 529962f5cafSSimon Glass ret = gpio_requestf(gpio, fmt, i); 530962f5cafSSimon Glass if (ret) 531962f5cafSSimon Glass goto err; 532962f5cafSSimon Glass ret = gpio_direction_input(gpio); 533962f5cafSSimon Glass if (ret) { 534962f5cafSSimon Glass gpio_free(gpio); 535962f5cafSSimon Glass goto err; 536962f5cafSSimon Glass } 537962f5cafSSimon Glass } 538962f5cafSSimon Glass 539962f5cafSSimon Glass return 0; 540962f5cafSSimon Glass err: 541962f5cafSSimon Glass for (i--; i >= 0; i--) 542962f5cafSSimon Glass gpio_free(gpio_num_array[i]); 543962f5cafSSimon Glass 544962f5cafSSimon Glass return ret; 545962f5cafSSimon Glass } 546962f5cafSSimon Glass 547e5901c94SSimon Glass /* 548e5901c94SSimon Glass * get a number comprised of multiple GPIO values. gpio_num_array points to 549e5901c94SSimon Glass * the array of gpio pin numbers to scan, terminated by -1. 550e5901c94SSimon Glass */ 551962f5cafSSimon Glass int gpio_get_values_as_int(const int *gpio_list) 552e5901c94SSimon Glass { 553e5901c94SSimon Glass int gpio; 554e5901c94SSimon Glass unsigned bitmask = 1; 555e5901c94SSimon Glass unsigned vector = 0; 556962f5cafSSimon Glass int ret; 557e5901c94SSimon Glass 558e5901c94SSimon Glass while (bitmask && 559962f5cafSSimon Glass ((gpio = *gpio_list++) != -1)) { 560962f5cafSSimon Glass ret = gpio_get_value(gpio); 561962f5cafSSimon Glass if (ret < 0) 562962f5cafSSimon Glass return ret; 563962f5cafSSimon Glass else if (ret) 564e5901c94SSimon Glass vector |= bitmask; 565e5901c94SSimon Glass bitmask <<= 1; 566e5901c94SSimon Glass } 567962f5cafSSimon Glass 568e5901c94SSimon Glass return vector; 569e5901c94SSimon Glass } 570e5901c94SSimon Glass 5713669e0e7SSimon Glass static int _gpio_request_by_name_nodev(const void *blob, int node, 5723669e0e7SSimon Glass const char *list_name, int index, 5733669e0e7SSimon Glass struct gpio_desc *desc, int flags, 5743669e0e7SSimon Glass bool add_index) 5753669e0e7SSimon Glass { 5763669e0e7SSimon Glass struct fdtdec_phandle_args args; 5773669e0e7SSimon Glass int ret; 5783669e0e7SSimon Glass 5793669e0e7SSimon Glass desc->dev = NULL; 5803669e0e7SSimon Glass desc->offset = 0; 5813669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(blob, node, list_name, 5823669e0e7SSimon Glass "#gpio-cells", 0, index, &args); 5833669e0e7SSimon Glass if (ret) { 5843669e0e7SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__); 5853669e0e7SSimon Glass goto err; 5863669e0e7SSimon Glass } 5873669e0e7SSimon Glass 5883669e0e7SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node, 5893669e0e7SSimon Glass &desc->dev); 5903669e0e7SSimon Glass if (ret) { 5913669e0e7SSimon Glass debug("%s: uclass_get_device_by_of_offset failed\n", __func__); 5923669e0e7SSimon Glass goto err; 5933669e0e7SSimon Glass } 5943669e0e7SSimon Glass ret = gpio_find_and_xlate(desc, &args); 5953669e0e7SSimon Glass if (ret) { 5963669e0e7SSimon Glass debug("%s: gpio_find_and_xlate failed\n", __func__); 5973669e0e7SSimon Glass goto err; 5983669e0e7SSimon Glass } 5993669e0e7SSimon Glass ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s", 6003669e0e7SSimon Glass fdt_get_name(blob, node, NULL), 6013669e0e7SSimon Glass list_name, index); 6023669e0e7SSimon Glass if (ret) { 6033669e0e7SSimon Glass debug("%s: dm_gpio_requestf failed\n", __func__); 6043669e0e7SSimon Glass goto err; 6053669e0e7SSimon Glass } 6063669e0e7SSimon Glass ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); 6073669e0e7SSimon Glass if (ret) { 6083669e0e7SSimon Glass debug("%s: dm_gpio_set_dir failed\n", __func__); 6093669e0e7SSimon Glass goto err; 6103669e0e7SSimon Glass } 6113669e0e7SSimon Glass 6123669e0e7SSimon Glass return 0; 6133669e0e7SSimon Glass err: 6143669e0e7SSimon Glass debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n", 6153669e0e7SSimon Glass __func__, fdt_get_name(blob, node, NULL), list_name, index, ret); 6163669e0e7SSimon Glass return ret; 6173669e0e7SSimon Glass } 6183669e0e7SSimon Glass 6193669e0e7SSimon Glass int gpio_request_by_name_nodev(const void *blob, int node, 6203669e0e7SSimon Glass const char *list_name, int index, 6213669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6223669e0e7SSimon Glass { 6233669e0e7SSimon Glass return _gpio_request_by_name_nodev(blob, node, list_name, index, desc, 6243669e0e7SSimon Glass flags, index > 0); 6253669e0e7SSimon Glass } 6263669e0e7SSimon Glass 6273669e0e7SSimon Glass int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, 6283669e0e7SSimon Glass struct gpio_desc *desc, int flags) 6293669e0e7SSimon Glass { 6303669e0e7SSimon Glass /* 6313669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6323669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6333669e0e7SSimon Glass * gpio_request_by_name_nodev() can be dropped. 6343669e0e7SSimon Glass */ 6353669e0e7SSimon Glass return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset, 6363669e0e7SSimon Glass list_name, index, desc, flags); 6373669e0e7SSimon Glass } 6383669e0e7SSimon Glass 6393669e0e7SSimon Glass int gpio_request_list_by_name_nodev(const void *blob, int node, 6403669e0e7SSimon Glass const char *list_name, 6413669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6423669e0e7SSimon Glass int flags) 6433669e0e7SSimon Glass { 6443669e0e7SSimon Glass int count; 6453669e0e7SSimon Glass int ret; 6463669e0e7SSimon Glass 6472984e7a1SPrzemyslaw Marczak for (count = 0; count < max_count; count++) { 6483669e0e7SSimon Glass ret = _gpio_request_by_name_nodev(blob, node, list_name, count, 6493669e0e7SSimon Glass &desc[count], flags, true); 6503669e0e7SSimon Glass if (ret == -ENOENT) 6513669e0e7SSimon Glass break; 6523669e0e7SSimon Glass else if (ret) 6533669e0e7SSimon Glass goto err; 6543669e0e7SSimon Glass } 6553669e0e7SSimon Glass 6563669e0e7SSimon Glass /* We ran out of GPIOs in the list */ 6573669e0e7SSimon Glass return count; 6583669e0e7SSimon Glass 6593669e0e7SSimon Glass err: 6603669e0e7SSimon Glass gpio_free_list_nodev(desc, count - 1); 6613669e0e7SSimon Glass 6623669e0e7SSimon Glass return ret; 6633669e0e7SSimon Glass } 6643669e0e7SSimon Glass 6653669e0e7SSimon Glass int gpio_request_list_by_name(struct udevice *dev, const char *list_name, 6663669e0e7SSimon Glass struct gpio_desc *desc, int max_count, 6673669e0e7SSimon Glass int flags) 6683669e0e7SSimon Glass { 6693669e0e7SSimon Glass /* 6703669e0e7SSimon Glass * This isn't ideal since we don't use dev->name in the debug() 6713669e0e7SSimon Glass * calls in gpio_request_by_name(), but we can do this until 6723669e0e7SSimon Glass * gpio_request_list_by_name_nodev() can be dropped. 6733669e0e7SSimon Glass */ 6743669e0e7SSimon Glass return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset, 6753669e0e7SSimon Glass list_name, desc, max_count, 6763669e0e7SSimon Glass flags); 6773669e0e7SSimon Glass } 6783669e0e7SSimon Glass 6793669e0e7SSimon Glass int gpio_get_list_count(struct udevice *dev, const char *list_name) 6803669e0e7SSimon Glass { 6813669e0e7SSimon Glass int ret; 6823669e0e7SSimon Glass 6833669e0e7SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 6843669e0e7SSimon Glass list_name, "#gpio-cells", 0, -1, 6853669e0e7SSimon Glass NULL); 6863669e0e7SSimon Glass if (ret) { 6873669e0e7SSimon Glass debug("%s: Node '%s', property '%s', GPIO count failed: %d\n", 6883669e0e7SSimon Glass __func__, dev->name, list_name, ret); 6893669e0e7SSimon Glass } 6903669e0e7SSimon Glass 6913669e0e7SSimon Glass return ret; 6923669e0e7SSimon Glass } 6933669e0e7SSimon Glass 6943669e0e7SSimon Glass int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) 6953669e0e7SSimon Glass { 6963669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 6973669e0e7SSimon Glass return _dm_gpio_free(desc->dev, desc->offset); 6983669e0e7SSimon Glass } 6993669e0e7SSimon Glass 7003669e0e7SSimon Glass int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count) 7013669e0e7SSimon Glass { 7023669e0e7SSimon Glass int i; 7033669e0e7SSimon Glass 7043669e0e7SSimon Glass /* For now, we don't do any checking of dev */ 7053669e0e7SSimon Glass for (i = 0; i < count; i++) 7063669e0e7SSimon Glass dm_gpio_free(dev, &desc[i]); 7073669e0e7SSimon Glass 7083669e0e7SSimon Glass return 0; 7093669e0e7SSimon Glass } 7103669e0e7SSimon Glass 7113669e0e7SSimon Glass int gpio_free_list_nodev(struct gpio_desc *desc, int count) 7123669e0e7SSimon Glass { 7133669e0e7SSimon Glass return gpio_free_list(NULL, desc, count); 7143669e0e7SSimon Glass } 7153669e0e7SSimon Glass 71696495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 717b892d127SSimon Glass static int gpio_renumber(struct udevice *removed_dev) 71896495d90SSimon Glass { 71996495d90SSimon Glass struct gpio_dev_priv *uc_priv; 72054c5d08aSHeiko Schocher struct udevice *dev; 72196495d90SSimon Glass struct uclass *uc; 72296495d90SSimon Glass unsigned base; 72396495d90SSimon Glass int ret; 72496495d90SSimon Glass 72596495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 72696495d90SSimon Glass if (ret) 72796495d90SSimon Glass return ret; 72896495d90SSimon Glass 72996495d90SSimon Glass /* Ensure that we have a base for each bank */ 73096495d90SSimon Glass base = 0; 73196495d90SSimon Glass uclass_foreach_dev(dev, uc) { 732b892d127SSimon Glass if (device_active(dev) && dev != removed_dev) { 733e564f054SSimon Glass uc_priv = dev_get_uclass_priv(dev); 73496495d90SSimon Glass uc_priv->gpio_base = base; 73596495d90SSimon Glass base += uc_priv->gpio_count; 73696495d90SSimon Glass } 73796495d90SSimon Glass } 73896495d90SSimon Glass 73996495d90SSimon Glass return 0; 74096495d90SSimon Glass } 74196495d90SSimon Glass 74256a71f89SSimon Glass int gpio_get_number(struct gpio_desc *desc) 74356a71f89SSimon Glass { 74456a71f89SSimon Glass struct udevice *dev = desc->dev; 74556a71f89SSimon Glass struct gpio_dev_priv *uc_priv; 74656a71f89SSimon Glass 74756a71f89SSimon Glass if (!dev) 74856a71f89SSimon Glass return -1; 74956a71f89SSimon Glass uc_priv = dev->uclass_priv; 75056a71f89SSimon Glass 75156a71f89SSimon Glass return uc_priv->gpio_base + desc->offset; 75256a71f89SSimon Glass } 75356a71f89SSimon Glass 75454c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 75596495d90SSimon Glass { 756e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 757b892d127SSimon Glass 758b892d127SSimon Glass uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *)); 759b892d127SSimon Glass if (!uc_priv->name) 760b892d127SSimon Glass return -ENOMEM; 761b892d127SSimon Glass 762b892d127SSimon Glass return gpio_renumber(NULL); 76396495d90SSimon Glass } 76496495d90SSimon Glass 76554c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 76696495d90SSimon Glass { 767e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 768b892d127SSimon Glass int i; 769b892d127SSimon Glass 770b892d127SSimon Glass for (i = 0; i < uc_priv->gpio_count; i++) { 771b892d127SSimon Glass if (uc_priv->name[i]) 772b892d127SSimon Glass free(uc_priv->name[i]); 773b892d127SSimon Glass } 774b892d127SSimon Glass free(uc_priv->name); 775b892d127SSimon Glass 776b892d127SSimon Glass return gpio_renumber(dev); 77796495d90SSimon Glass } 77896495d90SSimon Glass 77996495d90SSimon Glass UCLASS_DRIVER(gpio) = { 78096495d90SSimon Glass .id = UCLASS_GPIO, 78196495d90SSimon Glass .name = "gpio", 782ae89bb0dSBhuvanchandra DV .flags = DM_UC_FLAG_SEQ_ALIAS, 78396495d90SSimon Glass .post_probe = gpio_post_probe, 78496495d90SSimon Glass .pre_remove = gpio_pre_remove, 78596495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 78696495d90SSimon Glass }; 787