svn commit: r356891 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Sun Jan 19 19:51:20 UTC 2020


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),


More information about the svn-src-all mailing list