Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 May 2017 06:22:14 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r317874 - head/sys/mips/mediatek
Message-ID:  <201705060622.v466MECl091041@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sat May  6 06:22:14 2017
New Revision: 317874
URL: https://svnweb.freebsd.org/changeset/base/317874

Log:
  [mediatek] [gpio] add PPS / interrupt support.
  
  Submitted by:	Hiroki Mori <yamori813@yahoo.co.jp>
  Reviewed by:	mizhka
  Differential Revision:	https://reviews.freebsd.org/D9784

Modified:
  head/sys/mips/mediatek/mtk_gpio_v1.c

Modified: head/sys/mips/mediatek/mtk_gpio_v1.c
==============================================================================
--- head/sys/mips/mediatek/mtk_gpio_v1.c	Sat May  6 06:20:34 2017	(r317873)
+++ head/sys/mips/mediatek/mtk_gpio_v1.c	Sat May  6 06:22:14 2017	(r317874)
@@ -292,7 +292,8 @@ mtk_gpio_attach(device_t dev)
 
 	for (i = 0; i < sc->num_pins; i++) {
 		sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
-		    GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
+		    GPIO_PIN_INVIN | GPIO_PIN_INVOUT |
+		    GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING;
 		sc->pins[i].intr_polarity = INTR_POLARITY_HIGH;
 		sc->pins[i].intr_trigger = INTR_TRIGGER_EDGE;
 
@@ -500,22 +501,78 @@ out:
 }
 
 static int
+mtk_gpio_pic_map_fdt(struct mtk_gpio_softc *sc,
+    struct intr_map_data_fdt *daf, u_int *irqp, uint32_t *modep)
+{
+	u_int irq;
+
+	if (daf->ncells != 1) {
+		device_printf(sc->dev, "Invalid #interrupt-cells\n");
+		return (EINVAL);
+	}
+
+	irq = daf->cells[0];
+
+	if (irq >= sc->num_pins) {
+		device_printf(sc->dev, "Invalid interrupt number %u\n", irq);
+		return (EINVAL);
+	}
+
+	*irqp = irq;
+	if (modep != NULL)
+		*modep = GPIO_INTR_EDGE_BOTH;
+
+	return (0);
+}
+
+static int
+mtk_gpio_pic_map_gpio(struct mtk_gpio_softc *sc,
+    struct intr_map_data_gpio *dag, u_int *irqp, uint32_t *modep)
+{
+	u_int irq;
+
+	irq = dag->gpio_pin_num;
+	if (irq >= sc->num_pins) {
+		device_printf(sc->dev, "Invalid interrupt number %u\n", irq);
+		return (EINVAL);
+	}
+
+	*irqp = irq;
+	if (modep != NULL)
+		*modep = dag->gpio_intr_mode;
+
+	return (0);
+}
+
+static int
 mtk_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
     struct intr_irqsrc **isrcp)
 {
-	struct intr_map_data_fdt *daf;
+	int error;
+	u_int irq;
 	struct mtk_gpio_softc *sc;
 
-	if (data->type != INTR_MAP_DATA_FDT)
-		return (ENOTSUP);
-
 	sc = device_get_softc(dev);
-	daf = (struct intr_map_data_fdt *)data;
+	switch (data->type) {
+	case INTR_MAP_DATA_FDT:
+		error = (mtk_gpio_pic_map_fdt(sc, 
+		    (struct intr_map_data_fdt *)data, &irq, NULL));
+		break;
+	case INTR_MAP_DATA_GPIO:
+		error = (mtk_gpio_pic_map_gpio(sc, 
+		    (struct intr_map_data_gpio *)data, &irq, NULL));
+		break;
+	default:
+		error = EINVAL;
+		break;
+	}
 
-	if (daf->ncells != 1 || daf->cells[0] >= sc->num_pins)
-		return (EINVAL);
+	if (error != 0) {
+		device_printf(dev, "Invalid map type\n");
+		return (error);
+	}
 
-	*isrcp = PIC_INTR_ISRC(sc, daf->cells[0]);
+	*isrcp = PIC_INTR_ISRC(sc, irq);
 	return (0);
 }
 
@@ -600,6 +657,51 @@ mtk_gpio_pic_post_filter(device_t dev, s
 }
 
 static int
+mtk_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+    struct resource *res, struct intr_map_data *data)
+{
+	struct mtk_gpio_softc *sc;
+	uint32_t val;
+	int error;
+	uint32_t mode;
+	u_int irq;
+
+	if (data == NULL)
+		return (ENOTSUP);
+
+	sc = device_get_softc(dev);
+
+	switch (data->type) {
+	case INTR_MAP_DATA_FDT:
+		error = mtk_gpio_pic_map_fdt(sc, 
+		    (struct intr_map_data_fdt *)data, &irq, &mode);
+		break;
+	case INTR_MAP_DATA_GPIO:
+		error = mtk_gpio_pic_map_gpio(sc, 
+		    (struct intr_map_data_gpio *)data, &irq, &mode);
+		break;
+	default:
+		error = ENOTSUP;
+		break;
+	}
+
+	if (error != 0)
+		return (error);
+	
+	MTK_GPIO_LOCK(sc);
+	if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_RISING) {
+		val = MTK_READ_4(sc, GPIO_PIORENA) | (1u << irq);
+		MTK_WRITE_4(sc, GPIO_PIORENA, val);
+	}
+	if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_FALLING) {
+		val = MTK_READ_4(sc, GPIO_PIOFENA) | (1u << irq);
+		MTK_WRITE_4(sc, GPIO_PIOFENA, val);
+	}
+	MTK_GPIO_UNLOCK(sc);
+	return (0);
+}
+
+static int
 mtk_gpio_intr(void *arg)
 {
 	struct mtk_gpio_softc *sc;
@@ -607,6 +709,7 @@ mtk_gpio_intr(void *arg)
 
 	sc = arg;
 	interrupts = MTK_READ_4(sc, GPIO_PIOINT);
+	MTK_WRITE_4(sc, GPIO_PIOINT, interrupts);
 
 	for (i = 0; interrupts != 0; i++, interrupts >>= 1) {
 		if ((interrupts & 0x1) == 0)
@@ -649,6 +752,7 @@ static device_method_t mtk_gpio_methods[
 	DEVMETHOD(pic_disable_intr,	mtk_gpio_pic_disable_intr),
 	DEVMETHOD(pic_enable_intr,	mtk_gpio_pic_enable_intr),
 	DEVMETHOD(pic_map_intr,		mtk_gpio_pic_map_intr),
+	DEVMETHOD(pic_setup_intr,	mtk_gpio_pic_setup_intr),
 	DEVMETHOD(pic_post_filter,	mtk_gpio_pic_post_filter),
 	DEVMETHOD(pic_post_ithread,	mtk_gpio_pic_post_ithread),
 	DEVMETHOD(pic_pre_ithread,	mtk_gpio_pic_pre_ithread),



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705060622.v466MECl091041>