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-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"