From patchwork Tue Jul 7 12:58:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Kelleter?= X-Patchwork-Id: 492218 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 0809F14028F for ; Tue, 7 Jul 2015 23:02:46 +1000 (AEST) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 1C85028BE4A; Tue, 7 Jul 2015 15:01:39 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00 autolearn=unavailable version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id AA361280143 for ; Tue, 7 Jul 2015 15:01:25 +0200 (CEST) X-policyd-weight: using cached result; rate: -5.5 Received: from mout3.freenet.de (mout3.freenet.de [195.4.92.93]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Tue, 7 Jul 2015 15:01:25 +0200 (CEST) Received: from [195.4.92.141] (helo=mjail1.freenet.de) by mout3.freenet.de with esmtpa (ID gnther.kelleter@freenet.de) (port 25) (Exim 4.85 #1) id 1ZCSVI-0004gJ-MD; Tue, 07 Jul 2015 15:01:40 +0200 Received: from localhost ([::1]:34436 helo=mjail1.freenet.de) by mjail1.freenet.de with esmtpa (ID gnther.kelleter@freenet.de) (Exim 4.85 #1) id 1ZCSVI-0001g8-EY; Tue, 07 Jul 2015 15:01:40 +0200 Received: from mx15.freenet.de ([195.4.92.25]:55293) by mjail1.freenet.de with esmtpa (ID gnther.kelleter@freenet.de) (Exim 4.85 #1) id 1ZCSTI-0006Qf-R9; Tue, 07 Jul 2015 14:59:36 +0200 Received: from p4fe06185.dip0.t-ipconnect.de ([79.224.97.133]:60956 helo=gkelleter.devolo.com) by mx15.freenet.de with esmtpsa (ID gnther.kelleter@freenet.de) (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (port 25) (Exim 4.85 #1) id 1ZCSTI-0006Hc-MR; Tue, 07 Jul 2015 14:59:36 +0200 Received: by gkelleter.devolo.com (Postfix, from userid 1000) id 3F0D961119; Tue, 7 Jul 2015 14:59:33 +0200 (CEST) From: =?UTF-8?q?G=C3=BCnther=20Kelleter?= To: openwrt-devel@lists.openwrt.org Date: Tue, 7 Jul 2015 14:58:53 +0200 Message-Id: <1436273936-6908-5-git-send-email-guenther.kelleter@devolo.de> X-Mailer: git-send-email 2.4.4.88.gac2ab0d In-Reply-To: <1436273936-6908-1-git-send-email-guenther.kelleter@devolo.de> References: <1436273936-6908-1-git-send-email-guenther.kelleter@devolo.de> MIME-Version: 1.0 X-Originated-At: 79.224.97.133!60956 Subject: [OpenWrt-Devel] [PATCH v3 4/7] ar71xx: add support to use gpio irqs X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" Signed-off-by: Günther Kelleter --- .../739-MIPS-ath79-add-gpio-irq-support.patch | 225 +++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch diff --git a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch new file mode 100644 index 0000000..2b90df0 --- /dev/null +++ b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch @@ -0,0 +1,225 @@ +--- a/arch/mips/ath79/gpio.c ++++ b/arch/mips/ath79/gpio.c +@@ -20,9 +20,14 @@ + #include + #include + #include ++#include ++#include ++ ++#include + + #include + #include ++#include + #include "common.h" + + void __iomem *ath79_gpio_base; +@@ -31,6 +36,13 @@ EXPORT_SYMBOL_GPL(ath79_gpio_base); + static unsigned long ath79_gpio_count; + static DEFINE_SPINLOCK(ath79_gpio_lock); + ++/* ++ * gpio_both_edge is a bitmask of which gpio pins need to have ++ * the detect priority flipped from the interrupt handler to ++ * emulate IRQ_TYPE_EDGE_BOTH. ++ */ ++static unsigned long gpio_both_edge = 0; ++ + static void __ath79_gpio_set_value(unsigned gpio, int value) + { + void __iomem *base = ath79_gpio_base; +@@ -209,6 +221,133 @@ void __init ath79_gpio_output_select(uns + spin_unlock_irqrestore(&ath79_gpio_lock, flags); + } + ++static int ath79_gpio_irq_type(struct irq_data *d, unsigned type) ++{ ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; ++ void __iomem *base = ath79_gpio_base; ++ unsigned long flags; ++ unsigned long int_type; ++ unsigned long int_polarity; ++ unsigned long bit = (1 << offset); ++ ++ spin_lock_irqsave(&ath79_gpio_lock, flags); ++ ++ int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE); ++ int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY); ++ ++ gpio_both_edge &= ~bit; ++ ++ switch (type) { ++ case IRQ_TYPE_EDGE_RISING: ++ int_type &= ~bit; ++ int_polarity |= bit; ++ break; ++ ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type &= ~bit; ++ int_polarity &= ~bit; ++ break; ++ ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type |= bit; ++ int_polarity |= bit; ++ break; ++ ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type |= bit; ++ int_polarity &= ~bit; ++ break; ++ ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type |= bit; ++ /* set polarity based on current value */ ++ if (gpio_get_value(offset)) { ++ int_polarity &= ~bit; ++ } else { ++ int_polarity |= bit; ++ } ++ /* flip this gpio in the interrupt handler */ ++ gpio_both_edge |= bit; ++ break; ++ ++ default: ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags); ++ return -EINVAL; ++ } ++ ++ __raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE); ++ __raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY); ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << offset), ++ base + AR71XX_GPIO_REG_INT_MODE); ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset), ++ base + AR71XX_GPIO_REG_INT_ENABLE); ++ ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags); ++ return 0; ++} ++ ++static void ath79_gpio_irq_enable(struct irq_data *d) ++{ ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; ++ void __iomem *base = ath79_gpio_base; ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << offset), ++ base + AR71XX_GPIO_REG_INT_ENABLE); ++} ++ ++static void ath79_gpio_irq_disable(struct irq_data *d) ++{ ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; ++ void __iomem *base = ath79_gpio_base; ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset), ++ base + AR71XX_GPIO_REG_INT_ENABLE); ++} ++ ++static struct irq_chip ath79_gpio_irqchip = { ++ .name = "GPIO", ++ .irq_enable = ath79_gpio_irq_enable, ++ .irq_disable = ath79_gpio_irq_disable, ++ .irq_set_type = ath79_gpio_irq_type, ++}; ++ ++static irqreturn_t ath79_gpio_irq(int irq, void *dev) ++{ ++ void __iomem *base = ath79_gpio_base; ++ unsigned int stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING); ++ ++ while (stat) { ++ int bit_num = __ffs(stat); ++ unsigned long bit = (1<ngpio; irq++) { ++ irq_set_chip_data(irq, chip); ++ irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, handle_simple_irq); ++ irq_set_noprobe(irq); ++ } ++ ++ return 0; ++} ++ + void __init ath79_gpio_init(void) + { + int err; +@@ -245,6 +384,10 @@ void __init ath79_gpio_init(void) + err = gpiochip_add(&ath79_gpio_chip); + if (err) + panic("cannot add AR71xx GPIO chip, error=%d", err); ++ ++ ath79_gpio_irq_init(&ath79_gpio_chip); ++ ++ request_irq(ATH79_MISC_IRQ(2), ath79_gpio_irq, 0, "ath79-gpio", NULL); + } + + int gpio_get_value(unsigned gpio) +@@ -267,14 +410,22 @@ EXPORT_SYMBOL(gpio_set_value); + + int gpio_to_irq(unsigned gpio) + { +- /* FIXME */ +- return -EINVAL; ++ if (gpio > ath79_gpio_count) { ++ return -EINVAL; ++ } ++ ++ return ATH79_GPIO_IRQ_BASE + gpio; + } + EXPORT_SYMBOL(gpio_to_irq); + + int irq_to_gpio(unsigned irq) + { +- /* FIXME */ +- return -EINVAL; ++ unsigned gpio = irq - ATH79_GPIO_IRQ_BASE; ++ ++ if (gpio > ath79_gpio_count) { ++ return -EINVAL; ++ } ++ ++ return gpio; + } + EXPORT_SYMBOL(irq_to_gpio); +--- a/arch/mips/include/asm/mach-ath79/irq.h ++++ b/arch/mips/include/asm/mach-ath79/irq.h +@@ -10,7 +10,7 @@ + #define __ASM_MACH_ATH79_IRQ_H + + #define MIPS_CPU_IRQ_BASE 0 +-#define NR_IRQS 51 ++#define NR_IRQS 83 + + #define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x)) + +@@ -30,6 +30,10 @@ + #define ATH79_IP3_IRQ_COUNT 3 + #define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x)) + ++#define ATH79_GPIO_IRQ_BASE (ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT) ++#define ATH79_GPIO_IRQ_COUNT 32 ++#define ATH79_GPIO_IRQ(_x) (ATH79_GPIO_IRQ_BASE + (_x)) ++ + #include_next + + #endif /* __ASM_MACH_ATH79_IRQ_H */