Author: mmel
Date: Thu Apr 28 12:03:22 2016
New Revision: 298738
URL: https://svnweb.freebsd.org/changeset/base/298738

Log:
  GPIO: Add support for gpio pin interrupts.
  Add new function gpio_alloc_intr_resource(), which allows an allocation
  of interrupt resource associated to given gpio pin. It also allows to
  specify interrupt configuration.
  
  Note: This functionality is dependent on INTRNG, and must be
  implemented in each GPIO controller.

Modified:
  head/sys/dev/gpio/gpiobus.c
  head/sys/dev/gpio/gpiobusvar.h
  head/sys/kern/subr_intr.c
  head/sys/sys/gpio.h
  head/sys/sys/intr.h

Modified: head/sys/dev/gpio/gpiobus.c
==============================================================================
--- head/sys/dev/gpio/gpiobus.c Thu Apr 28 09:40:24 2016        (r298737)
+++ head/sys/dev/gpio/gpiobus.c Thu Apr 28 12:03:22 2016        (r298738)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/gpio.h>
+#include <sys/intr.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -72,6 +73,31 @@ static int gpiobus_pin_set(device_t, dev
 static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
 static int gpiobus_pin_toggle(device_t, device_t, uint32_t);
 
+/*
+ * XXX -> Move me to better place - gpio_subr.c?
+ * Also, this function must be changed when interrupt configuration
+ * data will be moved into struct resource.
+ */
+#ifdef INTRNG
+struct resource *
+gpio_alloc_intr_resource(device_t consumer_dev, int *rid, u_int alloc_flags,
+    gpio_pin_t pin, uint32_t intr_mode)
+{
+       u_int irqnum;
+
+       /*
+        * Allocate new fictitious interrupt number and store configuration
+        * into it.
+        */
+       irqnum = intr_gpio_map_irq(pin->dev, pin->pin, pin->flags, intr_mode);
+       if (irqnum == 0xFFFFFFFF)
+               return (NULL);
+
+       return (bus_alloc_resource(consumer_dev, SYS_RES_IRQ, rid,
+           irqnum, irqnum, 1, alloc_flags));
+}
+#endif
+
 int
 gpio_check_flags(uint32_t caps, uint32_t flags)
 {

Modified: head/sys/dev/gpio/gpiobusvar.h
==============================================================================
--- head/sys/dev/gpio/gpiobusvar.h      Thu Apr 28 09:40:24 2016        
(r298737)
+++ head/sys/dev/gpio/gpiobusvar.h      Thu Apr 28 12:03:22 2016        
(r298738)
@@ -61,6 +61,9 @@
 #define        GPIOBUS_WAIT            1
 #define        GPIOBUS_DONTWAIT        2
 
+/* Use default interrupt mode -  for gpio_alloc_intr_resource */
+#define GPIO_INTR_CONFORM      GPIO_INTR_NONE
+
 struct gpiobus_pin_data
 {
        int             mapped;         /* pin is mapped/reserved. */
@@ -122,6 +125,10 @@ int gpio_pin_is_active(gpio_pin_t pin, b
 int gpio_pin_set_active(gpio_pin_t pin, bool active);
 int gpio_pin_setflags(gpio_pin_t pin, uint32_t flags);
 #endif
+#ifdef INTRNG
+struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid,
+    u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode);
+#endif
 int gpio_check_flags(uint32_t, uint32_t);
 device_t gpiobus_attach_bus(device_t);
 int gpiobus_detach_bus(device_t);

Modified: head/sys/kern/subr_intr.c
==============================================================================
--- head/sys/kern/subr_intr.c   Thu Apr 28 09:40:24 2016        (r298737)
+++ head/sys/kern/subr_intr.c   Thu Apr 28 12:03:22 2016        (r298738)
@@ -596,6 +596,27 @@ intr_fdt_map_irq(phandle_t node, pcell_t
 }
 #endif
 
+/*
+ *  Store GPIO interrupt decription in framework and return unique interrupt
+ *  number (resource handle) associated with it.
+ */
+u_int
+intr_gpio_map_irq(device_t dev, u_int pin_num, u_int pin_flags, u_int 
intr_mode)
+{
+       struct intr_dev_data *ddata;
+
+       ddata = intr_ddata_alloc(0);
+       if (ddata == NULL)
+               return (0xFFFFFFFF);    /* no space left */
+
+       ddata->idd_dev = dev;
+       ddata->idd_data.type = INTR_MAP_DATA_GPIO;
+       ddata->idd_data.gpio.gpio_pin_num = pin_num;
+       ddata->idd_data.gpio.gpio_pin_flags = pin_flags;
+       ddata->idd_data.gpio.gpio_intr_mode = intr_mode;
+       return (ddata->idd_irq);
+}
+
 #ifdef INTR_SOLO
 /*
  *  Setup filter into interrupt source.

Modified: head/sys/sys/gpio.h
==============================================================================
--- head/sys/sys/gpio.h Thu Apr 28 09:40:24 2016        (r298737)
+++ head/sys/sys/gpio.h Thu Apr 28 12:03:22 2016        (r298738)
@@ -60,16 +60,26 @@
 #define GPIOMAXNAME            64
 
 /* GPIO pin configuration flags */
-#define GPIO_PIN_INPUT         0x0001  /* input direction */
-#define GPIO_PIN_OUTPUT                0x0002  /* output direction */
-#define GPIO_PIN_OPENDRAIN     0x0004  /* open-drain output */
-#define GPIO_PIN_PUSHPULL      0x0008  /* push-pull output */
-#define GPIO_PIN_TRISTATE      0x0010  /* output disabled */
-#define GPIO_PIN_PULLUP                0x0020  /* internal pull-up enabled */
-#define GPIO_PIN_PULLDOWN      0x0040  /* internal pull-down enabled */
-#define GPIO_PIN_INVIN         0x0080  /* invert input */
-#define GPIO_PIN_INVOUT                0x0100  /* invert output */
-#define GPIO_PIN_PULSATE       0x0200  /* pulsate in hardware */
+#define GPIO_PIN_INPUT         0x00000001      /* input direction */
+#define GPIO_PIN_OUTPUT                0x00000002      /* output direction */
+#define GPIO_PIN_OPENDRAIN     0x00000004      /* open-drain output */
+#define GPIO_PIN_PUSHPULL      0x00000008      /* push-pull output */
+#define GPIO_PIN_TRISTATE      0x00000010      /* output disabled */
+#define GPIO_PIN_PULLUP                0x00000020      /* internal pull-up 
enabled */
+#define GPIO_PIN_PULLDOWN      0x00000040      /* internal pull-down enabled */
+#define GPIO_PIN_INVIN         0x00000080      /* invert input */
+#define GPIO_PIN_INVOUT                0x00000100      /* invert output */
+#define GPIO_PIN_PULSATE       0x00000200      /* pulsate in hardware */
+/* GPIO interrupt capabilities */
+#define GPIO_INTR_NONE         0x00000000      /* no interrupt support */
+#define GPIO_INTR_LEVEL_LOW    0x00010000      /* level trigger, low */
+#define GPIO_INTR_LEVEL_HIGH   0x00020000      /* level trigger, high */
+#define GPIO_INTR_EDGE_RISING  0x00040000      /* edge trigger, rising */
+#define GPIO_INTR_EDGE_FALLING 0x00080000      /* edge trigger, falling */
+#define GPIO_INTR_EDGE_BOTH    0x00100000      /* edge trigger, both */
+#define GPIO_INTR_MASK         (GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH | \
+                               GPIO_INTR_EDGE_RISING |                       \
+                               GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
 
 struct gpio_pin {
        uint32_t gp_pin;                        /* pin number */

Modified: head/sys/sys/intr.h
==============================================================================
--- head/sys/sys/intr.h Thu Apr 28 09:40:24 2016        (r298737)
+++ head/sys/sys/intr.h Thu Apr 28 12:03:22 2016        (r298738)
@@ -35,6 +35,7 @@
 enum intr_map_data_type {
        INTR_MAP_DATA_ACPI,
        INTR_MAP_DATA_FDT,
+       INTR_MAP_DATA_GPIO,
 };
 
 #ifdef DEV_ACPI
@@ -51,6 +52,12 @@ struct intr_map_data_fdt {
 };
 #endif
 
+struct intr_map_data_gpio {
+       u_int                   gpio_pin_num;
+       u_int                   gpio_pin_flags;
+       u_int                   gpio_intr_mode;
+};
+
 struct intr_map_data {
        enum intr_map_data_type type;
        union {
@@ -60,6 +67,7 @@ struct intr_map_data {
 #ifdef FDT
                struct intr_map_data_fdt        fdt;
 #endif
+               struct intr_map_data_gpio       gpio;
        };
 };
 
@@ -130,6 +138,8 @@ u_int intr_acpi_map_irq(device_t, u_int,
 #ifdef FDT
 u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
 #endif
+u_int intr_gpio_map_irq(device_t dev, u_int pin_num, u_int pin_flags,
+    u_int intr_mode);
 
 #ifdef SMP
 int intr_bind_irq(device_t, struct resource *, int);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to