From patchwork Sun Jan 27 17:04:08 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwenhael Goavec-Merou X-Patchwork-Id: 2051961 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id A85A3DFE86 for ; Sun, 27 Jan 2013 17:08:15 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TzVfG-0000Vo-LX; Sun, 27 Jan 2013 17:05:06 +0000 Received: from smtp2-g21.free.fr ([2a01:e0c:1:1599::11]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TzVfC-0000VR-T1 for linux-arm-kernel@lists.infradead.org; Sun, 27 Jan 2013 17:05:05 +0000 Received: from dell.trabucayre.com (unknown [81.56.132.22]) by smtp2-g21.free.fr (Postfix) with ESMTP id 1D8554B01AB; Sun, 27 Jan 2013 18:04:53 +0100 (CET) From: Gwenhael Goavec-Merou To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] ARM: mxs: gpio-mxs: Add IRQ_TYPE_EDGE_BOTH support Date: Sun, 27 Jan 2013 18:04:08 +0100 Message-Id: <1359306248-28690-1-git-send-email-gwenhael.goavec-merou@armadeus.com> X-Mailer: git-send-email 1.7.12.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130127_120503_696588_5EA4F210 X-CRM114-Status: GOOD ( 11.42 ) X-Spam-Score: -1.2 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.7 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Grant Likely , Linus Walleij , Shawn Guo , Gwenhael Goavec-Merou X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds support for IRQ_TYPE_EDGE_BOTH needed for some driver (gpio-keys). Inspired from gpio-mxc.c Signed-off-by: Gwenhael Goavec-Merou --- drivers/gpio/gpio-mxs.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index fa2a63c..7690eec 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -65,6 +65,7 @@ struct mxs_gpio_port { struct irq_domain *domain; struct bgpio_chip bgc; enum mxs_gpio_id devid; + u32 both_edges; }; static inline int is_imx23_gpio(struct mxs_gpio_port *port) @@ -81,13 +82,24 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port) static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { + u32 val; u32 pin_mask = 1 << d->hwirq; + u32 gpio_idx = d->hwirq; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxs_gpio_port *port = gc->private; void __iomem *pin_addr; int edge; + port->both_edges &= ~(1 << gpio_idx); switch (type) { + case IRQ_TYPE_EDGE_BOTH: + val = gpio_get_value(port->bgc.gc.base + gpio_idx); + if (val) + edge = GPIO_INT_LOW_LEV; + else + edge = GPIO_INT_HIGH_LEV; + port->both_edges |= 1 << gpio_idx; + break; case IRQ_TYPE_EDGE_RISING: edge = GPIO_INT_RISE_EDGE; break; @@ -123,6 +135,22 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) return 0; } +static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) +{ + u32 bit, val, edge; + void __iomem *pin_addr; + + bit = 1<base + PINCTRL_IRQPOL(port); + val = readl(pin_addr); + edge = val&bit; + + if (edge) + writel(bit, pin_addr + MXS_CLR); + else + writel(bit, pin_addr + MXS_SET); +} /* MXS has one interrupt *per* gpio port */ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) @@ -137,6 +165,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; + if (port->both_edges & (1 << irqoffset)) + mxs_flip_edge(port, irqoffset); + generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); irq_stat &= ~(1 << irqoffset); }