Module Name:    src
Committed By:   hkenken
Date:           Sat Mar 22 05:19:18 UTC 2014

Modified Files:
        src/sys/arch/arm/imx: files.imx51 imxgpio.c

Log Message:
* GPIO interrupts of i.MX5 are divided into two groups.
  add IMX_GPIO_INTR_SPLIT option
* Support GPIO both edge trigger interrupt.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/imx/files.imx51
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/imx/imxgpio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/imx/files.imx51
diff -u src/sys/arch/arm/imx/files.imx51:1.6 src/sys/arch/arm/imx/files.imx51:1.7
--- src/sys/arch/arm/imx/files.imx51:1.6	Sat Mar 22 04:55:00 2014
+++ src/sys/arch/arm/imx/files.imx51	Sat Mar 22 05:19:18 2014
@@ -1,4 +1,4 @@
-#	$NetBSD: files.imx51,v 1.6 2014/03/22 04:55:00 hkenken Exp $
+#	$NetBSD: files.imx51,v 1.7 2014/03/22 05:19:18 hkenken Exp $
 #
 # Configuration info for the Freescale i.MX51
 #
@@ -56,6 +56,7 @@ device	imxgpio: gpiobus
 attach	imxgpio at axi
 file	arch/arm/imx/imxgpio.c		imxgpio		needs-flag
 file	arch/arm/imx/imx51_gpio.c	imxgpio
+defflag opt_imxgpio.h			IMX_GPIO_INTR_SPLIT
 
 # iMX IOMUX
 device	imxiomux : bus_space_generic

Index: src/sys/arch/arm/imx/imxgpio.c
diff -u src/sys/arch/arm/imx/imxgpio.c:1.3 src/sys/arch/arm/imx/imxgpio.c:1.4
--- src/sys/arch/arm/imx/imxgpio.c:1.3	Sat Oct 27 17:17:39 2012
+++ src/sys/arch/arm/imx/imxgpio.c	Sat Mar 22 05:19:18 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: imxgpio.c,v 1.3 2012/10/27 17:17:39 chs Exp $ */
+/*	$NetBSD: imxgpio.c,v 1.4 2014/03/22 05:19:18 hkenken Exp $ */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -29,12 +29,13 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxgpio.c,v 1.3 2012/10/27 17:17:39 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imxgpio.c,v 1.4 2014/03/22 05:19:18 hkenken Exp $");
 
 #define	_INTR_PRIVATE
 
 #include "locators.h"
 #include "gpio.h"
+#include "opt_imxgpio.h"
 
 #include <sys/param.h>
 #include <sys/evcnt.h>
@@ -82,7 +83,12 @@ const struct pic_ops gpio_pic_ops = {
 struct gpio_softc {
 	device_t gpio_dev;
 	struct pic_softc gpio_pic;
+#if defined(IMX_GPIO_INTR_SPLIT)
+	struct intrsource *gpio_is_0_15;
+	struct intrsource *gpio_is_16_31;
+#else
 	struct intrsource *gpio_is;
+#endif
 	bus_space_tag_t gpio_memt;
 	bus_space_handle_t gpio_memh;
 	uint32_t gpio_enable_mask;
@@ -174,6 +180,25 @@ gpio_pic_find_pending_irqs(struct pic_so
 		KASSERT(pending != 0);
 		irq = 31 - __builtin_clz(pending);
 		pending &= ~__BIT(irq);
+
+		const struct intrsource *is = pic->pic_sources[irq];
+		if (is->is_type == IST_EDGE_BOTH) {
+			/*
+			 * for both edge
+			 */
+			uint32_t icr_reg = GPIO_ICR1 + ((is->is_irq & 0x10) >> 2);
+			v = GPIO_READ(gpio, icr_reg);
+			uint32_t icr_shift = (is->is_irq & 0x0f) << 1;
+			uint32_t mask = (3 << icr_shift);
+			int gtype = __SHIFTOUT(v, mask);
+			if (gtype == GPIO_ICR_EDGE_RISING)
+				gtype = GPIO_ICR_EDGE_FALLING;
+			else if (gtype == GPIO_ICR_EDGE_FALLING)
+				gtype = GPIO_ICR_EDGE_RISING;
+			v &= ~mask;
+			v |= __SHIFTIN(gtype, mask);
+			GPIO_WRITE(gpio, icr_reg, v);
+		}
 		pic_mark_pending(&gpio->gpio_pic, irq);
 	} while (pending != 0);
 
@@ -184,7 +209,8 @@ gpio_pic_find_pending_irqs(struct pic_so
 	((GPIO_ICR_LEVEL_LOW << (2*IST_LEVEL_LOW)) | \
 	 (GPIO_ICR_LEVEL_HIGH << (2*IST_LEVEL_HIGH)) | \
 	 (GPIO_ICR_EDGE_RISING << (2*IST_EDGE_RISING)) | \
-	 (GPIO_ICR_EDGE_FALLING << (2*IST_EDGE_FALLING)))
+	 (GPIO_ICR_EDGE_FALLING << (2*IST_EDGE_FALLING)) | \
+	 (GPIO_ICR_EDGE_RISING << (2*IST_EDGE_BOTH)))
 
 void
 gpio_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
@@ -341,9 +367,18 @@ imxgpio_attach_common(device_t self, bus
 		aprint_normal(": interrupts %d..%d",
 		    irqbase, irqbase + GPIO_NPINS - 1);
 
+#if defined(IMX_GPIO_INTR_SPLIT)
+		gpio->gpio_is_0_15 = intr_establish(intr,
+		    IPL_NET, IST_LEVEL, pic_handle_intr, &gpio->gpio_pic);
+		KASSERT( gpio->gpio_is_0_15 != NULL );
+		gpio->gpio_is_16_31 = intr_establish(intr + 1,
+		    IPL_NET, IST_LEVEL, pic_handle_intr, &gpio->gpio_pic);
+		KASSERT( gpio->gpio_is_16_31 != NULL );
+#else
 		gpio->gpio_is = intr_establish(intr,
 		    IPL_NET, IST_LEVEL, pic_handle_intr, &gpio->gpio_pic);
 		KASSERT( gpio->gpio_is != NULL );
+#endif
 	}
 	aprint_normal("\n");
 		      

Reply via email to