Author: manu
Date: Sun Jan 19 19:51:20 2020
New Revision: 356891
URL: https://svnweb.freebsd.org/changeset/base/356891

Log:
  arm: allwinner: Add GPIO Interrupt support
  
  Not all pins in Allwinner have interrupts support so we rely
  on the padconf data to add the proper caps when pin_getcaps is called.
  The pin is switch to the specific "eint" function during setup_intr and
  switched back to its old function in teardown_intr.
  Only INTR_MAP_DATA_GPIO is supported for now.
  
  MFC after:    1 month

Modified:
  head/sys/arm/allwinner/aw_gpio.c

Modified: head/sys/arm/allwinner/aw_gpio.c
==============================================================================
--- head/sys/arm/allwinner/aw_gpio.c    Sun Jan 19 19:47:04 2020        
(r356890)
+++ head/sys/arm/allwinner/aw_gpio.c    Sun Jan 19 19:51:20 2020        
(r356891)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/gpio.h>
+#include <sys/proc.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -61,11 +62,18 @@ __FBSDID("$FreeBSD$");
 #include "opt_soc.h"
 #endif
 
+#ifdef INTRNG
+#include "pic_if.h"
+#endif
+
 #include "gpio_if.h"
 
 #define        AW_GPIO_DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     
\
-    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
+         GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
 
+#define        AW_GPIO_INTR_CAPS       (GPIO_INTR_LEVEL_LOW | 
GPIO_INTR_LEVEL_HIGH |   \
+         GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
+
 #define        AW_GPIO_NONE            0
 #define        AW_GPIO_PULLUP          1
 #define        AW_GPIO_PULLDOWN        2
@@ -249,19 +257,47 @@ struct clk_list {
        clk_t                   clk;
 };
 
+#ifdef INTRNG
+struct gpio_irqsrc {
+       struct intr_irqsrc      isrc;
+       u_int                   irq;
+       uint32_t                mode;
+       uint32_t                pin;
+       uint32_t                bank;
+       uint32_t                intnum;
+       uint32_t                intfunc;
+       uint32_t                oldfunc;
+       bool                    enabled;
+};
+#endif
+
+#define        AW_GPIO_MEMRES          0
+#define        AW_GPIO_IRQRES          1
+#define        AW_GPIO_RESSZ           2
+
 struct aw_gpio_softc {
        device_t                sc_dev;
        device_t                sc_busdev;
+       struct resource *       sc_res[AW_GPIO_RESSZ];
        struct mtx              sc_mtx;
        struct resource *       sc_mem_res;
        struct resource *       sc_irq_res;
-       bus_space_tag_t         sc_bst;
-       bus_space_handle_t      sc_bsh;
        void *                  sc_intrhand;
        struct aw_gpio_conf     *conf;
        TAILQ_HEAD(, clk_list)          clk_list;
+
+#ifdef INTRNG
+       struct gpio_irqsrc      *gpio_pic_irqsrc;
+       int                     nirqs;
+#endif
 };
 
+static struct resource_spec aw_gpio_res_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE },
+       { SYS_RES_IRQ,          0,      RF_ACTIVE | RF_SHAREABLE },
+       { -1,                   0,      0 }
+};
+
 #define        AW_GPIO_LOCK(_sc)               mtx_lock_spin(&(_sc)->sc_mtx)
 #define        AW_GPIO_UNLOCK(_sc)             mtx_unlock_spin(&(_sc)->sc_mtx)
 #define        AW_GPIO_LOCK_ASSERT(_sc)        mtx_assert(&(_sc)->sc_mtx, 
MA_OWNED)
@@ -271,15 +307,19 @@ struct aw_gpio_softc {
 #define        AW_GPIO_GP_DRV(_bank, _idx)     0x14 + ((_bank) * 0x24) + 
((_idx) << 2)
 #define        AW_GPIO_GP_PUL(_bank, _idx)     0x1c + ((_bank) * 0x24) + 
((_idx) << 2)
 
-#define        AW_GPIO_GP_INT_CFG0             0x200
-#define        AW_GPIO_GP_INT_CFG1             0x204
-#define        AW_GPIO_GP_INT_CFG2             0x208
-#define        AW_GPIO_GP_INT_CFG3             0x20c
+#define        AW_GPIO_GP_INT_BASE(_bank)      (0x200 + 0x20 * _bank)
 
-#define        AW_GPIO_GP_INT_CTL              0x210
-#define        AW_GPIO_GP_INT_STA              0x214
-#define        AW_GPIO_GP_INT_DEB              0x218
+#define        AW_GPIO_GP_INT_CFG(_bank, _pin) (AW_GPIO_GP_INT_BASE(_bank) + 
(0x4 * ((_pin) / 8)))
+#define        AW_GPIO_GP_INT_CTL(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 
0x10)
+#define        AW_GPIO_GP_INT_STA(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 
0x14)
+#define        AW_GPIO_GP_INT_DEB(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 
0x18)
 
+#define        AW_GPIO_INT_EDGE_POSITIVE       0x0
+#define        AW_GPIO_INT_EDGE_NEGATIVE       0x1
+#define        AW_GPIO_INT_LEVEL_HIGH          0x2
+#define        AW_GPIO_INT_LEVEL_LOW           0x3
+#define        AW_GPIO_INT_EDGE_BOTH           0x4
+
 static char *aw_gpio_parse_function(phandle_t node);
 static const char **aw_gpio_parse_pins(phandle_t node, int *pins_nb);
 static uint32_t aw_gpio_parse_bias(phandle_t node);
@@ -290,10 +330,16 @@ static int aw_gpio_pin_set(device_t dev, uint32_t pin,
 static int aw_gpio_pin_get_locked(struct aw_gpio_softc *sc, uint32_t pin, 
unsigned int *value);
 static int aw_gpio_pin_set_locked(struct aw_gpio_softc *sc, uint32_t pin, 
unsigned int value);
 
+static void aw_gpio_intr(void *arg);
+static void aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc);
+static void aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct 
intr_irqsrc *isrc);
+static void aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc);
+static int aw_gpio_register_isrcs(struct aw_gpio_softc *sc);
+
 #define        AW_GPIO_WRITE(_sc, _off, _val)          \
-    bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
+       bus_write_4((_sc)->sc_res[AW_GPIO_MEMRES], _off, _val)
 #define        AW_GPIO_READ(_sc, _off)         \
-    bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+       bus_read_4((_sc)->sc_res[AW_GPIO_MEMRES], _off)
 
 static uint32_t
 aw_gpio_get_function(struct aw_gpio_softc *sc, uint32_t pin)
@@ -492,6 +538,8 @@ aw_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32
                return (EINVAL);
 
        *caps = AW_GPIO_DEFAULT_CAPS;
+       if (sc->conf->padconf->pins[pin].eint_func != 0)
+               *caps |= AW_GPIO_INTR_CAPS;
 
        return (0);
 }
@@ -807,6 +855,27 @@ aw_gpio_pin_config_32(device_t dev, uint32_t first_pin
 }
 
 static int
+aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
+    pcell_t *gpios, uint32_t *pin, uint32_t *flags)
+{
+       struct aw_gpio_softc *sc;
+       int i;
+
+       sc = device_get_softc(bus);
+
+       /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
+       for (i = 0; i < sc->conf->padconf->npins; i++)
+               if (sc->conf->padconf->pins[i].port == gpios[0] &&
+                   sc->conf->padconf->pins[i].pin == gpios[1]) {
+                       *pin = i;
+                       break;
+               }
+       *flags = gpios[gcells - 1];
+
+       return (0);
+}
+
+static int
 aw_find_pinnum_by_name(struct aw_gpio_softc *sc, const char *pinname)
 {
        int i;
@@ -938,7 +1007,7 @@ aw_gpio_probe(device_t dev)
 static int
 aw_gpio_attach(device_t dev)
 {
-       int rid, error;
+       int error;
        phandle_t gpio;
        struct aw_gpio_softc *sc;
        struct clk_list *clkp, *clkp_tmp;
@@ -951,22 +1020,15 @@ aw_gpio_attach(device_t dev)
 
        mtx_init(&sc->sc_mtx, "aw gpio", "gpio", MTX_SPIN);
 
-       rid = 0;
-       sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
-           RF_ACTIVE);
-       if (!sc->sc_mem_res) {
-               device_printf(dev, "cannot allocate memory window\n");
-               goto fail;
+       if (bus_alloc_resources(dev, aw_gpio_res_spec, sc->sc_res) != 0) {
+               device_printf(dev, "cannot allocate device resources\n");
+               return (ENXIO);
        }
 
-       sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
-       sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
-
-       rid = 0;
-       sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-           RF_ACTIVE);
-       if (!sc->sc_irq_res) {
-               device_printf(dev, "cannot allocate interrupt\n");
+       if (bus_setup_intr(dev, sc->sc_res[AW_GPIO_IRQRES],
+           INTR_TYPE_CLK | INTR_MPSAFE, NULL, aw_gpio_intr, sc,
+           &sc->sc_intrhand)) {
+               device_printf(dev, "cannot setup interrupt handler\n");
                goto fail;
        }
 
@@ -1009,6 +1071,11 @@ aw_gpio_attach(device_t dev)
                goto fail;
        }
 
+#ifdef INTRNG
+       aw_gpio_register_isrcs(sc);
+       intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
+#endif
+
        sc->sc_busdev = gpiobus_attach_bus(dev);
        if (sc->sc_busdev == NULL)
                goto fail;
@@ -1062,40 +1129,339 @@ aw_gpio_detach(device_t dev)
        return (EBUSY);
 }
 
-static phandle_t
-aw_gpio_get_node(device_t dev, device_t bus)
+static void
+aw_gpio_intr(void *arg)
 {
+       struct aw_gpio_softc *sc;
+       struct intr_irqsrc *isrc;
+       uint32_t reg;
+       int irq;
 
-       /* We only have one child, the GPIO bus, which needs our own node. */
-       return (ofw_bus_get_node(dev));
+       sc = (struct aw_gpio_softc *)arg;
+
+       AW_GPIO_LOCK(sc);
+       for (irq = 0; irq < sc->nirqs; irq++) {
+               if (!sc->gpio_pic_irqsrc[irq].enabled)
+                       continue;
+
+               reg = AW_GPIO_READ(sc, 
AW_GPIO_GP_INT_STA(sc->gpio_pic_irqsrc[irq].bank));
+               if (!(reg & (1 << sc->gpio_pic_irqsrc[irq].intnum)))
+                       continue;
+
+               isrc = &sc->gpio_pic_irqsrc[irq].isrc;
+               if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) {
+                       aw_gpio_pic_disable_intr_locked(sc, isrc);
+                       aw_gpio_pic_post_filter(sc->sc_dev, isrc);
+                       device_printf(sc->sc_dev, "Stray irq %u disabled\n", 
irq);
+               }
+       }
+       AW_GPIO_UNLOCK(sc);
 }
 
+/*
+ * Interrupts support
+ */
+
 static int
-aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
-    pcell_t *gpios, uint32_t *pin, uint32_t *flags)
+aw_gpio_register_isrcs(struct aw_gpio_softc *sc)
 {
+       const char *name;
+       int nirqs;
+       int pin;
+       int err;
+
+       name = device_get_nameunit(sc->sc_dev);
+
+       for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
+               if (sc->conf->padconf->pins[pin].eint_func == 0)
+                       continue;
+
+               nirqs++;
+       }
+
+       sc->gpio_pic_irqsrc = malloc(sizeof(*sc->gpio_pic_irqsrc) * nirqs,
+           M_DEVBUF, M_WAITOK | M_ZERO);
+       for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
+               if (sc->conf->padconf->pins[pin].eint_func == 0)
+                       continue;
+
+               sc->gpio_pic_irqsrc[nirqs].pin = pin;
+               sc->gpio_pic_irqsrc[nirqs].bank = 
sc->conf->padconf->pins[pin].eint_bank;
+               sc->gpio_pic_irqsrc[nirqs].intnum = 
sc->conf->padconf->pins[pin].eint_num;
+               sc->gpio_pic_irqsrc[nirqs].intfunc = 
sc->conf->padconf->pins[pin].eint_func;
+               sc->gpio_pic_irqsrc[nirqs].irq = nirqs;
+               sc->gpio_pic_irqsrc[nirqs].mode = GPIO_INTR_CONFORM;
+
+               err = intr_isrc_register(&sc->gpio_pic_irqsrc[nirqs].isrc,
+                   sc->sc_dev, 0, "%s,%s", name,
+                   
sc->conf->padconf->pins[pin].functions[sc->conf->padconf->pins[pin].eint_func]);
+               if (err) {
+                       device_printf(sc->sc_dev, "intr_isrs_register failed 
for irq %d\n", nirqs);
+               }
+
+               nirqs++;
+       }
+
+       sc->nirqs = nirqs;
+
+       return (0);
+}
+
+static void
+aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct intr_irqsrc 
*isrc)
+{
+       u_int irq;
+       uint32_t reg;
+
+       AW_GPIO_LOCK_ASSERT(sc);
+       irq = ((struct gpio_irqsrc *)isrc)->irq;
+       reg = AW_GPIO_READ(sc, 
AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
+       reg &= ~(1 << sc->gpio_pic_irqsrc[irq].intnum);
+       AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), 
reg);
+
+       sc->gpio_pic_irqsrc[irq].enabled = false;
+}
+
+static void
+aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
        struct aw_gpio_softc *sc;
-       int i;
 
-       sc = device_get_softc(bus);
+       sc = device_get_softc(dev);
 
-       /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
-       for (i = 0; i < sc->conf->padconf->npins; i++)
-               if (sc->conf->padconf->pins[i].port == gpios[0] &&
-                   sc->conf->padconf->pins[i].pin == gpios[1]) {
-                       *pin = i;
+       AW_GPIO_LOCK(sc);
+       aw_gpio_pic_disable_intr_locked(sc, isrc);
+       AW_GPIO_UNLOCK(sc);
+}
+
+static void
+aw_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+       struct aw_gpio_softc *sc;
+       u_int irq;
+       uint32_t reg;
+
+       sc = device_get_softc(dev);
+       irq = ((struct gpio_irqsrc *)isrc)->irq;
+       AW_GPIO_LOCK(sc);
+       reg = AW_GPIO_READ(sc, 
AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
+       reg |= 1 << sc->gpio_pic_irqsrc[irq].intnum;
+       AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), 
reg);
+       AW_GPIO_UNLOCK(sc);
+
+       sc->gpio_pic_irqsrc[irq].enabled = true;
+}
+
+static int
+aw_gpio_pic_map_gpio(struct aw_gpio_softc *sc, struct intr_map_data_gpio *dag,
+    u_int *irqp, u_int *mode)
+{
+       u_int irq;
+       int pin;
+
+       irq = dag->gpio_pin_num;
+
+       for (pin = 0; pin < sc->nirqs; pin++)
+               if (sc->gpio_pic_irqsrc[pin].pin == irq)
                        break;
-               }
-       *flags = gpios[gcells - 1];
+       if (pin == sc->nirqs) {
+               device_printf(sc->sc_dev, "Invalid interrupt number %u\n", irq);
+               return (EINVAL);
+       }
 
+       switch (dag->gpio_intr_mode) {
+       case GPIO_INTR_LEVEL_LOW:
+       case GPIO_INTR_LEVEL_HIGH:
+       case GPIO_INTR_EDGE_RISING:
+       case GPIO_INTR_EDGE_FALLING:
+       case GPIO_INTR_EDGE_BOTH:
+               break;
+       default:
+               device_printf(sc->sc_dev, "Unsupported interrupt mode 0x%8x\n",
+                   dag->gpio_intr_mode);
+               return (EINVAL);
+       }
+
+       *irqp = pin;
+       if (mode != NULL)
+               *mode = dag->gpio_intr_mode;
+
        return (0);
 }
 
+static int
+aw_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
+    struct intr_irqsrc **isrcp)
+{
+       struct aw_gpio_softc *sc;
+       u_int irq;
+       int err;
+
+       sc = device_get_softc(dev);
+       switch (data->type) {
+       case INTR_MAP_DATA_GPIO:
+               err = aw_gpio_pic_map_gpio(sc,
+                   (struct intr_map_data_gpio *)data,
+                 &irq, NULL);
+               break;
+       default:
+               return (ENOTSUP);
+       };
+
+       if (err == 0)
+               *isrcp = &sc->gpio_pic_irqsrc[irq].isrc;
+       return (0);
+}
+
+static int
+aw_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+    struct resource *res, struct intr_map_data *data)
+{
+       struct aw_gpio_softc *sc;
+       struct gpio_irqsrc *gi;
+       uint32_t irqcfg;
+       uint32_t pinidx, reg;
+       u_int irq, mode;
+       int err;
+
+       sc = device_get_softc(dev);
+       gi = (struct gpio_irqsrc *)isrc;
+
+       switch (data->type) {
+       case INTR_MAP_DATA_GPIO:
+               err = aw_gpio_pic_map_gpio(sc,
+                   (struct intr_map_data_gpio *)data,
+                 &irq, &mode);
+               break;
+       default:
+               return (ENOTSUP);
+       };
+
+       pinidx = (sc->gpio_pic_irqsrc[irq].intnum % 8) * 4;
+
+       AW_GPIO_LOCK(sc);
+       switch (mode) {
+       case GPIO_INTR_LEVEL_LOW:
+               irqcfg = AW_GPIO_INT_LEVEL_LOW << pinidx;
+               break;
+       case GPIO_INTR_LEVEL_HIGH:
+               irqcfg = AW_GPIO_INT_LEVEL_HIGH << pinidx;
+               break;
+       case GPIO_INTR_EDGE_RISING:
+               irqcfg = AW_GPIO_INT_EDGE_POSITIVE << pinidx;
+               break;
+       case GPIO_INTR_EDGE_FALLING:
+               irqcfg = AW_GPIO_INT_EDGE_NEGATIVE << pinidx;
+               break;
+       case GPIO_INTR_EDGE_BOTH:
+               irqcfg = AW_GPIO_INT_EDGE_BOTH << pinidx;
+               break;
+       }
+
+       /* Switch the pin to interrupt mode */
+       sc->gpio_pic_irqsrc[irq].oldfunc = aw_gpio_get_function(sc,
+           sc->gpio_pic_irqsrc[irq].pin);
+       aw_gpio_set_function(sc, sc->gpio_pic_irqsrc[irq].pin,
+           sc->gpio_pic_irqsrc[irq].intfunc);
+
+       /* Write interrupt mode */
+       reg = AW_GPIO_READ(sc, 
+           AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
+           sc->gpio_pic_irqsrc[irq].intnum));
+       reg &= ~(0xF << pinidx);
+       reg |= irqcfg;
+       AW_GPIO_WRITE(sc,
+           AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
+           sc->gpio_pic_irqsrc[irq].intnum),
+           reg);
+
+       AW_GPIO_UNLOCK(sc);
+
+       return (0);
+}
+
+static int
+aw_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+    struct resource *res, struct intr_map_data *data)
+{
+       struct aw_gpio_softc *sc;
+       struct gpio_irqsrc *gi;
+
+       sc = device_get_softc(dev);
+       gi = (struct gpio_irqsrc *)isrc;
+
+       /* Switch back the pin to it's original function */
+       AW_GPIO_LOCK(sc);
+       aw_gpio_set_function(sc, gi->pin, gi->oldfunc);
+       AW_GPIO_UNLOCK(sc);
+
+       return (0);
+}
+
+static void
+aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+       struct aw_gpio_softc *sc;
+       struct gpio_irqsrc *gi;
+
+       sc = device_get_softc(dev);
+       gi = (struct gpio_irqsrc *)isrc;
+
+       arm_irq_memory_barrier(0);
+       AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
+}
+
+static void
+aw_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+       struct aw_gpio_softc *sc;
+       struct gpio_irqsrc *gi;
+
+       sc = device_get_softc(dev);
+       gi = (struct gpio_irqsrc *)isrc;
+
+       arm_irq_memory_barrier(0);
+       AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
+       aw_gpio_pic_enable_intr(dev, isrc);
+}
+
+static void
+aw_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+       struct aw_gpio_softc *sc;
+
+       sc = device_get_softc(dev);
+       aw_gpio_pic_disable_intr_locked(sc, isrc);
+}
+
+/*
+ * OFWBUS Interface
+ */
+static phandle_t
+aw_gpio_get_node(device_t dev, device_t bus)
+{
+
+       /* We only have one child, the GPIO bus, which needs our own node. */
+       return (ofw_bus_get_node(dev));
+}
+
 static device_method_t aw_gpio_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,         aw_gpio_probe),
        DEVMETHOD(device_attach,        aw_gpio_attach),
        DEVMETHOD(device_detach,        aw_gpio_detach),
+
+#ifdef INTRNG
+       /* Interrupt controller interface */
+       DEVMETHOD(pic_disable_intr,     aw_gpio_pic_disable_intr),
+       DEVMETHOD(pic_enable_intr,      aw_gpio_pic_enable_intr),
+       DEVMETHOD(pic_map_intr,         aw_gpio_pic_map_intr),
+       DEVMETHOD(pic_setup_intr,       aw_gpio_pic_setup_intr),
+       DEVMETHOD(pic_teardown_intr,    aw_gpio_pic_teardown_intr),
+       DEVMETHOD(pic_post_filter,      aw_gpio_pic_post_filter),
+       DEVMETHOD(pic_post_ithread,     aw_gpio_pic_post_ithread),
+       DEVMETHOD(pic_pre_ithread,      aw_gpio_pic_pre_ithread),
+#endif
 
        /* GPIO protocol */
        DEVMETHOD(gpio_get_bus,         aw_gpio_get_bus),
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to