From patchwork Mon Dec 22 18:47:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 5528751 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 38965BEEA8 for ; Mon, 22 Dec 2014 18:50:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2BBC9201B9 for ; Mon, 22 Dec 2014 18:50:37 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 41831201B4 for ; Mon, 22 Dec 2014 18:50:36 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Y381S-0005zw-Va; Mon, 22 Dec 2014 18:48:03 +0000 Received: from mail-ig0-x22d.google.com ([2607:f8b0:4001:c05::22d]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Y381O-0005xH-UG for linux-arm-kernel@lists.infradead.org; Mon, 22 Dec 2014 18:48:00 +0000 Received: by mail-ig0-f173.google.com with SMTP id r2so4402081igi.0 for ; Mon, 22 Dec 2014 10:47:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id; bh=M/kj16Wxa+lyijGtz+WZZfKITHGvPRla2OZkX+I9vpk=; b=lwrxmhqw1dfH+LX7UyHwY//BxniaP/k/5GfAJpJgU73djSgqMVwehCeJoTwp7NjrAa h5a0P9+QTHjaObYVjSV4yHGLl4VCep3q0KQe1B7h9NPhraSBH2lgkr158NydiAGz8EjG ABJIUNy447R8QsbuhEqyRcwdLlM3qMOjcLr+M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=M/kj16Wxa+lyijGtz+WZZfKITHGvPRla2OZkX+I9vpk=; b=h4ciF7UNrht3KffD/7/iVyrXDKcgcvQ5Fmor/ItUxOxVw9omTIXEjtnEB37MUDUXuf fSSLfaaPXixjMgwgPVy33hCEZBZvj/eDWzD9ajn9xf3bARD3Ha+18odNpAk9nztSJoYk h7ypxNMceAmcpIa58PLglxCI3h7L6tFf+6zdVmqmZ50yWXbw88jEzK7k+wYXLa43gKkA InBpaIhrfAj4fhg6bHvt8jqq2gakFk1JrLZ/Gt86gkkjttYyWh9efbOLkmYxwV5anoDM vlYpeH3W4P7Hs/ifJ6PoB3uAG5fxOMwTOeXxF6BFiZ0UtmOMxHMgQcEZcdpKI/p4FZZB KJxw== X-Gm-Message-State: ALoCoQlpn4SF6ZTPaB2l4Ll93qpVlnqvgmZ1gp7lcUO7VvmC1fUnFu3SmqLEnGpkug1SEzq99G4g X-Received: by 10.42.151.67 with SMTP id d3mr18624554icw.56.1419274057088; Mon, 22 Dec 2014 10:47:37 -0800 (PST) Received: from tictac.mtv.corp.google.com ([172.22.65.76]) by mx.google.com with ESMTPSA id uw1sm5222338igb.19.2014.12.22.10.47.35 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 22 Dec 2014 10:47:36 -0800 (PST) From: Doug Anderson To: Linus Walleij , Heiko Stuebner Subject: [PATCH] pinctrl: rockchip: Avoid losing interrupts when supporting both edges Date: Mon, 22 Dec 2014 10:47:29 -0800 Message-Id: <1419274049-5069-1-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141222_104759_090229_DFD7AB1F X-CRM114-Status: GOOD ( 14.64 ) X-Spam-Score: -0.8 (/) Cc: Alexandru Stan , linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Doug Anderson , linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_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 I was seeing cases where I was losing interrupts when inserting and removing SD cards. Sometimes the card would get "stuck" in the inserted state. I believe that the problem was related to the code to handle the case where we needed both rising and falling edges. This code would disable the interrupt as the polarity was switched. If an interrupt came at the wrong time it could be lost. We'll match what the gpio-dwapb.c driver does upstream and change the interrupt polarity without disabling things. Signed-off-by: Doug Anderson Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner --- drivers/pinctrl/pinctrl-rockchip.c | 45 +++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 3c22dbe..43eacc9 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1398,10 +1398,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) { struct irq_chip *chip = irq_get_chip(irq); struct rockchip_pin_bank *bank = irq_get_handler_data(irq); - u32 polarity = 0, data = 0; u32 pend; - bool edge_changed = false; - unsigned long flags; dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); @@ -1409,12 +1406,6 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); - if (bank->toggle_edge_mode) { - polarity = readl_relaxed(bank->reg_base + - GPIO_INT_POLARITY); - data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); - } - while (pend) { unsigned int virq; @@ -1434,27 +1425,31 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) * needs manual intervention. */ if (bank->toggle_edge_mode & BIT(irq)) { - if (data & BIT(irq)) - polarity &= ~BIT(irq); - else - polarity |= BIT(irq); + u32 data, data_old, polarity; + unsigned long flags; - edge_changed = true; - } + data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); + do { + spin_lock_irqsave(&bank->slock, flags); - generic_handle_irq(virq); - } + polarity = readl_relaxed(bank->reg_base + + GPIO_INT_POLARITY); + if (data & BIT(irq)) + polarity &= ~BIT(irq); + else + polarity |= BIT(irq); + writel(polarity, + bank->reg_base + GPIO_INT_POLARITY); - if (bank->toggle_edge_mode && edge_changed) { - /* Interrupt params should only be set with ints disabled */ - spin_lock_irqsave(&bank->slock, flags); + spin_unlock_irqrestore(&bank->slock, flags); - data = readl_relaxed(bank->reg_base + GPIO_INTEN); - writel_relaxed(0, bank->reg_base + GPIO_INTEN); - writel(polarity, bank->reg_base + GPIO_INT_POLARITY); - writel(data, bank->reg_base + GPIO_INTEN); + data_old = data; + data = readl_relaxed(bank->reg_base + + GPIO_EXT_PORT); + } while ((data & BIT(irq)) != (data_old & BIT(irq))); + } - spin_unlock_irqrestore(&bank->slock, flags); + generic_handle_irq(virq); } chained_irq_exit(chip, desc);