diff options
author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2012-12-21 14:26:08 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-12-22 16:39:23 +0100 |
commit | 8429aed80eeafc64a17e98f45cc93984d5938bb9 (patch) | |
tree | ae502c3d743fa59a2e5f12f97499b36c8c11c3ec /drivers/gpio | |
parent | b46b57f35a27090cfbac4900d1a3d522d7898e53 (diff) | |
download | barebox-8429aed80eeafc64a17e98f45cc93984d5938bb9.tar.gz barebox-8429aed80eeafc64a17e98f45cc93984d5938bb9.tar.xz |
gpiolib: add gpio_request and gpio_free support
as today if no request or free provided do not complain
if the gpio is not request auto requested at first use
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio.c | 89 |
1 files changed, 82 insertions, 7 deletions
diff --git a/drivers/gpio/gpio.c b/drivers/gpio/gpio.c index 042a0621b0..ed9f9236eb 100644 --- a/drivers/gpio/gpio.c +++ b/drivers/gpio/gpio.c @@ -1,19 +1,79 @@ #include <common.h> #include <gpio.h> #include <errno.h> +#include <malloc.h> static LIST_HEAD(chip_list); -static struct gpio_chip *gpio_desc[ARCH_NR_GPIOS]; +struct gpio_info { + struct gpio_chip *chip; + bool requested; + char *label; +}; + +static struct gpio_info gpio_desc[ARCH_NR_GPIOS]; + +static int gpio_ensure_requested(struct gpio_info *gi, int gpio) +{ + if (gi->requested) + return 0; + + return gpio_request(gpio, "gpio"); +} + +int gpio_request(unsigned gpio, const char *label) +{ + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; + int ret; + + if (!gpio_is_valid(gpio)) + return -EINVAL; + if (!chip) + return -EINVAL; + if (gi->requested) + return -EBUSY; + if (chip->ops->request) { + ret = chip->ops->request(chip, gpio - chip->base); + if (ret) + return ret; + } + + gi->requested = true; + gi->label = xstrdup(label); + + return 0; +} + +void gpio_free(unsigned gpio) +{ + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; + + if (!gpio_is_valid(gpio)) + return; + if (!chip) + return; + if (!gi->requested) + return; + if (chip->ops->free) + chip->ops->free(chip, gpio - chip->base); + + gi->requested = false; + free(gi->label); +} void gpio_set_value(unsigned gpio, int value) { - struct gpio_chip *chip = gpio_desc[gpio]; + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; if (!gpio_is_valid(gpio)) return; if (!chip) return; + if (gpio_ensure_requested(gi, gpio)) + return; if (!chip->ops->set) return; chip->ops->set(chip, gpio - chip->base, value); @@ -22,12 +82,17 @@ EXPORT_SYMBOL(gpio_set_value); int gpio_get_value(unsigned gpio) { - struct gpio_chip *chip = gpio_desc[gpio]; + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; + int ret; if (!gpio_is_valid(gpio)) return -EINVAL; if (!chip) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); + if (ret) + return ret; if (!chip->ops->get) return -ENOSYS; return chip->ops->get(chip, gpio - chip->base); @@ -36,12 +101,17 @@ EXPORT_SYMBOL(gpio_get_value); int gpio_direction_output(unsigned gpio, int value) { - struct gpio_chip *chip = gpio_desc[gpio]; + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; + int ret; if (!gpio_is_valid(gpio)) return -EINVAL; if (!chip) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); + if (ret) + return ret; if (!chip->ops->direction_output) return -ENOSYS; return chip->ops->direction_output(chip, gpio - chip->base, value); @@ -50,12 +120,17 @@ EXPORT_SYMBOL(gpio_direction_output); int gpio_direction_input(unsigned gpio) { - struct gpio_chip *chip = gpio_desc[gpio]; + struct gpio_info *gi = &gpio_desc[gpio]; + struct gpio_chip *chip = gi->chip; + int ret; if (!gpio_is_valid(gpio)) return -EINVAL; if (!chip) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); + if (ret) + return ret; if (!chip->ops->direction_input) return -ENOSYS; return chip->ops->direction_input(chip, gpio - chip->base); @@ -72,7 +147,7 @@ static int gpiochip_find_base(int start, int ngpio) start = 0; for (i = start; i < ARCH_NR_GPIOS; i++) { - struct gpio_chip *chip = gpio_desc[i]; + struct gpio_chip *chip = gpio_desc[i].chip; if (!chip) { spare++; @@ -107,7 +182,7 @@ int gpiochip_add(struct gpio_chip *chip) list_add_tail(&chip->list, &chip_list); for (i = chip->base; i < chip->base + chip->ngpio; i++) - gpio_desc[i] = chip; + gpio_desc[i].chip = chip; return 0; } |