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");