From patchwork Thu Oct 15 16:04:26 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 55044 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f200.google.com (mail-lb0-f200.google.com [209.85.217.200]) by patches.linaro.org (Postfix) with ESMTPS id 2115922FFA for ; Thu, 15 Oct 2015 16:04:39 +0000 (UTC) Received: by lbcao8 with SMTP id ao8sf12314032lbc.1 for ; Thu, 15 Oct 2015 09:04:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=wstk5LbYSaaacVLK0cc9wxYlI2PVFEfq7rAaFSbjTNw=; b=essK3J8kzPHCQtZ7HC2VoEg9ByhUtedgbaHzGO4jv4B/SpAz2+csgzMsS12ZifFaGt Kl4NaY9zP4Q9//zQuTUHgsNZ2RgGJqqDqbRFvZycevjjTVAIUztiyFI1C8BPZ2KboAZv mP5lZ1VLHnPwQinccA31eVHGhactZsjfhoLjXQmssjBX3a9JFTxS7CXx9EbltZpwxfYu GWxuwb7ojXlW6bSAkv5F3F3FAoPOGIsQBJCN3H2WF8f4AqkNanIGWlwUXsYQ30icfWfb WVBMe/VKtHTrly1b8gsg00VsaqPVFWw0qtYwaVctwWvMGyD5b7Hz915I4KrTdCWr0S+c qwiw== X-Gm-Message-State: ALoCoQnJwWTOM09VHxPVlBvCGWow1Iwf2EYzK631zzGbG4b1mCLEoTH+OcJqfWo4yneSgP+FRsaD X-Received: by 10.112.169.34 with SMTP id ab2mr2337793lbc.23.1444925078050; Thu, 15 Oct 2015 09:04:38 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.152.199 with SMTP id a190ls201025lfe.62.gmail; Thu, 15 Oct 2015 09:04:37 -0700 (PDT) X-Received: by 10.25.144.78 with SMTP id s75mr3382309lfd.116.1444925077886; Thu, 15 Oct 2015 09:04:37 -0700 (PDT) Received: from mail-lf0-f47.google.com (mail-lf0-f47.google.com. [209.85.215.47]) by mx.google.com with ESMTPS id h189si9591460lfh.51.2015.10.15.09.04.36 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Oct 2015 09:04:36 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) client-ip=209.85.215.47; Received: by lffy185 with SMTP id y185so34168885lff.2 for ; Thu, 15 Oct 2015 09:04:36 -0700 (PDT) X-Received: by 10.25.210.206 with SMTP id j197mr3360457lfg.86.1444925075551; Thu, 15 Oct 2015 09:04:35 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp721262lbq; Thu, 15 Oct 2015 09:04:34 -0700 (PDT) X-Received: by 10.66.189.232 with SMTP id gl8mr10888809pac.52.1444925074251; Thu, 15 Oct 2015 09:04:34 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id qz6si22515725pab.168.2015.10.15.09.04.33; Thu, 15 Oct 2015 09:04:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753666AbbJOQEd (ORCPT + 3 others); Thu, 15 Oct 2015 12:04:33 -0400 Received: from mail-lb0-f171.google.com ([209.85.217.171]:36835 "EHLO mail-lb0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753636AbbJOQEc (ORCPT ); Thu, 15 Oct 2015 12:04:32 -0400 Received: by lbcao8 with SMTP id ao8so74367027lbc.3 for ; Thu, 15 Oct 2015 09:04:31 -0700 (PDT) X-Received: by 10.112.134.102 with SMTP id pj6mr5152895lbb.14.1444925070229; Thu, 15 Oct 2015 09:04:30 -0700 (PDT) Received: from localhost.localdomain ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id c204sm2181575lfe.15.2015.10.15.09.04.28 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Oct 2015 09:04:29 -0700 (PDT) From: Linus Walleij To: linux-gpio@vger.kernel.org Cc: Alexandre Courbot , Linus Walleij , Jonas Gorski , Stefan Agner Subject: [PATCH v3] gpio: pl061: assign the apropriate handler for irqs Date: Thu, 15 Oct 2015 18:04:26 +0200 Message-Id: <1444925066-16934-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 2.4.3 Sender: linux-gpio-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-gpio@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The PL061 can handle level IRQs and edge IRQs, however it is just utilizing handle_simple_irq() for all IRQs. Inspired by Stefan Agners patch to vf610, this assigns the right handler depending on what type is set up, and after this handle_bad_irq() is only used as default and if the type is not specified, as is done in the OMAP driver: defining the IRQ type is really not optional for this driver. The interrupt handler was just writing the interrupt clearing register for all lines that were high when entering the handling loop, this is wrong: that register is only supposed to be written (on a per-line basis) for edge IRQs, so this ACK was moved to the .irq_ack() callback as is proper. Tested with PL061 on the ARM RealView PB11MPCore and the MMC/SC card detect GPIO. Cc: Jonas Gorski Cc: Stefan Agner Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 179339739d60..e15499936c18 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -181,7 +181,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpioiev |= bit; else gpioiev &= ~bit; - + irq_set_handler_locked(d, handle_level_irq); dev_dbg(gc->dev, "line %d: IRQ on %s level\n", offset, polarity ? "HIGH" : "LOW"); @@ -190,7 +190,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpiois &= ~bit; /* Select both edges, setting this makes GPIOEV be ignored */ gpioibe |= bit; - + irq_set_handler_locked(d, handle_edge_irq); dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset); } else if ((trigger & IRQ_TYPE_EDGE_RISING) || (trigger & IRQ_TYPE_EDGE_FALLING)) { @@ -205,7 +205,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpioiev |= bit; else gpioiev &= ~bit; - + irq_set_handler_locked(d, handle_edge_irq); dev_dbg(gc->dev, "line %d: IRQ on %s edge\n", offset, rising ? "RISING" : "FALLING"); @@ -214,6 +214,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpiois &= ~bit; gpioibe &= ~bit; gpioiev &= ~bit; + irq_set_handler_locked(d, handle_bad_irq); dev_warn(gc->dev, "no trigger selected for line %d\n", offset); } @@ -238,7 +239,6 @@ static void pl061_irq_handler(struct irq_desc *desc) chained_irq_enter(irqchip, desc); pending = readb(chip->base + GPIOMIS); - writeb(pending, chip->base + GPIOIC); if (pending) { for_each_set_bit(offset, &pending, PL061_GPIO_NR) generic_handle_irq(irq_find_mapping(gc->irqdomain, @@ -274,8 +274,28 @@ static void pl061_irq_unmask(struct irq_data *d) spin_unlock(&chip->lock); } +/** + * pl061_irq_ack() - ACK an edge IRQ + * @d: IRQ data for this IRQ + * + * This gets called from the edge IRQ handler to ACK the edge IRQ + * in the GPIOIC (interrupt-clear) register. For level IRQs this is + * not needed: these go away when the level signal goes away. + */ +static void pl061_irq_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); + u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); + + spin_lock(&chip->lock); + writeb(mask, chip->base + GPIOIC); + spin_unlock(&chip->lock); +} + static struct irq_chip pl061_irqchip = { .name = "pl061", + .irq_ack = pl061_irq_ack, .irq_mask = pl061_irq_mask, .irq_unmask = pl061_irq_unmask, .irq_set_type = pl061_irq_type, @@ -338,7 +358,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) } ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip, - irq_base, handle_simple_irq, + irq_base, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_info(&adev->dev, "could not add irqchip\n");