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.
This commit is contained in:
parent
f9ac50ac45
commit
39f6c1bdf4
@ -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, device_t, uint32_t, unsigned int);
|
||||
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)
|
||||
{
|
||||
|
@ -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, bool *active);
|
||||
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);
|
||||
|
@ -596,6 +596,27 @@ intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
|
||||
}
|
||||
#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.
|
||||
|
@ -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 */
|
||||
|
@ -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, enum intr_polarity,
|
||||
#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);
|
||||
|
Loading…
Reference in New Issue
Block a user