summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskra <skra@FreeBSD.org>2016-05-23 18:16:21 +0000
committerskra <skra@FreeBSD.org>2016-05-23 18:16:21 +0000
commit790244c47d31506ffa13efa2d15b404854f171ed (patch)
tree96d42c81496b35950cb313d066a8f9af70aea6fd
parentf7192b1fcde40164f626f5a033a754043526186e (diff)
downloadFreeBSD-src-790244c47d31506ffa13efa2d15b404854f171ed.zip
FreeBSD-src-790244c47d31506ffa13efa2d15b404854f171ed.tar.gz
INTRNG - support new interrupt mapping type INTR_MAP_DATA_GPIO
introduced in r298738. Reviewed by: ian
-rw-r--r--sys/arm/freescale/imx/imx_gpio.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c
index ddec272..1f17f5c 100644
--- a/sys/arm/freescale/imx/imx_gpio.c
+++ b/sys/arm/freescale/imx/imx_gpio.c
@@ -88,7 +88,14 @@ __FBSDID("$FreeBSD$");
#define IMX_GPIO_ISR_REG 0x018 /* Interrupt Status Register */
#define IMX_GPIO_EDGE_REG 0x01C /* Edge Detect Register */
+#ifdef INTRNG
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH | GPIO_INTR_EDGE_RISING | \
+ GPIO_INTR_EDGE_FALLING )
+#else
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+#endif
+
#define NGPIO 32
#ifdef INTRNG
@@ -156,15 +163,12 @@ static int imx51_gpio_pin_toggle(device_t, uint32_t pin);
#ifdef INTRNG
static int
-gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
- uint32_t *modep)
+gpio_pic_map_fdt(struct imx51_gpio_softc *sc, struct intr_map_data_fdt *daf,
+ u_int *irqp, uint32_t *modep)
{
- struct imx51_gpio_softc *sc;
- u_int irq, tripol;
+ u_int irq;
uint32_t mode;
- sc = device_get_softc(dev);
-
/*
* From devicetree/bindings/gpio/fsl-imx-gpio.txt:
* #interrupt-cells: 2. The first cell is the GPIO number. The second
@@ -176,18 +180,17 @@ gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
* We can do any single one of these modes, but nothing in combo.
*/
- if (ncells != 2) {
+ if (daf->ncells != 2) {
device_printf(sc->dev, "Invalid #interrupt-cells\n");
return (EINVAL);
}
- irq = cells[0];
- tripol = cells[1];
+ irq = daf->cells[0];
if (irq >= sc->gpio_npins) {
device_printf(sc->dev, "Invalid interrupt number %u\n", irq);
return (EINVAL);
}
- switch (tripol) {
+ switch (daf->cells[1]) {
case 1:
mode = GPIO_INTR_EDGE_RISING;
break;
@@ -202,7 +205,7 @@ gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
break;
default:
device_printf(sc->dev, "Unsupported interrupt mode 0x%2x\n",
- tripol);
+ daf->cells[1]);
return (ENOTSUP);
}
*irqp = irq;
@@ -212,23 +215,61 @@ gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
}
static int
+gpio_pic_map_gpio(struct imx51_gpio_softc *sc, struct intr_map_data_gpio *dag,
+ u_int *irqp, uint32_t *modep)
+{
+ u_int irq;
+ uint32_t mode;
+
+ irq = dag->gpio_pin_num;
+ if (irq >= sc->gpio_npins) {
+ device_printf(sc->dev, "Invalid interrupt number %u\n", irq);
+ return (EINVAL);
+ }
+
+ mode = dag->gpio_intr_mode;
+ if (mode != GPIO_INTR_LEVEL_LOW && mode != GPIO_INTR_LEVEL_HIGH &&
+ mode != GPIO_INTR_EDGE_RISING && mode != GPIO_INTR_EDGE_FALLING) {
+ device_printf(sc->dev, "Unsupported interrupt mode 0x%8x\n",
+ mode);
+ return (EINVAL);
+ }
+
+ *irqp = irq;
+ if (modep != NULL)
+ *modep = mode;
+ return (0);
+}
+
+static int
+gpio_pic_map(struct imx51_gpio_softc *sc, struct intr_map_data *data,
+ u_int *irqp, uint32_t *modep)
+{
+
+ switch (data->type) {
+ case INTR_MAP_DATA_FDT:
+ return (gpio_pic_map_fdt(sc, (struct intr_map_data_fdt *)data,
+ irqp, modep));
+ case INTR_MAP_DATA_GPIO:
+ return (gpio_pic_map_gpio(sc, (struct intr_map_data_gpio *)data,
+ irqp, modep));
+ default:
+ return (ENOTSUP);
+ }
+}
+
+static int
gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
int error;
u_int irq;
- struct intr_map_data_fdt *daf;
struct imx51_gpio_softc *sc;
- if (data->type != INTR_MAP_DATA_FDT)
- return (ENOTSUP);
-
- daf = (struct intr_map_data_fdt *)data;
- error = gpio_pic_map_fdt(dev, daf->ncells, daf->cells, &irq, NULL);
- if (error == 0) {
- sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
+ error = gpio_pic_map(sc, data, &irq, NULL);
+ if (error == 0)
*isrcp = &sc->gpio_pic_irqsrc[irq].gi_isrc;
- }
return (error);
}
@@ -257,21 +298,20 @@ static int
gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
struct resource *res, struct intr_map_data *data)
{
- struct intr_map_data_fdt *daf;
struct imx51_gpio_softc *sc;
struct gpio_irqsrc *gi;
int error, icfg;
u_int irq, reg, shift, wrk;
uint32_t mode;
+ if (data == NULL)
+ return (ENOTSUP);
+
sc = device_get_softc(dev);
gi = (struct gpio_irqsrc *)isrc;
/* Get config for interrupt. */
- if (data == NULL || data->type != INTR_MAP_DATA_FDT)
- return (ENOTSUP);
- daf = (struct intr_map_data_fdt *)data;
- error = gpio_pic_map_fdt(dev, daf->ncells, daf->cells, &irq, &mode);
+ error = gpio_pic_map(sc, data, &irq, &mode);
if (error != 0)
return (error);
if (gi->gi_irq != irq)
OpenPOWER on IntegriCloud