From patchwork Mon Nov 14 12:23:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 82099 Delivered-To: patch@linaro.org Received: by 10.140.97.165 with SMTP id m34csp980513qge; Mon, 14 Nov 2016 04:23:36 -0800 (PST) X-Received: by 10.99.150.10 with SMTP id c10mr28608984pge.46.1479126216683; Mon, 14 Nov 2016 04:23:36 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tp10si18425110pac.13.2016.11.14.04.23.36; Mon, 14 Nov 2016 04:23:36 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933520AbcKNMXe (ORCPT + 26 others); Mon, 14 Nov 2016 07:23:34 -0500 Received: from mail-lf0-f47.google.com ([209.85.215.47]:36846 "EHLO mail-lf0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752644AbcKNMXc (ORCPT ); Mon, 14 Nov 2016 07:23:32 -0500 Received: by mail-lf0-f47.google.com with SMTP id t196so56962700lff.3 for ; Mon, 14 Nov 2016 04:23:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=VHiWc9/QoNgBhLWbxqeEXVg/w0yVj66LC8UVdcvogEU=; b=a5xi718GZfrUKxlMwTWuJrMpg21PXlqI/+uFj4PS4t2n1yJzMh/Z6LFfh9HKvAWH9v E5b7wlcO4XAy0yRHSqR42X2Et03BSF3LXwQ1wGlJDdt/KKiDlh0p3YiMwphFE++JnXNN LnJgo3TilEau28ot6tjosSYCPfvLRjnLbu2j0= 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=VHiWc9/QoNgBhLWbxqeEXVg/w0yVj66LC8UVdcvogEU=; b=Qs/P6B0qyq1/gFf1YhW35ClAI/LxiznN3kdaAYOe2Wri9gQpAfs15zbXG92uIZESJR y3aVeZR4b7IULx6ZASDt91R6y7cSjfX18SQg0hbXeA2rm3AcZcmLqhNMUiAHiJJZqFe8 fTkcEN1PUZrAeIJBEytqqhFnOcyGdRS+Mnfw5SUX1x8o0tzs8FNjT1DtyCeMmYifV39J CRM7w1KEE31TGsz8rgV7B0cOyvlDf/p33x5QTYYluDa/kFoO1TaXoE+H9+f4K672tb5p H8oTpBqJANHyJATZ8E9csUtpVVcas9beHmMJ66sAjZr9hai4B5BzUBkJkvZgskqDzbZT UY/g== X-Gm-Message-State: ABUngvfd16YUfuBdRAq/fxA95zOKHki5qiKED0AdCfkZwqmmwZXkUhQ1FmBKduHWWx3ZF/m7 X-Received: by 10.25.190.86 with SMTP id o83mr8314963lff.109.1479126210337; Mon, 14 Nov 2016 04:23:30 -0800 (PST) Received: from linuslaptop.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id g68sm5062920ljg.37.2016.11.14.04.23.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Nov 2016 04:23:29 -0800 (PST) From: Linus Walleij To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: linux-gpio@vger.kernel.org, Phil Elwell , Stefan Wahren , Eric Anholt , Stephen Warren , Linus Walleij Subject: [PATCH 1/2] pinctrl: bcm2835: Fix ints for GPIOs 28-31 & 46-53 Date: Mon, 14 Nov 2016 13:23:26 +0100 Message-Id: <1479126206-20482-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Phil Elwell Contrary to the documentation, the BCM2835 GPIO controller actually has four interrupt lines - one each for the three IRQ groups and one common. Confusingly, the GPIO interrupt groups don't correspond directly with the GPIO control banks. Instead, GPIOs 0-27 generate IRQ GPIO0, 28-45 IRQ GPIO1 and 46-53 IRQ GPIO2. Awkwardly, the GPIOs for IRQ GPIO1 straddle two 32-entry GPIO banks, so split out a function to process the interrupts for a single GPIO bank. Cc: Stefan Wahren Cc: Eric Anholt Cc: Stephen Warren Signed-off-by: Phil Elwell Signed-off-by: Linus Walleij --- I want to apply this to cater for my GPIOLIB_IRQCHIP refactorings. --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 51 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) -- 2.7.4 diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index b2dd278f18b1..1d8fc104e26b 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 #define BCM2835_NUM_BANKS 2 +#define BCM2835_NUM_IRQS 3 #define BCM2835_PIN_BITMAP_SZ \ DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) @@ -88,13 +89,13 @@ enum bcm2835_pinconf_pull { struct bcm2835_gpio_irqdata { struct bcm2835_pinctrl *pc; - int bank; + int irqgroup; }; struct bcm2835_pinctrl { struct device *dev; void __iomem *base; - int irq[BCM2835_NUM_BANKS]; + int irq[BCM2835_NUM_IRQS]; /* note: locking assumes each bank will have its own unsigned long */ unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; @@ -105,7 +106,7 @@ struct bcm2835_pinctrl { struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; - struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_BANKS]; + struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS]; spinlock_t irq_lock[BCM2835_NUM_BANKS]; }; @@ -391,17 +392,16 @@ static struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; -static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, + unsigned int bank, u32 mask) { - struct bcm2835_gpio_irqdata *irqdata = dev_id; - struct bcm2835_pinctrl *pc = irqdata->pc; - int bank = irqdata->bank; unsigned long events; unsigned offset; unsigned gpio; unsigned int type; events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4); + events &= mask; events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; @@ -409,7 +409,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } - return events ? IRQ_HANDLED : IRQ_NONE; + + return (events != 0); +} + +static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +{ + struct bcm2835_gpio_irqdata *irqdata = dev_id; + struct bcm2835_pinctrl *pc = irqdata->pc; + int handled = 0; + + switch (irqdata->irqgroup) { + case 0: /* IRQ0 covers GPIOs 0-27 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff); + break; + case 1: /* IRQ1 covers GPIOs 28-45 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) | + bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); + break; + case 2: /* IRQ2 covers GPIOs 46-53 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); + break; + } + + return handled ? IRQ_HANDLED : IRQ_NONE; } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, @@ -1000,8 +1023,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; - int len; - char *name; /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); @@ -1016,10 +1037,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); + spin_lock_init(&pc->irq_lock[i]); + } + + for (i = 0; i < BCM2835_NUM_IRQS; i++) { + int len; + char *name; pc->irq[i] = irq_of_parse_and_map(np, i); pc->irq_data[i].pc = pc; - pc->irq_data[i].bank = i; - spin_lock_init(&pc->irq_lock[i]); + pc->irq_data[i].irqgroup = i; len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); @@ -1076,6 +1102,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { .remove = bcm2835_pinctrl_remove, .driver = { .name = MODULE_NAME, + .owner = THIS_MODULE, .of_match_table = bcm2835_pinctrl_match, }, };