diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 19:13:54 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 19:13:54 +0200 |
commit | 11e4afb49b7fa1fc8e1ffd850c1806dd86a08204 (patch) | |
tree | 9e57efcb106ae912f7bec718feb3f8ec607559bb /drivers/gpio/gpiolib.c | |
parent | ARM: 6131/1: MAINTAINERS: update for ARM/Gemini (diff) | |
parent | ARM: 6283/1: Remove useless PCIO_BASE definitions (diff) | |
download | linux-11e4afb49b7fa1fc8e1ffd850c1806dd86a08204.tar.xz linux-11e4afb49b7fa1fc8e1ffd850c1806dd86a08204.zip |
Merge branches 'gemini' and 'misc' into devel
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6d1b86661e63..4e51fe3c1fc4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -9,6 +9,7 @@ #include <linux/seq_file.h> #include <linux/gpio.h> #include <linux/idr.h> +#include <linux/slab.h> /* Optional implementation infrastructure for GPIO interfaces. @@ -398,7 +399,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, goto free_id; } - pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, "value"); + pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); if (!pdesc->value_sd) { ret = -ENODEV; goto free_id; @@ -415,7 +416,8 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, return 0; free_sd: - sysfs_put(pdesc->value_sd); + if (pdesc) + sysfs_put(pdesc->value_sd); free_id: idr_remove(&pdesc_idr, id); desc->flags &= GPIO_FLAGS_MASK; @@ -720,7 +722,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) unsigned long flags; struct gpio_desc *desc; int status = -EINVAL; - char *ioname = NULL; + const char *ioname = NULL; /* can't export until sysfs is available ... */ if (!gpio_class.p) { @@ -751,7 +753,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) struct device *dev; dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), - desc, ioname ? ioname : "gpio%d", gpio); + desc, ioname ? ioname : "gpio%u", gpio); if (!IS_ERR(dev)) { status = sysfs_create_group(&dev->kobj, &gpio_attr_group); @@ -891,10 +893,12 @@ EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low); void gpio_unexport(unsigned gpio) { struct gpio_desc *desc; - int status = -EINVAL; + int status = 0; - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } mutex_lock(&sysfs_lock); @@ -909,7 +913,6 @@ void gpio_unexport(unsigned gpio) clear_bit(FLAG_EXPORT, &desc->flags); put_device(dev); device_unregister(dev); - status = 0; } else status = -ENODEV; } @@ -1104,7 +1107,7 @@ unlock: fail: /* failures here can mean systems won't boot... */ if (status) - pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n", + pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; @@ -1445,6 +1448,49 @@ fail: } EXPORT_SYMBOL_GPL(gpio_direction_output); +/** + * gpio_set_debounce - sets @debounce time for a @gpio + * @gpio: the gpio to set debounce time + * @debounce: debounce time is microseconds + */ +int gpio_set_debounce(unsigned gpio, unsigned debounce) +{ + unsigned long flags; + struct gpio_chip *chip; + struct gpio_desc *desc = &gpio_desc[gpio]; + int status = -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + + if (!gpio_is_valid(gpio)) + goto fail; + chip = desc->chip; + if (!chip || !chip->set || !chip->set_debounce) + goto fail; + gpio -= chip->base; + if (gpio >= chip->ngpio) + goto fail; + status = gpio_ensure_requested(desc, gpio); + if (status < 0) + goto fail; + + /* now we know the gpio is valid and chip won't vanish */ + + spin_unlock_irqrestore(&gpio_lock, flags); + + might_sleep_if(extra_checks && chip->can_sleep); + + return chip->set_debounce(chip, gpio, debounce); + +fail: + spin_unlock_irqrestore(&gpio_lock, flags); + if (status) + pr_debug("%s: gpio-%d status %d\n", + __func__, gpio, status); + + return status; +} +EXPORT_SYMBOL_GPL(gpio_set_debounce); /* I/O calls are only valid after configuration completed; the relevant * "is this a valid GPIO" error checks should already have been done. |