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> 1096495d90SSimon Glass #include <asm/gpio.h> 11*fe1ef503SSimon Glass #include <linux/ctype.h> 1296495d90SSimon Glass 1396495d90SSimon Glass /** 1496495d90SSimon Glass * gpio_to_device() - Convert global GPIO number to device, number 1596495d90SSimon Glass * gpio: The numeric representation of the GPIO 1696495d90SSimon Glass * 1796495d90SSimon Glass * Convert the GPIO number to an entry in the list of GPIOs 1896495d90SSimon Glass * or GPIO blocks registered with the GPIO controller. Returns 1996495d90SSimon Glass * entry on success, NULL on error. 2096495d90SSimon Glass */ 2154c5d08aSHeiko Schocher static int gpio_to_device(unsigned int gpio, struct udevice **devp, 2296495d90SSimon Glass unsigned int *offset) 2396495d90SSimon Glass { 2496495d90SSimon Glass struct gpio_dev_priv *uc_priv; 2554c5d08aSHeiko Schocher struct udevice *dev; 2696495d90SSimon Glass int ret; 2796495d90SSimon Glass 2896495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 2996495d90SSimon Glass dev; 3096495d90SSimon Glass ret = uclass_next_device(&dev)) { 3196495d90SSimon Glass uc_priv = dev->uclass_priv; 3296495d90SSimon Glass if (gpio >= uc_priv->gpio_base && 3396495d90SSimon Glass gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 3496495d90SSimon Glass *devp = dev; 3596495d90SSimon Glass *offset = gpio - uc_priv->gpio_base; 3696495d90SSimon Glass return 0; 3796495d90SSimon Glass } 3896495d90SSimon Glass } 3996495d90SSimon Glass 4096495d90SSimon Glass /* No such GPIO */ 4196495d90SSimon Glass return ret ? ret : -EINVAL; 4296495d90SSimon Glass } 4396495d90SSimon Glass 4454c5d08aSHeiko Schocher int gpio_lookup_name(const char *name, struct udevice **devp, 4596495d90SSimon Glass unsigned int *offsetp, unsigned int *gpiop) 4696495d90SSimon Glass { 47*fe1ef503SSimon Glass struct gpio_dev_priv *uc_priv = NULL; 4854c5d08aSHeiko Schocher struct udevice *dev; 49*fe1ef503SSimon Glass ulong offset; 50*fe1ef503SSimon Glass int numeric; 5196495d90SSimon Glass int ret; 5296495d90SSimon Glass 5396495d90SSimon Glass if (devp) 5496495d90SSimon Glass *devp = NULL; 55*fe1ef503SSimon Glass numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; 5696495d90SSimon Glass for (ret = uclass_first_device(UCLASS_GPIO, &dev); 5796495d90SSimon Glass dev; 5896495d90SSimon Glass ret = uclass_next_device(&dev)) { 5996495d90SSimon Glass int len; 6096495d90SSimon Glass 6196495d90SSimon Glass uc_priv = dev->uclass_priv; 62*fe1ef503SSimon Glass if (numeric != -1) { 63*fe1ef503SSimon Glass offset = numeric - uc_priv->gpio_base; 64*fe1ef503SSimon Glass /* Allow GPIOs to be numbered from 0 */ 65*fe1ef503SSimon Glass if (offset >= 0 && offset < uc_priv->gpio_count) 66*fe1ef503SSimon Glass break; 67*fe1ef503SSimon Glass } 68*fe1ef503SSimon Glass 6996495d90SSimon Glass len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 7096495d90SSimon Glass 71939cda5bSSimon Glass if (!strncasecmp(name, uc_priv->bank_name, len)) { 72*fe1ef503SSimon Glass if (!strict_strtoul(name + len, 10, &offset)) 73*fe1ef503SSimon Glass break; 74*fe1ef503SSimon Glass } 75*fe1ef503SSimon Glass } 76*fe1ef503SSimon Glass 77*fe1ef503SSimon Glass if (!dev) 78*fe1ef503SSimon Glass return ret ? ret : -EINVAL; 79*fe1ef503SSimon Glass 8096495d90SSimon Glass if (devp) 8196495d90SSimon Glass *devp = dev; 8296495d90SSimon Glass if (offsetp) 8396495d90SSimon Glass *offsetp = offset; 8496495d90SSimon Glass if (gpiop) 8596495d90SSimon Glass *gpiop = uc_priv->gpio_base + offset; 8696495d90SSimon Glass 87*fe1ef503SSimon Glass return 0; 8896495d90SSimon Glass } 8996495d90SSimon Glass 9096495d90SSimon Glass /** 9196495d90SSimon Glass * gpio_request() - [COMPAT] Request GPIO 9296495d90SSimon Glass * gpio: GPIO number 9396495d90SSimon Glass * label: Name for the requested GPIO 9496495d90SSimon Glass * 9596495d90SSimon Glass * This function implements the API that's compatible with current 9696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 9796495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 9896495d90SSimon Glass */ 9996495d90SSimon Glass int gpio_request(unsigned gpio, const char *label) 10096495d90SSimon Glass { 10196495d90SSimon Glass unsigned int offset; 10254c5d08aSHeiko Schocher struct udevice *dev; 10396495d90SSimon Glass int ret; 10496495d90SSimon Glass 10596495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 10696495d90SSimon Glass if (ret) 10796495d90SSimon Glass return ret; 10896495d90SSimon Glass 10996495d90SSimon Glass if (!gpio_get_ops(dev)->request) 11096495d90SSimon Glass return 0; 11196495d90SSimon Glass 11296495d90SSimon Glass return gpio_get_ops(dev)->request(dev, offset, label); 11396495d90SSimon Glass } 11496495d90SSimon Glass 11596495d90SSimon Glass /** 11696495d90SSimon Glass * gpio_free() - [COMPAT] Relinquish GPIO 11796495d90SSimon Glass * gpio: GPIO number 11896495d90SSimon Glass * 11996495d90SSimon Glass * This function implements the API that's compatible with current 12096495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 12196495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 12296495d90SSimon Glass */ 12396495d90SSimon Glass int gpio_free(unsigned gpio) 12496495d90SSimon Glass { 12596495d90SSimon Glass unsigned int offset; 12654c5d08aSHeiko Schocher struct udevice *dev; 12796495d90SSimon Glass int ret; 12896495d90SSimon Glass 12996495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 13096495d90SSimon Glass if (ret) 13196495d90SSimon Glass return ret; 13296495d90SSimon Glass 13396495d90SSimon Glass if (!gpio_get_ops(dev)->free) 13496495d90SSimon Glass return 0; 13596495d90SSimon Glass return gpio_get_ops(dev)->free(dev, offset); 13696495d90SSimon Glass } 13796495d90SSimon Glass 13896495d90SSimon Glass /** 13996495d90SSimon Glass * gpio_direction_input() - [COMPAT] Set GPIO direction to input 14096495d90SSimon Glass * gpio: GPIO number 14196495d90SSimon Glass * 14296495d90SSimon Glass * This function implements the API that's compatible with current 14396495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 14496495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 14596495d90SSimon Glass */ 14696495d90SSimon Glass int gpio_direction_input(unsigned gpio) 14796495d90SSimon Glass { 14896495d90SSimon Glass unsigned int offset; 14954c5d08aSHeiko Schocher struct udevice *dev; 15096495d90SSimon Glass int ret; 15196495d90SSimon Glass 15296495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 15396495d90SSimon Glass if (ret) 15496495d90SSimon Glass return ret; 15596495d90SSimon Glass 15696495d90SSimon Glass return gpio_get_ops(dev)->direction_input(dev, offset); 15796495d90SSimon Glass } 15896495d90SSimon Glass 15996495d90SSimon Glass /** 16096495d90SSimon Glass * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 16196495d90SSimon Glass * gpio: GPIO number 16296495d90SSimon Glass * value: Logical value to be set on the GPIO pin 16396495d90SSimon Glass * 16496495d90SSimon Glass * This function implements the API that's compatible with current 16596495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 16696495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 16796495d90SSimon Glass */ 16896495d90SSimon Glass int gpio_direction_output(unsigned gpio, int value) 16996495d90SSimon Glass { 17096495d90SSimon Glass unsigned int offset; 17154c5d08aSHeiko Schocher struct udevice *dev; 17296495d90SSimon Glass int ret; 17396495d90SSimon Glass 17496495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 17596495d90SSimon Glass if (ret) 17696495d90SSimon Glass return ret; 17796495d90SSimon Glass 17896495d90SSimon Glass return gpio_get_ops(dev)->direction_output(dev, offset, value); 17996495d90SSimon Glass } 18096495d90SSimon Glass 18196495d90SSimon Glass /** 18296495d90SSimon Glass * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 18396495d90SSimon Glass * gpio: GPIO number 18496495d90SSimon Glass * 18596495d90SSimon Glass * This function implements the API that's compatible with current 18696495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 18796495d90SSimon Glass * GPIO driver. Returns the value of the GPIO pin, or negative value 18896495d90SSimon Glass * on error. 18996495d90SSimon Glass */ 19096495d90SSimon Glass int gpio_get_value(unsigned gpio) 19196495d90SSimon Glass { 19296495d90SSimon Glass unsigned int offset; 19354c5d08aSHeiko Schocher struct udevice *dev; 19496495d90SSimon Glass int ret; 19596495d90SSimon Glass 19696495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 19796495d90SSimon Glass if (ret) 19896495d90SSimon Glass return ret; 19996495d90SSimon Glass 20096495d90SSimon Glass return gpio_get_ops(dev)->get_value(dev, offset); 20196495d90SSimon Glass } 20296495d90SSimon Glass 20396495d90SSimon Glass /** 20496495d90SSimon Glass * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 20596495d90SSimon Glass * gpio: GPIO number 20696495d90SSimon Glass * value: Logical value to be set on the GPIO pin. 20796495d90SSimon Glass * 20896495d90SSimon Glass * This function implements the API that's compatible with current 20996495d90SSimon Glass * GPIO API used in U-Boot. The request is forwarded to particular 21096495d90SSimon Glass * GPIO driver. Returns 0 on success, negative value on error. 21196495d90SSimon Glass */ 21296495d90SSimon Glass int gpio_set_value(unsigned gpio, int value) 21396495d90SSimon Glass { 21496495d90SSimon Glass unsigned int offset; 21554c5d08aSHeiko Schocher struct udevice *dev; 21696495d90SSimon Glass int ret; 21796495d90SSimon Glass 21896495d90SSimon Glass ret = gpio_to_device(gpio, &dev, &offset); 21996495d90SSimon Glass if (ret) 22096495d90SSimon Glass return ret; 22196495d90SSimon Glass 22296495d90SSimon Glass return gpio_get_ops(dev)->set_value(dev, offset, value); 22396495d90SSimon Glass } 22496495d90SSimon Glass 22554c5d08aSHeiko Schocher const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) 22696495d90SSimon Glass { 22796495d90SSimon Glass struct gpio_dev_priv *priv; 22896495d90SSimon Glass 22996495d90SSimon Glass /* Must be called on an active device */ 23096495d90SSimon Glass priv = dev->uclass_priv; 23196495d90SSimon Glass assert(priv); 23296495d90SSimon Glass 23396495d90SSimon Glass *bit_count = priv->gpio_count; 23496495d90SSimon Glass return priv->bank_name; 23596495d90SSimon Glass } 23696495d90SSimon Glass 23796495d90SSimon Glass /* We need to renumber the GPIOs when any driver is probed/removed */ 23896495d90SSimon Glass static int gpio_renumber(void) 23996495d90SSimon Glass { 24096495d90SSimon Glass struct gpio_dev_priv *uc_priv; 24154c5d08aSHeiko Schocher struct udevice *dev; 24296495d90SSimon Glass struct uclass *uc; 24396495d90SSimon Glass unsigned base; 24496495d90SSimon Glass int ret; 24596495d90SSimon Glass 24696495d90SSimon Glass ret = uclass_get(UCLASS_GPIO, &uc); 24796495d90SSimon Glass if (ret) 24896495d90SSimon Glass return ret; 24996495d90SSimon Glass 25096495d90SSimon Glass /* Ensure that we have a base for each bank */ 25196495d90SSimon Glass base = 0; 25296495d90SSimon Glass uclass_foreach_dev(dev, uc) { 25396495d90SSimon Glass if (device_active(dev)) { 25496495d90SSimon Glass uc_priv = dev->uclass_priv; 25596495d90SSimon Glass uc_priv->gpio_base = base; 25696495d90SSimon Glass base += uc_priv->gpio_count; 25796495d90SSimon Glass } 25896495d90SSimon Glass } 25996495d90SSimon Glass 26096495d90SSimon Glass return 0; 26196495d90SSimon Glass } 26296495d90SSimon Glass 26354c5d08aSHeiko Schocher static int gpio_post_probe(struct udevice *dev) 26496495d90SSimon Glass { 26596495d90SSimon Glass return gpio_renumber(); 26696495d90SSimon Glass } 26796495d90SSimon Glass 26854c5d08aSHeiko Schocher static int gpio_pre_remove(struct udevice *dev) 26996495d90SSimon Glass { 27096495d90SSimon Glass return gpio_renumber(); 27196495d90SSimon Glass } 27296495d90SSimon Glass 27396495d90SSimon Glass UCLASS_DRIVER(gpio) = { 27496495d90SSimon Glass .id = UCLASS_GPIO, 27596495d90SSimon Glass .name = "gpio", 27696495d90SSimon Glass .post_probe = gpio_post_probe, 27796495d90SSimon Glass .pre_remove = gpio_pre_remove, 27896495d90SSimon Glass .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 27996495d90SSimon Glass }; 280