From patchwork Sat Jul 20 14:51:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris BREZILLON X-Patchwork-Id: 2830829 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4DC42C0319 for ; Sat, 20 Jul 2013 14:52:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 693B02014C for ; Sat, 20 Jul 2013 14:52:32 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 641F62014B for ; Sat, 20 Jul 2013 14:52:31 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V0YWA-0005Fu-IW; Sat, 20 Jul 2013 14:52:18 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V0YW8-000691-BG; Sat, 20 Jul 2013 14:52:16 +0000 Received: from 4.mo2.mail-out.ovh.net ([87.98.172.75] helo=mo2.mail-out.ovh.net) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V0YW4-00067l-1q for linux-arm-kernel@lists.infradead.org; Sat, 20 Jul 2013 14:52:13 +0000 Received: from mail401.ha.ovh.net (gw6.ovh.net [213.251.189.206]) by mo2.mail-out.ovh.net (Postfix) with SMTP id 60243DC12F1 for ; Sat, 20 Jul 2013 16:51:46 +0200 (CEST) Received: from b0.ovh.net (HELO queueout) (213.186.33.50) by b0.ovh.net with SMTP; 20 Jul 2013 16:46:53 +0200 Received: from cha74-5-78-236-240-82.fbx.proxad.net (HELO localhost.localdomain) (b.brezillon@overkiz.com@78.236.240.82) by ns0.ovh.net with SMTP; 20 Jul 2013 16:46:51 +0200 From: Boris BREZILLON To: Jean-Christophe Plagniol-Villard , Linus Walleij , Nicolas Ferre , Ludovic Desroches X-Ovh-Mailout: 178.32.228.2 (mo2.mail-out.ovh.net) Subject: [PATCH] pinctrl: at91: choose appropriate handler for level interrupts Date: Sat, 20 Jul 2013 16:51:33 +0200 Message-Id: <1374331893-16009-1-git-send-email-b.brezillon@overkiz.com> X-Mailer: git-send-email 1.7.9.5 X-Ovh-Tracer-Id: 11734973255523268780 X-Ovh-Remote: 78.236.240.82 (cha74-5-78-236-240-82.fbx.proxad.net) X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-OVH-SPAMSTATE: OK X-OVH-SPAMSCORE: -100 X-OVH-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeeijedrfedtucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-Spam-Check: DONE|U 0.5/N X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeeijedrfedtucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130720_105212_297602_7CD77C13 X-CRM114-Status: GOOD ( 16.16 ) X-Spam-Score: -1.9 (-) Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Boris BREZILLON X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current implementation handle both edge and level interrupts with the 'handle_simple_irq' handler. Level interrupts are active as long as the pin stays at the configured level (low or high). In this case we have to use 'handle_level_irq' which mask the interrupt until the handle has treated it. Signed-off-by: Boris BREZILLON Tested-by: Alexandre Belloni Acked-by: Nicolas Ferre --- drivers/pinctrl/pinctrl-at91.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 5d7529e..76e108d 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1241,18 +1241,22 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type) switch (type) { case IRQ_TYPE_EDGE_RISING: + irq_set_handler(d->irq, handle_simple_irq); writel_relaxed(mask, pio + PIO_ESR); writel_relaxed(mask, pio + PIO_REHLSR); break; case IRQ_TYPE_EDGE_FALLING: + irq_set_handler(d->irq, handle_simple_irq); writel_relaxed(mask, pio + PIO_ESR); writel_relaxed(mask, pio + PIO_FELLSR); break; case IRQ_TYPE_LEVEL_LOW: + irq_set_handler(d->irq, handle_level_irq); writel_relaxed(mask, pio + PIO_LSR); writel_relaxed(mask, pio + PIO_FELLSR); break; case IRQ_TYPE_LEVEL_HIGH: + irq_set_handler(d->irq, handle_level_irq); writel_relaxed(mask, pio + PIO_LSR); writel_relaxed(mask, pio + PIO_REHLSR); break; @@ -1261,6 +1265,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type) * disable additional interrupt modes: * fall back to default behavior */ + irq_set_handler(d->irq, handle_simple_irq); writel_relaxed(mask, pio + PIO_AIMDR); return 0; case IRQ_TYPE_NONE: @@ -1402,6 +1407,8 @@ static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { struct at91_gpio_chip *at91_gpio = h->host_data; + void __iomem *pio = at91_gpio->regbase; + u32 mask = 1 << hw; irq_set_lockdep_class(virq, &gpio_lock_class); @@ -1409,8 +1416,13 @@ static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, * Can use the "simple" and not "edge" handler since it's * shorter, and the AIC handles interrupts sanely. */ - irq_set_chip_and_handler(virq, &gpio_irqchip, - handle_simple_irq); + irq_set_chip(virq, &gpio_irqchip); + if ((at91_gpio->ops == &at91sam9x5_ops) && + (readl_relaxed(pio + PIO_AIMMR) & mask) && + (readl_relaxed(pio + PIO_ELSR) & mask)) + irq_set_handler(virq, handle_level_irq); + else + irq_set_handler(virq, handle_simple_irq); set_irq_flags(virq, IRQF_VALID); irq_set_chip_data(virq, at91_gpio);