Module: xenomai-3
Branch: master
Commit: a847734467bde3a979bd0916c57c4375b34fbaa0
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=a847734467bde3a979bd0916c57c4375b34fbaa0

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Jun 28 12:16:02 2016 +0200

drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

---

 include/rtdm/uapi/gpio.h        |    9 ++++++++-
 kernel/drivers/gpio/gpio-core.c |   31 +++++++++++++++++++++++++++----
 testsuite/gpiotest/gpiotest.c   |   34 +++++++++++++++++++++++++++++++---
 3 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/include/rtdm/uapi/gpio.h b/include/rtdm/uapi/gpio.h
index b0d4899..307e190 100644
--- a/include/rtdm/uapi/gpio.h
+++ b/include/rtdm/uapi/gpio.h
@@ -22,7 +22,14 @@
 
 #define GPIO_RTIOC_DIR_OUT             _IOW(RTDM_CLASS_GPIO, 0, int)
 #define GPIO_RTIOC_DIR_IN              _IO(RTDM_CLASS_GPIO, 1)
-#define GPIO_RTIOC_IRQEN               _IO(RTDM_CLASS_GPIO, 2)
+#define GPIO_RTIOC_IRQEN               _IOW(RTDM_CLASS_GPIO, 2, int) /* GPIO 
trigger */
 #define GPIO_RTIOC_IRQDIS              _IO(RTDM_CLASS_GPIO, 3)
 
+#define GPIO_TRIGGER_NONE              0x0 /* unspecified */
+#define GPIO_TRIGGER_EDGE_RISING       0x1
+#define GPIO_TRIGGER_EDGE_FALLING      0x2
+#define GPIO_TRIGGER_LEVEL_HIGH                0x4
+#define GPIO_TRIGGER_LEVEL_LOW         0x8
+#define GPIO_TRIGGER_MASK              0xf
+
 #endif /* !_RTDM_UAPI_GPIO_H */
diff --git a/kernel/drivers/gpio/gpio-core.c b/kernel/drivers/gpio/gpio-core.c
index e8a7ba1..6c1f351 100644
--- a/kernel/drivers/gpio/gpio-core.c
+++ b/kernel/drivers/gpio/gpio-core.c
@@ -44,10 +44,20 @@ static int gpio_pin_interrupt(rtdm_irq_t *irqh)
        return RTDM_IRQ_HANDLED;
 }
 
-static int request_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin)
+static int request_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin,
+                           int trigger)
 {
+       static const int trigger_flags[] = {
+               IRQ_TYPE_EDGE_RISING,
+               IRQ_TYPE_EDGE_FALLING,
+               IRQ_TYPE_LEVEL_HIGH,
+               IRQ_TYPE_LEVEL_LOW,
+       };
+       int irq_trigger, ret;
        unsigned int irq;
-       int ret;
+
+       if (trigger & ~GPIO_TRIGGER_MASK)
+               return -EINVAL;
 
        ret = gpio_request(gpio, pin->name);
        if (ret) {
@@ -66,6 +76,15 @@ static int request_gpio_irq(unsigned int gpio, struct 
rtdm_gpio_pin *pin)
 
        rtdm_event_clear(&pin->event);
        irq = gpio_to_irq(gpio);
+       /*
+        * Assumes GPIO_TRIGGER_xx values are forming a continuous
+        * sequence of bits starting at bit #0.
+        */
+       if (trigger) {
+               irq_trigger = trigger_flags[ffs(trigger) - 1];
+               irq_set_irq_type(irq, irq_trigger);
+       }
+       
        ret = rtdm_irq_request(&pin->irqh, irq, gpio_pin_interrupt,
                               0, pin->name, pin);
        if (ret) {
@@ -93,8 +112,8 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd,
 {
        struct rtdm_device *dev = rtdm_fd_device(fd);
        unsigned int gpio = rtdm_fd_minor(fd);
+       int ret = 0, val, trigger;
        struct rtdm_gpio_pin *pin;
-       int ret = 0, val;
        
        pin = container_of(dev, struct rtdm_gpio_pin, dev);
 
@@ -109,7 +128,11 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd,
                ret = gpio_direction_input(gpio);
                break;
        case GPIO_RTIOC_IRQEN:
-               ret = request_gpio_irq(gpio, pin);
+               ret = rtdm_safe_copy_from_user(fd, &trigger,
+                                      arg, sizeof(trigger));
+               if (ret)
+                       return ret;
+               ret = request_gpio_irq(gpio, pin, trigger);
                break;
        case GPIO_RTIOC_IRQDIS:
                release_gpio_irq(gpio, pin);
diff --git a/testsuite/gpiotest/gpiotest.c b/testsuite/gpiotest/gpiotest.c
index 0bdd39f..6e9ce5b 100644
--- a/testsuite/gpiotest/gpiotest.c
+++ b/testsuite/gpiotest/gpiotest.c
@@ -55,8 +55,21 @@ smokey_test_plugin(write_value,
 
 static int run_interrupt(struct smokey_test *t, int argc, char *const argv[])
 {
-       const char *device = NULL;
-       int fd, ret;
+       static struct {
+               const char *name;
+               int flag;
+       } trigger_types[] = {
+               { .name = "edge", .flag = GPIO_TRIGGER_EDGE_RISING },
+               { .name = "edge-rising", .flag = GPIO_TRIGGER_EDGE_RISING },
+               { .name = "edge-falling", .flag = GPIO_TRIGGER_EDGE_FALLING },
+               { .name = "edge-both", .flag = 
GPIO_TRIGGER_EDGE_FALLING|GPIO_TRIGGER_EDGE_RISING },
+               { .name = "level", .flag = GPIO_TRIGGER_LEVEL_LOW },
+               { .name = "level-low", .flag = GPIO_TRIGGER_LEVEL_LOW },
+               { .name = "level-high", .flag = GPIO_TRIGGER_LEVEL_HIGH },
+               { NULL, 0 },
+       };
+       const char *device = NULL, *trigname;
+       int fd, ret, trigger, n;
        fd_set set;
        
        smokey_parse_args(t, argc, argv);
@@ -75,7 +88,22 @@ static int run_interrupt(struct smokey_test *t, int argc, 
char *const argv[])
                return ret;
        }
 
-       ret = ioctl(fd, GPIO_RTIOC_IRQEN);
+       trigger = GPIO_TRIGGER_NONE;
+       if (SMOKEY_ARG_ISSET(interrupt, trigger)) {
+               trigname = SMOKEY_ARG_STRING(interrupt, trigger);
+               for (n = 0; trigger_types[n].name; n++) {
+                       if (strcmp(trigger_types[n].name, trigname) == 0) {
+                               trigger = trigger_types[n].flag;
+                               break;
+                   }
+               }
+               if (trigger == GPIO_TRIGGER_NONE) {
+                       warning("invalid trigger type %s", trigname);
+                       return -EINVAL;
+               }
+       }
+
+       ret = ioctl(fd, GPIO_RTIOC_IRQEN, &trigger);
        if (ret) {
                ret = -errno;
                warning("GPIO_RTIOC_IRQEN failed on %s [%s]",


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to