From patchwork Fri Nov 27 21:36:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Rosin X-Patchwork-Id: 7715361 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C25A8BEEE1 for ; Fri, 27 Nov 2015 21:39:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D0BDE2065B for ; Fri, 27 Nov 2015 21:39:07 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DB55E205B3 for ; Fri, 27 Nov 2015 21:39:06 +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 1a2Qhm-0008WP-QP; Fri, 27 Nov 2015 21:37:22 +0000 Received: from mail.lysator.liu.se ([130.236.254.3]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a2QhL-0008OQ-PJ for linux-arm-kernel@lists.infradead.org; Fri, 27 Nov 2015 21:36:57 +0000 Received: from mail.lysator.liu.se (localhost [127.0.0.1]) by mail.lysator.liu.se (Postfix) with ESMTP id 3FFE64007F; Fri, 27 Nov 2015 22:36:33 +0100 (CET) Received: from localhost.localdomain (217-210-101-82-no95.business.telia.com [217.210.101.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.lysator.liu.se (Postfix) with ESMTPSA id 7E3F94000E; Fri, 27 Nov 2015 22:36:32 +0100 (CET) From: Peter Rosin To: linux-gpio@vger.kernel.org Subject: [RFC PATCH 2/2] pinctrl: at91: expose the isr bit Date: Fri, 27 Nov 2015 22:36:13 +0100 Message-Id: <1448660173-29214-3-git-send-email-peda@lysator.liu.se> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1448660173-29214-1-git-send-email-peda@lysator.liu.se> References: <1448660173-29214-1-git-send-email-peda@lysator.liu.se> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151127_133656_189291_6D09EE95 X-CRM114-Status: GOOD ( 15.42 ) X-Spam-Score: -4.2 (----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexandre Courbot , Peter Rosin , Linus Walleij , linux-kernel@vger.kernel.org, Jean-Christophe Plagniol-Villard , Peter Rosin , linux-arm-kernel@lists.infradead.org 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.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 From: Peter Rosin This is a bit horrible, as reading the isr register will interfere with interrupts on other pins in the same pio. So, be careful... Signed-off-by: Peter Rosin --- drivers/pinctrl/pinctrl-at91.c | 50 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 2deb1309fcac..6ae615264e6a 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,8 @@ struct at91_gpio_chip { int pioc_hwirq; /* PIO bank interrupt identifier on AIC */ int pioc_virq; /* PIO bank Linux virtual interrupt */ int pioc_idx; /* PIO bank index */ + spinlock_t isr_lock; /* PIO_ISR cache lock */ + unsigned isr_cache; /* PIO_ISR cache */ void __iomem *regbase; /* PIO bank virtual address */ struct clk *clock; /* associated clock */ struct at91_pinctrl_mux_ops *ops; /* ops */ @@ -737,7 +740,9 @@ static int at91_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, continue; mask = pin_to_mask(pin->pin); + spin_lock(&gpio_chips[pin->bank]->isr_lock); at91_mux_disable_interrupt(pio, mask); + spin_unlock(&gpio_chips[pin->bank]->isr_lock); switch (pin->mux) { case AT91_MUX_GPIO: at91_mux_gpio_enable(pio, mask, 1); @@ -1331,6 +1336,29 @@ static int at91_gpio_get(struct gpio_chip *chip, unsigned offset) return (pdsr & mask) != 0; } +static int at91_gpio_get_isr(struct gpio_chip *chip, unsigned offset) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + int res; + + spin_lock(&at91_gpio->isr_lock); + if (readl_relaxed(pio + PIO_IMR)) { + /* do not clobber PIO_ISR if any interrupts are enabled */ + res = -EBUSY; + goto out; + } + + at91_gpio->isr_cache |= readl_relaxed(pio + PIO_ISR); + res = (at91_gpio->isr_cache & mask) != 0; + at91_gpio->isr_cache &= ~mask; + + out: + spin_unlock(&at91_gpio->isr_lock); + return res; +} + static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { @@ -1425,8 +1453,12 @@ static void gpio_irq_mask(struct irq_data *d) void __iomem *pio = at91_gpio->regbase; unsigned mask = 1 << d->hwirq; - if (pio) - writel_relaxed(mask, pio + PIO_IDR); + if (!pio) + return; + + spin_lock(&at91_gpio->isr_lock); + writel_relaxed(mask, pio + PIO_IDR); + spin_unlock(&at91_gpio->isr_lock); } static void gpio_irq_unmask(struct irq_data *d) @@ -1435,8 +1467,12 @@ static void gpio_irq_unmask(struct irq_data *d) void __iomem *pio = at91_gpio->regbase; unsigned mask = 1 << d->hwirq; - if (pio) - writel_relaxed(mask, pio + PIO_IER); + if (!pio) + return; + + spin_lock(&at91_gpio->isr_lock); + writel_relaxed(mask, pio + PIO_IER); + spin_unlock(&at91_gpio->isr_lock); } static int gpio_irq_type(struct irq_data *d, unsigned type) @@ -1562,8 +1598,10 @@ void at91_pinctrl_gpio_suspend(void) pio = gpio_chips[i]->regbase; backups[i] = readl_relaxed(pio + PIO_IMR); + spin_lock(&gpio_chips[i]->isr_lock); writel_relaxed(backups[i], pio + PIO_IDR); writel_relaxed(wakeups[i], pio + PIO_IER); + spin_unlock(&gpio_chips[i]->isr_lock); if (!wakeups[i]) clk_disable_unprepare(gpio_chips[i]->clock); @@ -1588,8 +1626,10 @@ void at91_pinctrl_gpio_resume(void) if (!wakeups[i]) clk_prepare_enable(gpio_chips[i]->clock); + spin_lock(&gpio_chips[i]->isr_lock); writel_relaxed(wakeups[i], pio + PIO_IDR); writel_relaxed(backups[i], pio + PIO_IER); + spin_unlock(&gpio_chips[i]->isr_lock); } } @@ -1713,6 +1753,7 @@ static struct gpio_chip at91_gpio_template = { .get_direction = at91_gpio_get_direction, .direction_input = at91_gpio_direction_input, .get = at91_gpio_get, + .get_isr = at91_gpio_get_isr, .direction_output = at91_gpio_direction_output, .set = at91_gpio_set, .set_multiple = at91_gpio_set_multiple, @@ -1789,6 +1830,7 @@ static int at91_gpio_probe(struct platform_device *pdev) } at91_chip->chip = at91_gpio_template; + spin_lock_init(&at91_chip->isr_lock); chip = &at91_chip->chip; chip->of_node = np;