svn commit: r298738 - in head/sys: dev/gpio kern sys
Michal Meloun
mmel at FreeBSD.org
Thu Apr 28 12:03:23 UTC 2016
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);
More information about the svn-src-head
mailing list