[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2017-02-08 Thread git repository hosting
Module: xenomai-3
Branch: master
Commit: a847734467bde3a979bd0916c57c4375b34fbaa0
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=a847734467bde3a979bd0916c57c4375b34fbaa0

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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 

[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2016-12-27 Thread git repository hosting
Module: xenomai-3
Branch: stable-3.0.x
Commit: a847734467bde3a979bd0916c57c4375b34fbaa0
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=a847734467bde3a979bd0916c57c4375b34fbaa0

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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;

[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2016-12-27 Thread git repository hosting
Module: xenomai-3
Branch: wip/drivers
Commit: a847734467bde3a979bd0916c57c4375b34fbaa0
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=a847734467bde3a979bd0916c57c4375b34fbaa0

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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;

[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2016-11-21 Thread git repository hosting
Module: xenomai-3
Branch: wip/drivers
Commit: cb10960b91a8a935342779211d62d8387a89c596
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=cb10960b91a8a935342779211d62d8387a89c596

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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;

[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2016-09-29 Thread git repository hosting
Module: xenomai-3
Branch: wip/drivers
Commit: 782624eb3a4b9f225174b121e75607a5c6e868ab
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=782624eb3a4b9f225174b121e75607a5c6e868ab

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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;

[Xenomai-git] Philippe Gerum : drivers/gpio: allow setting trigger type w/ GPIO_RTIOC_IRQEN

2016-06-28 Thread git repository hosting
Module: xenomai-3
Branch: wip/drivers
Commit: d4ef0363fe6fd10e9447ca3785b908d15729d2df
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d4ef0363fe6fd10e9447ca3785b908d15729d2df

Author: Philippe Gerum 
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_HIGH0x4
+#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(>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(>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, ,
+  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;