From patchwork Wed Jul 16 13:51:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Niebel X-Patchwork-Id: 4567131 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 4ECB7C0514 for ; Wed, 16 Jul 2014 13:42:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7D19420125 for ; Wed, 16 Jul 2014 13:42:19 +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 03AEA20114 for ; Wed, 16 Jul 2014 13:42:18 +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 1X7PQw-0008Dm-ES; Wed, 16 Jul 2014 13:39:46 +0000 Received: from smtprelay01.ispgateway.de ([80.67.31.28]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X7PQt-00089o-61 for linux-arm-kernel@lists.infradead.org; Wed, 16 Jul 2014 13:39:44 +0000 Received: from [89.246.71.91] (helo=mail6.tqsc.de) by smtprelay01.ispgateway.de with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.68) (envelope-from ) id 1X7PQQ-0004D1-O6; Wed, 16 Jul 2014 15:39:14 +0200 Received: from sc1006092vm.tqsc.de ([192.168.169.50] helo=ubuntu.tqsc.de) by mail6.tqsc.de with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1X7PQQ-0003C4-9k; Wed, 16 Jul 2014 15:39:14 +0200 From: Markus Niebel To: linux-arm-kernel@lists.infradead.org Subject: [[RFC PATCH]] gpio: gpio-mxc: make sure gpio is input when request IRQ Date: Wed, 16 Jul 2014 15:51:04 +0200 Message-Id: <1405518664-31313-1-git-send-email-list-09_linux_arm@tqsc.de> X-Mailer: git-send-email 1.7.9.5 X-Df-Sender: MTQ1NzgzNQ== X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140716_063943_594837_CAB522CB X-CRM114-Status: GOOD ( 12.32 ) X-Spam-Score: -0.0 (/) Cc: shawn.guo@linaro.org, Markus Niebel , kernel@pengutronix.de 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=-1.9 required=5.0 tests=BAYES_00,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: Markus Niebel When requesting an GPIO irq for imx Soc two things are missing: - there is no check, if the GPIO is already requested - there is no check, if the GPIO is configured as input The first case can lead to reconfiguring the GPIO pin from third party while it is used as IRQ pin, second case will (eventually) prevent IRQ from being seen by SOC becaus the pin is driven by Soc This patch tries to implement (logic taken roughly from gpio-omap) - basic check if gpio already requested - if needed requests the gpio and configures as IN. - if gpio is already requested it is only verified if pin is IN - gpio is locked as irq Tested on a not mainlined i.MX6 based hardware with pin configured by bootloader as OUT HIGH and expecting a low active IRQ. Signed-off-by: Markus Niebel --- drivers/gpio/gpio-mxc.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index db83b3c..4316a38 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -175,6 +175,31 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) u32 gpio = port->bgc.gc.base + gpio_idx; int edge; void __iomem *reg = port->base; + int ret = 0; + + if (!gpiochip_is_requested(&port->bgc.gc, gpio_idx)) { + char label[32]; + + snprintf(label, 32, "gpio%u-irq", gpio); + ret = gpio_request_one(gpio, GPIOF_DIR_IN, label); + } else { + val = readl(port->base + GPIO_GDIR); + if (val & BIT(gpio_idx)) + ret = -EINVAL; + } + + if (ret) { + dev_err(port->bgc.gc.dev, "unable to set gpio_idx %u as IN\n", + gpio_idx); + return ret; + } + + ret = gpio_lock_as_irq(&port->bgc.gc, gpio_idx); + if (ret) { + dev_err(port->bgc.gc.dev, "unable to lock gpio_idx %u for IRQ\n", + gpio_idx); + return ret; + } port->both_edges &= ~(1 << gpio_idx); switch (type) { @@ -231,6 +256,15 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) return 0; } +static void gpio_irq_shutdown(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxc_gpio_port *port = gc->private; + u32 gpio_idx = d->hwirq; + + gpio_unlock_as_irq(&port->bgc.gc, gpio_idx); +} + static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) { void __iomem *reg = port->base; @@ -353,6 +387,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) ct->chip.irq_mask = irq_gc_mask_clr_bit; ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = gpio_set_irq_type; + ct->chip.irq_shutdown = gpio_irq_shutdown; ct->chip.irq_set_wake = gpio_set_wake_irq; ct->regs.ack = GPIO_ISR; ct->regs.mask = GPIO_IMR;