From eb07313ffb53b8ea080dbcc7400e0ec1a57c836e Mon Sep 17 00:00:00 2001 From: Drasko DRASKOVIC Date: Fri, 5 Oct 2012 11:59:47 +0200 Subject: [PATCH] [PATCH][GPIO] Add IRQ edge setter to gpiolib Signed-off-by: Drasko DRASKOVIC --- Documentation/gpio.txt | 3 ++ drivers/gpio/gpiolib.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 5 +++ 3 files changed, 78 insertions(+), 0 deletions(-) diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index e08a883..8db95e1 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -712,6 +712,9 @@ requested using gpio_request(): /* change the polarity of a GPIO node in sysfs */ int gpio_sysfs_set_active_low(unsigned gpio, int value); + /* change the irq edge of a GPIO node in sysfs */ + gpio_sysfs_set_edge(unsigned gpio, unsigned int irq_type); + After a kernel driver requests a GPIO, it may only be made available in the sysfs interface by gpio_export(). The driver can control whether the signal direction may change. This helps drivers prevent userspace code diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d6c71e..9b07d67 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -820,6 +820,76 @@ EXPORT_SYMBOL_GPL(gpio_export_link); /** + * gpio_sysfs_set_edge - sets irq edge type for an exported GPIO node + * @gpio: gpio to set-up edge to, already exported + * @irq_type: irq type to be set + * + * Returns zero on success, else an error. + */ +int gpio_sysfs_set_edge(unsigned gpio, unsigned int irq_type) +{ + struct gpio_desc *desc; + struct device *dev = NULL; + int status = -EINVAL; + unsigned long trigger_flags = 0; + + if (!gpio_is_valid(gpio)) + goto done; + + mutex_lock(&sysfs_lock); + + desc = &gpio_desc[gpio]; + + if (test_bit(FLAG_EXPORT, &desc->flags)) { + dev = class_find_device(&gpio_class, NULL, desc, match_export); + if (dev == NULL) { + status = -ENODEV; + goto unlock; + } + } + + switch (irq_type) { + case IRQ_TYPE_NONE: + trigger_flags = 0; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger_flags = BIT(FLAG_TRIG_FALL); + break; + case IRQ_TYPE_EDGE_RISING: + trigger_flags = BIT(FLAG_TRIG_RISE); + break; + case IRQ_TYPE_EDGE_BOTH: + trigger_flags = BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE); + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger_flags = 0; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger_flags = 0; + break; + default: + trigger_flags = 0; + break; + } + + gpio_setup_irq(desc, dev, 0); + status = gpio_setup_irq(desc, dev, trigger_flags); + +unlock: + mutex_unlock(&sysfs_lock); + +done: + if (status) + pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); + + return status; +} +EXPORT_SYMBOL_GPL(gpio_sysfs_set_edge); + + + + +/** * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value * @gpio: gpio to change * @value: non-zero to use active low, i.e. inverted values diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index a9432fc..4827de8 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -252,6 +252,11 @@ static inline int gpio_sysfs_set_active_low(unsigned gpio, int value) return -ENOSYS; } +static inline int gpio_sysfs_set_edge(unsigned gpio, unsigned int irq_type) +{ + return -ENOSYS; +} + static inline void gpio_unexport(unsigned gpio) { } -- 1.7.6